Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/HeuristicLab.Problems.GaussianProcessTuning.sln
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/HeuristicLab.Problems.GaussianProcessTuning.sln	(revision 9101)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/HeuristicLab.Problems.GaussianProcessTuning.sln	(revision 9102)
@@ -21,4 +21,8 @@
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Instances.DataAnalysis.GaussianProcessRegression-3.3", "HeuristicLab.Problems.Instances.DataAnalysis.GaussianProcessRegression\Instances.DataAnalysis.GaussianProcessRegression-3.3.csproj", "{94C7714E-29D4-4D6D-B213-2C18D627AB75}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ILNumerics", "ILNumerics.2.14.4735.573\ILNumerics.csproj", "{93B4A10E-8979-4028-8CCF-49D88D6FAC0C}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeuristicLabAlgorithmsDataAnalysisExperimental", "HeuristicLab.Algorithms.DataAnalysis.Experimental\HeuristicLabAlgorithmsDataAnalysisExperimental.csproj", "{6142B24E-9C86-410B-A65A-1DE65C8C2349}"
+EndProject
 Global
 	GlobalSection(TestCaseManagementSettings) = postSolution
@@ -32,4 +36,7 @@
 		Release|x64 = Release|x64
 		Release|x86 = Release|x86
+		ReleaseBuild|Any CPU = ReleaseBuild|Any CPU
+		ReleaseBuild|x64 = ReleaseBuild|x64
+		ReleaseBuild|x86 = ReleaseBuild|x86
 	EndGlobalSection
 	GlobalSection(ProjectConfigurationPlatforms) = postSolution
@@ -42,4 +49,8 @@
 		{9A04599C-D608-4240-8DA6-D41F51C515A3}.Release|x64.ActiveCfg = Release|Any CPU
 		{9A04599C-D608-4240-8DA6-D41F51C515A3}.Release|x86.ActiveCfg = Release|Any CPU
+		{9A04599C-D608-4240-8DA6-D41F51C515A3}.ReleaseBuild|Any CPU.ActiveCfg = Release|Any CPU
+		{9A04599C-D608-4240-8DA6-D41F51C515A3}.ReleaseBuild|Any CPU.Build.0 = Release|Any CPU
+		{9A04599C-D608-4240-8DA6-D41F51C515A3}.ReleaseBuild|x64.ActiveCfg = Release|Any CPU
+		{9A04599C-D608-4240-8DA6-D41F51C515A3}.ReleaseBuild|x86.ActiveCfg = Release|Any CPU
 		{98C8AD2B-B035-4863-A01E-B659465FF6B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{98C8AD2B-B035-4863-A01E-B659465FF6B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
@@ -50,4 +61,8 @@
 		{98C8AD2B-B035-4863-A01E-B659465FF6B2}.Release|x64.ActiveCfg = Release|Any CPU
 		{98C8AD2B-B035-4863-A01E-B659465FF6B2}.Release|x86.ActiveCfg = Release|Any CPU
+		{98C8AD2B-B035-4863-A01E-B659465FF6B2}.ReleaseBuild|Any CPU.ActiveCfg = Release|Any CPU
+		{98C8AD2B-B035-4863-A01E-B659465FF6B2}.ReleaseBuild|Any CPU.Build.0 = Release|Any CPU
+		{98C8AD2B-B035-4863-A01E-B659465FF6B2}.ReleaseBuild|x64.ActiveCfg = Release|Any CPU
+		{98C8AD2B-B035-4863-A01E-B659465FF6B2}.ReleaseBuild|x86.ActiveCfg = Release|Any CPU
 		{94C7714E-29D4-4D6D-B213-2C18D627AB75}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{94C7714E-29D4-4D6D-B213-2C18D627AB75}.Debug|Any CPU.Build.0 = Debug|Any CPU
@@ -62,4 +77,40 @@
 		{94C7714E-29D4-4D6D-B213-2C18D627AB75}.Release|x86.ActiveCfg = Release|x86
 		{94C7714E-29D4-4D6D-B213-2C18D627AB75}.Release|x86.Build.0 = Release|x86
+		{94C7714E-29D4-4D6D-B213-2C18D627AB75}.ReleaseBuild|Any CPU.ActiveCfg = Release|Any CPU
+		{94C7714E-29D4-4D6D-B213-2C18D627AB75}.ReleaseBuild|Any CPU.Build.0 = Release|Any CPU
+		{94C7714E-29D4-4D6D-B213-2C18D627AB75}.ReleaseBuild|x64.ActiveCfg = Release|x64
+		{94C7714E-29D4-4D6D-B213-2C18D627AB75}.ReleaseBuild|x64.Build.0 = Release|x64
+		{94C7714E-29D4-4D6D-B213-2C18D627AB75}.ReleaseBuild|x86.ActiveCfg = Release|x86
+		{94C7714E-29D4-4D6D-B213-2C18D627AB75}.ReleaseBuild|x86.Build.0 = Release|x86
+		{93B4A10E-8979-4028-8CCF-49D88D6FAC0C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{93B4A10E-8979-4028-8CCF-49D88D6FAC0C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{93B4A10E-8979-4028-8CCF-49D88D6FAC0C}.Debug|x64.ActiveCfg = Debug|x64
+		{93B4A10E-8979-4028-8CCF-49D88D6FAC0C}.Debug|x64.Build.0 = Debug|x64
+		{93B4A10E-8979-4028-8CCF-49D88D6FAC0C}.Debug|x86.ActiveCfg = Debug|x86
+		{93B4A10E-8979-4028-8CCF-49D88D6FAC0C}.Debug|x86.Build.0 = Debug|x86
+		{93B4A10E-8979-4028-8CCF-49D88D6FAC0C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{93B4A10E-8979-4028-8CCF-49D88D6FAC0C}.Release|Any CPU.Build.0 = Release|Any CPU
+		{93B4A10E-8979-4028-8CCF-49D88D6FAC0C}.Release|x64.ActiveCfg = Release|x64
+		{93B4A10E-8979-4028-8CCF-49D88D6FAC0C}.Release|x64.Build.0 = Release|x64
+		{93B4A10E-8979-4028-8CCF-49D88D6FAC0C}.Release|x86.ActiveCfg = Release|x86
+		{93B4A10E-8979-4028-8CCF-49D88D6FAC0C}.Release|x86.Build.0 = Release|x86
+		{93B4A10E-8979-4028-8CCF-49D88D6FAC0C}.ReleaseBuild|Any CPU.ActiveCfg = ReleaseBuild|Any CPU
+		{93B4A10E-8979-4028-8CCF-49D88D6FAC0C}.ReleaseBuild|Any CPU.Build.0 = ReleaseBuild|Any CPU
+		{93B4A10E-8979-4028-8CCF-49D88D6FAC0C}.ReleaseBuild|x64.ActiveCfg = ReleaseBuild|x64
+		{93B4A10E-8979-4028-8CCF-49D88D6FAC0C}.ReleaseBuild|x64.Build.0 = ReleaseBuild|x64
+		{93B4A10E-8979-4028-8CCF-49D88D6FAC0C}.ReleaseBuild|x86.ActiveCfg = ReleaseBuild|x86
+		{93B4A10E-8979-4028-8CCF-49D88D6FAC0C}.ReleaseBuild|x86.Build.0 = ReleaseBuild|x86
+		{6142B24E-9C86-410B-A65A-1DE65C8C2349}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{6142B24E-9C86-410B-A65A-1DE65C8C2349}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{6142B24E-9C86-410B-A65A-1DE65C8C2349}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{6142B24E-9C86-410B-A65A-1DE65C8C2349}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{6142B24E-9C86-410B-A65A-1DE65C8C2349}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{6142B24E-9C86-410B-A65A-1DE65C8C2349}.Release|Any CPU.Build.0 = Release|Any CPU
+		{6142B24E-9C86-410B-A65A-1DE65C8C2349}.Release|x64.ActiveCfg = Release|Any CPU
+		{6142B24E-9C86-410B-A65A-1DE65C8C2349}.Release|x86.ActiveCfg = Release|Any CPU
+		{6142B24E-9C86-410B-A65A-1DE65C8C2349}.ReleaseBuild|Any CPU.ActiveCfg = Release|Any CPU
+		{6142B24E-9C86-410B-A65A-1DE65C8C2349}.ReleaseBuild|Any CPU.Build.0 = Release|Any CPU
+		{6142B24E-9C86-410B-A65A-1DE65C8C2349}.ReleaseBuild|x64.ActiveCfg = Release|Any CPU
+		{6142B24E-9C86-410B-A65A-1DE65C8C2349}.ReleaseBuild|x86.ActiveCfg = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Algorithms/Graphics/Triangularize.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Algorithms/Graphics/Triangularize.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Algorithms/Graphics/Triangularize.cs	(revision 9102)
@@ -0,0 +1,155 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace ILNumerics.Algorithms {
+    public partial class Graphic {
+
+        /// <summary>
+        /// Increase the number of triangles by doubling existing triangles
+        /// </summary>
+        /// <param name="vertices">Vertices</param>
+        /// <param name="triangles">Triangle index definitions</param>
+        /// <param name="iterations">Number of iterations, each iteration will make 4 triangles out of each triangle</param>
+        /// <param name="outVertices">[Output] Vertices.</param>
+        /// <param name="outTriangles">[Output] Triangles</param>
+        /// <remarks><para>Incoming triangles are expected not to be degenerated. This means:
+        /// Every edge is used only twice at most. No triangle shares more than 2
+        /// corners with some other triangle. </para>
+        /// 	<para>None of the incoming arrays will get altered</para></remarks>
+        public static void Triangularize(ILInArray<float> vertices, ILInArray<int> triangles,
+                                        int iterations,
+                                        ILOutArray<float> outVertices,
+                                        ILOutArray<int> outTriangles) {
+            using (ILScope.Enter(vertices, triangles)) {
+                int numVertices = vertices.Size[1];
+                int numTriangles = triangles.Size[1];
+                outVertices.a = vertices.C;
+                outTriangles.a = triangles.C;
+                // being pessimistic: expect to create a larger number of vertices than probable
+                outVertices[0, numVertices * 2] = 0;
+                outTriangles[0, numTriangles * 2] = 0;
+
+                int triIndLast = numTriangles;
+                int vertIndLast = numVertices;
+                for (int it = 0; it < iterations; it++) {
+                    int triIndItEnd = triIndLast;
+
+                    for (int triInd = 0; triInd < triIndItEnd; triInd++) {
+                        int vertInd0 = outTriangles.GetValue(0, triInd);
+                        int vertInd1 = outTriangles.GetValue(1, triInd);
+                        int vertInd2 = outTriangles.GetValue(2, triInd);
+                        // create new vertices
+                        float v0x = (outVertices.GetValue(0, vertInd0) + outVertices.GetValue(0, vertInd1)) / 2f;
+                        float v0y = (outVertices.GetValue(1, vertInd0) + outVertices.GetValue(1, vertInd1)) / 2f;
+                        float v0z = (outVertices.GetValue(2, vertInd0) + outVertices.GetValue(2, vertInd1)) / 2f;
+                        float v1x = (outVertices.GetValue(0, vertInd1) + outVertices.GetValue(0, vertInd2)) / 2f;
+                        float v1y = (outVertices.GetValue(1, vertInd1) + outVertices.GetValue(1, vertInd2)) / 2f;
+                        float v1z = (outVertices.GetValue(2, vertInd1) + outVertices.GetValue(2, vertInd2)) / 2f;
+                        float v2x = (outVertices.GetValue(0, vertInd2) + outVertices.GetValue(0, vertInd0)) / 2f;
+                        float v2y = (outVertices.GetValue(1, vertInd2) + outVertices.GetValue(1, vertInd0)) / 2f;
+                        float v2z = (outVertices.GetValue(2, vertInd2) + outVertices.GetValue(2, vertInd0)) / 2f;
+                        #region new vertex exists already? TODO: This needs to be replaced with a b-tree implementation!!
+                        int newVertID0 = -1;
+                        int newVertID1 = -1;
+                        int newVertID2 = -1;
+                        for (int vi = 0; vi < vertIndLast; vi++) {
+                            float tmpX = outVertices.GetValue(0, vi);
+                            float tmpY = outVertices.GetValue(1, vi);
+                            float tmpZ = outVertices.GetValue(2, vi);
+                            if (tmpX == v0x && tmpY == v0y && tmpZ == v0z) {
+                                newVertID0 = vi;
+                            }
+                            if (tmpX == v1x && tmpY == v1y && tmpZ == v1z) {
+                                newVertID1 = vi;
+                            }
+                            if (tmpX == v2x && tmpY == v2y && tmpZ == v2z) {
+                                newVertID2 = vi;
+                            }
+                            if (newVertID0 >= 0 && newVertID1 >= 0 && newVertID2 >= 0)
+                                break;
+                        }
+                        #endregion
+
+                        if (newVertID0 < 0) {
+                            newVertID0 = vertIndLast++;
+                            outVertices[0, newVertID0] = v0x;
+                            outVertices[1, newVertID0] = v0y;
+                            outVertices[2, newVertID0] = v0z;
+                        }
+                        if (newVertID1 < 0) {
+                            newVertID1 = vertIndLast++;
+                            outVertices[0, newVertID1] = v1x;
+                            outVertices[1, newVertID1] = v1y;
+                            outVertices[2, newVertID1] = v1z;
+                        }
+                        if (newVertID2 < 0) {
+                            newVertID2 = vertIndLast++;
+                            outVertices[0, newVertID2] = v2x;
+                            outVertices[1, newVertID2] = v2y;
+                            outVertices[2, newVertID2] = v2z;
+                        }
+
+                        // create new triangles 
+                        outTriangles.SetValue(newVertID0, 1, triInd);
+                        outTriangles.SetValue(newVertID2, 2, triInd);
+
+                        outTriangles.SetValue(newVertID2, 0, triIndLast);
+                        outTriangles.SetValue(newVertID1, 1, triIndLast);
+                        outTriangles.SetValue(vertInd2, 2, triIndLast++);
+
+                        outTriangles.SetValue(newVertID2, 0, triIndLast);
+                        outTriangles.SetValue(newVertID0, 1, triIndLast);
+                        outTriangles.SetValue(newVertID1, 2, triIndLast++);
+
+                        outTriangles.SetValue(newVertID0, 0, triIndLast);
+                        outTriangles.SetValue(vertInd1, 1, triIndLast);
+                        outTriangles.SetValue(newVertID1, 2, triIndLast++);
+                    }
+
+                }
+                outVertices.a = outVertices[":;0:" + (vertIndLast - 1)];
+                outTriangles.a = outTriangles[":;0:" + (triIndLast - 1)];
+            }
+        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Algorithms/MachineLearning/ILEM.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Algorithms/MachineLearning/ILEM.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Algorithms/MachineLearning/ILEM.cs	(revision 9102)
@@ -0,0 +1,283 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using ILNumerics.Exceptions;
+
+
+namespace ILNumerics {
+    public partial class ILMath {
+
+        /// <summary>
+        /// Determine method of center initialization for EM algorithm
+        /// </summary>
+        public enum EMInitializationMethod {
+            /// <summary>
+            /// Use the kmeans algorithm, choose random samples as centers for start 
+            /// </summary>
+            KMeans_random,
+            /// <summary>
+            /// Use the kmeans algorithm, choose first k samples as centers for start 
+            /// </summary>
+            KMeans_firstK,
+            /// <summary>
+            /// Provide custom centers in the 'InitCenter' argument
+            /// </summary>
+            User
+        }
+
+
+
+        /// <summary>
+        /// Expectation maximization algorithm
+        /// </summary>
+        /// <param name="Samples">Input data, data points in columns</param>
+        /// <param name="k">Number of clusters</param>
+        /// <param name="method">[Optional] Method used for initializing the cluster centers, default: kmeans_random</param>
+        /// <param name="UserCenters">[Optional] For method 'user': initial cluster centers, size samples.D[0] x k, for other methods ignored</param>
+        /// <param name="maxiterexit">[Optional] Break after that number of iterations, if no convergence was reached</param>
+        /// <param name="Sigma">[Output] Covariance estimation for all clusters, size d x d x k, d = samples.D[0]</param>
+        /// <param name="centerconverg_exit">[Optional] Exit iteration if norm(L) falls below that value, default: 0.001</param>
+        /// <returns>Estimated centers for all clusters, size samples.D[0] x k</returns>
+        /// <remarks><para>The EM algorithm expects the data samples to be drawn from <paramref name="k"/> multivariate normal distributions. 
+        /// It estimates the parameters 'center' and 'sigma (covariance)' of every distribution. Therefore, the position and 'shape' 
+        /// of each distribution is calculated in such a way, that the likelyhood of generating the given sample points is maximized.</para>
+        /// <para>The parameter k must be determined by the user. This reflects the a priori knowledge of the number of distributions 
+        /// or clusters in the data.</para>
+        /// <para>The algorithm exits, if one of the exit criteria is reached: 
+        /// <list type="bullet"><item>norm(L) &lt; 'centerconverg_exit' - where L is the difference between 
+        /// the centers from the last step and the centers just computed in the current step</item>
+        /// <item>the number of iteration steps exceeds the limit of 'maxiterexit' iterations.</item></list></para>
+        /// </remarks>
+        public static ILRetArray<double> em(ILInArray<double> Samples,
+                                    int k, ILOutArray<double> Sigma = null, EMInitializationMethod method = EMInitializationMethod.KMeans_random,
+                                    ILInArray<double> UserCenters = null, int maxiterexit = 10000, double centerconverg_exit = 0.001) {
+            using (ILScope.Enter(Samples, UserCenters)) {
+
+                ILArray<double> samples = check(Samples);
+                ILArray<double> userCenters = check(UserCenters, allowNullInput: true); 
+                if (k < 0)
+                    throw new ILArgumentException("k must be greater or equal 0");
+                if (isnull(samples))
+                    throw new ILArgumentException("input argument 'samples' must not be null");
+                if (method == EMInitializationMethod.User) {
+                    if (isnull(userCenters))
+                        throw new ILArgumentException("if initialization method 'user' was choosen, the parameter 'userCenters' must be used to provide custom initialization centers");
+                    if (userCenters.S[0] != samples.S[0])
+                        throw new ILArgumentException("the dimensionality (number of rows) of 'samples' and 'userCenters' must match");
+                }
+                // initialization
+                int d = samples.S[0], n = samples.S[1], count = 0;
+                ILArray<double> mu = empty<double>();
+                ILArray<double> sigm = repmat(eye<double>(d, d), 1, 1, k);
+                ILArray<double> gamma = zeros<double>(k, n);
+                ILArray<double> priors = ones<double>(1, k) / k;
+                ILArray<double> oldmu = zeros<double>(d, k);
+                switch (method) {
+                    case EMInitializationMethod.KMeans_random:
+                        kMeansClust(samples, k, outCenters: mu, centerInitRandom: true).Dispose();
+                        break;
+                    case EMInitializationMethod.KMeans_firstK:
+                        kMeansClust(samples, k, outCenters: mu, centerInitRandom: false).Dispose();
+                        break;
+                    case EMInitializationMethod.User:
+                        mu.a = userCenters;
+                        break;
+                    default:
+                        throw new ILArgumentException("invalid 'method' argument given");
+                }
+                // main loop
+                while (true) {
+                    using (ILScope.Enter()) {
+                        // E - Step
+                        for (int i = 0; i < k; i++) {
+                            gamma[i, full] = gauss(samples, mu[full, i], sigm[full, full, i]) / priors[i];
+                        }
+                        gamma.a = gamma / max(sum(gamma, 0), MachineParameterDouble.eps);
+
+                        // M - Step
+                        ILArray<double> Nk = sum(gamma, 1);
+                        priors.a = Nk / n;
+                        for (int i = 0; i < k; i++) {
+                            using (ILScope.Enter()) {
+                                mu[full, i] = sum(gamma[i, full] * samples, 1) / Nk[i];
+                                ILArray<double> tmpXnMinMuk = samples - mu[full, i];
+                                sigm[full, full, i] = multiply((gamma[i, full] * tmpXnMinMuk), tmpXnMinMuk.T) / Nk[i];
+                            }
+                        }
+
+                        // check exit condition
+                        if (norm(oldmu - mu) < (double)centerconverg_exit || count > maxiterexit)
+                            break;
+                        else {
+                            oldmu = mu;
+                            count = count + 1;
+                        }
+                    }
+                }
+                if (!isnull(Sigma)) {
+                    Sigma.a = sigm; 
+                }
+                return mu; 
+            }
+        }
+
+        private static ILRetArray<double> gauss(ILInArray<double> samples, ILInArray<double> mu, ILRetArray<double> sigma) {
+            using (ILScope.Enter(samples, mu, sigma)) { 
+                int d = samples.S[0], n = samples.S[1];
+                ILArray<double> sampMinMu = samples - mu;
+                ILArray<double> sigInv = linsolve(eye<double>(d, d), sigma[full,full]);
+                return 1 / ((double)pow(sqrt(2 * pi), d) * det(sigma)) * exp((double)-0.5 * sum(multiply(sigInv.T, sampMinMu) * sampMinMu, 0));  
+            }
+        }
+             
+
+#region HYCALPER AUTO GENERATED CODE
+
+
+        /// <summary>
+        /// Expectation maximization algorithm
+        /// </summary>
+        /// <param name="Samples">Input data, data points in columns</param>
+        /// <param name="k">Number of clusters</param>
+        /// <param name="method">[Optional] Method used for initializing the cluster centers, default: kmeans_random</param>
+        /// <param name="UserCenters">[Optional] For method 'user': initial cluster centers, size samples.D[0] x k, for other methods ignored</param>
+        /// <param name="maxiterexit">[Optional] Break after that number of iterations, if no convergence was reached</param>
+        /// <param name="Sigma">[Output] Covariance estimation for all clusters, size d x d x k, d = samples.D[0]</param>
+        /// <param name="centerconverg_exit">[Optional] Exit iteration if norm(L) falls below that value, default: 0.001</param>
+        /// <returns>Estimated centers for all clusters, size samples.D[0] x k</returns>
+        /// <remarks><para>The EM algorithm expects the data samples to be drawn from <paramref name="k"/> multivariate normal distributions. 
+        /// It estimates the parameters 'center' and 'sigma (covariance)' of every distribution. Therefore, the position and 'shape' 
+        /// of each distribution is calculated in such a way, that the likelyhood of generating the given sample points is maximized.</para>
+        /// <para>The parameter k must be determined by the user. This reflects the a priori knowledge of the number of distributions 
+        /// or clusters in the data.</para>
+        /// <para>The algorithm exits, if one of the exit criteria is reached: 
+        /// <list type="bullet"><item>norm(L) &lt; 'centerconverg_exit' - where L is the difference between 
+        /// the centers from the last step and the centers just computed in the current step</item>
+        /// <item>the number of iteration steps exceeds the limit of 'maxiterexit' iterations.</item></list></para>
+        /// </remarks>
+        public static ILRetArray<float> em(ILInArray<float> Samples,
+                                    int k, ILOutArray<float> Sigma = null, EMInitializationMethod method = EMInitializationMethod.KMeans_random,
+                                    ILInArray<float> UserCenters = null, int maxiterexit = 10000, double centerconverg_exit = 0.001) {
+            using (ILScope.Enter(Samples, UserCenters)) {
+
+                ILArray<float> samples = check(Samples);
+                ILArray<float> userCenters = check(UserCenters, allowNullInput: true); 
+                if (k < 0)
+                    throw new ILArgumentException("k must be greater or equal 0");
+                if (isnull(samples))
+                    throw new ILArgumentException("input argument 'samples' must not be null");
+                if (method == EMInitializationMethod.User) {
+                    if (isnull(userCenters))
+                        throw new ILArgumentException("if initialization method 'user' was choosen, the parameter 'userCenters' must be used to provide custom initialization centers");
+                    if (userCenters.S[0] != samples.S[0])
+                        throw new ILArgumentException("the dimensionality (number of rows) of 'samples' and 'userCenters' must match");
+                }
+                // initialization
+                int d = samples.S[0], n = samples.S[1], count = 0;
+                ILArray<float> mu = empty<float>();
+                ILArray<float> sigm = repmat(eye<float>(d, d), 1, 1, k);
+                ILArray<float> gamma = zeros<float>(k, n);
+                ILArray<float> priors = ones<float>(1, k) / k;
+                ILArray<float> oldmu = zeros<float>(d, k);
+                switch (method) {
+                    case EMInitializationMethod.KMeans_random:
+                        kMeansClust(samples, k, outCenters: mu, centerInitRandom: true).Dispose();
+                        break;
+                    case EMInitializationMethod.KMeans_firstK:
+                        kMeansClust(samples, k, outCenters: mu, centerInitRandom: false).Dispose();
+                        break;
+                    case EMInitializationMethod.User:
+                        mu.a = userCenters;
+                        break;
+                    default:
+                        throw new ILArgumentException("invalid 'method' argument given");
+                }
+                // main loop
+                while (true) {
+                    using (ILScope.Enter()) {
+                        // E - Step
+                        for (int i = 0; i < k; i++) {
+                            gamma[i, full] = gauss(samples, mu[full, i], sigm[full, full, i]) / priors[i];
+                        }
+                        gamma.a = gamma / max(sum(gamma, 0), MachineParameterSingle.eps);
+
+                        // M - Step
+                        ILArray<float> Nk = sum(gamma, 1);
+                        priors.a = Nk / n;
+                        for (int i = 0; i < k; i++) {
+                            using (ILScope.Enter()) {
+                                mu[full, i] = sum(gamma[i, full] * samples, 1) / Nk[i];
+                                ILArray<float> tmpXnMinMuk = samples - mu[full, i];
+                                sigm[full, full, i] = multiply((gamma[i, full] * tmpXnMinMuk), tmpXnMinMuk.T) / Nk[i];
+                            }
+                        }
+
+                        // check exit condition
+                        if (norm(oldmu - mu) < (float)centerconverg_exit || count > maxiterexit)
+                            break;
+                        else {
+                            oldmu = mu;
+                            count = count + 1;
+                        }
+                    }
+                }
+                if (!isnull(Sigma)) {
+                    Sigma.a = sigm; 
+                }
+                return mu; 
+            }
+        }
+
+        private static ILRetArray<float> gauss(ILInArray<float> samples, ILInArray<float> mu, ILRetArray<float> sigma) {
+            using (ILScope.Enter(samples, mu, sigma)) { 
+                int d = samples.S[0], n = samples.S[1];
+                ILArray<float> sampMinMu = samples - mu;
+                ILArray<float> sigInv = linsolve(eye<float>(d, d), sigma[full,full]);
+                return 1 / ((float)pow(sqrt(2 * pi), d) * det(sigma)) * exp((float)-0.5 * sum(multiply(sigInv.T, sampMinMu) * sampMinMu, 0));  
+            }
+        }
+             
+
+#endregion HYCALPER AUTO GENERATED CODE
+   }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Algorithms/MachineLearning/ILKNN.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Algorithms/MachineLearning/ILKNN.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Algorithms/MachineLearning/ILKNN.cs	(revision 9102)
@@ -0,0 +1,418 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using ILNumerics.Exceptions;
+
+
+namespace ILNumerics {
+    public partial class ILMath {
+
+        public enum DistanceMetrics {
+            Euclidian_L2,
+            Mahalanobis,
+            Manhattan_L1,
+            Minkowski,
+            Chebychev,
+            Cosine,
+            Pearsons,
+            Hamming,
+            Jaccard,
+            Spearman
+        }
+
+
+        /// <summary>
+        /// Search for k nearest neighbors for every sample in <paramref name="Samples"/> samples
+        /// </summary>
+        /// <param name="Samples">Samples matrix, samples in columns, the number of rows (dimensionality) must match the number of rows in <paramref name="Neighbors"/> </param>
+        /// <param name="Neighbors">Matrix of training samples/ neighbors, this will be searched for matching points, rows: dimensionality, columns: number of points</param>
+        /// <param name="k">[Optional] Number of neighbors to return, k must lay in range: 0 &le; k &lt neighbors.D[1]; default: 1</param>
+        /// <param name="metric">[Optional] Distance metric, one out of the <see cref="ILNumerics.ILMath.DistanceMetrics"/> enumeration. Supported are: Euclidian_L2,Manhattan_L1, 
+        /// Minkowski, Cosine, Pearsons and Hamming distances; default: 'Euclidian_L2'</param>
+        /// <param name="minkowski_parameter">[Optional] Exponent for minkowski distance; default: 2</param>
+        /// <param name="unstable_error">[Optional] For cosine and pearson distances: if some samples lead to numerical instabilities, an exception is generated; default: true</param>
+        /// <returns>Matrix of nearest neighbors, size: k x samples.D[1]; indices of points in <paramref name="Neighbors"/> matrix</returns>
+        public static ILRetArray<double> knn(ILInArray<double> Samples, ILInArray<double> Neighbors, int k = 10, 
+                                                DistanceMetrics metric = DistanceMetrics.Euclidian_L2, double minkowski_parameter = 2.0,
+                                                bool unstable_error = true) {
+            using (ILScope.Enter(Samples, Neighbors)) {
+
+                ILArray<double> samples = Samples; 
+                ILArray<double> neighbors = Neighbors; 
+
+                if (k < 0) {
+                    throw new ILArgumentException("k must be greater or equal 0");  
+                }
+                if (isnullorempty(neighbors)) {
+                    throw new ILArgumentException("input argument 'neighbors' must not be null or empty");
+                }
+                if (isnull(samples)) {
+                    throw new ILArgumentException("input argument 'samples' must not be null"); 
+                }
+                if (samples.S[0] != neighbors.S[0])
+                    throw new ILArgumentException("number of rows for 'neighbors' and 'samples' must match"); 
+                if (k > neighbors.S[1]) 
+                    throw new ILArgumentException("k must be smaller or equal to the number of datapoints (number of columns) in A"); 
+                int nn = neighbors.S[1], am = neighbors.S[0], sn = samples.S[1];
+                ILArray<double> ret = zeros<double>(k, sn);
+                switch (metric) {
+                    case DistanceMetrics.Euclidian_L2:
+                        for (int i = 0; i < sn; i++) {
+                            using (ILScope.Enter()) {
+                                ILArray<double> dist = neighbors - samples[full, i];
+                                dist.a = sum(dist * dist, 0);
+                                ILArray<double> indices = empty<double>();
+                                if (k == 1) {
+                                    min(dist, indices, 1).Dispose();
+                                    ret[full, i] = indices[0];
+                                } else {
+                                    sort(dist, indices, 1, false).Dispose();
+                                    ret[full, i] = indices[r(0, k - 1)];
+                                }
+                            }
+                        }
+                        break;
+                    case DistanceMetrics.Manhattan_L1:
+                        for (int i = 0; i < sn; i++) {
+                            using (ILScope.Enter()) {
+                                ILArray<double> dist = neighbors - samples[full, i];
+                                dist.a = sum(abs(dist), 0);
+                                ILArray<double> indices = empty<double>();
+                                if (k == 1) {
+                                    min(dist, indices, 1).Dispose();
+                                    ret[full, i] = indices[0];
+                                } else {
+                                    sort(dist, indices, 1, false).Dispose();
+                                    ret[full, i] = indices[r(0, k - 1)];
+                                }
+                            }
+                        }
+                        break;
+                    case DistanceMetrics.Minkowski:
+                        for (int i = 0; i < sn; i++) {
+                            using (ILScope.Enter()) {
+                                ILArray<double> dist = neighbors - samples[full, i];
+                                dist.a = sum(pow(dist,(double)minkowski_parameter), 0);
+                                ILArray<double> indices = empty<double>();
+                                if (k == 1) {
+                                    min(dist, indices, 0).Dispose();
+                                    ret[full, i] = indices[0];
+                                } else {
+                                    sort(dist, indices, 0, false).Dispose();
+                                    ret[full, i] = indices[r(0, k - 1)];
+                                }
+                            }
+                        }
+                        break;
+                    case DistanceMetrics.Cosine:
+                        ILArray<double> samples_normalized = sqrt(sum(samples * samples, 0));
+                        ILArray<double> neighbs_normalized = sqrt(sum(neighbors * neighbors, 0));
+                        if (unstable_error && !testStable(samples_normalized)) {
+                            throw new ILArgumentException("possibly numerical instability: some samples are too close to 0. Try using a different metric instead!");
+                        }
+                        if (unstable_error && !testStable(neighbs_normalized)) {
+                            throw new ILArgumentException("possibly numerical instability: some neighbors are too close to 0. Try using a different metric instead!");
+                        }
+                        neighbs_normalized.a = neighbors / neighbs_normalized;
+                        for (int i = 0; i < sn; i++) {
+                            using (ILScope.Enter()) {
+                                ILArray<double> dist = 1 - multiply(neighbs_normalized.T, samples[full, i]) / samples_normalized[i];
+                                ILArray<double> indices = empty<double>();
+                                if (k == 1) {
+                                    min(dist, indices, 0).Dispose();
+                                    ret[full, i] = indices[0];
+                                } else {
+                                    sort(dist, indices, 0, false).Dispose();
+                                    ret[full, i] = indices[r(0, k - 1)];
+                                }
+                            }
+                        }
+                        break;
+                    case DistanceMetrics.Pearsons:
+                        ILArray<double> samples_centered = samples - mean(samples, 0);
+                        ILArray<double> neighbs_centered = neighbors - mean(neighbors, 0);
+                        samples_normalized = sqrt(sum(samples_centered * samples_centered, 0));
+                        neighbs_normalized = sqrt(sum(neighbs_centered * neighbs_centered, 0));
+                        if (unstable_error && !testStable(samples_normalized)) {
+                            throw new ILArgumentException("possibly numerical instability: standard deviation for some neighbor points is close to zero. Try using a different metric instead!");
+                        }
+                        if (unstable_error && !testStable(neighbs_normalized)) {
+                            throw new ILArgumentException("possibly numerical instability: standard deviation for some neighbor points is close to zero. Try using a different metric instead!");
+                        }
+                        neighbs_normalized.a = neighbs_centered / neighbs_normalized;
+                        for (int i = 0; i < sn; i++) {
+                            using (ILScope.Enter()) {
+                                ILArray<double> dist = 1 - multiply(neighbs_normalized.T, samples_centered[full, i]) / samples_normalized[i];
+                                ILArray<double> indices = empty<double>();
+                                if (k == 1) {
+                                    min(dist,indices,0).Dispose(); 
+                                    ret[full, i] = indices[0]; 
+                                } else {
+                                    sort(dist, indices, 0, false).Dispose();
+                                    ret[full, i] = indices[r(0, k - 1)];
+                                }
+                            }
+                        }
+                        break;
+                    case DistanceMetrics.Hamming:
+                        if (samples.Any((a) => { return a != 0 && a != 1; })) {
+                            throw new ILArgumentException("hamming distance requires 0 and 1 as value for all elements of 'samples'");
+                        }
+                        if (neighbors.Any((a) => { return a != 0 && a != 1; })) {
+                            throw new ILArgumentException("hamming distance requires 0 and 1 as value for all elements of 'neighbors'");
+                        }
+                        for (int i = 0; i < sn; i++) {
+                            using (ILScope.Enter()) {
+                                ILArray<double> dist = sum(abs(neighbors - samples[full, i]), 0) / am; 
+                                ILArray<double> indices = empty<double>();
+                                if (k == 1) {
+                                    min(dist, indices, 1).Dispose();
+                                    ret[full, i] = indices[0];
+                                } else {
+                                    sort(dist, indices, 1, false).Dispose();
+                                    ret[full, i] = indices[r(0, k - 1)];
+                                }
+                            }
+                        }
+                        break;
+                    default:
+                        throw new ILArgumentException("the selected distance is not supported"); 
+                }
+                return ret; 
+            }
+             
+        }
+        /// <summary>
+        /// Test for numerical instability, expects positive data only!
+        /// </summary>
+        /// <param name="samples_normalized">Input data</param>
+        /// <returns>true: no instability detected, false, possible instablility</returns>
+        private static bool testStable(ILInArray<double> samples_normalized) {
+            using (ILScope.Enter(samples_normalized)) {
+                
+                double max, min;
+                samples_normalized.GetLimits(out min, out max);
+                return min > MachineParameterDouble.eps * max;
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// Search for k nearest neighbors for every sample in <paramref name="Samples"/> samples
+        /// </summary>
+        /// <param name="Samples">Samples matrix, samples in columns, the number of rows (dimensionality) must match the number of rows in <paramref name="Neighbors"/> </param>
+        /// <param name="Neighbors">Matrix of training samples/ neighbors, this will be searched for matching points, rows: dimensionality, columns: number of points</param>
+        /// <param name="k">[Optional] Number of neighbors to return, k must lay in range: 0 &le; k &lt neighbors.D[1]; default: 1</param>
+        /// <param name="metric">[Optional] Distance metric, one out of the <see cref="ILNumerics.ILMath.DistanceMetrics"/> enumeration. Supported are: Euclidian_L2,Manhattan_L1, 
+        /// Minkowski, Cosine, Pearsons and Hamming distances; default: 'Euclidian_L2'</param>
+        /// <param name="minkowski_parameter">[Optional] Exponent for minkowski distance; default: 2</param>
+        /// <param name="unstable_error">[Optional] For cosine and pearson distances: if some samples lead to numerical instabilities, an exception is generated; default: true</param>
+        /// <returns>Matrix of nearest neighbors, size: k x samples.D[1]; indices of points in <paramref name="Neighbors"/> matrix</returns>
+        public static ILRetArray<double> knn(ILInArray<float> Samples, ILInArray<float> Neighbors, int k = 10, 
+                                                DistanceMetrics metric = DistanceMetrics.Euclidian_L2, double minkowski_parameter = 2.0,
+                                                bool unstable_error = true) {
+            using (ILScope.Enter(Samples, Neighbors)) {
+
+                ILArray<float> samples = Samples; 
+                ILArray<float> neighbors = Neighbors; 
+
+                if (k < 0) {
+                    throw new ILArgumentException("k must be greater or equal 0");  
+                }
+                if (isnullorempty(neighbors)) {
+                    throw new ILArgumentException("input argument 'neighbors' must not be null or empty");
+                }
+                if (isnull(samples)) {
+                    throw new ILArgumentException("input argument 'samples' must not be null"); 
+                }
+                if (samples.S[0] != neighbors.S[0])
+                    throw new ILArgumentException("number of rows for 'neighbors' and 'samples' must match"); 
+                if (k > neighbors.S[1]) 
+                    throw new ILArgumentException("k must be smaller or equal to the number of datapoints (number of columns) in A"); 
+                int nn = neighbors.S[1], am = neighbors.S[0], sn = samples.S[1];
+                ILArray<double> ret = zeros<double>(k, sn);
+                switch (metric) {
+                    case DistanceMetrics.Euclidian_L2:
+                        for (int i = 0; i < sn; i++) {
+                            using (ILScope.Enter()) {
+                                ILArray<float> dist = neighbors - samples[full, i];
+                                dist.a = sum(dist * dist, 0);
+                                ILArray<double> indices = empty<double>();
+                                if (k == 1) {
+                                    min(dist, indices, 1).Dispose();
+                                    ret[full, i] = indices[0];
+                                } else {
+                                    sort(dist, indices, 1, false).Dispose();
+                                    ret[full, i] = indices[r(0, k - 1)];
+                                }
+                            }
+                        }
+                        break;
+                    case DistanceMetrics.Manhattan_L1:
+                        for (int i = 0; i < sn; i++) {
+                            using (ILScope.Enter()) {
+                                ILArray<float> dist = neighbors - samples[full, i];
+                                dist.a = sum(abs(dist), 0);
+                                ILArray<double> indices = empty<double>();
+                                if (k == 1) {
+                                    min(dist, indices, 1).Dispose();
+                                    ret[full, i] = indices[0];
+                                } else {
+                                    sort(dist, indices, 1, false).Dispose();
+                                    ret[full, i] = indices[r(0, k - 1)];
+                                }
+                            }
+                        }
+                        break;
+                    case DistanceMetrics.Minkowski:
+                        for (int i = 0; i < sn; i++) {
+                            using (ILScope.Enter()) {
+                                ILArray<float> dist = neighbors - samples[full, i];
+                                dist.a = sum(pow(dist,(float)minkowski_parameter), 0);
+                                ILArray<double> indices = empty<double>();
+                                if (k == 1) {
+                                    min(dist, indices, 0).Dispose();
+                                    ret[full, i] = indices[0];
+                                } else {
+                                    sort(dist, indices, 0, false).Dispose();
+                                    ret[full, i] = indices[r(0, k - 1)];
+                                }
+                            }
+                        }
+                        break;
+                    case DistanceMetrics.Cosine:
+                        ILArray<float> samples_normalized = sqrt(sum(samples * samples, 0));
+                        ILArray<float> neighbs_normalized = sqrt(sum(neighbors * neighbors, 0));
+                        if (unstable_error && !testStable(samples_normalized)) {
+                            throw new ILArgumentException("possibly numerical instability: some samples are too close to 0. Try using a different metric instead!");
+                        }
+                        if (unstable_error && !testStable(neighbs_normalized)) {
+                            throw new ILArgumentException("possibly numerical instability: some neighbors are too close to 0. Try using a different metric instead!");
+                        }
+                        neighbs_normalized.a = neighbors / neighbs_normalized;
+                        for (int i = 0; i < sn; i++) {
+                            using (ILScope.Enter()) {
+                                ILArray<float> dist = 1 - multiply(neighbs_normalized.T, samples[full, i]) / samples_normalized[i];
+                                ILArray<double> indices = empty<double>();
+                                if (k == 1) {
+                                    min(dist, indices, 0).Dispose();
+                                    ret[full, i] = indices[0];
+                                } else {
+                                    sort(dist, indices, 0, false).Dispose();
+                                    ret[full, i] = indices[r(0, k - 1)];
+                                }
+                            }
+                        }
+                        break;
+                    case DistanceMetrics.Pearsons:
+                        ILArray<float> samples_centered = samples - mean(samples, 0);
+                        ILArray<float> neighbs_centered = neighbors - mean(neighbors, 0);
+                        samples_normalized = sqrt(sum(samples_centered * samples_centered, 0));
+                        neighbs_normalized = sqrt(sum(neighbs_centered * neighbs_centered, 0));
+                        if (unstable_error && !testStable(samples_normalized)) {
+                            throw new ILArgumentException("possibly numerical instability: standard deviation for some neighbor points is close to zero. Try using a different metric instead!");
+                        }
+                        if (unstable_error && !testStable(neighbs_normalized)) {
+                            throw new ILArgumentException("possibly numerical instability: standard deviation for some neighbor points is close to zero. Try using a different metric instead!");
+                        }
+                        neighbs_normalized.a = neighbs_centered / neighbs_normalized;
+                        for (int i = 0; i < sn; i++) {
+                            using (ILScope.Enter()) {
+                                ILArray<float> dist = 1 - multiply(neighbs_normalized.T, samples_centered[full, i]) / samples_normalized[i];
+                                ILArray<double> indices = empty<double>();
+                                if (k == 1) {
+                                    min(dist,indices,0).Dispose(); 
+                                    ret[full, i] = indices[0]; 
+                                } else {
+                                    sort(dist, indices, 0, false).Dispose();
+                                    ret[full, i] = indices[r(0, k - 1)];
+                                }
+                            }
+                        }
+                        break;
+                    case DistanceMetrics.Hamming:
+                        if (samples.Any((a) => { return a != 0 && a != 1; })) {
+                            throw new ILArgumentException("hamming distance requires 0 and 1 as value for all elements of 'samples'");
+                        }
+                        if (neighbors.Any((a) => { return a != 0 && a != 1; })) {
+                            throw new ILArgumentException("hamming distance requires 0 and 1 as value for all elements of 'neighbors'");
+                        }
+                        for (int i = 0; i < sn; i++) {
+                            using (ILScope.Enter()) {
+                                ILArray<float> dist = sum(abs(neighbors - samples[full, i]), 0) / am; 
+                                ILArray<double> indices = empty<double>();
+                                if (k == 1) {
+                                    min(dist, indices, 1).Dispose();
+                                    ret[full, i] = indices[0];
+                                } else {
+                                    sort(dist, indices, 1, false).Dispose();
+                                    ret[full, i] = indices[r(0, k - 1)];
+                                }
+                            }
+                        }
+                        break;
+                    default:
+                        throw new ILArgumentException("the selected distance is not supported"); 
+                }
+                return ret; 
+            }
+             
+        }
+        /// <summary>
+        /// Test for numerical instability, expects positive data only!
+        /// </summary>
+        /// <param name="samples_normalized">Input data</param>
+        /// <returns>true: no instability detected, false, possible instablility</returns>
+        private static bool testStable(ILInArray<float> samples_normalized) {
+            using (ILScope.Enter(samples_normalized)) {
+               
+                float max, min;
+                samples_normalized.GetLimits(out min, out max);
+                return min > MachineParameterSingle.eps * max;
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+   }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Algorithms/MachineLearning/ILKRR.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Algorithms/MachineLearning/ILKRR.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Algorithms/MachineLearning/ILKRR.cs	(revision 9102)
@@ -0,0 +1,219 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace ILNumerics {
+    public partial class ILMath {
+
+        /// <summary>
+        /// Type definitions for possible kernels in kernel ridge regression
+        /// </summary>
+        public enum KRRTypes {
+            /// <summary>
+            /// Linear kernel <c>k(x,y) = x'*y</c>
+            /// </summary>
+            linear,
+            /// <summary>
+            /// Polynominal kernel <c>k(x,y) = (x'*y + c)^d</c>
+            /// </summary>
+            polynomial,
+            /// <summary>
+            /// Gaussian (exponential) kernel <c>k(x,y) = exp(-norm(x-y)/sigma)</c>
+            /// </summary>
+            gaussian
+        }
+
+        internal delegate ILRetArray<double> ILKRRApplyFunc(ILInArray<double> X, ILKRRResult C); 
+
+        /// <summary>
+        /// Encapsulates the result of a kernel ridge regression and makes it applicable to new data
+        /// </summary>
+        public class ILKRRResult : ILResult<double> {
+
+            private ILKRRApplyFunc m_applyFunc;
+            internal ILKRRApplyFunc ApplyFunc {
+                get { return m_applyFunc; }
+                set { m_applyFunc = value; }
+            } 
+            internal ILArray<double> Shift = returnType<double>();
+            internal ILArray<double> X = returnType<double>();
+            internal KRRTypes Kernel = KRRTypes.gaussian;
+            internal ILArray<double> KernelParameter = returnType<double>();
+            internal ILArray<double> Alpha = returnType<double>();
+
+            public override ILRetArray<double> Apply(ILInArray<double> Data, params ILBaseArray[] arguments)
+            {
+                if (IsDisposed) 
+                    throw new InvalidOperationException("this result has already been disposed");
+                return m_applyFunc(Data,this); 
+            }
+
+            public override void Dispose() {
+                if (IsDisposed) 
+                    return; 
+                base.Dispose();
+                if (!object.ReferenceEquals(Shift, null))
+                    Shift.Dispose();
+                if (!object.ReferenceEquals(X, null))
+                    X.Dispose();
+                if (!object.ReferenceEquals(KernelParameter, null))
+                    KernelParameter.Dispose(); 
+                if (!object.ReferenceEquals(Alpha,null))
+                    Alpha.Dispose(); 
+            }
+        }
+
+        /// <summary>
+        /// Calculate the kernel ridge regression (KRR) of X to Y
+        /// </summary>
+        /// <param name="X">Input data X, observations in columns</param>
+        /// <param name="Y">Input data Y (regression target)</param>
+        /// <returns>Kernel ridge regression model with linear kernel and no regularization</returns>
+        public static ILResult<double> krr(ILInArray<double> X, ILInArray<double> Y) {
+            return krr(X, Y, KRRTypes.linear, 1, -1);
+        }
+        /// <summary>
+        /// Calculate the kernel ridge regression (KRR) of X to Y
+        /// </summary>
+        /// <param name="X">Input data X, observations in columns</param>
+        /// <param name="Y">Input data Y (regression target)</param>
+        /// <param name="kernel">Kernel type to use</param>
+        /// <param name="Kernelparam">Kernel parameters, scalar constant, if invalid: defaults to 1</param>
+        /// <param name="Regularization">Regularization constant (set to -1 to have no regularization)</param>
+        /// <returns>The kernel ridge regression model</returns>
+        public static ILResult<double> krr(ILInArray<double> X, ILInArray<double> Y, KRRTypes kernel, 
+                                           ILInArray<double> Kernelparam, ILInArray<double> Regularization) {
+            using (ILScope.Enter(X, Y, Kernelparam, Regularization)) {
+                ILArray<double> x = check(X);
+                ILArray<double> y = check(Y);
+                ILArray<double> kernelparam = check(Kernelparam, (a) => { return (a.IsScalar) ? a : 1.0; });
+                ILArray<double> regularization = check(Regularization, (a) => { return (a.IsScalar) ? a : 0.0; });
+
+                ILKRRResult C = new ILKRRResult();
+
+                C.ApplyFunc = krrapply; 
+                // centering 
+                C.Shift.a = mean(x, 1);
+                //% X = X - repmat(C.Shift,1,n); 
+                x = x - repmat(C.Shift, 1, x.S[1]);
+                ILArray<double> K = empty<double>();
+                switch (kernel) {
+                    case KRRTypes.linear:
+                        K = multiply(x.T, x);                                                               // linear: K = X'*X; 
+                        break;
+                    case KRRTypes.polynomial:
+                        K = pow((multiply(x.T, x) + 1), kernelparam);                                           // % K = (X'*X + 1).^kernelparameter;
+                        break;
+                    case KRRTypes.gaussian:
+                        K = gkernel(x, x, kernelparam);                                                     // % K = gkernel(X,X,kernelparameter); 
+                        break;
+                }
+                C.X.a = x.C;
+                C.Kernel = kernel;
+                C.KernelParameter.a = kernelparam;
+                
+                y = (y.S[0] < y.S[1]) ? y.T : y.C;                                                          // if (size(y,1) < size(y,2)) y = y'; end
+                if (regularization == 0) {                                                                    // if (~exist('regularization') || regularization == 0) 
+                    ILArray<double> U = empty<double>();                                                      //    [U,V] = eig(K);
+                    ILArray<double> V = empty<double>();
+                    U.a = eigSymm(K, V);
+                    ILArray<double> c = diag(V);                                                              //    c = diag(V);  
+                    ILArray<double> minLooErr = double.PositiveInfinity;                                      //    minLooErr = inf;
+                    //                                                                                        //    cr = find(c > 1e-12)';                                 
+                    foreach (int ci in find(c > 1e-12)) {                                                     //    for ci = cr      
+                        using (ILScope.Enter()) {
+                            ILArray<double> Sd = c / (c + c[ci]);                                             //        Sd = c./(c + c(ci)); 
+                            ILArray<double> S = multiply(U, diag(Sd), U.T);                                   //        S = U * diag(Sd) * U';
+                            ILArray<double> looer = sum(y - multiply(S, y) / pow(1 - diag(S), 2.0)) / x.S[1];   //        looerr = sum((y - S*y)./(1-diag(S)).^2) ./ n; 
+                            if (minLooErr > looer) {                                                          //        if (minLooErr > looerr) 
+                                minLooErr.a = looer;                                                          //            minLooErr = looerr;
+                                regularization.a = c[ci];                                                     //            regularization = c(ci);
+                            }                                                                                 //        end
+                        }                                                                                     //    end
+                    }
+                    // since we already have U, lets compute alpha that way
+                    C.Alpha.a = multiply(U, diag(1 / (c + regularization)), U.T, y).T;                        //    C.alpha = U * diag(1./(c + regularization)) * U' * y; 
+                    //                                                                                        //    C.alpha = C.alpha';
+                    return C;                                                                                 //    return; 
+                } else {                                                                                      //end
+                    C.Alpha.a = linsolve((K + diag(zeros(1, x.S[1]) + regularization)), y).T;                 // C.alpha = (K + diag(zeros(1,n) + regularization))\y; 
+                    return C;                                                                                 // C.alpha = C.alpha'; 
+                }                                                                                             //end 
+            }
+        }
+
+        private static ILRetArray<double> gkernel(ILInArray<double> X1, ILInArray<double> X2, ILInArray<double> kernelparam) {
+            using (ILScope.Enter(X1, X2, kernelparam)) {
+                int d = X1.S[0], n1 = X1.S[1], n2 = X2.S[1];                    // [d,n1] = size(X1); n2 = size(X2,2); 
+                ILArray<double> XX = multiply(X1.T, X2);                        // XX = X1'*X2; 
+                ILArray<double> K = repmat(sum(X2 * X2, 0), n1, 1);             // K = repmat(sum(X2.^2,1),n1,1); 
+                K.a = K + repmat(sum(X1 * X1, 0).T, 1, n2);                     // K = K + repmat(sum(X1.^2,1)',1,n2); 
+                K.a = K - 2 * XX;                                               // K = K - 2.*XX; 
+                K.a = exp(-K / (2 * d * kernelparam * kernelparam));            // K = exp(-K./(2 * d * w.^2)); 
+                return K; 
+            }
+        }
+
+        private static ILRetArray<double> krrapply(ILInArray<double> X, ILKRRResult C) {
+            using (ILScope.Enter(X)) {
+                ILArray<double> x = check(X);  
+                int d = x.S[0], n = x.S[1];                                     // [d,n] = size(X); 
+                x.a = x - repmat(C.Shift, 1, n);                                  // X = X - repmat(C.Shift,1,n); 
+                ILArray<double> K = empty<double>();
+                switch (C.Kernel) {
+                    case KRRTypes.linear:
+                        K.a = multiply(x.T, C.X);                               // K = X'*C.X; 
+                        break;
+                    case KRRTypes.polynomial:
+                        K.a = pow(multiply(x.T, C.X) + 1, C.KernelParameter);    // K = (X'*C.X + 1).^C.parameter; 
+                        break;
+                    case KRRTypes.gaussian:
+                        K.a = gkernel(x, C.X, C.KernelParameter);                // K = gkernel(X,C.X,C.parameter); 
+                        break;
+                }
+                return sum(C.Alpha * K, 1).T;                              //Y = sum(repmat(C.alpha,n,1).*K,2)';  
+            }
+        }
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Algorithms/MachineLearning/ILOLS.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Algorithms/MachineLearning/ILOLS.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Algorithms/MachineLearning/ILOLS.cs	(revision 9102)
@@ -0,0 +1,132 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace ILNumerics {
+    public partial class ILMath {
+
+        internal delegate ILRetArray<T> ILRidgeRegressionApplyFunc<T>(ILInArray<T> X, ILRidgeRegressionResult<T> C); 
+        /// <summary>
+        /// This class stores the result of a ridge regression
+        /// </summary>
+        /// <typeparam name="T">Element type (precision) for the result</typeparam>
+        /// <remarks>This class is returned from <see cref="ILNumerics.ILMath.ridge_regression(ILInArray&lt;double>, ILInArray&lt;double>, ILBaseArray, ILBaseArray)"/>
+        /// and all its overloads. The class stores all data needed to apply the regression result to new data points. Therefore a 
+        /// function <see cref="ILNumerics.ILMath.ILRidgeRegressionResult{T}.Apply(ILNumerics.ILInArray{T}, ILNumerics.ILBaseArray[])" /> is provided.
+        /// <para>The class implements the <c>IDisposable</c> interface and should be used inside a 'using' block or manually be disposed 
+        /// after use.</para></remarks>
+        public class ILRidgeRegressionResult<T> : ILResult<T> {
+            internal ILRidgeRegressionApplyFunc<T> m_applyFunc; 
+            internal ILArray<T> m_centerX = ILMath.returnType<T>();
+            internal ILArray<T> m_centerY = ILMath.returnType<T>();
+            internal ILArray<T> m_weights = ILMath.returnType<T>();
+            internal int m_p = 1; 
+            internal ILArray<T> m_pow = ILMath.returnType<T>();
+            
+            /// <summary>
+            /// Apply the result on new datapoints
+            /// </summary>
+            /// <param name="X">New datapoints, same dimension as used for learning</param>
+            /// <returns></returns>
+            public override ILRetArray<T> Apply(ILInArray<T> X, params ILBaseArray[] arguments) {
+                if (IsDisposed) 
+                    throw new Exceptions.ILInvalidOperationException("the regression result is disposed already"); 
+                return m_applyFunc(X,this); 
+            }
+
+            #region IDisposable Members
+            /// <summary>
+            /// Dispose off the result and free all storages used 
+            /// </summary>
+            public override void Dispose() {
+                base.Dispose(); 
+                m_centerX.Dispose(); 
+                m_centerY.Dispose(); 
+                m_weights.Dispose(); 
+                m_pow.Dispose(); 
+            }
+
+            #endregion
+        }
+        /// <summary>
+        /// Ordinary least squares regression/ ridge regression
+        /// </summary>
+        /// <param name="X">Data matrix, data points in columns</param>
+        /// <param name="Y">Training targets (or 'labels') corresponding to <paramref name="X"/></param>
+        /// <param name="Degree">Highest degree of polynomials for the design matrix</param> 
+        /// <param name="Regularization">Regularization constant (usually some "small" summand for stabilizing the matrix inversion).</param>
+        /// <returns>Train result used for applying the model to new data.</returns>
+        public static ILRidgeRegressionResult<double> ridge_regression(ILInArray<double> X, ILInArray<double> Y, ILBaseArray Degree, ILBaseArray Regularization) {
+            using (ILScope.Enter(X, Y, Degree, Regularization)) {
+
+                ILArray<double> x = check(X);
+                ILArray<double> y = check(Y); 
+
+                ILRidgeRegressionResult<double> ret = new ILRidgeRegressionResult<double>(); 
+                double c = (double)todouble(Regularization); 
+                int p = (int)toint32(Degree); 
+                if (c < 0) c = 1e-10; 
+                if (p < 1) p = 1; 
+                ret.m_pow.a  = repmat(vec<double>(1,p).T,x.S[0],1)[full];
+                ILArray<double> Xd = pow(repmat(x, p, 1), repmat(ret.m_pow, 1, x.S[1])); 
+                ret.m_p = p; 
+                ret.m_centerX.a = mean(Xd,1);
+                ret.m_centerY.a = mean(y,1); 
+                Xd.a = Xd - ret.m_centerX; 
+                ILArray<double> Yd = y - ret.m_centerY; 
+                ret.m_weights.a = linsolve(multiply(Xd,Xd.T) + c * eye(Xd.S[0],Xd.S[0]) , multiply(Xd,y.T));
+                ret.m_applyFunc = RidgeRegressionApply; 
+                return ret; 
+            }
+        }
+
+        internal static ILRetArray<double> RidgeRegressionApply(ILInArray<double> X, ILRidgeRegressionResult<double> C) {
+            using (ILScope.Enter(X)) {
+                int n = X.S[1];
+                ILArray<double> Xd = pow(repmat(X, C.m_p, 1),repmat(reshape(C.m_pow, numel(C.m_pow), 1), 1, n));
+                return multiply(C.m_weights.T, (Xd - repmat(C.m_centerX, 1, n))) + repmat(C.m_centerY, 1, n);
+            }
+        }
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Algorithms/MachineLearning/ILPCA.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Algorithms/MachineLearning/ILPCA.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Algorithms/MachineLearning/ILPCA.cs	(revision 9102)
@@ -0,0 +1,182 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace ILNumerics {
+    // ToDo: DOKU Example PCA
+    public partial class ILMath {
+
+        /// <summary>
+        /// Principal Component Analysis (PCA)
+        /// </summary>
+        /// <param name="A">Data matrix, size (m,n); each of n observations is expected in a column of m variables</param>
+        /// <param name="outWeights">[Output] Weights for scaling the components according to the original data</param>
+        /// <param name="outCenter">[Output] Vector pointing to the center of the input data A</param>
+        /// <param name="outScores">[Output] Scaling factors for the component to recreate original data</param>
+        /// <returns>PCA components; weights, center and scores are returned at optional output parameters</returns>
+        /// <remarks>Principal Component Analysis (PCA) is commonly used as method for dimension reduction. It computes 
+        /// a number of 'principal components' which span a space of orthogonal directions. The nice property is, these 
+        /// directions are choosen such, as to maximize the variance of original data, once they are projected onto them. 
+        /// We can simply pick only a subset of components, having associated a high variance and leave out other components, which do
+        /// not contribute much to the distribution of the original data. The resulting subspace is constructed of fewer
+        /// dimensions as the original space - with a smaller reconstrution error. Therefore, PCA is commonly used 
+        /// for visualizing higher dimensional data in only two or three dimensional plots. It helps analyzing datasets which 
+        /// otherwise could only be visualized by picking individual dimensions. By help of PCA, 'interesting' directions 
+        /// in the data are identified.
+        /// <para>Any output parameter are optional and may be ommited ore provided as null parameter: 
+        /// <list type="bullet">
+        /// <item><b>components</b> (return value) prinicipal components. Matrix of size m x m, m components are provided in columns. The first 
+        /// component marks the direction in the data A, which corresponds to the largest variance (i.e. by projecting the data onto 
+        /// that direction, the largest variance would be created). Adjacent components are all orthogonal to each other. 
+        /// The components are ordered in columns of decreasing variance.</item>
+        /// <item><b>weights</b> vectors. While the components returned are normalized to length 1, the 'weights' vector 
+        /// contains the factors needed, to scale the components in order to reflect the real spacial distances in the 
+        /// original data.</item>
+        /// <item><b>center</b> of the original data. The vector points to the weight middle of A.</item>
+        /// <item><b>scores</b> is a matrix of size m by n. For each datapoint given in A, it contains factors for each component 
+        /// needed to reproduce the original data point in terms of the components.</item>
+        /// </list></para>
+        /// </remarks>
+        public static ILRetArray<double> pca(ILInArray<double> A,ILOutArray<double> outWeights = null, 
+                                              ILOutArray<double> outCenter = null, ILOutArray<double> outScores = null) {
+            using (ILScope.Enter(A)) {
+                if (isnull(A))
+                    throw new Exceptions.ILArgumentException("data input argument A must not be null"); 
+                ILArray<double> ret = empty(); 
+                if (!A.IsEmpty) {
+                    ILArray<double> Center = sum(A, 1) / A.S[1];
+                    ILArray<double> centeredA = A - Center;
+                    if (!isnull(outWeights)) {
+                        outWeights.a = eigSymm(multiply(centeredA, centeredA.T), ret);
+                        if (!outWeights.IsVector) {
+                            outWeights.a = diag(outWeights);
+                        }
+                        outWeights.a = flipud(outWeights);
+                    } else {
+                        eigSymm(multiply(centeredA, centeredA.T), ret).Dispose();
+                    }
+                    ret = fliplr(ret); 
+                    if (!isnull(outScores))
+                        outScores.a = multiply(ret.T, centeredA);
+                    if (!isnull(outCenter)) 
+                        outCenter.a = Center; 
+                    return ret;
+                } else {
+                    if (!isnull(outWeights))
+                        outWeights.a = empty<double>(); 
+                    if (!isnull(outCenter)) 
+                        outCenter.a = empty<double>(); 
+                    if (!isnull(outScores))
+                        outScores.a = empty<double>(); 
+                    return empty<double>(); 
+                }
+            }
+        }
+
+        /// <summary>
+        /// Principal Component Analysis (PCA)
+        /// </summary>
+        /// <param name="A">Data matrix, size (m,n); each of n observations is expected in a column of m variables</param>
+        /// <param name="outWeights">[Output] Weights for scaling the components according to the original data</param>
+        /// <param name="outCenter">[Output] Vector pointing to the center of the input data A</param>
+        /// <param name="outScores">[Output] Scaling factors for the component to recreate original data</param>
+        /// <returns>PCA components; weights, center and scores are returned at optional output parameters</returns>
+        /// <remarks>Principal Component Analysis (PCA) is commonly used as method for dimension reduction. It computes 
+        /// a number of 'principal components' which span a space of orthogonal directions. The nice property is, these 
+        /// directions are choosen such, as to maximize the variance of original data, once they are projected onto them. 
+        /// We can simply pick only a subset of components, having associated a high variance and leave out other components, which do
+        /// not contribute much to the distribution of the original data. The resulting subspace is constructed of fewer
+        /// dimensions as the original space - with a smaller reconstrution error. Therefore, PCA is commonly used 
+        /// for visualizing higher dimensional data in only two or three dimensional plots. It helps analyzing datasets which 
+        /// otherwise could only be visualized by picking individual dimensions. By help of PCA, 'interesting' directions 
+        /// in the data are identified.
+        /// <para>Any output parameter are optional and may be ommited ore provided as null parameter: 
+        /// <list type="bullet">
+        /// <item><b>components</b> (return value) prinicipal components. Matrix of size m x m, m components ar provided in columns. The first 
+        /// component marks the direction in the data A, which corresponds to the largest variance (i.e. by projecting the data onto 
+        /// that direction, the largest variance would be created). Adjacent components are all orthogonal to each other. 
+        /// The components are ordered in columns of decreasing variance.</item>
+        /// <item><b>weights</b> vectors. While the components returned are normalized to length 1, the 'weights' vector 
+        /// contains the factors needed, to scale the components in order to reflect the real spacial distances in the 
+        /// original data.</item>
+        /// <item><b>center</b> of the original data. The vector points to the weight middle of A.</item>
+        /// <item><b>scores</b> is a matrix of size m by n. For each datapoint given in A, it contains factors for each component 
+        /// needed to reproduce the original data point in terms of the components.</item>
+        /// </list></para>
+        /// </remarks>
+        public static ILRetArray<float> pca(ILInArray<float> A, ILOutArray<float> outWeights = null,
+                                              ILOutArray<float> outCenter = null, ILOutArray<float> outScores = null) {
+            using (ILScope.Enter(A)) {
+                if (isnull(A))
+                    throw new Exceptions.ILArgumentException("data input argument A must not be null");
+                ILArray<float> ret = empty<float>();
+                if (!A.IsEmpty) {
+                    ILArray<float> Center = sum(A, 1) / A.S[1];
+                    ILArray<float> centeredA = A - Center;
+                    if (!isnull(outWeights)) {
+                        outWeights.a = eigSymm(multiply(centeredA, centeredA.T), ret);
+                        if (!outWeights.IsVector) {
+                            outWeights.a = diag(outWeights);
+                        }
+                        outWeights.a = flipud<float>(outWeights);
+                    } else {
+                        eigSymm(multiply(centeredA, centeredA.T), ret).Dispose();
+                    }
+                    if (!isnull(outScores))
+                        outScores.a = multiply(ret.T, centeredA);
+                    if (!isnull(outCenter))
+                        outCenter.a = Center;
+                    return fliplr<float>(ret);
+                } else {
+                    if (!isnull(outWeights))
+                        outWeights.a = empty<float>();
+                    if (!isnull(outCenter))
+                        outCenter.a = empty<float>();
+                    if (!isnull(outScores))
+                        outScores.a = empty<float>();
+                    return empty<float>();
+                }
+            }
+        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Algorithms/MachineLearning/ILResult.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Algorithms/MachineLearning/ILResult.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Algorithms/MachineLearning/ILResult.cs	(revision 9102)
@@ -0,0 +1,72 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace ILNumerics {
+    /// <summary>
+    /// Result datatype, used for storing computational results and applying them to new data within ILNumerics machine learning functions
+    /// </summary>
+    /// <typeparam name="T">Datatype of underlying array elements</typeparam>
+    public abstract class ILResult<T> : IDisposable {
+        private bool m_disposed = false;
+
+        public bool IsDisposed {
+            get { return m_disposed; }
+            set { m_disposed = value; }
+        } 
+        /// <summary>
+        /// Apply the result on new datapoints
+        /// </summary>
+        /// <param name="X">New datapoints, same dimension as used for learning</param>
+        /// <returns></returns>
+        public abstract ILRetArray<T> Apply(ILInArray<T> X, params ILBaseArray[] arguments);
+
+        #region IDisposable Members
+        public virtual void Dispose() {
+            if (IsDisposed) return; 
+            m_disposed = true; 
+        }
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Algorithms/MachineLearning/kmeansclust.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Algorithms/MachineLearning/kmeansclust.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Algorithms/MachineLearning/kmeansclust.cs	(revision 9102)
@@ -0,0 +1,266 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Exceptions;
+
+
+
+namespace ILNumerics {
+
+
+    public partial class ILMath {
+
+
+        /// <summary>
+        /// K-Means clustering: find clusters in data matrix X
+        /// </summary>
+        /// <param name="X">Data matrix, data points are given as columns</param>
+        /// <param name="k">Initial number of clusters expected</param>
+        /// <param name="centerInitRandom">[Optional] false: pick the first k data points as initial centers, true: pick random datapoints (default)</param>
+        /// <param name="maxIterations">[Optional] Maximum number of iterations, the computation will exit after that many iterations, default: 10.000</param>
+        /// <param name="outCenters">[Input/Output/Optional] If not null on entry, outCenters will contain the centers of the clusters found, default: null</param>
+        /// <returns>Vector of length n with with indices of the clustersm which were assigned to each datapoint</returns>
+        /// <remarks><para>If <paramref name="outCenters"/> is given not null on input, the algorithm returns the computed centers in that parameter. A 
+        /// matrix may be given on input, in order to give a hint of the initial center positions. This may help to find correct cluster centers - even if 
+        /// the initial hint is not exact. In order to do so, the matrix given must be of the correct size (X.D[0] by k) and <paramref name="centerInitRandom"/>
+        /// must be set to <c>false</c>.</para></remarks>
+        public static ILRetArray<double> kMeansClust(ILInArray<double> X, ILBaseArray k, int maxIterations = 10000, 
+                                                                    bool centerInitRandom = true, ILOutArray<double> outCenters = null) {
+            using (ILScope.Enter(X, k)) {
+                if (object.Equals(X, null)) {
+                    throw new ILArgumentException("X must be data matrix (not null)");
+                }
+                if (X.IsEmpty) {
+                    if (!object.Equals(outCenters, null)) {
+                        if (X.S[0] > 0) {
+                            outCenters.a = empty<double>(new ILSize(X.S[0], 0));
+                        } else {
+                            outCenters.a = empty<double>(new ILSize(0, X.S[1]));
+                        }
+                        return empty<double>(X.S);
+                    }
+                }
+                if (object.Equals(k, null) || !k.IsScalar || !k.IsNumeric) {
+                    throw new ILArgumentException("number of clusters k must be numeric scalar");
+                }
+                int iK = toint32(k).GetValue(0);
+                if (X.S[1] < iK) {
+                    throw new ILArgumentException("too few datapoints provided for " + iK.ToString() + " clusters");
+                }
+                if (iK < 0) {
+                    throw new ILArgumentException("number of clusters must be positive");
+                }
+                int d = X.S[0], n = X.S[1];
+                if (iK == 0) {
+                    if (!object.Equals(outCenters, null)) {
+                        outCenters.a = empty<double>(new ILSize(d, iK));
+                    }
+                    return empty<double>(new ILSize(0, n));
+                }
+
+                // initialize centers by using random datapoints
+                ILArray<double> centers = empty<double>();
+                if (centerInitRandom) {
+                    ILArray<double> pickIndices = empty();
+                    sort(rand(1, n), pickIndices, 1, false).Dispose();
+                    centers.a = X[full, pickIndices[r(0, iK - 1)]];
+                } else {
+                    if (!isnull(outCenters) && outCenters.S[0] == d && outCenters.S[1] == iK) {
+                        centers.a = outCenters; 
+                    } else {
+                        centers.a = X[full, r(0, iK - 1)];
+                    }
+                }
+
+                ILArray<double> classes = zeros<double>(1, n);
+                ILArray<double> oldCenters = centers.C;
+#if KMEANSVERBOSE
+                System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); 
+#endif
+                while (maxIterations-- > 0) {
+#if KMEANSVERBOSE
+                    sw.Restart(); 
+#endif
+                    for (int i = 0; i < n; i++) {
+                        // find cluster affiliates
+                        using (ILScope.Enter()) {
+                            ILArray<double> minDistIdx = empty();
+                            //min(sum(abs(centers - X[full, i])), minDistIdx, 1).Dispose();
+                            min(distL1(centers, X[full, i]), minDistIdx, 1).Dispose();
+                            classes[i] = (double)minDistIdx[0];
+                        }
+                    }
+                    System.Diagnostics.Debug.Print("kmeans: 1 of {0} MemoryPool.Info: {1}", maxIterations, ILMemoryPool.Pool.Info(true));
+                    for (int i = 0; i < iK; i++) {
+                        using (ILScope.Enter())
+                        {
+                            ILArray<double> inClass = X[full, find(classes == i)];
+                            if (inClass.IsEmpty) {
+                                centers[full, i] = double.NaN;
+                            } else {
+                                centers[full, i] = mean(inClass, 1);
+                            }
+                        }
+                    }
+#if KMEANSVERBOSE
+                    sw.Stop(); 
+                    Console.Out.WriteLine("Changed centers: {0} elapsed: {1}ms",(double)sum(any(oldCenters != centers)), sw.ElapsedMilliseconds); 
+#endif
+                    if (allall(oldCenters == centers)) break;
+                    oldCenters.a = centers.C;
+                }
+                if (!object.Equals(outCenters, null))
+                    outCenters.a = centers;
+                return classes;
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// K-Means clustering: find clusters in data matrix X
+        /// </summary>
+        /// <param name="X">Data matrix, data points are given as columns</param>
+        /// <param name="k">Initial number of clusters expected</param>
+        /// <param name="centerInitRandom">[Optional] false: pick the first k data points as initial centers, true: pick random datapoints (default)</param>
+        /// <param name="maxIterations">[Optional] Maximum number of iterations, the computation will exit after that many iterations, default: 10.000</param>
+        /// <param name="outCenters">[Input/Output/Optional] If not null on entry, outCenters will contain the centers of the clusters found, default: null</param>
+        /// <returns>Vector of length n with with indices of the clustersm which were assigned to each datapoint</returns>
+        /// <remarks><para>If <paramref name="outCenters"/> is given not null on input, the algorithm returns the computed centers in that parameter. A 
+        /// matrix may be given on input, in order to give a hint of the initial center positions. This may help to find correct cluster centers - even if 
+        /// the initial hint is not exact. In order to do so, the matrix given must be of the correct size (X.D[0] by k) and <paramref name="centerInitRandom"/>
+        /// must be set to <c>false</c>.</para></remarks>
+        public static ILRetArray<float> kMeansClust(ILInArray<float> X, ILBaseArray k, int maxIterations = 10000, 
+                                                                    bool centerInitRandom = true, ILOutArray<float> outCenters = null) {
+            using (ILScope.Enter(X, k)) {
+                if (object.Equals(X, null)) {
+                    throw new ILArgumentException("X must be data matrix (not null)");
+                }
+                if (X.IsEmpty) {
+                    if (!object.Equals(outCenters, null)) {
+                        if (X.S[0] > 0) {
+                            outCenters.a = empty<float>(new ILSize(X.S[0], 0));
+                        } else {
+                            outCenters.a = empty<float>(new ILSize(0, X.S[1]));
+                        }
+                        return empty<float>(X.S);
+                    }
+                }
+                if (object.Equals(k, null) || !k.IsScalar || !k.IsNumeric) {
+                    throw new ILArgumentException("number of clusters k must be numeric scalar");
+                }
+                int iK = toint32(k).GetValue(0);
+                if (X.S[1] < iK) {
+                    throw new ILArgumentException("too few datapoints provided for " + iK.ToString() + " clusters");
+                }
+                if (iK < 0) {
+                    throw new ILArgumentException("number of clusters must be positive");
+                }
+                int d = X.S[0], n = X.S[1];
+                if (iK == 0) {
+                    if (!object.Equals(outCenters, null)) {
+                        outCenters.a = empty<float>(new ILSize(d, iK));
+                    }
+                    return empty<float>(new ILSize(0, n));
+                }
+
+                // initialize centers by using random datapoints
+                ILArray<float> centers = empty<float>();
+                if (centerInitRandom) {
+                    ILArray<double> pickIndices = empty();
+                    sort(rand(1, n), pickIndices, 1, false).Dispose();
+                    centers.a = X[full, pickIndices[r(0, iK - 1)]];
+                } else {
+                    if (!isnull(outCenters) && outCenters.S[0] == d && outCenters.S[1] == iK) {
+                        centers.a = outCenters; 
+                    } else {
+                        centers.a = X[full, r(0, iK - 1)];
+                    }
+                }
+
+                ILArray<float> classes = zeros<float>(1, n);
+                ILArray<float> oldCenters = centers.C;
+#if KMEANSVERBOSE
+                System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); 
+#endif
+                while (maxIterations-- > 0) {
+#if KMEANSVERBOSE
+                    sw.Restart(); 
+#endif
+                    for (int i = 0; i < n; i++) {
+                        // find cluster affiliates
+                        using (ILScope.Enter()) {
+                            ILArray<double> minDistIdx = empty();
+                            //min(sum(abs(centers - X[full, i])), minDistIdx, 1).Dispose();
+                            min(distL1(centers, X[full, i]), minDistIdx, 1).Dispose();
+                            classes[i] = (float)minDistIdx[0];
+                        }
+                    }
+                    System.Diagnostics.Debug.Print("kmeans: 1 of {0} MemoryPool.Info: {1}", maxIterations, ILMemoryPool.Pool.Info(true));
+                    for (int i = 0; i < iK; i++) {
+                        using (ILScope.Enter())
+                        {
+                            ILArray<float> inClass = X[full, find(classes == i)];
+                            if (inClass.IsEmpty) {
+                                centers[full, i] = float.NaN;
+                            } else {
+                                centers[full, i] = mean(inClass, 1);
+                            }
+                        }
+                    }
+#if KMEANSVERBOSE
+                    sw.Stop(); 
+                    Console.Out.WriteLine("Changed centers: {0} elapsed: {1}ms",(double)sum(any(oldCenters != centers)), sw.ElapsedMilliseconds); 
+#endif
+                    if (allall(oldCenters == centers)) break;
+                    oldCenters.a = centers.C;
+                }
+                if (!object.Equals(outCenters, null))
+                    outCenters.a = centers;
+                return classes;
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Algorithms/MachineLearning/kmeansclustLoopUnroll.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Algorithms/MachineLearning/kmeansclustLoopUnroll.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Algorithms/MachineLearning/kmeansclustLoopUnroll.cs	(revision 9102)
@@ -0,0 +1,229 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Exceptions; 
+
+namespace ILNumerics {
+    
+    
+    public partial class ILMath { 
+
+        /// <summary>
+        /// find clusters for data matrix X
+        /// </summary>
+        /// <param name="X">data matrix, data points are given as columns</param>
+        /// <param name="k">initial number of clusters expected</param>
+        /// <param name="centerInitRandom">false: pick the first k data points as initial centers, true: pick random datapoints</param>
+        /// <param name="maxIterations">maximum number of iterations, the computation will exit after that many iterations.</param>
+        /// <returns>vector of length n with with indices of clusters assigned to each datapoint</returns>
+        public static ILRetArray<double> kMeansClust(ILInArray<double> X, ILBaseArray k, int maxIterations, bool centerInitRandom) {
+            return kMeansClust(X, k, maxIterations, centerInitRandom, null);
+        }
+
+        /// <summary>
+        /// find clusters for data matrix X
+        /// </summary>
+        /// <param name="X">data matrix, data points are given as columns</param>
+        /// <param name="k">initial number of clusters expected</param>
+        /// <param name="centerInitRandom">false: pick the first k data points as initial centers, true: pick random datapoints</param>
+        /// <param name="maxIterations">maximum number of iterations, the computation will exit after that many iterations.</param>
+        /// <param name="outCenters">return type. if assigned on entry, outCenters will contain the centers of the clusters found.</param>
+        /// <returns>vector of length n with with indices of clusters assigned to each datapoint</returns>
+        public static ILRetArray<double> kMeansClust (ILInArray<double> X, ILBaseArray k, int maxIterations, bool centerInitRandom, ILOutArray<double> outCenters) {
+            using (ILScope.Enter(X, k)) {
+                if (object.Equals(X,null)) {
+                    throw new ILArgumentException("X must be data matrix (not null)"); 
+                }
+                if (X.IsEmpty) {
+                    if (!object.Equals(outCenters, null)) {
+                        if (X.D[0] > 0) {
+                            outCenters.a = empty<double>(new ILSize(X.D[0], 0));
+                        } else {
+                            outCenters.a = empty<double>(new ILSize(0, X.D[1]));
+                        }
+                        return empty<double>(X.D);
+                    }
+                }
+                if (object.Equals(k,null) || !k.IsScalar || !k.IsNumeric) {
+                    throw new ILArgumentException("number of clusters k must be numeric scalar"); 
+                }
+                int iK = toint32(k).GetValue(0);
+                if (X.D[1] < iK) {
+                    throw new ILArgumentException("too few datapoints provided for " + iK.ToString() + " clusters");
+                }
+                if (iK < 0) {
+                    throw new ILArgumentException("number of clusters must be positive");
+                }
+                int d = X.D[0], n = X.D[1]; 
+                if (iK == 0) {
+                    if (!object.Equals(outCenters, null)) {
+                        outCenters.a = empty<double>(new ILSize(d, iK)); 
+                    }
+                    return empty<double>(new ILSize(0, n)); 
+                }
+
+                // initialize centers by using random datapoints
+                ILArray<double> centers = empty();
+                if (centerInitRandom) {
+                    ILArray<double> pickIndices = empty(); 
+                    sort(rand(1,n),pickIndices,1,false).Dispose();
+                    centers.a = X[full,pickIndices[r(0,iK-1)]]; 
+                } else {
+                    centers.a = X[full,r(0,iK-1)]; 
+                }
+
+                ILArray<double> classes = zeros(1,n);
+                ILArray<double> oldCenters = centers.C; 
+#if KMEANSVERBOSE
+                System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); 
+#endif
+                while (maxIterations --> 0) {
+#if KMEANSVERBOSE
+                    sw.Restart(); 
+#endif
+                    //ILArray<double> distances = zeros(1, iK);
+
+                    double[] Xarr = X.GetArrayForRead();
+                    double[] Carr = classes.GetArrayForWrite(); 
+                    double[] CentArr = centers.GetArrayForRead(); 
+                    double[] Xcur = ILMemoryPool.Pool.New<double>(X.D[0]); 
+
+                    for (int i = 0; i < n; i++) {
+                        // copy current X[i]
+                        int startInd = i * X.D[0]; 
+                        for (int a = X.D[0]; a --> 0; ) {
+                            Xcur[a] = Xarr[startInd + a]; 
+                        }
+                        // distances to all centers
+                        double dist = double.MaxValue; 
+                        for (int c = 0; c < iK; c++) {
+                            double tmp = 0, tmp1 = 0; 
+                            startInd = c * X.D[0]; 
+                            for (int c1 = X.D[0]; c1-->0; ) {
+                                tmp = CentArr[c1 + startInd] -  Xcur[c1]; 
+                                tmp1 += tmp * tmp; 
+                            }
+                            if (tmp1 < dist) {
+                                dist = tmp1;
+                                Carr[i] = c;
+                                if (dist == 0) 
+                                    break; 
+                            }
+                        }
+                    }
+                    ILMemoryPool.Pool.RegisterObject(Xcur); 
+
+                        // find cluster affiliates
+                        //using (ILScope.Enter()) {
+
+                            ////  - for testing a more "similar 2 Fortran" implementation: 
+                            //ILArray<double> tmpX = X[full, i];
+                            //for (int j = 0; j < iK; j++) {
+                            //    using (ILScope.Enter()) {
+
+                            //        //! ... find its nearest cluster 
+                            //        //do j = 1, K
+                            //        //    distances(j) = sum(                                &
+                            //        //                        abs(                           &
+                            //        //                            X(1:M,i) - centers(1:M,j)))
+                            //        //end do
+
+                            //        //tmpArr = minloc ( distances(1:K) )
+                            //        //classes(i) = tmpArr(1);
+
+                            //        distances[j] = sum(abs(tmpX - centers[full, j]));
+                            //    }
+                            //}
+                            //ILArray<double> minDistIdx = empty();
+                            //min(distances, minDistIdx, 1).Dispose();
+                            //int found = (int)minDistIdx[0];
+                            //classes[i] = found;
+
+                            //ILArray<double> minDistIdx = empty();
+                            //min(sum(apply((a, b) => { return Math.Abs(a - b); }, centers, repmat(X[full, i], 1, iK))), minDistIdx, 1).Dispose();
+                            //int found = (int)minDistIdx[0];
+                            //classes[i] = found;
+
+
+
+                            //ILArray<double> minDistIdx = empty();
+                            //min(sum(abs(centers - repmat(X[full, i], 1, iK))), minDistIdx, 1).Dispose();
+                            //int found = (int)minDistIdx[0];
+                            //classes[i] = found;
+                            
+                            //numInClass[found] = numInClass[found] + 1; 
+                        //}
+                    //}
+                    System.Diagnostics.Debug.Print("kmeans: 1 of {0} MemoryPool.Info: {1}",maxIterations, ILMemoryPool.Pool.Info(true));
+                    // update centroids
+                    //centers[full] = 0; 
+                    //for (int i = 0; i < n; i++) {
+                    //    centers[full,classes[i]] = centers[full,classes[i]] + X[full,i]; 
+                    //}
+                    //numInClass[numInClass == 0] = double.NaN; 
+                    //centers = centers / repmat(numInClass,d,1); 
+
+                    for (int i = 0; i < iK; i++) {
+                        using (EnterScope()) {
+                            ILArray<double> inClass = X[full, find(classes == i)];
+                            if (inClass.IsEmpty) {
+                                centers[full, i] = double.NaN;
+                            } else {
+                                centers[full, i] = mean(inClass, 1);
+                            }
+                        }
+                    }
+#if KMEANSVERBOSE
+                    sw.Stop(); 
+                    Console.Out.WriteLine("Changed centers: {0} elapsed: {1}ms",(double)sum(any(oldCenters != centers)), sw.ElapsedMilliseconds); 
+#endif
+                    if (allall(oldCenters == centers)) break; 
+                    oldCenters.a = centers.C; 
+                }
+                if (!object.Equals(outCenters, null))
+                    outCenters.a = centers; 
+                return classes; 
+            }
+        }
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Algorithms/MachineLearning/kmeansclustMT.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Algorithms/MachineLearning/kmeansclustMT.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Algorithms/MachineLearning/kmeansclustMT.cs	(revision 9102)
@@ -0,0 +1,203 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Threading; 
+using System.Text;
+using ILNumerics.Exceptions; 
+
+namespace ILNumerics {
+    
+    
+    public partial class ILMath { 
+
+        /// <summary>
+        /// find clusters for data matrix X
+        /// </summary>
+        /// <param name="X">data matrix, data points are given as columns</param>
+        /// <param name="k">initial number of clusters expected</param>
+        /// <param name="centerInitRandom">false: pick the first k data points as initial centers, true: pick random datapoints</param>
+        /// <param name="maxIterations">maximum number of iterations, the computation will exit after that many iterations.</param>
+        /// <returns>vector of length n with with indices of clusters assigned to each datapoint</returns>
+        public static ILRetArray<double> kMeansClustMT(ILInArray<double> X, ILBaseArray k, int maxIterations, bool centerInitRandom) {
+            return kMeansClustMT(X, k, maxIterations, centerInitRandom, null);
+        }
+        /// <summary>
+        /// find clusters for data matrix X
+        /// </summary>
+        /// <param name="X">data matrix, data points are given as columns</param>
+        /// <param name="k">initial number of clusters expected</param>
+        /// <param name="centerInitRandom">false: pick the first k data points as initial centers, true: pick random datapoints</param>
+        /// <param name="maxIterations">maximum number of iterations, the computation will exit after that many iterations.</param>
+        /// <param name="outCenters">return type. if assigned on entry, outCenters will contain the centers of the clusters found.</param>
+        /// <returns>vector of length n with with indices of clusters assigned to each datapoint</returns>
+        public static ILRetArray<double> kMeansClustMT (ILInArray<double> X, ILBaseArray k, int maxIterations, bool centerInitRandom, ILOutArray<double> outCenters) {
+            using (ILScope.Enter(X, k)) {
+                if (object.Equals(X,null)) {
+                    throw new ILArgumentException("X must be data matrix (not null)"); 
+                }
+                if (X.IsEmpty) {
+                    if (!object.Equals(outCenters, null)) {
+                        if (X.D[0] > 0) {
+                            outCenters.a = empty<double>(new ILSize(X.D[0], 0));
+                        } else {
+                            outCenters.a = empty<double>(new ILSize(0, X.D[1]));
+                        }
+                        return empty<double>(X.D);
+                    }
+                }
+                if (object.Equals(k,null) || !k.IsScalar || !k.IsNumeric) {
+                    throw new ILArgumentException("number of clusters k must be numeric scalar"); 
+                }
+                int iK = toint32(k).GetValue(0);
+                if (X.D[1] < iK) {
+                    throw new ILArgumentException("too few datapoints provided for " + iK.ToString() + " clusters");
+                }
+                if (iK < 0) {
+                    throw new ILArgumentException("number of clusters must be positive");
+                }
+                int d = X.D[0], n = X.D[1]; 
+                if (iK == 0) {
+                    if (!object.Equals(outCenters, null)) {
+                        outCenters.a = empty<double>(new ILSize(d,iK)); 
+                    }
+                    return empty<double>(new ILSize(0,n)); 
+                }
+
+                // initialize centers by using random datapoints
+                ILArray<double> centers = empty();
+                if (centerInitRandom) {
+                    ILArray<double> pickIndices = empty(); 
+                    sort(rand(1,n),pickIndices,1,false).Dispose();
+                    centers.a = X[full,pickIndices[r(0,iK-1)]]; 
+                } else {
+                    centers.a = X[full,r(0,iK-1)]; 
+                }
+
+                ILArray<double> classes = zeros(1,n);
+                ILArray<double> oldCenters = centers.C; 
+#if KMEANSVERBOSE
+                System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); 
+#endif
+                int maxNTSetting = Settings.MaxNumberThreads, workerCount = 1, workItemLen = 0;
+                int workItemCount = maxNTSetting; 
+                int wi = 0; 
+                Settings.MaxNumberThreads = 1;
+                Action<object> loopOverN = data => {
+                        Tuple<ILInArray<double>, ILInArray<double>, ILOutArray<double>> rng
+                            = (Tuple<ILInArray<double>, ILInArray<double>, ILOutArray<double>>)data;
+                        try {
+                            using (ILScope.Enter(rng.Item1, rng.Item2)) {
+                                ILArray<double> Xl = rng.Item1;
+                                ILArray<double> centersl = rng.Item2;
+                                for (int i = Xl.D[1]; i-- > 0; ) {
+                                    ILArray<double> minDistIdx = empty();
+                                    min(sum(abs(centersl - repmat(Xl[full, i], 1, iK))), minDistIdx, 1).Dispose();
+                                    rng.Item3[i] = minDistIdx[0];
+                                }
+                            }
+                        } finally {
+                            Interlocked.Decrement(ref workerCount);
+                        }
+                };
+                List<ILArray<double>> classesSplit = new List<ILArray<double>>(workItemCount);
+                List<ILArray<double>> XSplit = new List<ILArray<double>>(workItemCount); 
+                
+                while (maxIterations --> 0) {
+#if KMEANSVERBOSE
+                    sw.Restart(); 
+#endif
+                    workItemLen = n / workItemCount;
+                    workerCount = 1; 
+                    for (wi = 0; wi < workItemCount - 1; wi++) {
+                        if (classesSplit.Count <= wi) {
+                            classesSplit.Add(zeros<double>(1,workItemLen)); 
+                        }
+                        if (XSplit.Count <= wi) {
+                            XSplit.Add(X[full,r(wi * workItemLen, (wi + 1) * workItemLen - 1)]); 
+                        }
+                        Tuple<ILInArray<double>, ILInArray<double>, ILOutArray<double>> rng
+                            = new Tuple<ILInArray<double>, ILInArray<double>, ILOutArray<double>>(
+                                XSplit[wi], centers.C, classesSplit[wi]);
+                        Interlocked.Increment(ref workerCount);
+                        ThreadPool.QueueUserWorkItem(new WaitCallback(loopOverN), rng);
+                    }
+                    // loop for main thread
+                    ILArray<double> tmpOutClasses = zeros<double>(1,n - wi * workItemLen); 
+                    Tuple<ILInArray<double>, ILInArray<double>, ILOutArray<double>> rngL
+                        = new Tuple<ILInArray<double>, ILInArray<double>, ILOutArray<double>>(
+                            X[full, r(wi * workItemLen, n - 1)], centers.C, tmpOutClasses);
+                    loopOverN(rngL);
+                    classes[r(wi * workItemLen, n - 1)] = tmpOutClasses; 
+
+                    SpinWait.SpinUntil(() => { return workerCount <= 0; });
+                    Settings.MaxNumberThreads = maxNTSetting;
+                    // resamble
+                    for (wi = 0; wi < workItemCount - 1; wi++)
+                    {
+                        classes[r(wi * workItemLen, (wi + 1)* workItemLen - 1)] = classesSplit[wi]; 
+			        }
+                    System.Diagnostics.Debug.Print("kmeans: 1 of {0} MemoryPool.Info: {1}", maxIterations, ILMemoryPool.Pool.Info(true));
+                    for (int i = 0; i < iK; i++) {
+                        using (EnterScope()) {
+                            ILArray<double> inClass = X[full, find(classes == i)];
+                            if (inClass.IsEmpty) {
+                                centers[full, i] = double.NaN;
+                            } else {
+                                centers[full, i] = mean(inClass, 1);
+                                ILArray<double> inClassDiff = inClass - repmat(centers[full, i], 1, size(inClass, 1));
+                            }
+                        }
+                    }
+#if KMEANSVERBOSE
+                    sw.Stop(); 
+                    Console.Out.WriteLine("Changed centers: {0} elapsed: {1}ms",(double)sum(any(oldCenters != centers)), sw.ElapsedMilliseconds); 
+#endif
+                    if (allall(oldCenters == centers)) break;
+                    oldCenters.a = centers.C;
+                }
+                if (!object.Equals(outCenters, null))
+                    outCenters.a = centers; 
+                return classes; 
+            }
+        }
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Algorithms/Sorting/ILBucketSort.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Algorithms/Sorting/ILBucketSort.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Algorithms/Sorting/ILBucketSort.cs	(revision 9102)
@@ -0,0 +1,291 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Windows.Forms; 
+using ILNumerics.Exceptions; 
+ 
+using ILNumerics.Misc; 
+
+namespace ILNumerics.Algorithms {
+
+    /// <summary>
+    /// Bucket sort algorithm (for internal use)
+    /// </summary>
+    /// <remarks>This class is not intended to be used directly. Sorting functionality is supplied by <see cref="ILMath.sort(ILInArray{double})"/></remarks>
+    internal class ILBucketSort {
+        /// <summary>
+        /// Sort method for bucket sorts
+        /// </summary>
+        public enum SortMethod {
+            /// <summary>
+            /// Constant length
+            /// </summary>
+            ConstantLength,
+            /// <summary>
+            /// Variable length
+            /// </summary>
+            VariableLenth
+        }
+
+        /// <summary>
+        /// Bucket sort algorithm 
+        /// </summary>
+        /// <param name="input"></param>
+        /// <param name="indices">Return corresponding source element indices</param>
+        /// <param name="mapper"></param>
+        /// <param name="method"></param>
+        public static ILQueueList<ElementType,IndexType> BucketSort<ElementType,SubelementType,IndexType> (
+                                            IEnumerable<ElementType> input,
+                                            IEnumerable<IndexType> indices,
+                                            ILKeyMapper<ElementType,SubelementType> mapper,
+                                            SortMethod method) {
+            if (mapper == null) 
+                throw new ILInvalidOperationException("ILBucketSort: key mapper must not be null!");
+            if (input == null) {
+                return new ILQueueList<ElementType,IndexType>(); 
+            }
+            // do the sort now
+            switch (method) {
+                case SortMethod.VariableLenth: 
+                    return bucketSort_variableLength<ElementType,SubelementType,IndexType>(input,mapper); 
+                case SortMethod.ConstantLength:
+                    if (indices != null) 
+                        return bucketSort_constantLength(input,indices,mapper);
+                    else 
+                        return bucketSort_constantLength<ElementType,SubelementType,IndexType>(input,mapper);
+                default: 
+                    throw new ILArgumentException("ILBucketSort: unknown sort method specified."); 
+            }
+        }
+
+        private static ILQueueList<ElementType, IndexType>
+            bucketSort_variableLength<ElementType, SubelementType, IndexType>(
+                                    IEnumerable<ElementType> input,
+                                    ILKeyMapper<ElementType, SubelementType> mapper) {
+            using (ILScope.Enter()) {
+                int m = mapper.NumberOfKeys;
+                ILQueueList<ElementType, IndexType>[] buckets = new ILQueueList<ElementType, IndexType>[m];
+                ILQueueList<ElementType, IndexType> Q = new ILQueueList<ElementType, IndexType>();
+                IEnumerable<ElementType> inp = input;
+
+                #region compute lmax
+                int maxLen = 0, tmp = 0;
+                foreach (ElementType elem in inp) {
+                    tmp = mapper.SubelementsCount(elem);
+                    if (tmp > maxLen)
+                        maxLen = tmp;
+                }
+                #endregion
+                #region create Lengths array
+                ILQueueList<ElementType, IndexType>[] Lengths = new ILQueueList<ElementType, IndexType>[maxLen];
+                foreach (ElementType elem in inp) {
+                    int len = mapper.SubelementsCount(elem) - 1;
+                    if (Lengths[len] == null) {
+                        Lengths[len] = new ILQueueList<ElementType, IndexType>();
+                    }
+                    Lengths[len].Enqueue(elem);
+                }
+                #endregion
+                #region create bucket indices for each position: Noempty array
+                ILQueueList<int, byte>[] Noempty = new ILQueueList<int, byte>[maxLen];
+                ILLogical alreadyFound = new ILLogical(new ILSize(maxLen, m));
+                byte tr = (byte)1;
+                foreach (ElementType s in inp) {
+                    for (int l = mapper.SubelementsCount(s); l-- > 0; ) {
+                        int hpos = mapper.Map(s, l, 0);
+                        if (alreadyFound.GetValue(l, hpos) == 0) {
+                            alreadyFound.SetValue(tr, l, hpos);
+                            if (Noempty[l] == null) {
+                                // create list and init with new value
+                                Noempty[l] = new ILQueueList<int, byte>();
+                            }
+                            Noempty[l].Enqueue(hpos);
+                        }
+                    }
+                }
+                alreadyFound.Dispose();
+                for (int i = 0; i < maxLen; i++) {
+                    // sort lists for each length
+                    Noempty[i] = bucketSort_constantLength<int, int, byte>(Noempty[i], new ILIntLimitedKeyMapper(m));
+                }
+                #endregion
+                #region sort
+                ILListItem<ElementType, IndexType> curElement;
+                for (int l = maxLen; l-- > 0; ) {
+                    // sort Length[l] list
+                    if (Lengths[l] != null) {
+                        Q.AddToStart(Lengths[l]);
+                    }
+                    // sort from last sorting loop (l+1)
+                    while (Q.Count > 0) {
+                        curElement = Q.Dequeue();
+                        int hpos = mapper.Map(curElement.Data, l, 0);
+                        if (buckets[hpos] == null) {
+                            buckets[hpos] = new ILQueueList<ElementType, IndexType>();
+                        }
+                        buckets[hpos].Enqueue(curElement);
+                    }
+                    // collect queues
+                    foreach (int c in Noempty[l]) {
+                        Q.Enqueue(buckets[c]);
+                        buckets[c].Clear();
+                    }
+                }
+                #endregion
+                return Q;
+            }
+        }
+        internal static ILQueueList<ElementType,IndexType> 
+            bucketSort_constantLength<ElementType,SubelementType,IndexType>(
+                                    IEnumerable<ElementType> input,
+                                    ILKeyMapper<ElementType,SubelementType> mapper) {
+            int m = mapper.NumberOfKeys;
+            int tmp = 0; 
+            ILQueueList<ElementType,IndexType>[] buckets = new ILQueueList<ElementType,IndexType>[m];
+            ILQueueList<ElementType,IndexType> Q = new ILQueueList<ElementType,IndexType>(); 
+            // find longest element 
+            int maxLen = 0;
+            foreach (ElementType elem in input) {
+                tmp = mapper.SubelementsCount( elem );  
+                if (tmp > maxLen)
+                    maxLen = tmp;
+            }
+            // sort into buckets 
+            tmp = 0; 
+            for (int k = maxLen; k-- > 0; ) {
+                // walk along the input 
+                if (k == maxLen - 1) {
+                    foreach (ElementType elem in input) {
+                        // put current into bucket
+                        int bpos = mapper.Map(elem,k,0);
+                        if (buckets[bpos] == null) {
+                            // must create list first
+                            buckets[bpos] = new ILQueueList<ElementType,IndexType>();
+                        } 
+                        // append to list 
+                        buckets[bpos].Enqueue(elem); 
+                    }
+                } else {
+                    while (Q.Count > 0) {
+                        // put current into bucket
+                        ILListItem<ElementType,IndexType> elem = Q.Dequeue(); 
+                        int bpos = mapper.Map(elem.Data,k,0);
+                        if (buckets[bpos] == null) {
+                            // must create list first
+                            buckets[bpos] = new ILQueueList<ElementType,IndexType>();
+                        } 
+                        // append to list 
+                        buckets[bpos].Enqueue(elem); 
+                    }
+                }
+                // concatenate all buckets 
+                for (int i = 0; i < buckets.Length; i++) {
+                    if (buckets[i] != null && buckets[i].Count > 0) {
+                        Q.Enqueue(buckets[i]); 
+                        buckets[i].Clear();
+                    }
+                }
+                // goto previous position in strings 
+            }
+            return Q;
+        }
+
+        internal static ILQueueList<ElementType,IndexType> 
+            bucketSort_constantLength<ElementType,SubelementType,IndexType>(
+                                            IEnumerable<ElementType> input,
+                                            IEnumerable<IndexType> indices, 
+                                            ILKeyMapper<ElementType,SubelementType> mapper) {
+            int m = mapper.NumberOfKeys;
+            int tmp = 0; 
+            ILQueueList<ElementType,IndexType>[] buckets = new ILQueueList<ElementType,IndexType>[m];
+            ILQueueList<ElementType,IndexType> Q = new ILQueueList<ElementType,IndexType>(); 
+            // find longest element 
+            int maxLen = 0;
+            foreach (ElementType elem in input) {
+                tmp = mapper.SubelementsCount( elem );  
+                if (tmp > maxLen)
+                    maxLen = tmp;
+            }
+            // sort into buckets 
+            IEnumerator<IndexType> indIt = indices.GetEnumerator();
+            indIt.MoveNext(); 
+            for (int k = maxLen; k-- > 0; ) {
+                // walk along the input 
+                if (k == maxLen - 1) {
+                    foreach (ElementType elem in input) {
+                        // put current into bucket
+                        int bpos = mapper.Map(elem,k,0);
+                        if (buckets[bpos] == null) {
+                            // must create list first
+                            buckets[bpos] = new ILQueueList<ElementType,IndexType>();
+                        } 
+                        // append to list 
+                        buckets[bpos].Enqueue(elem,indIt.Current);
+                        indIt.MoveNext(); 
+                    }
+                } else {
+                    while (Q.Count > 0) {
+                        // put current into bucket
+                        ILListItem<ElementType,IndexType> elem = Q.Dequeue(); 
+                        int bpos = mapper.Map(elem.Data,k,0);
+                        if (buckets[bpos] == null) {
+                            // must create list first
+                            buckets[bpos] = new ILQueueList<ElementType,IndexType>();
+                        } 
+                        // append to list 
+                        buckets[bpos].Enqueue(elem); 
+                    }
+                }
+                // concatenate all buckets 
+                for (int i = 0; i < buckets.Length; i++) {
+                    if (buckets[i] != null && buckets[i].Count > 0) {
+                        Q.Enqueue(buckets[i]); 
+                        buckets[i].Clear();
+                    }
+                }
+                // goto previous position in strings 
+            }
+            return Q;
+        }
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Algorithms/Sorting/ILKeyMapper.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Algorithms/Sorting/ILKeyMapper.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Algorithms/Sorting/ILKeyMapper.cs	(revision 9102)
@@ -0,0 +1,208 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace ILNumerics.Algorithms {
+    /// <summary>
+    /// Key mapper class, to be overriden for user defined classes to be sorted with bucket sort
+    /// </summary>
+    /// <typeparam name="ElementType">Type of elements. Elements are constructed out of any number of subelements</typeparam>
+    /// <typeparam name="SubelementType">Type of subelements</typeparam>
+    /// <remarks>This class can be extended to enable sorting (bucket sort) for arbitrary types. The elements of those types may be devidable into subelements.
+    /// <para>Examples of sortable classes:
+    /// <list>
+    /// <item>colors: number/type of subelements: 1/any (e.g. the color code). One should write a <![CDATA[ILKeyMapper<Color,int>]]>.</item>
+    /// <item>strings: number/type of subelements: arbitrary/char. Here a sample ILASCIKeyMapper implementation exists already. This implementation is the default implementation used for bucket sort via ILMath.sort().</item>
+    /// <item>trees: number/type of subelements: arbitrary/tree nodes. One should write a key mapper to map a node of a tree to a bucket number</item>
+    /// <item>...</item></list></para></remarks>
+    internal abstract class ILKeyMapper<ElementType,SubelementType> {
+        /// <summary>
+        /// Maps subelement types to bucket index
+        /// </summary>
+        /// <param name="inSubelement">Item</param>
+        /// <returns>Bucket index</returns>
+        public abstract int Map (SubelementType inSubelement); 
+        /// <summary>
+        /// Map subelemt - provide fallback on error
+        /// </summary>
+        /// <param name="element">Element item</param>
+        /// <param name="position">Position of subelement in element item to be mapped</param>
+        /// <param name="fallback">If position is out of range, give back fallback</param>
+        /// <returns>Mapped bucket for subelement or fallback on error</returns>
+        public virtual int Map(ElementType element, int position, int fallback) {
+            if (SubelementsCount(element) > position) 
+                return Map(GetSubelement(element,position));
+            else 
+                return fallback; 
+        }
+        /// <summary>
+        /// Count subelements in an element
+        /// </summary>
+        /// <param name="element"></param>
+        /// <returns></returns>
+        public abstract int SubelementsCount (ElementType element); 
+        /// <summary>
+        /// Get subelement from element item
+        /// </summary>
+        /// <param name="element">Element item</param>
+        /// <param name="idx">Position of subitem in element</param>
+        /// <returns>Subitem referenced</returns>
+        public abstract SubelementType GetSubelement (ElementType element, int idx); 
+        
+        private int m_numberOfKeys = 0; 
+        /// <summary>
+        /// Maximum number of keys (different subitems)
+        /// </summary>
+        public int NumberOfKeys {
+            get {
+                return m_numberOfKeys; 
+            }
+        }
+        /// <summary>
+        /// Construct key mapper
+        /// </summary>
+        /// <param name="NumberOfKeys">Maximm number of different subitems (keys)</param>
+        public ILKeyMapper (int NumberOfKeys) {
+            m_numberOfKeys = NumberOfKeys; 
+        }
+    }
+    /// <summary>
+    /// Concrete implementation of a key mapper for strings
+    /// </summary>
+    /// <remarks>this class is the default key mapper, used for bucket sort on strings</remarks>
+    internal class ILASCIIKeyMapper : ILKeyMapper<string, char> {
+        /// <summary>
+        /// map subelement to bucket 
+        /// </summary>
+        /// <param name="inSubelement">subelement to be mapped</param>
+        /// <returns>ASCII code of the subelement character</returns>
+        public override int  Map(char inSubelement) {
+            return (int)inSubelement; 
+        }
+        /// <summary>
+        /// Map char out of string with fallback
+        /// </summary>
+        /// <param name="element">full string item</param>
+        /// <param name="position">position of character in string</param>
+        /// <param name="fallback">fallback bucket number, if position is out of range</param>
+        /// <returns>ASCII code for character specified, fallback on error</returns>
+        public override int Map(string element, int position, int fallback) {
+            if (element.Length > position)
+                return (int)element[position]; 
+            else 
+                return fallback; 
+        }
+        /// <summary>
+        /// give one char from string
+        /// </summary>
+        /// <param name="element">full string item</param>
+        /// <param name="idx">character position in string</param>
+        /// <returns>character in string</returns>
+        /// <exception cref="IndexOutOfRangeException"> if idx is not within element ranges</exception>
+        public override char  GetSubelement(string element, int idx) {
+ 	           return element[idx];
+        }
+        /// <summary>
+        /// Count numer of characters in string
+        /// </summary>
+        /// <param name="element">element item</param>
+        /// <returns>number of characters in string - length of string</returns>
+        public override int SubelementsCount(string element) {
+            if (object.Equals(element,null))
+                return 0; 
+            return element.Length;             
+        }
+        /// <summary>
+        /// construct ASCII key mapper for 256 buckets
+        /// </summary>
+        public ILASCIIKeyMapper() : base(256) {}
+    }
+    /// <summary>
+    /// Integer key mapper - sample implementation for bucket sort
+    /// </summary>
+    /// <remarks>This mapper may be used for sorting integers with bucketsort. 
+    /// <para>The integers to be sorted must be positive and limited. It corresponds to the number of buckets to be created.</para>
+    /// <para>This implementation serves as a sample implementation for bucket sort. You should consider using quicksort instead, which is implemented for ILMath.sort()</para></remarks>
+    internal class ILIntLimitedKeyMapper : ILKeyMapper<int,int> {
+        /// <summary>
+        /// Gives subelement - i.e. the element itself
+        /// </summary>
+        /// <param name="element">element</param>
+        /// <param name="idx">(ignored)</param>
+        /// <returns>element</returns>
+        public override int GetSubelement(int element, int idx) {
+            return element; 
+        }
+        /// <summary>
+        /// map element - ignoring position &amp; fallback
+        /// </summary>
+        /// <param name="element">integer element</param>
+        /// <param name="position">(ignored)</param>
+        /// <param name="fallback">(ignored)</param>
+        /// <returns>integer element</returns>
+        public override int Map(int element, int position, int fallback) {
+            return element; 
+        }
+        /// <summary>
+        /// map (copy) subelement
+        /// </summary>
+        /// <param name="inSubelement">subelement</param>
+        /// <returns>subelement</returns>
+        public override int Map(int inSubelement) {
+            return inSubelement; 
+        }
+        /// <summary>
+        /// number of subelements in an element (Here: always 1)
+        /// </summary>
+        /// <param name="element">element</param>
+        /// <returns>1</returns>
+        public override int SubelementsCount(int element) {
+            return 1; 
+        }
+        /// <summary>
+        /// construct integer key mapper
+        /// </summary>
+        /// <param name="limit">maximum number of buckets to be used</param>
+        public ILIntLimitedKeyMapper (int limit) : base(limit) {} 
+    }
+}
+
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Algorithms/Sorting/ILQueue.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Algorithms/Sorting/ILQueue.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Algorithms/Sorting/ILQueue.cs	(revision 9102)
@@ -0,0 +1,281 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Algorithms; 
+using System.Collections; 
+
+namespace ILNumerics.Misc {
+    /// <summary>
+    /// List items to be used in ILQueueList
+    /// </summary>
+    /// <typeparam name="T1">Data type</typeparam>
+    /// <typeparam name="T2">Index type</typeparam>
+    /// <remarks>This class is not intended to be used directly. Internally it serves as a helper class for sorting.</remarks>
+    internal class ILListItem<T1,T2> {
+        internal T1 Data; 
+        internal T2 m_index; 
+        internal ILListItem<T1,T2> Next; 
+        /// <summary>
+        /// construct list item by data
+        /// </summary>
+        /// <param name="item">item data</param>
+        /// <remarks>the indet will be set to its default value</remarks>
+        public ILListItem(T1 item) {
+            Data = item; 
+            m_index = default(T2); 
+        }
+        /// <summary>
+        /// construct list item, takes item data and index
+        /// </summary>
+        /// <param name="item">item data</param>
+        /// <param name="index">index</param>
+        public ILListItem(T1 item, T2 index) {
+            Data = item; 
+            m_index = index; 
+        }
+        /// <summary>
+        /// index stored with this item
+        /// </summary>
+        public T2 Index {
+            get {
+                return m_index; 
+            } 
+            set {
+                m_index = value; 
+            }
+        }
+    }
+    /// <summary>
+    /// Queuelist - a queue with partial list properties 
+    /// </summary>
+    /// <typeparam name="T1">data type</typeparam>
+    /// <typeparam name="T2">index type</typeparam>
+    /// <remarks>This class is not intended to be used directly. Internally it serves as a helper class for sorting.</remarks>
+    internal class ILQueueList<T1,T2> : IEnumerable<T1> {
+        internal ILListItem<T1,T2> Head;  
+        internal ILListItem<T1,T2> Tail;  
+        internal int m_count = 0; 
+        /// <summary>
+        /// number of items currentliy in the queue (readonly)
+        /// </summary>
+        public int Count {                    
+            get {
+                return m_count; 
+            }
+        }
+
+        /// <summary>
+        /// add indexed item at end of queue
+        /// </summary>
+        public void Enqueue(T1 item, T2 index) {
+            if (Head == null) {
+                Head = new ILListItem<T1,T2>(item, index); 
+                Tail = Head; 
+            } else {
+                ILListItem<T1,T2> newItem = new ILListItem<T1,T2>(item,index); 
+                Tail.Next = newItem; 
+                Tail = newItem; 
+            }
+            m_count++; 
+        }
+
+        /// <summary>
+        /// add item at end of queue
+        /// </summary>
+        public void Enqueue(T1 item) {
+            if (Head == null) {
+                Head = new ILListItem<T1,T2>(item); 
+                Tail = Head; 
+            } else {
+                ILListItem<T1,T2> newItem = new ILListItem<T1,T2>(item); 
+                Tail.Next = newItem; 
+                Tail = newItem; 
+            }
+            m_count++; 
+        }
+        /// <summary>
+        /// add item at end of queue
+        /// </summary>
+        public void Enqueue(ILListItem<T1,T2> item) {
+            System.Diagnostics.Debug.Assert(item.Next == null); 
+            if (Head == null) {
+                Head = item; 
+                Tail = item; 
+            } else {
+                Tail.Next = item; 
+                Tail = item; 
+            }
+            m_count++; 
+        }
+        /// <summary>
+        /// add queue list to end of this queue list
+        /// </summary>
+        /// <param name="list">queue list to be added</param>
+        public void Enqueue(ILQueueList<T1,T2> list) {
+            if (list == null || list.Count == 0) return; 
+            if (Tail != null) {
+                Tail.Next = list.Head; 
+                Tail = list.Tail; 
+            } else {
+                Head = list.Head; 
+                Tail = list.Tail; 
+            }
+            m_count += list.m_count; 
+        }
+        
+        /// <summary>
+        /// Remove from start of queue
+        /// </summary>
+        /// <returns>item from start of queue</returns>
+        public ILListItem<T1,T2> Dequeue() {
+            switch (m_count) {
+                case 0: 
+                    return null; 
+                case 1:
+                    ILListItem<T1,T2> retIt = Head;
+                    Head = null; 
+                    Tail = null; 
+                    m_count--; 
+                    System.Diagnostics.Debug.Assert(retIt.Next == null);
+                    return retIt; 
+                default: 
+                    retIt = Head;
+                    Head = Head.Next; 
+                    m_count--; 
+                    retIt.Next = null; 
+                    return retIt; 
+            }
+        }
+
+        /// <summary>
+        /// Add to start of queue
+        /// </summary>
+        /// <param name="item">item data to add to start of queue</param>
+        public void AddToStart(T1 item) {
+            ILListItem<T1,T2> newLItem = new ILListItem<T1,T2>(item); 
+            newLItem.Next = Head;
+            Head = newLItem; 
+            m_count++; 
+        }
+        /// <summary>
+        /// concatenate 2 queuelists
+        /// </summary>
+        /// <param name="qlist">queue list to be added at start of this queuelist</param>
+        public void AddToStart(ILQueueList<T1,T2> qlist) {
+            m_count += qlist.m_count; 
+            qlist.Tail.Next = Head; 
+            Head = qlist.Head; 
+        }
+        /// <summary>
+        /// sort utilizing bucket sort
+        /// </summary>
+        /// <typeparam name="SubelementType">subelement type</typeparam>
+        /// <param name="mapper">keymapper mapping subelement items to buckets</param>
+        public void Sort<SubelementType>(ILKeyMapper<T1,SubelementType> mapper) {
+            ILQueueList<T1,T2> ret = ILBucketSort.BucketSort<T1,SubelementType,T2>(this,null,mapper,ILBucketSort.SortMethod.ConstantLength); 
+            this.Head = ret.Head;
+            this.Tail = ret.Tail; 
+        }
+        /// <summary>
+        /// convert (copy) items to system array
+        /// </summary>
+        /// <returns>system array with items</returns>
+        public T1[] ToArray() {
+            T1[] ret = new T1[m_count];
+            ILListItem<T1,T2> curr = Head; 
+            for (int i = 0; curr != null; i++) {
+                ret[i] = curr.Data; 
+                curr = curr.Next; 
+            }
+            return ret; 
+        }
+        /// <summary>
+        /// Clear this queue list from all elements 
+        /// </summary>
+        public void Clear() {
+            Head = null; 
+            Tail = null; 
+            m_count = 0; 
+        }
+
+        #region IEnumerable<T> Member
+        /// <summary>
+        /// Create enumerator utilizing 'foreach'
+        /// </summary>
+        /// <returns>enumerator for contained elements</returns>
+        public IEnumerator<T1> GetEnumerator() {
+            ILListItem<T1,T2> curr = Head; 
+            while (curr != null) { 
+                yield return curr.Data; 
+                curr = curr.Next; 
+            }
+        }
+        /// <summary>
+        /// Gives enumerator for contained items (ILListItem)
+        /// </summary>
+        public IEnumerable<ILListItem<T1,T2>> ListItems {
+            get {
+                ILListItem<T1,T2> curr = Head; 
+                while (curr != null) { 
+                    yield return curr; 
+                    curr = curr.Next; 
+                }
+            }
+        }
+        #endregion
+
+        #region IEnumerable Member
+        /// <summary>
+        /// gives enumerator for internal list items (ILListItem)
+        /// </summary>
+        /// <returns>ILListItem's</returns>
+        IEnumerator IEnumerable.GetEnumerator() {
+            ILListItem<T1,T2> curr = Head; 
+            while (curr != null) {
+                yield return curr; 
+                curr = curr.Next;
+            }
+        }
+
+        #endregion
+    }       
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Algorithms/Sorting/ILQuickSortMT.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Algorithms/Sorting/ILQuickSortMT.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Algorithms/Sorting/ILQuickSortMT.cs	(revision 9102)
@@ -0,0 +1,9813 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Algorithms; 
+using ILNumerics.Exceptions;
+using ILNumerics;
+using ILNumerics.Misc;
+using System.Threading;
+
+
+
+namespace ILNumerics.Algorithms {
+
+    /// <summary>
+    /// the class provides a number of one dimensional quicksort implementations for several datatypes/ properties
+    /// </summary>
+    internal partial class ILQuickSort {
+
+        private static int s_threadCount; 
+        private struct ILQuickSortQueueItemData {
+            public int lo;
+            public int hi;
+        }
+        [ThreadStatic]
+        private static int[] s_quickSortStackMT;
+        [ThreadStatic]
+        private volatile static int s_quickSortStackPos;
+
+
+
+        /// <summary>
+        /// inline one dimensional quick sort, ascending, arbitrary element spacing, multithreaded
+        /// </summary>
+        /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+        /// <param name="lo">lowest index of sorting range</param>
+        /// <param name="hi">highest index of sorting range</param>
+        /// <param name="inc">spacing between elements (dimension specifier)</param>
+        /// <remarks>
+        /// <para>This function provides a low level in-place implementation of the quicksort algorithm. It is used by the 
+        /// higher level sorting API provided by <see cref="M:ILNumerics.ILMath.sort"/>. It is recommended to use the overloads 
+        /// of <see cref="M:ILNumerics.ILMath.sort()"/> instead of this function. That way, the decision, which lower level function
+        /// is to be called is made by the library automatically.</para>
+        /// <para>A quicksort algorithm is used for ranges of minimum lengths specified by 
+        /// <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/> and above. 
+        /// Below that length, a simple insertion sort is used instead.</para>
+        /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+        /// memory is needed to perform the sorting. That 'stack' memory defaults to length 100. The stack array
+        /// is cached internally.</para>
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>This function internally parallelizes the sorting in a very efficient manner. It usually outperforms 
+        /// non-parallelized versions of the quicksort algorithm for larger arrays. For smaller arrays, it may be more 
+        /// efficient, to use the non parallelized version instead: <see cref="M:ILNumerics.ILMath.QuickSortAsc(double[], int, int, int)"/></para></remarks>
+        public static void QuickSortAscMT( double[] vecP, int lo, int hi, int inc) {
+            System.Diagnostics.Debug.Assert(vecP != null && vecP.Length > hi);
+            System.Diagnostics.Debug.Assert(lo <= hi);
+            System.Diagnostics.Debug.Assert(lo >= 0);
+            if (vecP.Length < 2) return;
+            unsafe {
+                fixed ( double* vec = vecP) {
+                    
+                    if (checkNaNAsc(lo, ref hi, inc, vec)) return; 
+                    s_threadCount = 1;
+                    QuickSortAsc_ITMT_noNaN(vec, lo, hi, inc);
+
+                } // fixed
+            } // unsafe 
+            Interlocked.Decrement(ref s_threadCount);
+            SpinWait.SpinUntil(() => {
+                return s_threadCount <= 0;
+            });
+        }
+
+        /// <summary>
+        /// inline one dimensional quick sort, descending, arbitrary element spacing, multithreaded
+        /// </summary>
+        /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+        /// <param name="lo">lowest index of sorting range</param>
+        /// <param name="hi">highest index of sorting range</param>
+        /// <param name="inc">spacing between elements (dimension specifier)</param>
+        /// <remarks>        
+        /// <para>This function provides a low level in-place implementation of the quicksort algorithm. It is used by the 
+        /// higher level sorting API provided by <see cref="M:ILNumerics.ILMath.sort"/>. It is recommended to use the overloads 
+        /// of <see cref="M:ILNumerics.ILMath.sort()"/> instead of this function. That way, the decision, which lower level function
+        /// is to be called is made by the library automatically.</para>
+        /// <para>A quicksort algorithm is used for ranges of minimum lengths specified by 
+        /// <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/> and above. 
+        /// Below that length, a simple insertion sort is used instead.</para>
+        /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+        /// memory is needed to perform the sorting. That 'stack' memory defaults to length 100.</para>
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>This function internally parallelizes the sorting in a very efficient manner. It usually outperforms 
+        /// non-parallelized versions of the quicksort algorithm for larger arrays. For smaller arrays, it may be more 
+        /// efficient, to use the non parallelized version instead: <see cref="M:ILNumerics.ILMath.QuickSortAsc(double[], int, int, int)"/></para></remarks>
+        public static void QuickSortDescMT( double[] vecP, int lo, int hi, int inc) {
+            System.Diagnostics.Debug.Assert(vecP != null && vecP.Length > hi);
+            System.Diagnostics.Debug.Assert(lo <= hi);
+            System.Diagnostics.Debug.Assert(lo >= 0);
+            if (vecP.Length < 2) return;
+            unsafe {
+                fixed ( double* vec = vecP) {
+                    
+                    if (checkNaNDesc(lo, ref hi, inc, vec)) return; 
+                    s_threadCount = 1;
+                    QuickSortDesc_ITMT_noNaN(vec, lo, hi, inc);
+
+                } // fixed
+            } // unsafe 
+            Interlocked.Decrement(ref s_threadCount);
+            SpinWait.SpinUntil(() => {
+                return s_threadCount <= 0;
+            });
+        }
+        /// <summary>
+        /// inline one dimensional quick sort, ascending, arbitrary element spacing, indices aware
+        /// </summary>
+        /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+        /// <param name="lo">lowest index of sorting range</param>
+        /// <param name="hi">highest index of sorting range</param>
+        /// <param name="idxP">indices vector, content will in-place be sorted along with <paramref name="vecP"/></param>
+        /// <param name="inc">spacing between elements (dimension specifier)</param>
+        /// <remarks>
+        /// <para>This function provides a low level in-place implementation of the quicksort algorithm. It is used by the 
+        /// higher level sorting API provided by <see cref="M:ILNumerics.ILMath.sort"/>. It is recommended to use the overloads 
+        /// of <see cref="M:ILNumerics.ILMath.sort()"/> instead of this function. That way, the decision, which lower level function
+        /// is to be called is made by the library automatically.</para>
+        /// <para>A quicksort algorithm is used for ranges of minimum lengths specified by 
+        /// <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/> and above. 
+        /// Below that length, a simple insertion sort is used instead.</para>
+        /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+        /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+        /// The size is determined by the value of 
+        /// <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/>.</para>
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>This function internally parallelizes the sorting in a very efficient manner. It usually outperforms 
+        /// non-parallelized versions of the quicksort algorithm for larger arrays. For smaller arrays, it may be more 
+        /// efficient, to use the non parallelized version instead: <see cref="M:ILNumerics.ILMath.QuickSortAsc(double[], int, int, int)"/></para></remarks>
+        public static void QuickSortAscIDXMT( double[] vecP,  double[] idxP, int lo, int hi, int inc) {
+            System.Diagnostics.Debug.Assert(vecP != null && vecP.Length > hi);
+            System.Diagnostics.Debug.Assert(idxP != null && idxP.Length > hi);
+            System.Diagnostics.Debug.Assert(lo <= hi);
+            System.Diagnostics.Debug.Assert(lo >= 0);
+            if (vecP.Length < 2) return;
+            int[] stack = ILMemoryPool.Pool.New<int>(ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth * 2);
+            unsafe {
+                fixed ( double* vecIdx = idxP)
+                fixed ( double* vec = vecP) {
+                    
+                    if (checkNaNIDXAsc(lo, ref hi, inc, vecIdx, vec)) return;
+                    s_threadCount = 1;
+                    QuickSortAscIDX_ITMT_noNaN(vec, vecIdx, lo, hi, inc);
+
+                } // fixed
+            } // unsafe 
+            Interlocked.Decrement(ref s_threadCount);
+            SpinWait.SpinUntil(() => {
+                return s_threadCount <= 0;
+            });
+        }
+
+        /// <summary>
+        /// inline one dimensional quick sort, descending, arbitrary element spacing, indices aware
+        /// </summary>
+        /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+        /// <param name="lo">lowest index of sorting range</param>
+        /// <param name="hi">highest index of sorting range</param>
+        /// <param name="idxP">indices vector, content will in-place be sorted along with <paramref name="vecP"/></param>
+        /// <param name="inc">spacing between elements (dimension specifier)</param>
+        /// <remarks>
+        /// <para>This function provides a low level in-place implementation of the quicksort algorithm. It is used by the 
+        /// higher level sorting API provided by <see cref="M:ILNumerics.ILMath.sort"/>. It is recommended to use the overloads 
+        /// of <see cref="M:ILNumerics.ILMath.sort()"/> instead of this function. That way, the decision, which lower level function
+        /// is to be called is made by the library automatically.</para>
+        /// <para>A quicksort algorithm is used for ranges of minimum lengths specified by 
+        /// <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/> and above. 
+        /// Below that length, a simple insertion sort is used instead.</para>
+        /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+        /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+        /// The size is determined by the value of 
+        /// <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/>.</para>
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>This function internally parallelizes the sorting in a very efficient manner. It usually outperforms 
+        /// non-parallelized versions of the quicksort algorithm for larger arrays. For smaller arrays, it may be more 
+        /// efficient, to use the non parallelized version instead: <see cref="M:ILNumerics.ILMath.QuickSortAsc(double[], int, int, int)"/></para></remarks>
+        public static void QuickSortDescIDXMT( double[] vecP,  double[] idxP, int lo, int hi, int inc) {
+            System.Diagnostics.Debug.Assert(vecP != null && vecP.Length > hi);
+            System.Diagnostics.Debug.Assert(idxP != null && idxP.Length > hi);
+            System.Diagnostics.Debug.Assert(lo <= hi);
+            System.Diagnostics.Debug.Assert(lo >= 0);
+           
+            if (vecP.Length < 2) return;
+            int[] stack = ILMemoryPool.Pool.New<int>(ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth * 2);
+            unsafe {
+                fixed ( double* vecIdx = idxP)
+                fixed ( double* vec = vecP) {
+                    
+                    if (checkNaNIDXDesc(lo,ref hi, inc, vecIdx, vec)) return; 
+                    Interlocked.Increment(ref s_threadCount);
+                    QuickSortDescIDX_ITMT_noNaN(vec, vecIdx, lo, hi, inc);
+                } // fixed
+            } // unsafe 
+            Interlocked.Decrement(ref s_threadCount);
+            SpinWait.SpinUntil(() => {
+                return s_threadCount <= 0;
+            });
+        }
+
+        #region private functions
+        unsafe private static void QuickSortAsc_ITMT_noNaN( double* vec, int lo, int hi, int inc) {
+            int pivotIndex, i, j;
+            s_quickSortStackPos = -1;
+            
+            double a1, a2, a3;
+            
+            double temp, pivotItem;
+            for (; ; ) {
+                #region innerloop
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp <= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                        }
+                        *(vec + i + inc) = pivotItem;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--];
+                } else {
+                    #region quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo);
+                    a2 = *(vec + pivotIndex);
+                    a3 = *(vec + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 > a2) {
+                        if (a1 > a3) {
+                            if (a3 > a2) {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a2;
+                                *(vec + lo + inc) = a3;
+                            } else {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a3;
+                                *(vec + lo + inc) = a2;
+                            }
+                        } else {
+                            *(vec + lo) = a2;
+                            *(vec + lo + inc) = a1;
+                        }
+                    } else {
+                        if (a2 > a3) {
+                            *(vec + hi) = a2;
+                            if (a3 > a1) {
+                                *(vec + lo + inc) = a3;
+                            } else {
+                                *(vec + lo + inc) = a1;
+                                *(vec + lo) = a3;
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2;
+                        }
+                    }
+                    #endregion
+                    
+                    double* vecI = vec + lo + inc, vecJ = vec + hi;
+                    pivotItem = *vecI;
+                    for (; ; ) {
+                        do vecI += inc; while (*vecI < pivotItem);
+                        do vecJ -= inc; while (*vecJ > pivotItem);
+                        if (vecJ < vecI) break;
+                        temp = *vecI;
+                        *vecI = *vecJ;
+                        *vecJ = temp;
+                    }
+                    *(vec + lo + inc) = *vecJ;
+                    *vecJ = pivotItem;
+
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif
+                    #endregion
+                    i = (int)(vecI - vec);
+                    j = (int)(vecJ - vec);
+                    if (hi - i + inc < j - lo) {
+                        if (s_threadCount < 100
+                                && (j - lo) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = i;
+                            data.hi = hi;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortAsc_ITMT_noNaN(vec, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = hi;
+                            s_quickSortStackMT[++s_quickSortStackPos] = i;
+                        }
+                        hi = j - inc;
+                    } else {
+                        if (s_threadCount < 100
+                            && (hi - i + inc) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = lo;
+                            data.hi = j - inc;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                //Console.Out.WriteLine("Thread start: {0} ({1} - {2} Count:{3})", Thread.CurrentThread.ManagedThreadId, lo, hi, threadCount.ThreadCount);
+                                QuickSortAsc_ITMT_noNaN(vec, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = j - inc;
+                            s_quickSortStackMT[++s_quickSortStackPos] = lo;
+                        }
+                        lo = i;
+                    }
+                }
+                #endregion inner loop
+            }
+        }
+        unsafe private static void QuickSortDesc_ITMT_noNaN( double* vec, int lo, int hi, int inc) {
+            int pivotIndex, i, j;
+            s_quickSortStackPos = -1;
+            
+            double a1, a2, a3;
+            
+            double temp, pivotItem;
+            for (; ; ) {
+                #region innerloop
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp >= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                        }
+                        *(vec + i + inc) = pivotItem;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--];
+                } else {
+                    #region quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo);
+                    a2 = *(vec + pivotIndex);
+                    a3 = *(vec + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 < a2) {
+                        if (a1 < a3) {
+                            if (a3 < a2) {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a2;
+                                *(vec + lo + inc) = a3;
+                            } else {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a3;
+                                *(vec + lo + inc) = a2;
+                            }
+                        } else {
+                            *(vec + lo) = a2;
+                            *(vec + lo + inc) = a1;
+                        }
+                    } else {
+                        if (a2 < a3) {
+                            *(vec + hi) = a2;
+                            if (a3 < a1) {
+                                *(vec + lo + inc) = a3;
+                            } else {
+                                *(vec + lo + inc) = a1;
+                                *(vec + lo) = a3;
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2;
+                        }
+                    }
+                    #endregion
+                    
+                    double* vecI = vec + lo + inc, vecJ = vec + hi;
+                    pivotItem = *vecI;
+                    for (; ; ) {
+                        do vecI += inc; while (*vecI > pivotItem);
+                        do vecJ -= inc; while (*vecJ < pivotItem);
+                        if (vecJ < vecI) break;
+                        temp = *vecI;
+                        *vecI = *vecJ;
+                        *vecJ = temp;
+                    }
+                    *(vec + lo + inc) = *vecJ;
+                    *vecJ = pivotItem;
+
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif
+                    #endregion
+                    i = (int)(vecI - vec);
+                    j = (int)(vecJ - vec);
+                    if (hi - i + inc < j - lo) {
+                        if (s_threadCount < 100
+                                && (j - lo) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = i;
+                            data.hi = hi;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortDesc_ITMT_noNaN(vec, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = hi;
+                            s_quickSortStackMT[++s_quickSortStackPos] = i;
+                        }
+                        hi = j - inc;
+                    } else {
+                        if (s_threadCount < 100
+                            && (hi - i + inc) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = lo;
+                            data.hi = j - inc;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                //Console.Out.WriteLine("Thread start: {0} ({1} - {2} Count:{3})", Thread.CurrentThread.ManagedThreadId, lo, hi, threadCount.ThreadCount);
+                                QuickSortDesc_ITMT_noNaN(vec, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = j - inc;
+                            s_quickSortStackMT[++s_quickSortStackPos] = lo;
+                        }
+                        lo = i;
+                    }
+                }
+                #endregion inner loop
+            }
+        }
+        unsafe private static void QuickSortAscIDX_ITMT_noNaN( double* vec, double* vecIdx, int lo, int hi, int inc) {
+            
+            double temp, pivotItem;
+            int pivotIndex, j, i;
+            s_quickSortStackPos = -1;
+            
+            double a1, a2, a3;
+            
+            double ai1, ai2, ai3;
+            for (; ; ) {
+                #region inner loop
+                if (hi - lo < (ILNumerics.Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        ai1 = *(vecIdx + j);
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp <= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                            *(vecIdx + i + inc) = *(vecIdx + i);
+                        }
+                        *(vec + i + inc) = pivotItem;
+                        *(vecIdx + i + inc) = ai1;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--];
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo);
+                    a2 = *(vec + pivotIndex);
+                    a3 = *(vec + hi);
+                    ai1 = *(vecIdx + lo);
+                    ai2 = *(vecIdx + pivotIndex);
+                    ai3 = *(vecIdx + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    *(vecIdx + pivotIndex) = *(vecIdx + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 > a2) {
+                        if (a1 > a3) {
+                            if (a3 > a2) {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a2;
+                                *(vec + lo + inc) = a3;
+                                *(vecIdx + hi) = ai1;
+                                *(vecIdx + lo) = ai2;
+                                *(vecIdx + lo + inc) = ai3;
+                            } else {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a3;
+                                *(vec + lo + inc) = a2;
+                                *(vecIdx + hi) = ai1;
+                                *(vecIdx + lo) = ai3;
+                                *(vecIdx + lo + inc) = ai2;
+                            }
+                        } else {
+                            *(vec + lo) = a2;
+                            *(vec + lo + inc) = a1;
+                            *(vecIdx + lo) = ai2;
+                            *(vecIdx + lo + inc) = ai1;
+                        }
+                    } else {
+                        if (a2 > a3) {
+                            *(vec + hi) = a2;
+                            *(vecIdx + hi) = ai2;
+                            if (a3 > a1) {
+                                *(vec + lo + inc) = a3;
+                                *(vecIdx + lo + inc) = ai3;
+                            } else {
+                                *(vec + lo + inc) = a1;
+                                *(vec + lo) = a3;
+                                *(vecIdx + lo + inc) = ai1;
+                                *(vecIdx + lo) = ai3;
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2;
+                            *(vecIdx + lo + inc) = ai2;
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi;
+                    pivotItem = *(vec + lo + inc);
+                    ai1 = *(vecIdx + lo + inc);
+                    for (; ; ) {
+                        do i += inc; while (*(vec + i) < pivotItem);
+                        do j -= inc; while (*(vec + j) > pivotItem);
+                        if (j < i) break;
+                        temp = *(vec + i);
+                        ai2 = *(vecIdx + i);
+                        *(vec + i) = *(vec + j);
+                        *(vec + j) = temp;
+                        *(vecIdx + i) = *(vecIdx + j);
+                        *(vecIdx + j) = ai2;
+                    }
+                    *(vec + lo + inc) = *(vec + j);
+                    *(vec + j) = pivotItem;
+                    *(vecIdx + lo + inc) = *(vecIdx + j);
+                    *(vecIdx + j) = ai1;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif
+                    if (hi - i + inc < j - lo) {
+                        if (s_threadCount < 100
+                                && (j - lo) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = i;
+                            data.hi = hi;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortAscIDX_ITMT_noNaN(vec, vecIdx, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = hi;
+                            s_quickSortStackMT[++s_quickSortStackPos] = i;
+                        }
+                        hi = j - inc;
+                    } else {
+                        if (s_threadCount < 100
+                            && (hi - i + inc) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = lo;
+                            data.hi = j - inc;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortAscIDX_ITMT_noNaN(vec, vecIdx, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = j - inc;
+                            s_quickSortStackMT[++s_quickSortStackPos] = lo;
+                        }
+                        lo = i;
+                    }
+                }
+                #endregion
+            }
+        }
+        unsafe private static void QuickSortDescIDX_ITMT_noNaN( double* vec, double* vecIdx, int lo, int hi, int inc) {
+            
+            double temp, pivotItem;
+            int pivotIndex, j, i;
+            s_quickSortStackPos = -1;
+            
+            double a1, a2, a3;
+            
+            double ai1, ai2, ai3;
+            for (; ; ) {
+                #region inner loop
+                if (hi - lo < (ILNumerics.Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        ai1 = *(vecIdx + j);
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp >= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                            *(vecIdx + i + inc) = *(vecIdx + i);
+                        }
+                        *(vec + i + inc) = pivotItem;
+                        *(vecIdx + i + inc) = ai1;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--];
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo);
+                    a2 = *(vec + pivotIndex);
+                    a3 = *(vec + hi);
+                    ai1 = *(vecIdx + lo);
+                    ai2 = *(vecIdx + pivotIndex);
+                    ai3 = *(vecIdx + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    *(vecIdx + pivotIndex) = *(vecIdx + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 < a2) {
+                        if (a1 < a3) {
+                            if (a3 < a2) {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a2;
+                                *(vec + lo + inc) = a3;
+                                *(vecIdx + hi) = ai1;
+                                *(vecIdx + lo) = ai2;
+                                *(vecIdx + lo + inc) = ai3;
+                            } else {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a3;
+                                *(vec + lo + inc) = a2;
+                                *(vecIdx + hi) = ai1;
+                                *(vecIdx + lo) = ai3;
+                                *(vecIdx + lo + inc) = ai2;
+                            }
+                        } else {
+                            *(vec + lo) = a2;
+                            *(vec + lo + inc) = a1;
+                            *(vecIdx + lo) = ai2;
+                            *(vecIdx + lo + inc) = ai1;
+                        }
+                    } else {
+                        if (a2 < a3) {
+                            *(vec + hi) = a2;
+                            *(vecIdx + hi) = ai2;
+                            if (a3 < a1) {
+                                *(vec + lo + inc) = a3;
+                                *(vecIdx + lo + inc) = ai3;
+                            } else {
+                                *(vec + lo + inc) = a1;
+                                *(vec + lo) = a3;
+                                *(vecIdx + lo + inc) = ai1;
+                                *(vecIdx + lo) = ai3;
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2;
+                            *(vecIdx + lo + inc) = ai2;
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi;
+                    pivotItem = *(vec + lo + inc);
+                    ai1 = *(vecIdx + lo + inc);
+                    for (; ; ) {
+                        do i += inc; while (*(vec + i) > pivotItem);
+                        do j -= inc; while (*(vec + j) < pivotItem);
+                        if (j < i) break;
+                        temp = *(vec + i);
+                        ai2 = *(vecIdx + i);
+                        *(vec + i) = *(vec + j);
+                        *(vec + j) = temp;
+                        *(vecIdx + i) = *(vecIdx + j);
+                        *(vecIdx + j) = ai2;
+                    }
+                    *(vec + lo + inc) = *(vec + j);
+                    *(vec + j) = pivotItem;
+                    *(vecIdx + lo + inc) = *(vecIdx + j);
+                    *(vecIdx + j) = ai1;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif
+                    if (hi - i + inc < j - lo) {
+                        if (s_threadCount < 100
+                                && (j - lo) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = i;
+                            data.hi = hi;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortDescIDX_ITMT_noNaN(vec, vecIdx, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = hi;
+                            s_quickSortStackMT[++s_quickSortStackPos] = i;
+                        }
+                        hi = j - inc;
+                    } else {
+                        if (s_threadCount < 100
+                            && (hi - i + inc) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = lo;
+                            data.hi = j - inc;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortDescIDX_ITMT_noNaN(vec, vecIdx, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = j - inc;
+                            s_quickSortStackMT[++s_quickSortStackPos] = lo;
+                        }
+                        lo = i;
+                    }
+                }
+                #endregion
+            }
+        }
+        #endregion 
+        
+
+#region HYCALPER AUTO GENERATED CODE
+
+
+        /// <summary>
+        /// inline one dimensional quick sort, ascending, arbitrary element spacing, multithreaded
+        /// </summary>
+        /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+        /// <param name="lo">lowest index of sorting range</param>
+        /// <param name="hi">highest index of sorting range</param>
+        /// <param name="inc">spacing between elements (dimension specifier)</param>
+        /// <remarks>
+        /// <para>This function provides a low level in-place implementation of the quicksort algorithm. It is used by the 
+        /// higher level sorting API provided by <see cref="M:ILNumerics.ILMath.sort"/>. It is recommended to use the overloads 
+        /// of <see cref="M:ILNumerics.ILMath.sort()"/> instead of this function. That way, the decision, which lower level function
+        /// is to be called is made by the library automatically.</para>
+        /// <para>A quicksort algorithm is used for ranges of minimum lengths specified by 
+        /// <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/> and above. 
+        /// Below that length, a simple insertion sort is used instead.</para>
+        /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+        /// memory is needed to perform the sorting. That 'stack' memory defaults to length 100. The stack array
+        /// is cached internally.</para>
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>This function internally parallelizes the sorting in a very efficient manner. It usually outperforms 
+        /// non-parallelized versions of the quicksort algorithm for larger arrays. For smaller arrays, it may be more 
+        /// efficient, to use the non parallelized version instead: <see cref="M:ILNumerics.ILMath.QuickSortAsc(double[], int, int, int)"/></para></remarks>
+        public static void QuickSortAscMT( UInt64[] vecP, int lo, int hi, int inc) {
+            System.Diagnostics.Debug.Assert(vecP != null && vecP.Length > hi);
+            System.Diagnostics.Debug.Assert(lo <= hi);
+            System.Diagnostics.Debug.Assert(lo >= 0);
+            if (vecP.Length < 2) return;
+            unsafe {
+                fixed ( UInt64* vec = vecP) {
+                    
+                    s_threadCount = 1;
+                    QuickSortAsc_ITMT_noNaN(vec, lo, hi, inc);
+
+                } // fixed
+            } // unsafe 
+            Interlocked.Decrement(ref s_threadCount);
+            SpinWait.SpinUntil(() => {
+                return s_threadCount <= 0;
+            });
+        }
+
+        /// <summary>
+        /// inline one dimensional quick sort, descending, arbitrary element spacing, multithreaded
+        /// </summary>
+        /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+        /// <param name="lo">lowest index of sorting range</param>
+        /// <param name="hi">highest index of sorting range</param>
+        /// <param name="inc">spacing between elements (dimension specifier)</param>
+        /// <remarks>        
+        /// <para>This function provides a low level in-place implementation of the quicksort algorithm. It is used by the 
+        /// higher level sorting API provided by <see cref="M:ILNumerics.ILMath.sort"/>. It is recommended to use the overloads 
+        /// of <see cref="M:ILNumerics.ILMath.sort()"/> instead of this function. That way, the decision, which lower level function
+        /// is to be called is made by the library automatically.</para>
+        /// <para>A quicksort algorithm is used for ranges of minimum lengths specified by 
+        /// <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/> and above. 
+        /// Below that length, a simple insertion sort is used instead.</para>
+        /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+        /// memory is needed to perform the sorting. That 'stack' memory defaults to length 100.</para>
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>This function internally parallelizes the sorting in a very efficient manner. It usually outperforms 
+        /// non-parallelized versions of the quicksort algorithm for larger arrays. For smaller arrays, it may be more 
+        /// efficient, to use the non parallelized version instead: <see cref="M:ILNumerics.ILMath.QuickSortAsc(double[], int, int, int)"/></para></remarks>
+        public static void QuickSortDescMT( UInt64[] vecP, int lo, int hi, int inc) {
+            System.Diagnostics.Debug.Assert(vecP != null && vecP.Length > hi);
+            System.Diagnostics.Debug.Assert(lo <= hi);
+            System.Diagnostics.Debug.Assert(lo >= 0);
+            if (vecP.Length < 2) return;
+            unsafe {
+                fixed ( UInt64* vec = vecP) {
+                    
+                    s_threadCount = 1;
+                    QuickSortDesc_ITMT_noNaN(vec, lo, hi, inc);
+
+                } // fixed
+            } // unsafe 
+            Interlocked.Decrement(ref s_threadCount);
+            SpinWait.SpinUntil(() => {
+                return s_threadCount <= 0;
+            });
+        }
+        /// <summary>
+        /// inline one dimensional quick sort, ascending, arbitrary element spacing, indices aware
+        /// </summary>
+        /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+        /// <param name="lo">lowest index of sorting range</param>
+        /// <param name="hi">highest index of sorting range</param>
+        /// <param name="idxP">indices vector, content will in-place be sorted along with <paramref name="vecP"/></param>
+        /// <param name="inc">spacing between elements (dimension specifier)</param>
+        /// <remarks>
+        /// <para>This function provides a low level in-place implementation of the quicksort algorithm. It is used by the 
+        /// higher level sorting API provided by <see cref="M:ILNumerics.ILMath.sort"/>. It is recommended to use the overloads 
+        /// of <see cref="M:ILNumerics.ILMath.sort()"/> instead of this function. That way, the decision, which lower level function
+        /// is to be called is made by the library automatically.</para>
+        /// <para>A quicksort algorithm is used for ranges of minimum lengths specified by 
+        /// <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/> and above. 
+        /// Below that length, a simple insertion sort is used instead.</para>
+        /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+        /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+        /// The size is determined by the value of 
+        /// <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/>.</para>
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>This function internally parallelizes the sorting in a very efficient manner. It usually outperforms 
+        /// non-parallelized versions of the quicksort algorithm for larger arrays. For smaller arrays, it may be more 
+        /// efficient, to use the non parallelized version instead: <see cref="M:ILNumerics.ILMath.QuickSortAsc(double[], int, int, int)"/></para></remarks>
+        public static void QuickSortAscIDXMT( UInt64[] vecP,  double[] idxP, int lo, int hi, int inc) {
+            System.Diagnostics.Debug.Assert(vecP != null && vecP.Length > hi);
+            System.Diagnostics.Debug.Assert(idxP != null && idxP.Length > hi);
+            System.Diagnostics.Debug.Assert(lo <= hi);
+            System.Diagnostics.Debug.Assert(lo >= 0);
+            if (vecP.Length < 2) return;
+            int[] stack = ILMemoryPool.Pool.New<int>(ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth * 2);
+            unsafe {
+                fixed ( double* vecIdx = idxP)
+                fixed ( UInt64* vec = vecP) {
+                    
+                    s_threadCount = 1;
+                    QuickSortAscIDX_ITMT_noNaN(vec, vecIdx, lo, hi, inc);
+
+                } // fixed
+            } // unsafe 
+            Interlocked.Decrement(ref s_threadCount);
+            SpinWait.SpinUntil(() => {
+                return s_threadCount <= 0;
+            });
+        }
+
+        /// <summary>
+        /// inline one dimensional quick sort, descending, arbitrary element spacing, indices aware
+        /// </summary>
+        /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+        /// <param name="lo">lowest index of sorting range</param>
+        /// <param name="hi">highest index of sorting range</param>
+        /// <param name="idxP">indices vector, content will in-place be sorted along with <paramref name="vecP"/></param>
+        /// <param name="inc">spacing between elements (dimension specifier)</param>
+        /// <remarks>
+        /// <para>This function provides a low level in-place implementation of the quicksort algorithm. It is used by the 
+        /// higher level sorting API provided by <see cref="M:ILNumerics.ILMath.sort"/>. It is recommended to use the overloads 
+        /// of <see cref="M:ILNumerics.ILMath.sort()"/> instead of this function. That way, the decision, which lower level function
+        /// is to be called is made by the library automatically.</para>
+        /// <para>A quicksort algorithm is used for ranges of minimum lengths specified by 
+        /// <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/> and above. 
+        /// Below that length, a simple insertion sort is used instead.</para>
+        /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+        /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+        /// The size is determined by the value of 
+        /// <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/>.</para>
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>This function internally parallelizes the sorting in a very efficient manner. It usually outperforms 
+        /// non-parallelized versions of the quicksort algorithm for larger arrays. For smaller arrays, it may be more 
+        /// efficient, to use the non parallelized version instead: <see cref="M:ILNumerics.ILMath.QuickSortAsc(double[], int, int, int)"/></para></remarks>
+        public static void QuickSortDescIDXMT( UInt64[] vecP,  double[] idxP, int lo, int hi, int inc) {
+            System.Diagnostics.Debug.Assert(vecP != null && vecP.Length > hi);
+            System.Diagnostics.Debug.Assert(idxP != null && idxP.Length > hi);
+            System.Diagnostics.Debug.Assert(lo <= hi);
+            System.Diagnostics.Debug.Assert(lo >= 0);
+           
+            if (vecP.Length < 2) return;
+            int[] stack = ILMemoryPool.Pool.New<int>(ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth * 2);
+            unsafe {
+                fixed ( double* vecIdx = idxP)
+                fixed ( UInt64* vec = vecP) {
+                    
+                    Interlocked.Increment(ref s_threadCount);
+                    QuickSortDescIDX_ITMT_noNaN(vec, vecIdx, lo, hi, inc);
+                } // fixed
+            } // unsafe 
+            Interlocked.Decrement(ref s_threadCount);
+            SpinWait.SpinUntil(() => {
+                return s_threadCount <= 0;
+            });
+        }
+
+        #region private functions
+        unsafe private static void QuickSortAsc_ITMT_noNaN( UInt64* vec, int lo, int hi, int inc) {
+            int pivotIndex, i, j;
+            s_quickSortStackPos = -1;
+           
+            UInt64 a1, a2, a3;
+           
+            UInt64 temp, pivotItem;
+            for (; ; ) {
+                #region innerloop
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp <= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                        }
+                        *(vec + i + inc) = pivotItem;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--];
+                } else {
+                    #region quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo);
+                    a2 = *(vec + pivotIndex);
+                    a3 = *(vec + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 > a2) {
+                        if (a1 > a3) {
+                            if (a3 > a2) {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a2;
+                                *(vec + lo + inc) = a3;
+                            } else {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a3;
+                                *(vec + lo + inc) = a2;
+                            }
+                        } else {
+                            *(vec + lo) = a2;
+                            *(vec + lo + inc) = a1;
+                        }
+                    } else {
+                        if (a2 > a3) {
+                            *(vec + hi) = a2;
+                            if (a3 > a1) {
+                                *(vec + lo + inc) = a3;
+                            } else {
+                                *(vec + lo + inc) = a1;
+                                *(vec + lo) = a3;
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2;
+                        }
+                    }
+                    #endregion
+                   
+                    UInt64* vecI = vec + lo + inc, vecJ = vec + hi;
+                    pivotItem = *vecI;
+                    for (; ; ) {
+                        do vecI += inc; while (*vecI < pivotItem);
+                        do vecJ -= inc; while (*vecJ > pivotItem);
+                        if (vecJ < vecI) break;
+                        temp = *vecI;
+                        *vecI = *vecJ;
+                        *vecJ = temp;
+                    }
+                    *(vec + lo + inc) = *vecJ;
+                    *vecJ = pivotItem;
+
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif
+                    #endregion
+                    i = (int)(vecI - vec);
+                    j = (int)(vecJ - vec);
+                    if (hi - i + inc < j - lo) {
+                        if (s_threadCount < 100
+                                && (j - lo) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = i;
+                            data.hi = hi;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortAsc_ITMT_noNaN(vec, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = hi;
+                            s_quickSortStackMT[++s_quickSortStackPos] = i;
+                        }
+                        hi = j - inc;
+                    } else {
+                        if (s_threadCount < 100
+                            && (hi - i + inc) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = lo;
+                            data.hi = j - inc;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                //Console.Out.WriteLine("Thread start: {0} ({1} - {2} Count:{3})", Thread.CurrentThread.ManagedThreadId, lo, hi, threadCount.ThreadCount);
+                                QuickSortAsc_ITMT_noNaN(vec, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = j - inc;
+                            s_quickSortStackMT[++s_quickSortStackPos] = lo;
+                        }
+                        lo = i;
+                    }
+                }
+                #endregion inner loop
+            }
+        }
+        unsafe private static void QuickSortDesc_ITMT_noNaN( UInt64* vec, int lo, int hi, int inc) {
+            int pivotIndex, i, j;
+            s_quickSortStackPos = -1;
+           
+            UInt64 a1, a2, a3;
+           
+            UInt64 temp, pivotItem;
+            for (; ; ) {
+                #region innerloop
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp >= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                        }
+                        *(vec + i + inc) = pivotItem;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--];
+                } else {
+                    #region quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo);
+                    a2 = *(vec + pivotIndex);
+                    a3 = *(vec + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 < a2) {
+                        if (a1 < a3) {
+                            if (a3 < a2) {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a2;
+                                *(vec + lo + inc) = a3;
+                            } else {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a3;
+                                *(vec + lo + inc) = a2;
+                            }
+                        } else {
+                            *(vec + lo) = a2;
+                            *(vec + lo + inc) = a1;
+                        }
+                    } else {
+                        if (a2 < a3) {
+                            *(vec + hi) = a2;
+                            if (a3 < a1) {
+                                *(vec + lo + inc) = a3;
+                            } else {
+                                *(vec + lo + inc) = a1;
+                                *(vec + lo) = a3;
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2;
+                        }
+                    }
+                    #endregion
+                   
+                    UInt64* vecI = vec + lo + inc, vecJ = vec + hi;
+                    pivotItem = *vecI;
+                    for (; ; ) {
+                        do vecI += inc; while (*vecI > pivotItem);
+                        do vecJ -= inc; while (*vecJ < pivotItem);
+                        if (vecJ < vecI) break;
+                        temp = *vecI;
+                        *vecI = *vecJ;
+                        *vecJ = temp;
+                    }
+                    *(vec + lo + inc) = *vecJ;
+                    *vecJ = pivotItem;
+
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif
+                    #endregion
+                    i = (int)(vecI - vec);
+                    j = (int)(vecJ - vec);
+                    if (hi - i + inc < j - lo) {
+                        if (s_threadCount < 100
+                                && (j - lo) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = i;
+                            data.hi = hi;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortDesc_ITMT_noNaN(vec, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = hi;
+                            s_quickSortStackMT[++s_quickSortStackPos] = i;
+                        }
+                        hi = j - inc;
+                    } else {
+                        if (s_threadCount < 100
+                            && (hi - i + inc) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = lo;
+                            data.hi = j - inc;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                //Console.Out.WriteLine("Thread start: {0} ({1} - {2} Count:{3})", Thread.CurrentThread.ManagedThreadId, lo, hi, threadCount.ThreadCount);
+                                QuickSortDesc_ITMT_noNaN(vec, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = j - inc;
+                            s_quickSortStackMT[++s_quickSortStackPos] = lo;
+                        }
+                        lo = i;
+                    }
+                }
+                #endregion inner loop
+            }
+        }
+        unsafe private static void QuickSortAscIDX_ITMT_noNaN( UInt64* vec, double* vecIdx, int lo, int hi, int inc) {
+           
+            UInt64 temp, pivotItem;
+            int pivotIndex, j, i;
+            s_quickSortStackPos = -1;
+           
+            UInt64 a1, a2, a3;
+           
+            double ai1, ai2, ai3;
+            for (; ; ) {
+                #region inner loop
+                if (hi - lo < (ILNumerics.Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        ai1 = *(vecIdx + j);
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp <= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                            *(vecIdx + i + inc) = *(vecIdx + i);
+                        }
+                        *(vec + i + inc) = pivotItem;
+                        *(vecIdx + i + inc) = ai1;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--];
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo);
+                    a2 = *(vec + pivotIndex);
+                    a3 = *(vec + hi);
+                    ai1 = *(vecIdx + lo);
+                    ai2 = *(vecIdx + pivotIndex);
+                    ai3 = *(vecIdx + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    *(vecIdx + pivotIndex) = *(vecIdx + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 > a2) {
+                        if (a1 > a3) {
+                            if (a3 > a2) {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a2;
+                                *(vec + lo + inc) = a3;
+                                *(vecIdx + hi) = ai1;
+                                *(vecIdx + lo) = ai2;
+                                *(vecIdx + lo + inc) = ai3;
+                            } else {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a3;
+                                *(vec + lo + inc) = a2;
+                                *(vecIdx + hi) = ai1;
+                                *(vecIdx + lo) = ai3;
+                                *(vecIdx + lo + inc) = ai2;
+                            }
+                        } else {
+                            *(vec + lo) = a2;
+                            *(vec + lo + inc) = a1;
+                            *(vecIdx + lo) = ai2;
+                            *(vecIdx + lo + inc) = ai1;
+                        }
+                    } else {
+                        if (a2 > a3) {
+                            *(vec + hi) = a2;
+                            *(vecIdx + hi) = ai2;
+                            if (a3 > a1) {
+                                *(vec + lo + inc) = a3;
+                                *(vecIdx + lo + inc) = ai3;
+                            } else {
+                                *(vec + lo + inc) = a1;
+                                *(vec + lo) = a3;
+                                *(vecIdx + lo + inc) = ai1;
+                                *(vecIdx + lo) = ai3;
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2;
+                            *(vecIdx + lo + inc) = ai2;
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi;
+                    pivotItem = *(vec + lo + inc);
+                    ai1 = *(vecIdx + lo + inc);
+                    for (; ; ) {
+                        do i += inc; while (*(vec + i) < pivotItem);
+                        do j -= inc; while (*(vec + j) > pivotItem);
+                        if (j < i) break;
+                        temp = *(vec + i);
+                        ai2 = *(vecIdx + i);
+                        *(vec + i) = *(vec + j);
+                        *(vec + j) = temp;
+                        *(vecIdx + i) = *(vecIdx + j);
+                        *(vecIdx + j) = ai2;
+                    }
+                    *(vec + lo + inc) = *(vec + j);
+                    *(vec + j) = pivotItem;
+                    *(vecIdx + lo + inc) = *(vecIdx + j);
+                    *(vecIdx + j) = ai1;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif
+                    if (hi - i + inc < j - lo) {
+                        if (s_threadCount < 100
+                                && (j - lo) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = i;
+                            data.hi = hi;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortAscIDX_ITMT_noNaN(vec, vecIdx, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = hi;
+                            s_quickSortStackMT[++s_quickSortStackPos] = i;
+                        }
+                        hi = j - inc;
+                    } else {
+                        if (s_threadCount < 100
+                            && (hi - i + inc) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = lo;
+                            data.hi = j - inc;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortAscIDX_ITMT_noNaN(vec, vecIdx, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = j - inc;
+                            s_quickSortStackMT[++s_quickSortStackPos] = lo;
+                        }
+                        lo = i;
+                    }
+                }
+                #endregion
+            }
+        }
+        unsafe private static void QuickSortDescIDX_ITMT_noNaN( UInt64* vec, double* vecIdx, int lo, int hi, int inc) {
+           
+            UInt64 temp, pivotItem;
+            int pivotIndex, j, i;
+            s_quickSortStackPos = -1;
+           
+            UInt64 a1, a2, a3;
+           
+            double ai1, ai2, ai3;
+            for (; ; ) {
+                #region inner loop
+                if (hi - lo < (ILNumerics.Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        ai1 = *(vecIdx + j);
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp >= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                            *(vecIdx + i + inc) = *(vecIdx + i);
+                        }
+                        *(vec + i + inc) = pivotItem;
+                        *(vecIdx + i + inc) = ai1;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--];
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo);
+                    a2 = *(vec + pivotIndex);
+                    a3 = *(vec + hi);
+                    ai1 = *(vecIdx + lo);
+                    ai2 = *(vecIdx + pivotIndex);
+                    ai3 = *(vecIdx + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    *(vecIdx + pivotIndex) = *(vecIdx + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 < a2) {
+                        if (a1 < a3) {
+                            if (a3 < a2) {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a2;
+                                *(vec + lo + inc) = a3;
+                                *(vecIdx + hi) = ai1;
+                                *(vecIdx + lo) = ai2;
+                                *(vecIdx + lo + inc) = ai3;
+                            } else {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a3;
+                                *(vec + lo + inc) = a2;
+                                *(vecIdx + hi) = ai1;
+                                *(vecIdx + lo) = ai3;
+                                *(vecIdx + lo + inc) = ai2;
+                            }
+                        } else {
+                            *(vec + lo) = a2;
+                            *(vec + lo + inc) = a1;
+                            *(vecIdx + lo) = ai2;
+                            *(vecIdx + lo + inc) = ai1;
+                        }
+                    } else {
+                        if (a2 < a3) {
+                            *(vec + hi) = a2;
+                            *(vecIdx + hi) = ai2;
+                            if (a3 < a1) {
+                                *(vec + lo + inc) = a3;
+                                *(vecIdx + lo + inc) = ai3;
+                            } else {
+                                *(vec + lo + inc) = a1;
+                                *(vec + lo) = a3;
+                                *(vecIdx + lo + inc) = ai1;
+                                *(vecIdx + lo) = ai3;
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2;
+                            *(vecIdx + lo + inc) = ai2;
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi;
+                    pivotItem = *(vec + lo + inc);
+                    ai1 = *(vecIdx + lo + inc);
+                    for (; ; ) {
+                        do i += inc; while (*(vec + i) > pivotItem);
+                        do j -= inc; while (*(vec + j) < pivotItem);
+                        if (j < i) break;
+                        temp = *(vec + i);
+                        ai2 = *(vecIdx + i);
+                        *(vec + i) = *(vec + j);
+                        *(vec + j) = temp;
+                        *(vecIdx + i) = *(vecIdx + j);
+                        *(vecIdx + j) = ai2;
+                    }
+                    *(vec + lo + inc) = *(vec + j);
+                    *(vec + j) = pivotItem;
+                    *(vecIdx + lo + inc) = *(vecIdx + j);
+                    *(vecIdx + j) = ai1;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif
+                    if (hi - i + inc < j - lo) {
+                        if (s_threadCount < 100
+                                && (j - lo) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = i;
+                            data.hi = hi;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortDescIDX_ITMT_noNaN(vec, vecIdx, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = hi;
+                            s_quickSortStackMT[++s_quickSortStackPos] = i;
+                        }
+                        hi = j - inc;
+                    } else {
+                        if (s_threadCount < 100
+                            && (hi - i + inc) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = lo;
+                            data.hi = j - inc;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortDescIDX_ITMT_noNaN(vec, vecIdx, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = j - inc;
+                            s_quickSortStackMT[++s_quickSortStackPos] = lo;
+                        }
+                        lo = i;
+                    }
+                }
+                #endregion
+            }
+        }
+        #endregion 
+        
+
+        /// <summary>
+        /// inline one dimensional quick sort, ascending, arbitrary element spacing, multithreaded
+        /// </summary>
+        /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+        /// <param name="lo">lowest index of sorting range</param>
+        /// <param name="hi">highest index of sorting range</param>
+        /// <param name="inc">spacing between elements (dimension specifier)</param>
+        /// <remarks>
+        /// <para>This function provides a low level in-place implementation of the quicksort algorithm. It is used by the 
+        /// higher level sorting API provided by <see cref="M:ILNumerics.ILMath.sort"/>. It is recommended to use the overloads 
+        /// of <see cref="M:ILNumerics.ILMath.sort()"/> instead of this function. That way, the decision, which lower level function
+        /// is to be called is made by the library automatically.</para>
+        /// <para>A quicksort algorithm is used for ranges of minimum lengths specified by 
+        /// <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/> and above. 
+        /// Below that length, a simple insertion sort is used instead.</para>
+        /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+        /// memory is needed to perform the sorting. That 'stack' memory defaults to length 100. The stack array
+        /// is cached internally.</para>
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>This function internally parallelizes the sorting in a very efficient manner. It usually outperforms 
+        /// non-parallelized versions of the quicksort algorithm for larger arrays. For smaller arrays, it may be more 
+        /// efficient, to use the non parallelized version instead: <see cref="M:ILNumerics.ILMath.QuickSortAsc(double[], int, int, int)"/></para></remarks>
+        public static void QuickSortAscMT( UInt32[] vecP, int lo, int hi, int inc) {
+            System.Diagnostics.Debug.Assert(vecP != null && vecP.Length > hi);
+            System.Diagnostics.Debug.Assert(lo <= hi);
+            System.Diagnostics.Debug.Assert(lo >= 0);
+            if (vecP.Length < 2) return;
+            unsafe {
+                fixed ( UInt32* vec = vecP) {
+                    
+                    s_threadCount = 1;
+                    QuickSortAsc_ITMT_noNaN(vec, lo, hi, inc);
+
+                } // fixed
+            } // unsafe 
+            Interlocked.Decrement(ref s_threadCount);
+            SpinWait.SpinUntil(() => {
+                return s_threadCount <= 0;
+            });
+        }
+
+        /// <summary>
+        /// inline one dimensional quick sort, descending, arbitrary element spacing, multithreaded
+        /// </summary>
+        /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+        /// <param name="lo">lowest index of sorting range</param>
+        /// <param name="hi">highest index of sorting range</param>
+        /// <param name="inc">spacing between elements (dimension specifier)</param>
+        /// <remarks>        
+        /// <para>This function provides a low level in-place implementation of the quicksort algorithm. It is used by the 
+        /// higher level sorting API provided by <see cref="M:ILNumerics.ILMath.sort"/>. It is recommended to use the overloads 
+        /// of <see cref="M:ILNumerics.ILMath.sort()"/> instead of this function. That way, the decision, which lower level function
+        /// is to be called is made by the library automatically.</para>
+        /// <para>A quicksort algorithm is used for ranges of minimum lengths specified by 
+        /// <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/> and above. 
+        /// Below that length, a simple insertion sort is used instead.</para>
+        /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+        /// memory is needed to perform the sorting. That 'stack' memory defaults to length 100.</para>
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>This function internally parallelizes the sorting in a very efficient manner. It usually outperforms 
+        /// non-parallelized versions of the quicksort algorithm for larger arrays. For smaller arrays, it may be more 
+        /// efficient, to use the non parallelized version instead: <see cref="M:ILNumerics.ILMath.QuickSortAsc(double[], int, int, int)"/></para></remarks>
+        public static void QuickSortDescMT( UInt32[] vecP, int lo, int hi, int inc) {
+            System.Diagnostics.Debug.Assert(vecP != null && vecP.Length > hi);
+            System.Diagnostics.Debug.Assert(lo <= hi);
+            System.Diagnostics.Debug.Assert(lo >= 0);
+            if (vecP.Length < 2) return;
+            unsafe {
+                fixed ( UInt32* vec = vecP) {
+                    
+                    s_threadCount = 1;
+                    QuickSortDesc_ITMT_noNaN(vec, lo, hi, inc);
+
+                } // fixed
+            } // unsafe 
+            Interlocked.Decrement(ref s_threadCount);
+            SpinWait.SpinUntil(() => {
+                return s_threadCount <= 0;
+            });
+        }
+        /// <summary>
+        /// inline one dimensional quick sort, ascending, arbitrary element spacing, indices aware
+        /// </summary>
+        /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+        /// <param name="lo">lowest index of sorting range</param>
+        /// <param name="hi">highest index of sorting range</param>
+        /// <param name="idxP">indices vector, content will in-place be sorted along with <paramref name="vecP"/></param>
+        /// <param name="inc">spacing between elements (dimension specifier)</param>
+        /// <remarks>
+        /// <para>This function provides a low level in-place implementation of the quicksort algorithm. It is used by the 
+        /// higher level sorting API provided by <see cref="M:ILNumerics.ILMath.sort"/>. It is recommended to use the overloads 
+        /// of <see cref="M:ILNumerics.ILMath.sort()"/> instead of this function. That way, the decision, which lower level function
+        /// is to be called is made by the library automatically.</para>
+        /// <para>A quicksort algorithm is used for ranges of minimum lengths specified by 
+        /// <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/> and above. 
+        /// Below that length, a simple insertion sort is used instead.</para>
+        /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+        /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+        /// The size is determined by the value of 
+        /// <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/>.</para>
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>This function internally parallelizes the sorting in a very efficient manner. It usually outperforms 
+        /// non-parallelized versions of the quicksort algorithm for larger arrays. For smaller arrays, it may be more 
+        /// efficient, to use the non parallelized version instead: <see cref="M:ILNumerics.ILMath.QuickSortAsc(double[], int, int, int)"/></para></remarks>
+        public static void QuickSortAscIDXMT( UInt32[] vecP,  double[] idxP, int lo, int hi, int inc) {
+            System.Diagnostics.Debug.Assert(vecP != null && vecP.Length > hi);
+            System.Diagnostics.Debug.Assert(idxP != null && idxP.Length > hi);
+            System.Diagnostics.Debug.Assert(lo <= hi);
+            System.Diagnostics.Debug.Assert(lo >= 0);
+            if (vecP.Length < 2) return;
+            int[] stack = ILMemoryPool.Pool.New<int>(ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth * 2);
+            unsafe {
+                fixed ( double* vecIdx = idxP)
+                fixed ( UInt32* vec = vecP) {
+                    
+                    s_threadCount = 1;
+                    QuickSortAscIDX_ITMT_noNaN(vec, vecIdx, lo, hi, inc);
+
+                } // fixed
+            } // unsafe 
+            Interlocked.Decrement(ref s_threadCount);
+            SpinWait.SpinUntil(() => {
+                return s_threadCount <= 0;
+            });
+        }
+
+        /// <summary>
+        /// inline one dimensional quick sort, descending, arbitrary element spacing, indices aware
+        /// </summary>
+        /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+        /// <param name="lo">lowest index of sorting range</param>
+        /// <param name="hi">highest index of sorting range</param>
+        /// <param name="idxP">indices vector, content will in-place be sorted along with <paramref name="vecP"/></param>
+        /// <param name="inc">spacing between elements (dimension specifier)</param>
+        /// <remarks>
+        /// <para>This function provides a low level in-place implementation of the quicksort algorithm. It is used by the 
+        /// higher level sorting API provided by <see cref="M:ILNumerics.ILMath.sort"/>. It is recommended to use the overloads 
+        /// of <see cref="M:ILNumerics.ILMath.sort()"/> instead of this function. That way, the decision, which lower level function
+        /// is to be called is made by the library automatically.</para>
+        /// <para>A quicksort algorithm is used for ranges of minimum lengths specified by 
+        /// <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/> and above. 
+        /// Below that length, a simple insertion sort is used instead.</para>
+        /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+        /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+        /// The size is determined by the value of 
+        /// <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/>.</para>
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>This function internally parallelizes the sorting in a very efficient manner. It usually outperforms 
+        /// non-parallelized versions of the quicksort algorithm for larger arrays. For smaller arrays, it may be more 
+        /// efficient, to use the non parallelized version instead: <see cref="M:ILNumerics.ILMath.QuickSortAsc(double[], int, int, int)"/></para></remarks>
+        public static void QuickSortDescIDXMT( UInt32[] vecP,  double[] idxP, int lo, int hi, int inc) {
+            System.Diagnostics.Debug.Assert(vecP != null && vecP.Length > hi);
+            System.Diagnostics.Debug.Assert(idxP != null && idxP.Length > hi);
+            System.Diagnostics.Debug.Assert(lo <= hi);
+            System.Diagnostics.Debug.Assert(lo >= 0);
+           
+            if (vecP.Length < 2) return;
+            int[] stack = ILMemoryPool.Pool.New<int>(ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth * 2);
+            unsafe {
+                fixed ( double* vecIdx = idxP)
+                fixed ( UInt32* vec = vecP) {
+                    
+                    Interlocked.Increment(ref s_threadCount);
+                    QuickSortDescIDX_ITMT_noNaN(vec, vecIdx, lo, hi, inc);
+                } // fixed
+            } // unsafe 
+            Interlocked.Decrement(ref s_threadCount);
+            SpinWait.SpinUntil(() => {
+                return s_threadCount <= 0;
+            });
+        }
+
+        #region private functions
+        unsafe private static void QuickSortAsc_ITMT_noNaN( UInt32* vec, int lo, int hi, int inc) {
+            int pivotIndex, i, j;
+            s_quickSortStackPos = -1;
+           
+            UInt32 a1, a2, a3;
+           
+            UInt32 temp, pivotItem;
+            for (; ; ) {
+                #region innerloop
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp <= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                        }
+                        *(vec + i + inc) = pivotItem;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--];
+                } else {
+                    #region quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo);
+                    a2 = *(vec + pivotIndex);
+                    a3 = *(vec + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 > a2) {
+                        if (a1 > a3) {
+                            if (a3 > a2) {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a2;
+                                *(vec + lo + inc) = a3;
+                            } else {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a3;
+                                *(vec + lo + inc) = a2;
+                            }
+                        } else {
+                            *(vec + lo) = a2;
+                            *(vec + lo + inc) = a1;
+                        }
+                    } else {
+                        if (a2 > a3) {
+                            *(vec + hi) = a2;
+                            if (a3 > a1) {
+                                *(vec + lo + inc) = a3;
+                            } else {
+                                *(vec + lo + inc) = a1;
+                                *(vec + lo) = a3;
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2;
+                        }
+                    }
+                    #endregion
+                   
+                    UInt32* vecI = vec + lo + inc, vecJ = vec + hi;
+                    pivotItem = *vecI;
+                    for (; ; ) {
+                        do vecI += inc; while (*vecI < pivotItem);
+                        do vecJ -= inc; while (*vecJ > pivotItem);
+                        if (vecJ < vecI) break;
+                        temp = *vecI;
+                        *vecI = *vecJ;
+                        *vecJ = temp;
+                    }
+                    *(vec + lo + inc) = *vecJ;
+                    *vecJ = pivotItem;
+
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif
+                    #endregion
+                    i = (int)(vecI - vec);
+                    j = (int)(vecJ - vec);
+                    if (hi - i + inc < j - lo) {
+                        if (s_threadCount < 100
+                                && (j - lo) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = i;
+                            data.hi = hi;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortAsc_ITMT_noNaN(vec, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = hi;
+                            s_quickSortStackMT[++s_quickSortStackPos] = i;
+                        }
+                        hi = j - inc;
+                    } else {
+                        if (s_threadCount < 100
+                            && (hi - i + inc) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = lo;
+                            data.hi = j - inc;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                //Console.Out.WriteLine("Thread start: {0} ({1} - {2} Count:{3})", Thread.CurrentThread.ManagedThreadId, lo, hi, threadCount.ThreadCount);
+                                QuickSortAsc_ITMT_noNaN(vec, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = j - inc;
+                            s_quickSortStackMT[++s_quickSortStackPos] = lo;
+                        }
+                        lo = i;
+                    }
+                }
+                #endregion inner loop
+            }
+        }
+        unsafe private static void QuickSortDesc_ITMT_noNaN( UInt32* vec, int lo, int hi, int inc) {
+            int pivotIndex, i, j;
+            s_quickSortStackPos = -1;
+           
+            UInt32 a1, a2, a3;
+           
+            UInt32 temp, pivotItem;
+            for (; ; ) {
+                #region innerloop
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp >= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                        }
+                        *(vec + i + inc) = pivotItem;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--];
+                } else {
+                    #region quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo);
+                    a2 = *(vec + pivotIndex);
+                    a3 = *(vec + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 < a2) {
+                        if (a1 < a3) {
+                            if (a3 < a2) {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a2;
+                                *(vec + lo + inc) = a3;
+                            } else {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a3;
+                                *(vec + lo + inc) = a2;
+                            }
+                        } else {
+                            *(vec + lo) = a2;
+                            *(vec + lo + inc) = a1;
+                        }
+                    } else {
+                        if (a2 < a3) {
+                            *(vec + hi) = a2;
+                            if (a3 < a1) {
+                                *(vec + lo + inc) = a3;
+                            } else {
+                                *(vec + lo + inc) = a1;
+                                *(vec + lo) = a3;
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2;
+                        }
+                    }
+                    #endregion
+                   
+                    UInt32* vecI = vec + lo + inc, vecJ = vec + hi;
+                    pivotItem = *vecI;
+                    for (; ; ) {
+                        do vecI += inc; while (*vecI > pivotItem);
+                        do vecJ -= inc; while (*vecJ < pivotItem);
+                        if (vecJ < vecI) break;
+                        temp = *vecI;
+                        *vecI = *vecJ;
+                        *vecJ = temp;
+                    }
+                    *(vec + lo + inc) = *vecJ;
+                    *vecJ = pivotItem;
+
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif
+                    #endregion
+                    i = (int)(vecI - vec);
+                    j = (int)(vecJ - vec);
+                    if (hi - i + inc < j - lo) {
+                        if (s_threadCount < 100
+                                && (j - lo) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = i;
+                            data.hi = hi;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortDesc_ITMT_noNaN(vec, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = hi;
+                            s_quickSortStackMT[++s_quickSortStackPos] = i;
+                        }
+                        hi = j - inc;
+                    } else {
+                        if (s_threadCount < 100
+                            && (hi - i + inc) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = lo;
+                            data.hi = j - inc;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                //Console.Out.WriteLine("Thread start: {0} ({1} - {2} Count:{3})", Thread.CurrentThread.ManagedThreadId, lo, hi, threadCount.ThreadCount);
+                                QuickSortDesc_ITMT_noNaN(vec, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = j - inc;
+                            s_quickSortStackMT[++s_quickSortStackPos] = lo;
+                        }
+                        lo = i;
+                    }
+                }
+                #endregion inner loop
+            }
+        }
+        unsafe private static void QuickSortAscIDX_ITMT_noNaN( UInt32* vec, double* vecIdx, int lo, int hi, int inc) {
+           
+            UInt32 temp, pivotItem;
+            int pivotIndex, j, i;
+            s_quickSortStackPos = -1;
+           
+            UInt32 a1, a2, a3;
+           
+            double ai1, ai2, ai3;
+            for (; ; ) {
+                #region inner loop
+                if (hi - lo < (ILNumerics.Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        ai1 = *(vecIdx + j);
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp <= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                            *(vecIdx + i + inc) = *(vecIdx + i);
+                        }
+                        *(vec + i + inc) = pivotItem;
+                        *(vecIdx + i + inc) = ai1;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--];
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo);
+                    a2 = *(vec + pivotIndex);
+                    a3 = *(vec + hi);
+                    ai1 = *(vecIdx + lo);
+                    ai2 = *(vecIdx + pivotIndex);
+                    ai3 = *(vecIdx + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    *(vecIdx + pivotIndex) = *(vecIdx + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 > a2) {
+                        if (a1 > a3) {
+                            if (a3 > a2) {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a2;
+                                *(vec + lo + inc) = a3;
+                                *(vecIdx + hi) = ai1;
+                                *(vecIdx + lo) = ai2;
+                                *(vecIdx + lo + inc) = ai3;
+                            } else {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a3;
+                                *(vec + lo + inc) = a2;
+                                *(vecIdx + hi) = ai1;
+                                *(vecIdx + lo) = ai3;
+                                *(vecIdx + lo + inc) = ai2;
+                            }
+                        } else {
+                            *(vec + lo) = a2;
+                            *(vec + lo + inc) = a1;
+                            *(vecIdx + lo) = ai2;
+                            *(vecIdx + lo + inc) = ai1;
+                        }
+                    } else {
+                        if (a2 > a3) {
+                            *(vec + hi) = a2;
+                            *(vecIdx + hi) = ai2;
+                            if (a3 > a1) {
+                                *(vec + lo + inc) = a3;
+                                *(vecIdx + lo + inc) = ai3;
+                            } else {
+                                *(vec + lo + inc) = a1;
+                                *(vec + lo) = a3;
+                                *(vecIdx + lo + inc) = ai1;
+                                *(vecIdx + lo) = ai3;
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2;
+                            *(vecIdx + lo + inc) = ai2;
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi;
+                    pivotItem = *(vec + lo + inc);
+                    ai1 = *(vecIdx + lo + inc);
+                    for (; ; ) {
+                        do i += inc; while (*(vec + i) < pivotItem);
+                        do j -= inc; while (*(vec + j) > pivotItem);
+                        if (j < i) break;
+                        temp = *(vec + i);
+                        ai2 = *(vecIdx + i);
+                        *(vec + i) = *(vec + j);
+                        *(vec + j) = temp;
+                        *(vecIdx + i) = *(vecIdx + j);
+                        *(vecIdx + j) = ai2;
+                    }
+                    *(vec + lo + inc) = *(vec + j);
+                    *(vec + j) = pivotItem;
+                    *(vecIdx + lo + inc) = *(vecIdx + j);
+                    *(vecIdx + j) = ai1;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif
+                    if (hi - i + inc < j - lo) {
+                        if (s_threadCount < 100
+                                && (j - lo) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = i;
+                            data.hi = hi;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortAscIDX_ITMT_noNaN(vec, vecIdx, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = hi;
+                            s_quickSortStackMT[++s_quickSortStackPos] = i;
+                        }
+                        hi = j - inc;
+                    } else {
+                        if (s_threadCount < 100
+                            && (hi - i + inc) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = lo;
+                            data.hi = j - inc;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortAscIDX_ITMT_noNaN(vec, vecIdx, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = j - inc;
+                            s_quickSortStackMT[++s_quickSortStackPos] = lo;
+                        }
+                        lo = i;
+                    }
+                }
+                #endregion
+            }
+        }
+        unsafe private static void QuickSortDescIDX_ITMT_noNaN( UInt32* vec, double* vecIdx, int lo, int hi, int inc) {
+           
+            UInt32 temp, pivotItem;
+            int pivotIndex, j, i;
+            s_quickSortStackPos = -1;
+           
+            UInt32 a1, a2, a3;
+           
+            double ai1, ai2, ai3;
+            for (; ; ) {
+                #region inner loop
+                if (hi - lo < (ILNumerics.Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        ai1 = *(vecIdx + j);
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp >= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                            *(vecIdx + i + inc) = *(vecIdx + i);
+                        }
+                        *(vec + i + inc) = pivotItem;
+                        *(vecIdx + i + inc) = ai1;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--];
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo);
+                    a2 = *(vec + pivotIndex);
+                    a3 = *(vec + hi);
+                    ai1 = *(vecIdx + lo);
+                    ai2 = *(vecIdx + pivotIndex);
+                    ai3 = *(vecIdx + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    *(vecIdx + pivotIndex) = *(vecIdx + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 < a2) {
+                        if (a1 < a3) {
+                            if (a3 < a2) {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a2;
+                                *(vec + lo + inc) = a3;
+                                *(vecIdx + hi) = ai1;
+                                *(vecIdx + lo) = ai2;
+                                *(vecIdx + lo + inc) = ai3;
+                            } else {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a3;
+                                *(vec + lo + inc) = a2;
+                                *(vecIdx + hi) = ai1;
+                                *(vecIdx + lo) = ai3;
+                                *(vecIdx + lo + inc) = ai2;
+                            }
+                        } else {
+                            *(vec + lo) = a2;
+                            *(vec + lo + inc) = a1;
+                            *(vecIdx + lo) = ai2;
+                            *(vecIdx + lo + inc) = ai1;
+                        }
+                    } else {
+                        if (a2 < a3) {
+                            *(vec + hi) = a2;
+                            *(vecIdx + hi) = ai2;
+                            if (a3 < a1) {
+                                *(vec + lo + inc) = a3;
+                                *(vecIdx + lo + inc) = ai3;
+                            } else {
+                                *(vec + lo + inc) = a1;
+                                *(vec + lo) = a3;
+                                *(vecIdx + lo + inc) = ai1;
+                                *(vecIdx + lo) = ai3;
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2;
+                            *(vecIdx + lo + inc) = ai2;
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi;
+                    pivotItem = *(vec + lo + inc);
+                    ai1 = *(vecIdx + lo + inc);
+                    for (; ; ) {
+                        do i += inc; while (*(vec + i) > pivotItem);
+                        do j -= inc; while (*(vec + j) < pivotItem);
+                        if (j < i) break;
+                        temp = *(vec + i);
+                        ai2 = *(vecIdx + i);
+                        *(vec + i) = *(vec + j);
+                        *(vec + j) = temp;
+                        *(vecIdx + i) = *(vecIdx + j);
+                        *(vecIdx + j) = ai2;
+                    }
+                    *(vec + lo + inc) = *(vec + j);
+                    *(vec + j) = pivotItem;
+                    *(vecIdx + lo + inc) = *(vecIdx + j);
+                    *(vecIdx + j) = ai1;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif
+                    if (hi - i + inc < j - lo) {
+                        if (s_threadCount < 100
+                                && (j - lo) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = i;
+                            data.hi = hi;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortDescIDX_ITMT_noNaN(vec, vecIdx, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = hi;
+                            s_quickSortStackMT[++s_quickSortStackPos] = i;
+                        }
+                        hi = j - inc;
+                    } else {
+                        if (s_threadCount < 100
+                            && (hi - i + inc) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = lo;
+                            data.hi = j - inc;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortDescIDX_ITMT_noNaN(vec, vecIdx, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = j - inc;
+                            s_quickSortStackMT[++s_quickSortStackPos] = lo;
+                        }
+                        lo = i;
+                    }
+                }
+                #endregion
+            }
+        }
+        #endregion 
+        
+
+        /// <summary>
+        /// inline one dimensional quick sort, ascending, arbitrary element spacing, multithreaded
+        /// </summary>
+        /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+        /// <param name="lo">lowest index of sorting range</param>
+        /// <param name="hi">highest index of sorting range</param>
+        /// <param name="inc">spacing between elements (dimension specifier)</param>
+        /// <remarks>
+        /// <para>This function provides a low level in-place implementation of the quicksort algorithm. It is used by the 
+        /// higher level sorting API provided by <see cref="M:ILNumerics.ILMath.sort"/>. It is recommended to use the overloads 
+        /// of <see cref="M:ILNumerics.ILMath.sort()"/> instead of this function. That way, the decision, which lower level function
+        /// is to be called is made by the library automatically.</para>
+        /// <para>A quicksort algorithm is used for ranges of minimum lengths specified by 
+        /// <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/> and above. 
+        /// Below that length, a simple insertion sort is used instead.</para>
+        /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+        /// memory is needed to perform the sorting. That 'stack' memory defaults to length 100. The stack array
+        /// is cached internally.</para>
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>This function internally parallelizes the sorting in a very efficient manner. It usually outperforms 
+        /// non-parallelized versions of the quicksort algorithm for larger arrays. For smaller arrays, it may be more 
+        /// efficient, to use the non parallelized version instead: <see cref="M:ILNumerics.ILMath.QuickSortAsc(double[], int, int, int)"/></para></remarks>
+        public static void QuickSortAscMT( UInt16[] vecP, int lo, int hi, int inc) {
+            System.Diagnostics.Debug.Assert(vecP != null && vecP.Length > hi);
+            System.Diagnostics.Debug.Assert(lo <= hi);
+            System.Diagnostics.Debug.Assert(lo >= 0);
+            if (vecP.Length < 2) return;
+            unsafe {
+                fixed ( UInt16* vec = vecP) {
+                    
+                    s_threadCount = 1;
+                    QuickSortAsc_ITMT_noNaN(vec, lo, hi, inc);
+
+                } // fixed
+            } // unsafe 
+            Interlocked.Decrement(ref s_threadCount);
+            SpinWait.SpinUntil(() => {
+                return s_threadCount <= 0;
+            });
+        }
+
+        /// <summary>
+        /// inline one dimensional quick sort, descending, arbitrary element spacing, multithreaded
+        /// </summary>
+        /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+        /// <param name="lo">lowest index of sorting range</param>
+        /// <param name="hi">highest index of sorting range</param>
+        /// <param name="inc">spacing between elements (dimension specifier)</param>
+        /// <remarks>        
+        /// <para>This function provides a low level in-place implementation of the quicksort algorithm. It is used by the 
+        /// higher level sorting API provided by <see cref="M:ILNumerics.ILMath.sort"/>. It is recommended to use the overloads 
+        /// of <see cref="M:ILNumerics.ILMath.sort()"/> instead of this function. That way, the decision, which lower level function
+        /// is to be called is made by the library automatically.</para>
+        /// <para>A quicksort algorithm is used for ranges of minimum lengths specified by 
+        /// <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/> and above. 
+        /// Below that length, a simple insertion sort is used instead.</para>
+        /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+        /// memory is needed to perform the sorting. That 'stack' memory defaults to length 100.</para>
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>This function internally parallelizes the sorting in a very efficient manner. It usually outperforms 
+        /// non-parallelized versions of the quicksort algorithm for larger arrays. For smaller arrays, it may be more 
+        /// efficient, to use the non parallelized version instead: <see cref="M:ILNumerics.ILMath.QuickSortAsc(double[], int, int, int)"/></para></remarks>
+        public static void QuickSortDescMT( UInt16[] vecP, int lo, int hi, int inc) {
+            System.Diagnostics.Debug.Assert(vecP != null && vecP.Length > hi);
+            System.Diagnostics.Debug.Assert(lo <= hi);
+            System.Diagnostics.Debug.Assert(lo >= 0);
+            if (vecP.Length < 2) return;
+            unsafe {
+                fixed ( UInt16* vec = vecP) {
+                    
+                    s_threadCount = 1;
+                    QuickSortDesc_ITMT_noNaN(vec, lo, hi, inc);
+
+                } // fixed
+            } // unsafe 
+            Interlocked.Decrement(ref s_threadCount);
+            SpinWait.SpinUntil(() => {
+                return s_threadCount <= 0;
+            });
+        }
+        /// <summary>
+        /// inline one dimensional quick sort, ascending, arbitrary element spacing, indices aware
+        /// </summary>
+        /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+        /// <param name="lo">lowest index of sorting range</param>
+        /// <param name="hi">highest index of sorting range</param>
+        /// <param name="idxP">indices vector, content will in-place be sorted along with <paramref name="vecP"/></param>
+        /// <param name="inc">spacing between elements (dimension specifier)</param>
+        /// <remarks>
+        /// <para>This function provides a low level in-place implementation of the quicksort algorithm. It is used by the 
+        /// higher level sorting API provided by <see cref="M:ILNumerics.ILMath.sort"/>. It is recommended to use the overloads 
+        /// of <see cref="M:ILNumerics.ILMath.sort()"/> instead of this function. That way, the decision, which lower level function
+        /// is to be called is made by the library automatically.</para>
+        /// <para>A quicksort algorithm is used for ranges of minimum lengths specified by 
+        /// <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/> and above. 
+        /// Below that length, a simple insertion sort is used instead.</para>
+        /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+        /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+        /// The size is determined by the value of 
+        /// <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/>.</para>
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>This function internally parallelizes the sorting in a very efficient manner. It usually outperforms 
+        /// non-parallelized versions of the quicksort algorithm for larger arrays. For smaller arrays, it may be more 
+        /// efficient, to use the non parallelized version instead: <see cref="M:ILNumerics.ILMath.QuickSortAsc(double[], int, int, int)"/></para></remarks>
+        public static void QuickSortAscIDXMT( UInt16[] vecP,  double[] idxP, int lo, int hi, int inc) {
+            System.Diagnostics.Debug.Assert(vecP != null && vecP.Length > hi);
+            System.Diagnostics.Debug.Assert(idxP != null && idxP.Length > hi);
+            System.Diagnostics.Debug.Assert(lo <= hi);
+            System.Diagnostics.Debug.Assert(lo >= 0);
+            if (vecP.Length < 2) return;
+            int[] stack = ILMemoryPool.Pool.New<int>(ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth * 2);
+            unsafe {
+                fixed ( double* vecIdx = idxP)
+                fixed ( UInt16* vec = vecP) {
+                    
+                    s_threadCount = 1;
+                    QuickSortAscIDX_ITMT_noNaN(vec, vecIdx, lo, hi, inc);
+
+                } // fixed
+            } // unsafe 
+            Interlocked.Decrement(ref s_threadCount);
+            SpinWait.SpinUntil(() => {
+                return s_threadCount <= 0;
+            });
+        }
+
+        /// <summary>
+        /// inline one dimensional quick sort, descending, arbitrary element spacing, indices aware
+        /// </summary>
+        /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+        /// <param name="lo">lowest index of sorting range</param>
+        /// <param name="hi">highest index of sorting range</param>
+        /// <param name="idxP">indices vector, content will in-place be sorted along with <paramref name="vecP"/></param>
+        /// <param name="inc">spacing between elements (dimension specifier)</param>
+        /// <remarks>
+        /// <para>This function provides a low level in-place implementation of the quicksort algorithm. It is used by the 
+        /// higher level sorting API provided by <see cref="M:ILNumerics.ILMath.sort"/>. It is recommended to use the overloads 
+        /// of <see cref="M:ILNumerics.ILMath.sort()"/> instead of this function. That way, the decision, which lower level function
+        /// is to be called is made by the library automatically.</para>
+        /// <para>A quicksort algorithm is used for ranges of minimum lengths specified by 
+        /// <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/> and above. 
+        /// Below that length, a simple insertion sort is used instead.</para>
+        /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+        /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+        /// The size is determined by the value of 
+        /// <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/>.</para>
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>This function internally parallelizes the sorting in a very efficient manner. It usually outperforms 
+        /// non-parallelized versions of the quicksort algorithm for larger arrays. For smaller arrays, it may be more 
+        /// efficient, to use the non parallelized version instead: <see cref="M:ILNumerics.ILMath.QuickSortAsc(double[], int, int, int)"/></para></remarks>
+        public static void QuickSortDescIDXMT( UInt16[] vecP,  double[] idxP, int lo, int hi, int inc) {
+            System.Diagnostics.Debug.Assert(vecP != null && vecP.Length > hi);
+            System.Diagnostics.Debug.Assert(idxP != null && idxP.Length > hi);
+            System.Diagnostics.Debug.Assert(lo <= hi);
+            System.Diagnostics.Debug.Assert(lo >= 0);
+           
+            if (vecP.Length < 2) return;
+            int[] stack = ILMemoryPool.Pool.New<int>(ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth * 2);
+            unsafe {
+                fixed ( double* vecIdx = idxP)
+                fixed ( UInt16* vec = vecP) {
+                    
+                    Interlocked.Increment(ref s_threadCount);
+                    QuickSortDescIDX_ITMT_noNaN(vec, vecIdx, lo, hi, inc);
+                } // fixed
+            } // unsafe 
+            Interlocked.Decrement(ref s_threadCount);
+            SpinWait.SpinUntil(() => {
+                return s_threadCount <= 0;
+            });
+        }
+
+        #region private functions
+        unsafe private static void QuickSortAsc_ITMT_noNaN( UInt16* vec, int lo, int hi, int inc) {
+            int pivotIndex, i, j;
+            s_quickSortStackPos = -1;
+           
+            UInt16 a1, a2, a3;
+           
+            UInt16 temp, pivotItem;
+            for (; ; ) {
+                #region innerloop
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp <= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                        }
+                        *(vec + i + inc) = pivotItem;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--];
+                } else {
+                    #region quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo);
+                    a2 = *(vec + pivotIndex);
+                    a3 = *(vec + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 > a2) {
+                        if (a1 > a3) {
+                            if (a3 > a2) {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a2;
+                                *(vec + lo + inc) = a3;
+                            } else {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a3;
+                                *(vec + lo + inc) = a2;
+                            }
+                        } else {
+                            *(vec + lo) = a2;
+                            *(vec + lo + inc) = a1;
+                        }
+                    } else {
+                        if (a2 > a3) {
+                            *(vec + hi) = a2;
+                            if (a3 > a1) {
+                                *(vec + lo + inc) = a3;
+                            } else {
+                                *(vec + lo + inc) = a1;
+                                *(vec + lo) = a3;
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2;
+                        }
+                    }
+                    #endregion
+                   
+                    UInt16* vecI = vec + lo + inc, vecJ = vec + hi;
+                    pivotItem = *vecI;
+                    for (; ; ) {
+                        do vecI += inc; while (*vecI < pivotItem);
+                        do vecJ -= inc; while (*vecJ > pivotItem);
+                        if (vecJ < vecI) break;
+                        temp = *vecI;
+                        *vecI = *vecJ;
+                        *vecJ = temp;
+                    }
+                    *(vec + lo + inc) = *vecJ;
+                    *vecJ = pivotItem;
+
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif
+                    #endregion
+                    i = (int)(vecI - vec);
+                    j = (int)(vecJ - vec);
+                    if (hi - i + inc < j - lo) {
+                        if (s_threadCount < 100
+                                && (j - lo) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = i;
+                            data.hi = hi;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortAsc_ITMT_noNaN(vec, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = hi;
+                            s_quickSortStackMT[++s_quickSortStackPos] = i;
+                        }
+                        hi = j - inc;
+                    } else {
+                        if (s_threadCount < 100
+                            && (hi - i + inc) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = lo;
+                            data.hi = j - inc;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                //Console.Out.WriteLine("Thread start: {0} ({1} - {2} Count:{3})", Thread.CurrentThread.ManagedThreadId, lo, hi, threadCount.ThreadCount);
+                                QuickSortAsc_ITMT_noNaN(vec, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = j - inc;
+                            s_quickSortStackMT[++s_quickSortStackPos] = lo;
+                        }
+                        lo = i;
+                    }
+                }
+                #endregion inner loop
+            }
+        }
+        unsafe private static void QuickSortDesc_ITMT_noNaN( UInt16* vec, int lo, int hi, int inc) {
+            int pivotIndex, i, j;
+            s_quickSortStackPos = -1;
+           
+            UInt16 a1, a2, a3;
+           
+            UInt16 temp, pivotItem;
+            for (; ; ) {
+                #region innerloop
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp >= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                        }
+                        *(vec + i + inc) = pivotItem;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--];
+                } else {
+                    #region quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo);
+                    a2 = *(vec + pivotIndex);
+                    a3 = *(vec + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 < a2) {
+                        if (a1 < a3) {
+                            if (a3 < a2) {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a2;
+                                *(vec + lo + inc) = a3;
+                            } else {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a3;
+                                *(vec + lo + inc) = a2;
+                            }
+                        } else {
+                            *(vec + lo) = a2;
+                            *(vec + lo + inc) = a1;
+                        }
+                    } else {
+                        if (a2 < a3) {
+                            *(vec + hi) = a2;
+                            if (a3 < a1) {
+                                *(vec + lo + inc) = a3;
+                            } else {
+                                *(vec + lo + inc) = a1;
+                                *(vec + lo) = a3;
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2;
+                        }
+                    }
+                    #endregion
+                   
+                    UInt16* vecI = vec + lo + inc, vecJ = vec + hi;
+                    pivotItem = *vecI;
+                    for (; ; ) {
+                        do vecI += inc; while (*vecI > pivotItem);
+                        do vecJ -= inc; while (*vecJ < pivotItem);
+                        if (vecJ < vecI) break;
+                        temp = *vecI;
+                        *vecI = *vecJ;
+                        *vecJ = temp;
+                    }
+                    *(vec + lo + inc) = *vecJ;
+                    *vecJ = pivotItem;
+
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif
+                    #endregion
+                    i = (int)(vecI - vec);
+                    j = (int)(vecJ - vec);
+                    if (hi - i + inc < j - lo) {
+                        if (s_threadCount < 100
+                                && (j - lo) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = i;
+                            data.hi = hi;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortDesc_ITMT_noNaN(vec, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = hi;
+                            s_quickSortStackMT[++s_quickSortStackPos] = i;
+                        }
+                        hi = j - inc;
+                    } else {
+                        if (s_threadCount < 100
+                            && (hi - i + inc) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = lo;
+                            data.hi = j - inc;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                //Console.Out.WriteLine("Thread start: {0} ({1} - {2} Count:{3})", Thread.CurrentThread.ManagedThreadId, lo, hi, threadCount.ThreadCount);
+                                QuickSortDesc_ITMT_noNaN(vec, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = j - inc;
+                            s_quickSortStackMT[++s_quickSortStackPos] = lo;
+                        }
+                        lo = i;
+                    }
+                }
+                #endregion inner loop
+            }
+        }
+        unsafe private static void QuickSortAscIDX_ITMT_noNaN( UInt16* vec, double* vecIdx, int lo, int hi, int inc) {
+           
+            UInt16 temp, pivotItem;
+            int pivotIndex, j, i;
+            s_quickSortStackPos = -1;
+           
+            UInt16 a1, a2, a3;
+           
+            double ai1, ai2, ai3;
+            for (; ; ) {
+                #region inner loop
+                if (hi - lo < (ILNumerics.Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        ai1 = *(vecIdx + j);
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp <= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                            *(vecIdx + i + inc) = *(vecIdx + i);
+                        }
+                        *(vec + i + inc) = pivotItem;
+                        *(vecIdx + i + inc) = ai1;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--];
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo);
+                    a2 = *(vec + pivotIndex);
+                    a3 = *(vec + hi);
+                    ai1 = *(vecIdx + lo);
+                    ai2 = *(vecIdx + pivotIndex);
+                    ai3 = *(vecIdx + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    *(vecIdx + pivotIndex) = *(vecIdx + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 > a2) {
+                        if (a1 > a3) {
+                            if (a3 > a2) {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a2;
+                                *(vec + lo + inc) = a3;
+                                *(vecIdx + hi) = ai1;
+                                *(vecIdx + lo) = ai2;
+                                *(vecIdx + lo + inc) = ai3;
+                            } else {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a3;
+                                *(vec + lo + inc) = a2;
+                                *(vecIdx + hi) = ai1;
+                                *(vecIdx + lo) = ai3;
+                                *(vecIdx + lo + inc) = ai2;
+                            }
+                        } else {
+                            *(vec + lo) = a2;
+                            *(vec + lo + inc) = a1;
+                            *(vecIdx + lo) = ai2;
+                            *(vecIdx + lo + inc) = ai1;
+                        }
+                    } else {
+                        if (a2 > a3) {
+                            *(vec + hi) = a2;
+                            *(vecIdx + hi) = ai2;
+                            if (a3 > a1) {
+                                *(vec + lo + inc) = a3;
+                                *(vecIdx + lo + inc) = ai3;
+                            } else {
+                                *(vec + lo + inc) = a1;
+                                *(vec + lo) = a3;
+                                *(vecIdx + lo + inc) = ai1;
+                                *(vecIdx + lo) = ai3;
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2;
+                            *(vecIdx + lo + inc) = ai2;
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi;
+                    pivotItem = *(vec + lo + inc);
+                    ai1 = *(vecIdx + lo + inc);
+                    for (; ; ) {
+                        do i += inc; while (*(vec + i) < pivotItem);
+                        do j -= inc; while (*(vec + j) > pivotItem);
+                        if (j < i) break;
+                        temp = *(vec + i);
+                        ai2 = *(vecIdx + i);
+                        *(vec + i) = *(vec + j);
+                        *(vec + j) = temp;
+                        *(vecIdx + i) = *(vecIdx + j);
+                        *(vecIdx + j) = ai2;
+                    }
+                    *(vec + lo + inc) = *(vec + j);
+                    *(vec + j) = pivotItem;
+                    *(vecIdx + lo + inc) = *(vecIdx + j);
+                    *(vecIdx + j) = ai1;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif
+                    if (hi - i + inc < j - lo) {
+                        if (s_threadCount < 100
+                                && (j - lo) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = i;
+                            data.hi = hi;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortAscIDX_ITMT_noNaN(vec, vecIdx, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = hi;
+                            s_quickSortStackMT[++s_quickSortStackPos] = i;
+                        }
+                        hi = j - inc;
+                    } else {
+                        if (s_threadCount < 100
+                            && (hi - i + inc) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = lo;
+                            data.hi = j - inc;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortAscIDX_ITMT_noNaN(vec, vecIdx, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = j - inc;
+                            s_quickSortStackMT[++s_quickSortStackPos] = lo;
+                        }
+                        lo = i;
+                    }
+                }
+                #endregion
+            }
+        }
+        unsafe private static void QuickSortDescIDX_ITMT_noNaN( UInt16* vec, double* vecIdx, int lo, int hi, int inc) {
+           
+            UInt16 temp, pivotItem;
+            int pivotIndex, j, i;
+            s_quickSortStackPos = -1;
+           
+            UInt16 a1, a2, a3;
+           
+            double ai1, ai2, ai3;
+            for (; ; ) {
+                #region inner loop
+                if (hi - lo < (ILNumerics.Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        ai1 = *(vecIdx + j);
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp >= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                            *(vecIdx + i + inc) = *(vecIdx + i);
+                        }
+                        *(vec + i + inc) = pivotItem;
+                        *(vecIdx + i + inc) = ai1;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--];
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo);
+                    a2 = *(vec + pivotIndex);
+                    a3 = *(vec + hi);
+                    ai1 = *(vecIdx + lo);
+                    ai2 = *(vecIdx + pivotIndex);
+                    ai3 = *(vecIdx + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    *(vecIdx + pivotIndex) = *(vecIdx + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 < a2) {
+                        if (a1 < a3) {
+                            if (a3 < a2) {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a2;
+                                *(vec + lo + inc) = a3;
+                                *(vecIdx + hi) = ai1;
+                                *(vecIdx + lo) = ai2;
+                                *(vecIdx + lo + inc) = ai3;
+                            } else {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a3;
+                                *(vec + lo + inc) = a2;
+                                *(vecIdx + hi) = ai1;
+                                *(vecIdx + lo) = ai3;
+                                *(vecIdx + lo + inc) = ai2;
+                            }
+                        } else {
+                            *(vec + lo) = a2;
+                            *(vec + lo + inc) = a1;
+                            *(vecIdx + lo) = ai2;
+                            *(vecIdx + lo + inc) = ai1;
+                        }
+                    } else {
+                        if (a2 < a3) {
+                            *(vec + hi) = a2;
+                            *(vecIdx + hi) = ai2;
+                            if (a3 < a1) {
+                                *(vec + lo + inc) = a3;
+                                *(vecIdx + lo + inc) = ai3;
+                            } else {
+                                *(vec + lo + inc) = a1;
+                                *(vec + lo) = a3;
+                                *(vecIdx + lo + inc) = ai1;
+                                *(vecIdx + lo) = ai3;
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2;
+                            *(vecIdx + lo + inc) = ai2;
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi;
+                    pivotItem = *(vec + lo + inc);
+                    ai1 = *(vecIdx + lo + inc);
+                    for (; ; ) {
+                        do i += inc; while (*(vec + i) > pivotItem);
+                        do j -= inc; while (*(vec + j) < pivotItem);
+                        if (j < i) break;
+                        temp = *(vec + i);
+                        ai2 = *(vecIdx + i);
+                        *(vec + i) = *(vec + j);
+                        *(vec + j) = temp;
+                        *(vecIdx + i) = *(vecIdx + j);
+                        *(vecIdx + j) = ai2;
+                    }
+                    *(vec + lo + inc) = *(vec + j);
+                    *(vec + j) = pivotItem;
+                    *(vecIdx + lo + inc) = *(vecIdx + j);
+                    *(vecIdx + j) = ai1;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif
+                    if (hi - i + inc < j - lo) {
+                        if (s_threadCount < 100
+                                && (j - lo) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = i;
+                            data.hi = hi;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortDescIDX_ITMT_noNaN(vec, vecIdx, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = hi;
+                            s_quickSortStackMT[++s_quickSortStackPos] = i;
+                        }
+                        hi = j - inc;
+                    } else {
+                        if (s_threadCount < 100
+                            && (hi - i + inc) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = lo;
+                            data.hi = j - inc;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortDescIDX_ITMT_noNaN(vec, vecIdx, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = j - inc;
+                            s_quickSortStackMT[++s_quickSortStackPos] = lo;
+                        }
+                        lo = i;
+                    }
+                }
+                #endregion
+            }
+        }
+        #endregion 
+        
+
+        /// <summary>
+        /// inline one dimensional quick sort, ascending, arbitrary element spacing, multithreaded
+        /// </summary>
+        /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+        /// <param name="lo">lowest index of sorting range</param>
+        /// <param name="hi">highest index of sorting range</param>
+        /// <param name="inc">spacing between elements (dimension specifier)</param>
+        /// <remarks>
+        /// <para>This function provides a low level in-place implementation of the quicksort algorithm. It is used by the 
+        /// higher level sorting API provided by <see cref="M:ILNumerics.ILMath.sort"/>. It is recommended to use the overloads 
+        /// of <see cref="M:ILNumerics.ILMath.sort()"/> instead of this function. That way, the decision, which lower level function
+        /// is to be called is made by the library automatically.</para>
+        /// <para>A quicksort algorithm is used for ranges of minimum lengths specified by 
+        /// <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/> and above. 
+        /// Below that length, a simple insertion sort is used instead.</para>
+        /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+        /// memory is needed to perform the sorting. That 'stack' memory defaults to length 100. The stack array
+        /// is cached internally.</para>
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>This function internally parallelizes the sorting in a very efficient manner. It usually outperforms 
+        /// non-parallelized versions of the quicksort algorithm for larger arrays. For smaller arrays, it may be more 
+        /// efficient, to use the non parallelized version instead: <see cref="M:ILNumerics.ILMath.QuickSortAsc(double[], int, int, int)"/></para></remarks>
+        public static void QuickSortAscMT( Int64[] vecP, int lo, int hi, int inc) {
+            System.Diagnostics.Debug.Assert(vecP != null && vecP.Length > hi);
+            System.Diagnostics.Debug.Assert(lo <= hi);
+            System.Diagnostics.Debug.Assert(lo >= 0);
+            if (vecP.Length < 2) return;
+            unsafe {
+                fixed ( Int64* vec = vecP) {
+                    
+                    s_threadCount = 1;
+                    QuickSortAsc_ITMT_noNaN(vec, lo, hi, inc);
+
+                } // fixed
+            } // unsafe 
+            Interlocked.Decrement(ref s_threadCount);
+            SpinWait.SpinUntil(() => {
+                return s_threadCount <= 0;
+            });
+        }
+
+        /// <summary>
+        /// inline one dimensional quick sort, descending, arbitrary element spacing, multithreaded
+        /// </summary>
+        /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+        /// <param name="lo">lowest index of sorting range</param>
+        /// <param name="hi">highest index of sorting range</param>
+        /// <param name="inc">spacing between elements (dimension specifier)</param>
+        /// <remarks>        
+        /// <para>This function provides a low level in-place implementation of the quicksort algorithm. It is used by the 
+        /// higher level sorting API provided by <see cref="M:ILNumerics.ILMath.sort"/>. It is recommended to use the overloads 
+        /// of <see cref="M:ILNumerics.ILMath.sort()"/> instead of this function. That way, the decision, which lower level function
+        /// is to be called is made by the library automatically.</para>
+        /// <para>A quicksort algorithm is used for ranges of minimum lengths specified by 
+        /// <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/> and above. 
+        /// Below that length, a simple insertion sort is used instead.</para>
+        /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+        /// memory is needed to perform the sorting. That 'stack' memory defaults to length 100.</para>
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>This function internally parallelizes the sorting in a very efficient manner. It usually outperforms 
+        /// non-parallelized versions of the quicksort algorithm for larger arrays. For smaller arrays, it may be more 
+        /// efficient, to use the non parallelized version instead: <see cref="M:ILNumerics.ILMath.QuickSortAsc(double[], int, int, int)"/></para></remarks>
+        public static void QuickSortDescMT( Int64[] vecP, int lo, int hi, int inc) {
+            System.Diagnostics.Debug.Assert(vecP != null && vecP.Length > hi);
+            System.Diagnostics.Debug.Assert(lo <= hi);
+            System.Diagnostics.Debug.Assert(lo >= 0);
+            if (vecP.Length < 2) return;
+            unsafe {
+                fixed ( Int64* vec = vecP) {
+                    
+                    s_threadCount = 1;
+                    QuickSortDesc_ITMT_noNaN(vec, lo, hi, inc);
+
+                } // fixed
+            } // unsafe 
+            Interlocked.Decrement(ref s_threadCount);
+            SpinWait.SpinUntil(() => {
+                return s_threadCount <= 0;
+            });
+        }
+        /// <summary>
+        /// inline one dimensional quick sort, ascending, arbitrary element spacing, indices aware
+        /// </summary>
+        /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+        /// <param name="lo">lowest index of sorting range</param>
+        /// <param name="hi">highest index of sorting range</param>
+        /// <param name="idxP">indices vector, content will in-place be sorted along with <paramref name="vecP"/></param>
+        /// <param name="inc">spacing between elements (dimension specifier)</param>
+        /// <remarks>
+        /// <para>This function provides a low level in-place implementation of the quicksort algorithm. It is used by the 
+        /// higher level sorting API provided by <see cref="M:ILNumerics.ILMath.sort"/>. It is recommended to use the overloads 
+        /// of <see cref="M:ILNumerics.ILMath.sort()"/> instead of this function. That way, the decision, which lower level function
+        /// is to be called is made by the library automatically.</para>
+        /// <para>A quicksort algorithm is used for ranges of minimum lengths specified by 
+        /// <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/> and above. 
+        /// Below that length, a simple insertion sort is used instead.</para>
+        /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+        /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+        /// The size is determined by the value of 
+        /// <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/>.</para>
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>This function internally parallelizes the sorting in a very efficient manner. It usually outperforms 
+        /// non-parallelized versions of the quicksort algorithm for larger arrays. For smaller arrays, it may be more 
+        /// efficient, to use the non parallelized version instead: <see cref="M:ILNumerics.ILMath.QuickSortAsc(double[], int, int, int)"/></para></remarks>
+        public static void QuickSortAscIDXMT( Int64[] vecP,  double[] idxP, int lo, int hi, int inc) {
+            System.Diagnostics.Debug.Assert(vecP != null && vecP.Length > hi);
+            System.Diagnostics.Debug.Assert(idxP != null && idxP.Length > hi);
+            System.Diagnostics.Debug.Assert(lo <= hi);
+            System.Diagnostics.Debug.Assert(lo >= 0);
+            if (vecP.Length < 2) return;
+            int[] stack = ILMemoryPool.Pool.New<int>(ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth * 2);
+            unsafe {
+                fixed ( double* vecIdx = idxP)
+                fixed ( Int64* vec = vecP) {
+                    
+                    s_threadCount = 1;
+                    QuickSortAscIDX_ITMT_noNaN(vec, vecIdx, lo, hi, inc);
+
+                } // fixed
+            } // unsafe 
+            Interlocked.Decrement(ref s_threadCount);
+            SpinWait.SpinUntil(() => {
+                return s_threadCount <= 0;
+            });
+        }
+
+        /// <summary>
+        /// inline one dimensional quick sort, descending, arbitrary element spacing, indices aware
+        /// </summary>
+        /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+        /// <param name="lo">lowest index of sorting range</param>
+        /// <param name="hi">highest index of sorting range</param>
+        /// <param name="idxP">indices vector, content will in-place be sorted along with <paramref name="vecP"/></param>
+        /// <param name="inc">spacing between elements (dimension specifier)</param>
+        /// <remarks>
+        /// <para>This function provides a low level in-place implementation of the quicksort algorithm. It is used by the 
+        /// higher level sorting API provided by <see cref="M:ILNumerics.ILMath.sort"/>. It is recommended to use the overloads 
+        /// of <see cref="M:ILNumerics.ILMath.sort()"/> instead of this function. That way, the decision, which lower level function
+        /// is to be called is made by the library automatically.</para>
+        /// <para>A quicksort algorithm is used for ranges of minimum lengths specified by 
+        /// <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/> and above. 
+        /// Below that length, a simple insertion sort is used instead.</para>
+        /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+        /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+        /// The size is determined by the value of 
+        /// <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/>.</para>
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>This function internally parallelizes the sorting in a very efficient manner. It usually outperforms 
+        /// non-parallelized versions of the quicksort algorithm for larger arrays. For smaller arrays, it may be more 
+        /// efficient, to use the non parallelized version instead: <see cref="M:ILNumerics.ILMath.QuickSortAsc(double[], int, int, int)"/></para></remarks>
+        public static void QuickSortDescIDXMT( Int64[] vecP,  double[] idxP, int lo, int hi, int inc) {
+            System.Diagnostics.Debug.Assert(vecP != null && vecP.Length > hi);
+            System.Diagnostics.Debug.Assert(idxP != null && idxP.Length > hi);
+            System.Diagnostics.Debug.Assert(lo <= hi);
+            System.Diagnostics.Debug.Assert(lo >= 0);
+           
+            if (vecP.Length < 2) return;
+            int[] stack = ILMemoryPool.Pool.New<int>(ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth * 2);
+            unsafe {
+                fixed ( double* vecIdx = idxP)
+                fixed ( Int64* vec = vecP) {
+                    
+                    Interlocked.Increment(ref s_threadCount);
+                    QuickSortDescIDX_ITMT_noNaN(vec, vecIdx, lo, hi, inc);
+                } // fixed
+            } // unsafe 
+            Interlocked.Decrement(ref s_threadCount);
+            SpinWait.SpinUntil(() => {
+                return s_threadCount <= 0;
+            });
+        }
+
+        #region private functions
+        unsafe private static void QuickSortAsc_ITMT_noNaN( Int64* vec, int lo, int hi, int inc) {
+            int pivotIndex, i, j;
+            s_quickSortStackPos = -1;
+           
+            Int64 a1, a2, a3;
+           
+            Int64 temp, pivotItem;
+            for (; ; ) {
+                #region innerloop
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp <= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                        }
+                        *(vec + i + inc) = pivotItem;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--];
+                } else {
+                    #region quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo);
+                    a2 = *(vec + pivotIndex);
+                    a3 = *(vec + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 > a2) {
+                        if (a1 > a3) {
+                            if (a3 > a2) {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a2;
+                                *(vec + lo + inc) = a3;
+                            } else {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a3;
+                                *(vec + lo + inc) = a2;
+                            }
+                        } else {
+                            *(vec + lo) = a2;
+                            *(vec + lo + inc) = a1;
+                        }
+                    } else {
+                        if (a2 > a3) {
+                            *(vec + hi) = a2;
+                            if (a3 > a1) {
+                                *(vec + lo + inc) = a3;
+                            } else {
+                                *(vec + lo + inc) = a1;
+                                *(vec + lo) = a3;
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2;
+                        }
+                    }
+                    #endregion
+                   
+                    Int64* vecI = vec + lo + inc, vecJ = vec + hi;
+                    pivotItem = *vecI;
+                    for (; ; ) {
+                        do vecI += inc; while (*vecI < pivotItem);
+                        do vecJ -= inc; while (*vecJ > pivotItem);
+                        if (vecJ < vecI) break;
+                        temp = *vecI;
+                        *vecI = *vecJ;
+                        *vecJ = temp;
+                    }
+                    *(vec + lo + inc) = *vecJ;
+                    *vecJ = pivotItem;
+
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif
+                    #endregion
+                    i = (int)(vecI - vec);
+                    j = (int)(vecJ - vec);
+                    if (hi - i + inc < j - lo) {
+                        if (s_threadCount < 100
+                                && (j - lo) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = i;
+                            data.hi = hi;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortAsc_ITMT_noNaN(vec, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = hi;
+                            s_quickSortStackMT[++s_quickSortStackPos] = i;
+                        }
+                        hi = j - inc;
+                    } else {
+                        if (s_threadCount < 100
+                            && (hi - i + inc) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = lo;
+                            data.hi = j - inc;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                //Console.Out.WriteLine("Thread start: {0} ({1} - {2} Count:{3})", Thread.CurrentThread.ManagedThreadId, lo, hi, threadCount.ThreadCount);
+                                QuickSortAsc_ITMT_noNaN(vec, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = j - inc;
+                            s_quickSortStackMT[++s_quickSortStackPos] = lo;
+                        }
+                        lo = i;
+                    }
+                }
+                #endregion inner loop
+            }
+        }
+        unsafe private static void QuickSortDesc_ITMT_noNaN( Int64* vec, int lo, int hi, int inc) {
+            int pivotIndex, i, j;
+            s_quickSortStackPos = -1;
+           
+            Int64 a1, a2, a3;
+           
+            Int64 temp, pivotItem;
+            for (; ; ) {
+                #region innerloop
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp >= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                        }
+                        *(vec + i + inc) = pivotItem;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--];
+                } else {
+                    #region quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo);
+                    a2 = *(vec + pivotIndex);
+                    a3 = *(vec + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 < a2) {
+                        if (a1 < a3) {
+                            if (a3 < a2) {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a2;
+                                *(vec + lo + inc) = a3;
+                            } else {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a3;
+                                *(vec + lo + inc) = a2;
+                            }
+                        } else {
+                            *(vec + lo) = a2;
+                            *(vec + lo + inc) = a1;
+                        }
+                    } else {
+                        if (a2 < a3) {
+                            *(vec + hi) = a2;
+                            if (a3 < a1) {
+                                *(vec + lo + inc) = a3;
+                            } else {
+                                *(vec + lo + inc) = a1;
+                                *(vec + lo) = a3;
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2;
+                        }
+                    }
+                    #endregion
+                   
+                    Int64* vecI = vec + lo + inc, vecJ = vec + hi;
+                    pivotItem = *vecI;
+                    for (; ; ) {
+                        do vecI += inc; while (*vecI > pivotItem);
+                        do vecJ -= inc; while (*vecJ < pivotItem);
+                        if (vecJ < vecI) break;
+                        temp = *vecI;
+                        *vecI = *vecJ;
+                        *vecJ = temp;
+                    }
+                    *(vec + lo + inc) = *vecJ;
+                    *vecJ = pivotItem;
+
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif
+                    #endregion
+                    i = (int)(vecI - vec);
+                    j = (int)(vecJ - vec);
+                    if (hi - i + inc < j - lo) {
+                        if (s_threadCount < 100
+                                && (j - lo) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = i;
+                            data.hi = hi;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortDesc_ITMT_noNaN(vec, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = hi;
+                            s_quickSortStackMT[++s_quickSortStackPos] = i;
+                        }
+                        hi = j - inc;
+                    } else {
+                        if (s_threadCount < 100
+                            && (hi - i + inc) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = lo;
+                            data.hi = j - inc;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                //Console.Out.WriteLine("Thread start: {0} ({1} - {2} Count:{3})", Thread.CurrentThread.ManagedThreadId, lo, hi, threadCount.ThreadCount);
+                                QuickSortDesc_ITMT_noNaN(vec, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = j - inc;
+                            s_quickSortStackMT[++s_quickSortStackPos] = lo;
+                        }
+                        lo = i;
+                    }
+                }
+                #endregion inner loop
+            }
+        }
+        unsafe private static void QuickSortAscIDX_ITMT_noNaN( Int64* vec, double* vecIdx, int lo, int hi, int inc) {
+           
+            Int64 temp, pivotItem;
+            int pivotIndex, j, i;
+            s_quickSortStackPos = -1;
+           
+            Int64 a1, a2, a3;
+           
+            double ai1, ai2, ai3;
+            for (; ; ) {
+                #region inner loop
+                if (hi - lo < (ILNumerics.Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        ai1 = *(vecIdx + j);
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp <= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                            *(vecIdx + i + inc) = *(vecIdx + i);
+                        }
+                        *(vec + i + inc) = pivotItem;
+                        *(vecIdx + i + inc) = ai1;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--];
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo);
+                    a2 = *(vec + pivotIndex);
+                    a3 = *(vec + hi);
+                    ai1 = *(vecIdx + lo);
+                    ai2 = *(vecIdx + pivotIndex);
+                    ai3 = *(vecIdx + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    *(vecIdx + pivotIndex) = *(vecIdx + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 > a2) {
+                        if (a1 > a3) {
+                            if (a3 > a2) {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a2;
+                                *(vec + lo + inc) = a3;
+                                *(vecIdx + hi) = ai1;
+                                *(vecIdx + lo) = ai2;
+                                *(vecIdx + lo + inc) = ai3;
+                            } else {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a3;
+                                *(vec + lo + inc) = a2;
+                                *(vecIdx + hi) = ai1;
+                                *(vecIdx + lo) = ai3;
+                                *(vecIdx + lo + inc) = ai2;
+                            }
+                        } else {
+                            *(vec + lo) = a2;
+                            *(vec + lo + inc) = a1;
+                            *(vecIdx + lo) = ai2;
+                            *(vecIdx + lo + inc) = ai1;
+                        }
+                    } else {
+                        if (a2 > a3) {
+                            *(vec + hi) = a2;
+                            *(vecIdx + hi) = ai2;
+                            if (a3 > a1) {
+                                *(vec + lo + inc) = a3;
+                                *(vecIdx + lo + inc) = ai3;
+                            } else {
+                                *(vec + lo + inc) = a1;
+                                *(vec + lo) = a3;
+                                *(vecIdx + lo + inc) = ai1;
+                                *(vecIdx + lo) = ai3;
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2;
+                            *(vecIdx + lo + inc) = ai2;
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi;
+                    pivotItem = *(vec + lo + inc);
+                    ai1 = *(vecIdx + lo + inc);
+                    for (; ; ) {
+                        do i += inc; while (*(vec + i) < pivotItem);
+                        do j -= inc; while (*(vec + j) > pivotItem);
+                        if (j < i) break;
+                        temp = *(vec + i);
+                        ai2 = *(vecIdx + i);
+                        *(vec + i) = *(vec + j);
+                        *(vec + j) = temp;
+                        *(vecIdx + i) = *(vecIdx + j);
+                        *(vecIdx + j) = ai2;
+                    }
+                    *(vec + lo + inc) = *(vec + j);
+                    *(vec + j) = pivotItem;
+                    *(vecIdx + lo + inc) = *(vecIdx + j);
+                    *(vecIdx + j) = ai1;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif
+                    if (hi - i + inc < j - lo) {
+                        if (s_threadCount < 100
+                                && (j - lo) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = i;
+                            data.hi = hi;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortAscIDX_ITMT_noNaN(vec, vecIdx, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = hi;
+                            s_quickSortStackMT[++s_quickSortStackPos] = i;
+                        }
+                        hi = j - inc;
+                    } else {
+                        if (s_threadCount < 100
+                            && (hi - i + inc) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = lo;
+                            data.hi = j - inc;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortAscIDX_ITMT_noNaN(vec, vecIdx, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = j - inc;
+                            s_quickSortStackMT[++s_quickSortStackPos] = lo;
+                        }
+                        lo = i;
+                    }
+                }
+                #endregion
+            }
+        }
+        unsafe private static void QuickSortDescIDX_ITMT_noNaN( Int64* vec, double* vecIdx, int lo, int hi, int inc) {
+           
+            Int64 temp, pivotItem;
+            int pivotIndex, j, i;
+            s_quickSortStackPos = -1;
+           
+            Int64 a1, a2, a3;
+           
+            double ai1, ai2, ai3;
+            for (; ; ) {
+                #region inner loop
+                if (hi - lo < (ILNumerics.Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        ai1 = *(vecIdx + j);
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp >= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                            *(vecIdx + i + inc) = *(vecIdx + i);
+                        }
+                        *(vec + i + inc) = pivotItem;
+                        *(vecIdx + i + inc) = ai1;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--];
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo);
+                    a2 = *(vec + pivotIndex);
+                    a3 = *(vec + hi);
+                    ai1 = *(vecIdx + lo);
+                    ai2 = *(vecIdx + pivotIndex);
+                    ai3 = *(vecIdx + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    *(vecIdx + pivotIndex) = *(vecIdx + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 < a2) {
+                        if (a1 < a3) {
+                            if (a3 < a2) {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a2;
+                                *(vec + lo + inc) = a3;
+                                *(vecIdx + hi) = ai1;
+                                *(vecIdx + lo) = ai2;
+                                *(vecIdx + lo + inc) = ai3;
+                            } else {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a3;
+                                *(vec + lo + inc) = a2;
+                                *(vecIdx + hi) = ai1;
+                                *(vecIdx + lo) = ai3;
+                                *(vecIdx + lo + inc) = ai2;
+                            }
+                        } else {
+                            *(vec + lo) = a2;
+                            *(vec + lo + inc) = a1;
+                            *(vecIdx + lo) = ai2;
+                            *(vecIdx + lo + inc) = ai1;
+                        }
+                    } else {
+                        if (a2 < a3) {
+                            *(vec + hi) = a2;
+                            *(vecIdx + hi) = ai2;
+                            if (a3 < a1) {
+                                *(vec + lo + inc) = a3;
+                                *(vecIdx + lo + inc) = ai3;
+                            } else {
+                                *(vec + lo + inc) = a1;
+                                *(vec + lo) = a3;
+                                *(vecIdx + lo + inc) = ai1;
+                                *(vecIdx + lo) = ai3;
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2;
+                            *(vecIdx + lo + inc) = ai2;
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi;
+                    pivotItem = *(vec + lo + inc);
+                    ai1 = *(vecIdx + lo + inc);
+                    for (; ; ) {
+                        do i += inc; while (*(vec + i) > pivotItem);
+                        do j -= inc; while (*(vec + j) < pivotItem);
+                        if (j < i) break;
+                        temp = *(vec + i);
+                        ai2 = *(vecIdx + i);
+                        *(vec + i) = *(vec + j);
+                        *(vec + j) = temp;
+                        *(vecIdx + i) = *(vecIdx + j);
+                        *(vecIdx + j) = ai2;
+                    }
+                    *(vec + lo + inc) = *(vec + j);
+                    *(vec + j) = pivotItem;
+                    *(vecIdx + lo + inc) = *(vecIdx + j);
+                    *(vecIdx + j) = ai1;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif
+                    if (hi - i + inc < j - lo) {
+                        if (s_threadCount < 100
+                                && (j - lo) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = i;
+                            data.hi = hi;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortDescIDX_ITMT_noNaN(vec, vecIdx, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = hi;
+                            s_quickSortStackMT[++s_quickSortStackPos] = i;
+                        }
+                        hi = j - inc;
+                    } else {
+                        if (s_threadCount < 100
+                            && (hi - i + inc) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = lo;
+                            data.hi = j - inc;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortDescIDX_ITMT_noNaN(vec, vecIdx, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = j - inc;
+                            s_quickSortStackMT[++s_quickSortStackPos] = lo;
+                        }
+                        lo = i;
+                    }
+                }
+                #endregion
+            }
+        }
+        #endregion 
+        
+
+        /// <summary>
+        /// inline one dimensional quick sort, ascending, arbitrary element spacing, multithreaded
+        /// </summary>
+        /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+        /// <param name="lo">lowest index of sorting range</param>
+        /// <param name="hi">highest index of sorting range</param>
+        /// <param name="inc">spacing between elements (dimension specifier)</param>
+        /// <remarks>
+        /// <para>This function provides a low level in-place implementation of the quicksort algorithm. It is used by the 
+        /// higher level sorting API provided by <see cref="M:ILNumerics.ILMath.sort"/>. It is recommended to use the overloads 
+        /// of <see cref="M:ILNumerics.ILMath.sort()"/> instead of this function. That way, the decision, which lower level function
+        /// is to be called is made by the library automatically.</para>
+        /// <para>A quicksort algorithm is used for ranges of minimum lengths specified by 
+        /// <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/> and above. 
+        /// Below that length, a simple insertion sort is used instead.</para>
+        /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+        /// memory is needed to perform the sorting. That 'stack' memory defaults to length 100. The stack array
+        /// is cached internally.</para>
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>This function internally parallelizes the sorting in a very efficient manner. It usually outperforms 
+        /// non-parallelized versions of the quicksort algorithm for larger arrays. For smaller arrays, it may be more 
+        /// efficient, to use the non parallelized version instead: <see cref="M:ILNumerics.ILMath.QuickSortAsc(double[], int, int, int)"/></para></remarks>
+        public static void QuickSortAscMT( Int32[] vecP, int lo, int hi, int inc) {
+            System.Diagnostics.Debug.Assert(vecP != null && vecP.Length > hi);
+            System.Diagnostics.Debug.Assert(lo <= hi);
+            System.Diagnostics.Debug.Assert(lo >= 0);
+            if (vecP.Length < 2) return;
+            unsafe {
+                fixed ( Int32* vec = vecP) {
+                    
+                    s_threadCount = 1;
+                    QuickSortAsc_ITMT_noNaN(vec, lo, hi, inc);
+
+                } // fixed
+            } // unsafe 
+            Interlocked.Decrement(ref s_threadCount);
+            SpinWait.SpinUntil(() => {
+                return s_threadCount <= 0;
+            });
+        }
+
+        /// <summary>
+        /// inline one dimensional quick sort, descending, arbitrary element spacing, multithreaded
+        /// </summary>
+        /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+        /// <param name="lo">lowest index of sorting range</param>
+        /// <param name="hi">highest index of sorting range</param>
+        /// <param name="inc">spacing between elements (dimension specifier)</param>
+        /// <remarks>        
+        /// <para>This function provides a low level in-place implementation of the quicksort algorithm. It is used by the 
+        /// higher level sorting API provided by <see cref="M:ILNumerics.ILMath.sort"/>. It is recommended to use the overloads 
+        /// of <see cref="M:ILNumerics.ILMath.sort()"/> instead of this function. That way, the decision, which lower level function
+        /// is to be called is made by the library automatically.</para>
+        /// <para>A quicksort algorithm is used for ranges of minimum lengths specified by 
+        /// <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/> and above. 
+        /// Below that length, a simple insertion sort is used instead.</para>
+        /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+        /// memory is needed to perform the sorting. That 'stack' memory defaults to length 100.</para>
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>This function internally parallelizes the sorting in a very efficient manner. It usually outperforms 
+        /// non-parallelized versions of the quicksort algorithm for larger arrays. For smaller arrays, it may be more 
+        /// efficient, to use the non parallelized version instead: <see cref="M:ILNumerics.ILMath.QuickSortAsc(double[], int, int, int)"/></para></remarks>
+        public static void QuickSortDescMT( Int32[] vecP, int lo, int hi, int inc) {
+            System.Diagnostics.Debug.Assert(vecP != null && vecP.Length > hi);
+            System.Diagnostics.Debug.Assert(lo <= hi);
+            System.Diagnostics.Debug.Assert(lo >= 0);
+            if (vecP.Length < 2) return;
+            unsafe {
+                fixed ( Int32* vec = vecP) {
+                    
+                    s_threadCount = 1;
+                    QuickSortDesc_ITMT_noNaN(vec, lo, hi, inc);
+
+                } // fixed
+            } // unsafe 
+            Interlocked.Decrement(ref s_threadCount);
+            SpinWait.SpinUntil(() => {
+                return s_threadCount <= 0;
+            });
+        }
+        /// <summary>
+        /// inline one dimensional quick sort, ascending, arbitrary element spacing, indices aware
+        /// </summary>
+        /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+        /// <param name="lo">lowest index of sorting range</param>
+        /// <param name="hi">highest index of sorting range</param>
+        /// <param name="idxP">indices vector, content will in-place be sorted along with <paramref name="vecP"/></param>
+        /// <param name="inc">spacing between elements (dimension specifier)</param>
+        /// <remarks>
+        /// <para>This function provides a low level in-place implementation of the quicksort algorithm. It is used by the 
+        /// higher level sorting API provided by <see cref="M:ILNumerics.ILMath.sort"/>. It is recommended to use the overloads 
+        /// of <see cref="M:ILNumerics.ILMath.sort()"/> instead of this function. That way, the decision, which lower level function
+        /// is to be called is made by the library automatically.</para>
+        /// <para>A quicksort algorithm is used for ranges of minimum lengths specified by 
+        /// <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/> and above. 
+        /// Below that length, a simple insertion sort is used instead.</para>
+        /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+        /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+        /// The size is determined by the value of 
+        /// <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/>.</para>
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>This function internally parallelizes the sorting in a very efficient manner. It usually outperforms 
+        /// non-parallelized versions of the quicksort algorithm for larger arrays. For smaller arrays, it may be more 
+        /// efficient, to use the non parallelized version instead: <see cref="M:ILNumerics.ILMath.QuickSortAsc(double[], int, int, int)"/></para></remarks>
+        public static void QuickSortAscIDXMT( Int32[] vecP,  double[] idxP, int lo, int hi, int inc) {
+            System.Diagnostics.Debug.Assert(vecP != null && vecP.Length > hi);
+            System.Diagnostics.Debug.Assert(idxP != null && idxP.Length > hi);
+            System.Diagnostics.Debug.Assert(lo <= hi);
+            System.Diagnostics.Debug.Assert(lo >= 0);
+            if (vecP.Length < 2) return;
+            int[] stack = ILMemoryPool.Pool.New<int>(ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth * 2);
+            unsafe {
+                fixed ( double* vecIdx = idxP)
+                fixed ( Int32* vec = vecP) {
+                    
+                    s_threadCount = 1;
+                    QuickSortAscIDX_ITMT_noNaN(vec, vecIdx, lo, hi, inc);
+
+                } // fixed
+            } // unsafe 
+            Interlocked.Decrement(ref s_threadCount);
+            SpinWait.SpinUntil(() => {
+                return s_threadCount <= 0;
+            });
+        }
+
+        /// <summary>
+        /// inline one dimensional quick sort, descending, arbitrary element spacing, indices aware
+        /// </summary>
+        /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+        /// <param name="lo">lowest index of sorting range</param>
+        /// <param name="hi">highest index of sorting range</param>
+        /// <param name="idxP">indices vector, content will in-place be sorted along with <paramref name="vecP"/></param>
+        /// <param name="inc">spacing between elements (dimension specifier)</param>
+        /// <remarks>
+        /// <para>This function provides a low level in-place implementation of the quicksort algorithm. It is used by the 
+        /// higher level sorting API provided by <see cref="M:ILNumerics.ILMath.sort"/>. It is recommended to use the overloads 
+        /// of <see cref="M:ILNumerics.ILMath.sort()"/> instead of this function. That way, the decision, which lower level function
+        /// is to be called is made by the library automatically.</para>
+        /// <para>A quicksort algorithm is used for ranges of minimum lengths specified by 
+        /// <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/> and above. 
+        /// Below that length, a simple insertion sort is used instead.</para>
+        /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+        /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+        /// The size is determined by the value of 
+        /// <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/>.</para>
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>This function internally parallelizes the sorting in a very efficient manner. It usually outperforms 
+        /// non-parallelized versions of the quicksort algorithm for larger arrays. For smaller arrays, it may be more 
+        /// efficient, to use the non parallelized version instead: <see cref="M:ILNumerics.ILMath.QuickSortAsc(double[], int, int, int)"/></para></remarks>
+        public static void QuickSortDescIDXMT( Int32[] vecP,  double[] idxP, int lo, int hi, int inc) {
+            System.Diagnostics.Debug.Assert(vecP != null && vecP.Length > hi);
+            System.Diagnostics.Debug.Assert(idxP != null && idxP.Length > hi);
+            System.Diagnostics.Debug.Assert(lo <= hi);
+            System.Diagnostics.Debug.Assert(lo >= 0);
+           
+            if (vecP.Length < 2) return;
+            int[] stack = ILMemoryPool.Pool.New<int>(ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth * 2);
+            unsafe {
+                fixed ( double* vecIdx = idxP)
+                fixed ( Int32* vec = vecP) {
+                    
+                    Interlocked.Increment(ref s_threadCount);
+                    QuickSortDescIDX_ITMT_noNaN(vec, vecIdx, lo, hi, inc);
+                } // fixed
+            } // unsafe 
+            Interlocked.Decrement(ref s_threadCount);
+            SpinWait.SpinUntil(() => {
+                return s_threadCount <= 0;
+            });
+        }
+
+        #region private functions
+        unsafe private static void QuickSortAsc_ITMT_noNaN( Int32* vec, int lo, int hi, int inc) {
+            int pivotIndex, i, j;
+            s_quickSortStackPos = -1;
+           
+            Int32 a1, a2, a3;
+           
+            Int32 temp, pivotItem;
+            for (; ; ) {
+                #region innerloop
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp <= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                        }
+                        *(vec + i + inc) = pivotItem;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--];
+                } else {
+                    #region quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo);
+                    a2 = *(vec + pivotIndex);
+                    a3 = *(vec + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 > a2) {
+                        if (a1 > a3) {
+                            if (a3 > a2) {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a2;
+                                *(vec + lo + inc) = a3;
+                            } else {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a3;
+                                *(vec + lo + inc) = a2;
+                            }
+                        } else {
+                            *(vec + lo) = a2;
+                            *(vec + lo + inc) = a1;
+                        }
+                    } else {
+                        if (a2 > a3) {
+                            *(vec + hi) = a2;
+                            if (a3 > a1) {
+                                *(vec + lo + inc) = a3;
+                            } else {
+                                *(vec + lo + inc) = a1;
+                                *(vec + lo) = a3;
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2;
+                        }
+                    }
+                    #endregion
+                   
+                    Int32* vecI = vec + lo + inc, vecJ = vec + hi;
+                    pivotItem = *vecI;
+                    for (; ; ) {
+                        do vecI += inc; while (*vecI < pivotItem);
+                        do vecJ -= inc; while (*vecJ > pivotItem);
+                        if (vecJ < vecI) break;
+                        temp = *vecI;
+                        *vecI = *vecJ;
+                        *vecJ = temp;
+                    }
+                    *(vec + lo + inc) = *vecJ;
+                    *vecJ = pivotItem;
+
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif
+                    #endregion
+                    i = (int)(vecI - vec);
+                    j = (int)(vecJ - vec);
+                    if (hi - i + inc < j - lo) {
+                        if (s_threadCount < 100
+                                && (j - lo) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = i;
+                            data.hi = hi;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortAsc_ITMT_noNaN(vec, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = hi;
+                            s_quickSortStackMT[++s_quickSortStackPos] = i;
+                        }
+                        hi = j - inc;
+                    } else {
+                        if (s_threadCount < 100
+                            && (hi - i + inc) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = lo;
+                            data.hi = j - inc;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                //Console.Out.WriteLine("Thread start: {0} ({1} - {2} Count:{3})", Thread.CurrentThread.ManagedThreadId, lo, hi, threadCount.ThreadCount);
+                                QuickSortAsc_ITMT_noNaN(vec, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = j - inc;
+                            s_quickSortStackMT[++s_quickSortStackPos] = lo;
+                        }
+                        lo = i;
+                    }
+                }
+                #endregion inner loop
+            }
+        }
+        unsafe private static void QuickSortDesc_ITMT_noNaN( Int32* vec, int lo, int hi, int inc) {
+            int pivotIndex, i, j;
+            s_quickSortStackPos = -1;
+           
+            Int32 a1, a2, a3;
+           
+            Int32 temp, pivotItem;
+            for (; ; ) {
+                #region innerloop
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp >= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                        }
+                        *(vec + i + inc) = pivotItem;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--];
+                } else {
+                    #region quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo);
+                    a2 = *(vec + pivotIndex);
+                    a3 = *(vec + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 < a2) {
+                        if (a1 < a3) {
+                            if (a3 < a2) {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a2;
+                                *(vec + lo + inc) = a3;
+                            } else {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a3;
+                                *(vec + lo + inc) = a2;
+                            }
+                        } else {
+                            *(vec + lo) = a2;
+                            *(vec + lo + inc) = a1;
+                        }
+                    } else {
+                        if (a2 < a3) {
+                            *(vec + hi) = a2;
+                            if (a3 < a1) {
+                                *(vec + lo + inc) = a3;
+                            } else {
+                                *(vec + lo + inc) = a1;
+                                *(vec + lo) = a3;
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2;
+                        }
+                    }
+                    #endregion
+                   
+                    Int32* vecI = vec + lo + inc, vecJ = vec + hi;
+                    pivotItem = *vecI;
+                    for (; ; ) {
+                        do vecI += inc; while (*vecI > pivotItem);
+                        do vecJ -= inc; while (*vecJ < pivotItem);
+                        if (vecJ < vecI) break;
+                        temp = *vecI;
+                        *vecI = *vecJ;
+                        *vecJ = temp;
+                    }
+                    *(vec + lo + inc) = *vecJ;
+                    *vecJ = pivotItem;
+
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif
+                    #endregion
+                    i = (int)(vecI - vec);
+                    j = (int)(vecJ - vec);
+                    if (hi - i + inc < j - lo) {
+                        if (s_threadCount < 100
+                                && (j - lo) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = i;
+                            data.hi = hi;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortDesc_ITMT_noNaN(vec, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = hi;
+                            s_quickSortStackMT[++s_quickSortStackPos] = i;
+                        }
+                        hi = j - inc;
+                    } else {
+                        if (s_threadCount < 100
+                            && (hi - i + inc) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = lo;
+                            data.hi = j - inc;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                //Console.Out.WriteLine("Thread start: {0} ({1} - {2} Count:{3})", Thread.CurrentThread.ManagedThreadId, lo, hi, threadCount.ThreadCount);
+                                QuickSortDesc_ITMT_noNaN(vec, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = j - inc;
+                            s_quickSortStackMT[++s_quickSortStackPos] = lo;
+                        }
+                        lo = i;
+                    }
+                }
+                #endregion inner loop
+            }
+        }
+        unsafe private static void QuickSortAscIDX_ITMT_noNaN( Int32* vec, double* vecIdx, int lo, int hi, int inc) {
+           
+            Int32 temp, pivotItem;
+            int pivotIndex, j, i;
+            s_quickSortStackPos = -1;
+           
+            Int32 a1, a2, a3;
+           
+            double ai1, ai2, ai3;
+            for (; ; ) {
+                #region inner loop
+                if (hi - lo < (ILNumerics.Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        ai1 = *(vecIdx + j);
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp <= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                            *(vecIdx + i + inc) = *(vecIdx + i);
+                        }
+                        *(vec + i + inc) = pivotItem;
+                        *(vecIdx + i + inc) = ai1;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--];
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo);
+                    a2 = *(vec + pivotIndex);
+                    a3 = *(vec + hi);
+                    ai1 = *(vecIdx + lo);
+                    ai2 = *(vecIdx + pivotIndex);
+                    ai3 = *(vecIdx + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    *(vecIdx + pivotIndex) = *(vecIdx + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 > a2) {
+                        if (a1 > a3) {
+                            if (a3 > a2) {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a2;
+                                *(vec + lo + inc) = a3;
+                                *(vecIdx + hi) = ai1;
+                                *(vecIdx + lo) = ai2;
+                                *(vecIdx + lo + inc) = ai3;
+                            } else {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a3;
+                                *(vec + lo + inc) = a2;
+                                *(vecIdx + hi) = ai1;
+                                *(vecIdx + lo) = ai3;
+                                *(vecIdx + lo + inc) = ai2;
+                            }
+                        } else {
+                            *(vec + lo) = a2;
+                            *(vec + lo + inc) = a1;
+                            *(vecIdx + lo) = ai2;
+                            *(vecIdx + lo + inc) = ai1;
+                        }
+                    } else {
+                        if (a2 > a3) {
+                            *(vec + hi) = a2;
+                            *(vecIdx + hi) = ai2;
+                            if (a3 > a1) {
+                                *(vec + lo + inc) = a3;
+                                *(vecIdx + lo + inc) = ai3;
+                            } else {
+                                *(vec + lo + inc) = a1;
+                                *(vec + lo) = a3;
+                                *(vecIdx + lo + inc) = ai1;
+                                *(vecIdx + lo) = ai3;
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2;
+                            *(vecIdx + lo + inc) = ai2;
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi;
+                    pivotItem = *(vec + lo + inc);
+                    ai1 = *(vecIdx + lo + inc);
+                    for (; ; ) {
+                        do i += inc; while (*(vec + i) < pivotItem);
+                        do j -= inc; while (*(vec + j) > pivotItem);
+                        if (j < i) break;
+                        temp = *(vec + i);
+                        ai2 = *(vecIdx + i);
+                        *(vec + i) = *(vec + j);
+                        *(vec + j) = temp;
+                        *(vecIdx + i) = *(vecIdx + j);
+                        *(vecIdx + j) = ai2;
+                    }
+                    *(vec + lo + inc) = *(vec + j);
+                    *(vec + j) = pivotItem;
+                    *(vecIdx + lo + inc) = *(vecIdx + j);
+                    *(vecIdx + j) = ai1;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif
+                    if (hi - i + inc < j - lo) {
+                        if (s_threadCount < 100
+                                && (j - lo) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = i;
+                            data.hi = hi;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortAscIDX_ITMT_noNaN(vec, vecIdx, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = hi;
+                            s_quickSortStackMT[++s_quickSortStackPos] = i;
+                        }
+                        hi = j - inc;
+                    } else {
+                        if (s_threadCount < 100
+                            && (hi - i + inc) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = lo;
+                            data.hi = j - inc;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortAscIDX_ITMT_noNaN(vec, vecIdx, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = j - inc;
+                            s_quickSortStackMT[++s_quickSortStackPos] = lo;
+                        }
+                        lo = i;
+                    }
+                }
+                #endregion
+            }
+        }
+        unsafe private static void QuickSortDescIDX_ITMT_noNaN( Int32* vec, double* vecIdx, int lo, int hi, int inc) {
+           
+            Int32 temp, pivotItem;
+            int pivotIndex, j, i;
+            s_quickSortStackPos = -1;
+           
+            Int32 a1, a2, a3;
+           
+            double ai1, ai2, ai3;
+            for (; ; ) {
+                #region inner loop
+                if (hi - lo < (ILNumerics.Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        ai1 = *(vecIdx + j);
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp >= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                            *(vecIdx + i + inc) = *(vecIdx + i);
+                        }
+                        *(vec + i + inc) = pivotItem;
+                        *(vecIdx + i + inc) = ai1;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--];
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo);
+                    a2 = *(vec + pivotIndex);
+                    a3 = *(vec + hi);
+                    ai1 = *(vecIdx + lo);
+                    ai2 = *(vecIdx + pivotIndex);
+                    ai3 = *(vecIdx + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    *(vecIdx + pivotIndex) = *(vecIdx + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 < a2) {
+                        if (a1 < a3) {
+                            if (a3 < a2) {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a2;
+                                *(vec + lo + inc) = a3;
+                                *(vecIdx + hi) = ai1;
+                                *(vecIdx + lo) = ai2;
+                                *(vecIdx + lo + inc) = ai3;
+                            } else {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a3;
+                                *(vec + lo + inc) = a2;
+                                *(vecIdx + hi) = ai1;
+                                *(vecIdx + lo) = ai3;
+                                *(vecIdx + lo + inc) = ai2;
+                            }
+                        } else {
+                            *(vec + lo) = a2;
+                            *(vec + lo + inc) = a1;
+                            *(vecIdx + lo) = ai2;
+                            *(vecIdx + lo + inc) = ai1;
+                        }
+                    } else {
+                        if (a2 < a3) {
+                            *(vec + hi) = a2;
+                            *(vecIdx + hi) = ai2;
+                            if (a3 < a1) {
+                                *(vec + lo + inc) = a3;
+                                *(vecIdx + lo + inc) = ai3;
+                            } else {
+                                *(vec + lo + inc) = a1;
+                                *(vec + lo) = a3;
+                                *(vecIdx + lo + inc) = ai1;
+                                *(vecIdx + lo) = ai3;
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2;
+                            *(vecIdx + lo + inc) = ai2;
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi;
+                    pivotItem = *(vec + lo + inc);
+                    ai1 = *(vecIdx + lo + inc);
+                    for (; ; ) {
+                        do i += inc; while (*(vec + i) > pivotItem);
+                        do j -= inc; while (*(vec + j) < pivotItem);
+                        if (j < i) break;
+                        temp = *(vec + i);
+                        ai2 = *(vecIdx + i);
+                        *(vec + i) = *(vec + j);
+                        *(vec + j) = temp;
+                        *(vecIdx + i) = *(vecIdx + j);
+                        *(vecIdx + j) = ai2;
+                    }
+                    *(vec + lo + inc) = *(vec + j);
+                    *(vec + j) = pivotItem;
+                    *(vecIdx + lo + inc) = *(vecIdx + j);
+                    *(vecIdx + j) = ai1;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif
+                    if (hi - i + inc < j - lo) {
+                        if (s_threadCount < 100
+                                && (j - lo) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = i;
+                            data.hi = hi;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortDescIDX_ITMT_noNaN(vec, vecIdx, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = hi;
+                            s_quickSortStackMT[++s_quickSortStackPos] = i;
+                        }
+                        hi = j - inc;
+                    } else {
+                        if (s_threadCount < 100
+                            && (hi - i + inc) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = lo;
+                            data.hi = j - inc;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortDescIDX_ITMT_noNaN(vec, vecIdx, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = j - inc;
+                            s_quickSortStackMT[++s_quickSortStackPos] = lo;
+                        }
+                        lo = i;
+                    }
+                }
+                #endregion
+            }
+        }
+        #endregion 
+        
+
+        /// <summary>
+        /// inline one dimensional quick sort, ascending, arbitrary element spacing, multithreaded
+        /// </summary>
+        /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+        /// <param name="lo">lowest index of sorting range</param>
+        /// <param name="hi">highest index of sorting range</param>
+        /// <param name="inc">spacing between elements (dimension specifier)</param>
+        /// <remarks>
+        /// <para>This function provides a low level in-place implementation of the quicksort algorithm. It is used by the 
+        /// higher level sorting API provided by <see cref="M:ILNumerics.ILMath.sort"/>. It is recommended to use the overloads 
+        /// of <see cref="M:ILNumerics.ILMath.sort()"/> instead of this function. That way, the decision, which lower level function
+        /// is to be called is made by the library automatically.</para>
+        /// <para>A quicksort algorithm is used for ranges of minimum lengths specified by 
+        /// <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/> and above. 
+        /// Below that length, a simple insertion sort is used instead.</para>
+        /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+        /// memory is needed to perform the sorting. That 'stack' memory defaults to length 100. The stack array
+        /// is cached internally.</para>
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>This function internally parallelizes the sorting in a very efficient manner. It usually outperforms 
+        /// non-parallelized versions of the quicksort algorithm for larger arrays. For smaller arrays, it may be more 
+        /// efficient, to use the non parallelized version instead: <see cref="M:ILNumerics.ILMath.QuickSortAsc(double[], int, int, int)"/></para></remarks>
+        public static void QuickSortAscMT( Int16[] vecP, int lo, int hi, int inc) {
+            System.Diagnostics.Debug.Assert(vecP != null && vecP.Length > hi);
+            System.Diagnostics.Debug.Assert(lo <= hi);
+            System.Diagnostics.Debug.Assert(lo >= 0);
+            if (vecP.Length < 2) return;
+            unsafe {
+                fixed ( Int16* vec = vecP) {
+                    
+                    s_threadCount = 1;
+                    QuickSortAsc_ITMT_noNaN(vec, lo, hi, inc);
+
+                } // fixed
+            } // unsafe 
+            Interlocked.Decrement(ref s_threadCount);
+            SpinWait.SpinUntil(() => {
+                return s_threadCount <= 0;
+            });
+        }
+
+        /// <summary>
+        /// inline one dimensional quick sort, descending, arbitrary element spacing, multithreaded
+        /// </summary>
+        /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+        /// <param name="lo">lowest index of sorting range</param>
+        /// <param name="hi">highest index of sorting range</param>
+        /// <param name="inc">spacing between elements (dimension specifier)</param>
+        /// <remarks>        
+        /// <para>This function provides a low level in-place implementation of the quicksort algorithm. It is used by the 
+        /// higher level sorting API provided by <see cref="M:ILNumerics.ILMath.sort"/>. It is recommended to use the overloads 
+        /// of <see cref="M:ILNumerics.ILMath.sort()"/> instead of this function. That way, the decision, which lower level function
+        /// is to be called is made by the library automatically.</para>
+        /// <para>A quicksort algorithm is used for ranges of minimum lengths specified by 
+        /// <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/> and above. 
+        /// Below that length, a simple insertion sort is used instead.</para>
+        /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+        /// memory is needed to perform the sorting. That 'stack' memory defaults to length 100.</para>
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>This function internally parallelizes the sorting in a very efficient manner. It usually outperforms 
+        /// non-parallelized versions of the quicksort algorithm for larger arrays. For smaller arrays, it may be more 
+        /// efficient, to use the non parallelized version instead: <see cref="M:ILNumerics.ILMath.QuickSortAsc(double[], int, int, int)"/></para></remarks>
+        public static void QuickSortDescMT( Int16[] vecP, int lo, int hi, int inc) {
+            System.Diagnostics.Debug.Assert(vecP != null && vecP.Length > hi);
+            System.Diagnostics.Debug.Assert(lo <= hi);
+            System.Diagnostics.Debug.Assert(lo >= 0);
+            if (vecP.Length < 2) return;
+            unsafe {
+                fixed ( Int16* vec = vecP) {
+                    
+                    s_threadCount = 1;
+                    QuickSortDesc_ITMT_noNaN(vec, lo, hi, inc);
+
+                } // fixed
+            } // unsafe 
+            Interlocked.Decrement(ref s_threadCount);
+            SpinWait.SpinUntil(() => {
+                return s_threadCount <= 0;
+            });
+        }
+        /// <summary>
+        /// inline one dimensional quick sort, ascending, arbitrary element spacing, indices aware
+        /// </summary>
+        /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+        /// <param name="lo">lowest index of sorting range</param>
+        /// <param name="hi">highest index of sorting range</param>
+        /// <param name="idxP">indices vector, content will in-place be sorted along with <paramref name="vecP"/></param>
+        /// <param name="inc">spacing between elements (dimension specifier)</param>
+        /// <remarks>
+        /// <para>This function provides a low level in-place implementation of the quicksort algorithm. It is used by the 
+        /// higher level sorting API provided by <see cref="M:ILNumerics.ILMath.sort"/>. It is recommended to use the overloads 
+        /// of <see cref="M:ILNumerics.ILMath.sort()"/> instead of this function. That way, the decision, which lower level function
+        /// is to be called is made by the library automatically.</para>
+        /// <para>A quicksort algorithm is used for ranges of minimum lengths specified by 
+        /// <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/> and above. 
+        /// Below that length, a simple insertion sort is used instead.</para>
+        /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+        /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+        /// The size is determined by the value of 
+        /// <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/>.</para>
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>This function internally parallelizes the sorting in a very efficient manner. It usually outperforms 
+        /// non-parallelized versions of the quicksort algorithm for larger arrays. For smaller arrays, it may be more 
+        /// efficient, to use the non parallelized version instead: <see cref="M:ILNumerics.ILMath.QuickSortAsc(double[], int, int, int)"/></para></remarks>
+        public static void QuickSortAscIDXMT( Int16[] vecP,  double[] idxP, int lo, int hi, int inc) {
+            System.Diagnostics.Debug.Assert(vecP != null && vecP.Length > hi);
+            System.Diagnostics.Debug.Assert(idxP != null && idxP.Length > hi);
+            System.Diagnostics.Debug.Assert(lo <= hi);
+            System.Diagnostics.Debug.Assert(lo >= 0);
+            if (vecP.Length < 2) return;
+            int[] stack = ILMemoryPool.Pool.New<int>(ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth * 2);
+            unsafe {
+                fixed ( double* vecIdx = idxP)
+                fixed ( Int16* vec = vecP) {
+                    
+                    s_threadCount = 1;
+                    QuickSortAscIDX_ITMT_noNaN(vec, vecIdx, lo, hi, inc);
+
+                } // fixed
+            } // unsafe 
+            Interlocked.Decrement(ref s_threadCount);
+            SpinWait.SpinUntil(() => {
+                return s_threadCount <= 0;
+            });
+        }
+
+        /// <summary>
+        /// inline one dimensional quick sort, descending, arbitrary element spacing, indices aware
+        /// </summary>
+        /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+        /// <param name="lo">lowest index of sorting range</param>
+        /// <param name="hi">highest index of sorting range</param>
+        /// <param name="idxP">indices vector, content will in-place be sorted along with <paramref name="vecP"/></param>
+        /// <param name="inc">spacing between elements (dimension specifier)</param>
+        /// <remarks>
+        /// <para>This function provides a low level in-place implementation of the quicksort algorithm. It is used by the 
+        /// higher level sorting API provided by <see cref="M:ILNumerics.ILMath.sort"/>. It is recommended to use the overloads 
+        /// of <see cref="M:ILNumerics.ILMath.sort()"/> instead of this function. That way, the decision, which lower level function
+        /// is to be called is made by the library automatically.</para>
+        /// <para>A quicksort algorithm is used for ranges of minimum lengths specified by 
+        /// <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/> and above. 
+        /// Below that length, a simple insertion sort is used instead.</para>
+        /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+        /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+        /// The size is determined by the value of 
+        /// <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/>.</para>
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>This function internally parallelizes the sorting in a very efficient manner. It usually outperforms 
+        /// non-parallelized versions of the quicksort algorithm for larger arrays. For smaller arrays, it may be more 
+        /// efficient, to use the non parallelized version instead: <see cref="M:ILNumerics.ILMath.QuickSortAsc(double[], int, int, int)"/></para></remarks>
+        public static void QuickSortDescIDXMT( Int16[] vecP,  double[] idxP, int lo, int hi, int inc) {
+            System.Diagnostics.Debug.Assert(vecP != null && vecP.Length > hi);
+            System.Diagnostics.Debug.Assert(idxP != null && idxP.Length > hi);
+            System.Diagnostics.Debug.Assert(lo <= hi);
+            System.Diagnostics.Debug.Assert(lo >= 0);
+           
+            if (vecP.Length < 2) return;
+            int[] stack = ILMemoryPool.Pool.New<int>(ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth * 2);
+            unsafe {
+                fixed ( double* vecIdx = idxP)
+                fixed ( Int16* vec = vecP) {
+                    
+                    Interlocked.Increment(ref s_threadCount);
+                    QuickSortDescIDX_ITMT_noNaN(vec, vecIdx, lo, hi, inc);
+                } // fixed
+            } // unsafe 
+            Interlocked.Decrement(ref s_threadCount);
+            SpinWait.SpinUntil(() => {
+                return s_threadCount <= 0;
+            });
+        }
+
+        #region private functions
+        unsafe private static void QuickSortAsc_ITMT_noNaN( Int16* vec, int lo, int hi, int inc) {
+            int pivotIndex, i, j;
+            s_quickSortStackPos = -1;
+           
+            Int16 a1, a2, a3;
+           
+            Int16 temp, pivotItem;
+            for (; ; ) {
+                #region innerloop
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp <= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                        }
+                        *(vec + i + inc) = pivotItem;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--];
+                } else {
+                    #region quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo);
+                    a2 = *(vec + pivotIndex);
+                    a3 = *(vec + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 > a2) {
+                        if (a1 > a3) {
+                            if (a3 > a2) {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a2;
+                                *(vec + lo + inc) = a3;
+                            } else {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a3;
+                                *(vec + lo + inc) = a2;
+                            }
+                        } else {
+                            *(vec + lo) = a2;
+                            *(vec + lo + inc) = a1;
+                        }
+                    } else {
+                        if (a2 > a3) {
+                            *(vec + hi) = a2;
+                            if (a3 > a1) {
+                                *(vec + lo + inc) = a3;
+                            } else {
+                                *(vec + lo + inc) = a1;
+                                *(vec + lo) = a3;
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2;
+                        }
+                    }
+                    #endregion
+                   
+                    Int16* vecI = vec + lo + inc, vecJ = vec + hi;
+                    pivotItem = *vecI;
+                    for (; ; ) {
+                        do vecI += inc; while (*vecI < pivotItem);
+                        do vecJ -= inc; while (*vecJ > pivotItem);
+                        if (vecJ < vecI) break;
+                        temp = *vecI;
+                        *vecI = *vecJ;
+                        *vecJ = temp;
+                    }
+                    *(vec + lo + inc) = *vecJ;
+                    *vecJ = pivotItem;
+
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif
+                    #endregion
+                    i = (int)(vecI - vec);
+                    j = (int)(vecJ - vec);
+                    if (hi - i + inc < j - lo) {
+                        if (s_threadCount < 100
+                                && (j - lo) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = i;
+                            data.hi = hi;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortAsc_ITMT_noNaN(vec, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = hi;
+                            s_quickSortStackMT[++s_quickSortStackPos] = i;
+                        }
+                        hi = j - inc;
+                    } else {
+                        if (s_threadCount < 100
+                            && (hi - i + inc) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = lo;
+                            data.hi = j - inc;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                //Console.Out.WriteLine("Thread start: {0} ({1} - {2} Count:{3})", Thread.CurrentThread.ManagedThreadId, lo, hi, threadCount.ThreadCount);
+                                QuickSortAsc_ITMT_noNaN(vec, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = j - inc;
+                            s_quickSortStackMT[++s_quickSortStackPos] = lo;
+                        }
+                        lo = i;
+                    }
+                }
+                #endregion inner loop
+            }
+        }
+        unsafe private static void QuickSortDesc_ITMT_noNaN( Int16* vec, int lo, int hi, int inc) {
+            int pivotIndex, i, j;
+            s_quickSortStackPos = -1;
+           
+            Int16 a1, a2, a3;
+           
+            Int16 temp, pivotItem;
+            for (; ; ) {
+                #region innerloop
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp >= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                        }
+                        *(vec + i + inc) = pivotItem;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--];
+                } else {
+                    #region quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo);
+                    a2 = *(vec + pivotIndex);
+                    a3 = *(vec + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 < a2) {
+                        if (a1 < a3) {
+                            if (a3 < a2) {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a2;
+                                *(vec + lo + inc) = a3;
+                            } else {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a3;
+                                *(vec + lo + inc) = a2;
+                            }
+                        } else {
+                            *(vec + lo) = a2;
+                            *(vec + lo + inc) = a1;
+                        }
+                    } else {
+                        if (a2 < a3) {
+                            *(vec + hi) = a2;
+                            if (a3 < a1) {
+                                *(vec + lo + inc) = a3;
+                            } else {
+                                *(vec + lo + inc) = a1;
+                                *(vec + lo) = a3;
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2;
+                        }
+                    }
+                    #endregion
+                   
+                    Int16* vecI = vec + lo + inc, vecJ = vec + hi;
+                    pivotItem = *vecI;
+                    for (; ; ) {
+                        do vecI += inc; while (*vecI > pivotItem);
+                        do vecJ -= inc; while (*vecJ < pivotItem);
+                        if (vecJ < vecI) break;
+                        temp = *vecI;
+                        *vecI = *vecJ;
+                        *vecJ = temp;
+                    }
+                    *(vec + lo + inc) = *vecJ;
+                    *vecJ = pivotItem;
+
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif
+                    #endregion
+                    i = (int)(vecI - vec);
+                    j = (int)(vecJ - vec);
+                    if (hi - i + inc < j - lo) {
+                        if (s_threadCount < 100
+                                && (j - lo) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = i;
+                            data.hi = hi;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortDesc_ITMT_noNaN(vec, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = hi;
+                            s_quickSortStackMT[++s_quickSortStackPos] = i;
+                        }
+                        hi = j - inc;
+                    } else {
+                        if (s_threadCount < 100
+                            && (hi - i + inc) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = lo;
+                            data.hi = j - inc;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                //Console.Out.WriteLine("Thread start: {0} ({1} - {2} Count:{3})", Thread.CurrentThread.ManagedThreadId, lo, hi, threadCount.ThreadCount);
+                                QuickSortDesc_ITMT_noNaN(vec, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = j - inc;
+                            s_quickSortStackMT[++s_quickSortStackPos] = lo;
+                        }
+                        lo = i;
+                    }
+                }
+                #endregion inner loop
+            }
+        }
+        unsafe private static void QuickSortAscIDX_ITMT_noNaN( Int16* vec, double* vecIdx, int lo, int hi, int inc) {
+           
+            Int16 temp, pivotItem;
+            int pivotIndex, j, i;
+            s_quickSortStackPos = -1;
+           
+            Int16 a1, a2, a3;
+           
+            double ai1, ai2, ai3;
+            for (; ; ) {
+                #region inner loop
+                if (hi - lo < (ILNumerics.Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        ai1 = *(vecIdx + j);
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp <= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                            *(vecIdx + i + inc) = *(vecIdx + i);
+                        }
+                        *(vec + i + inc) = pivotItem;
+                        *(vecIdx + i + inc) = ai1;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--];
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo);
+                    a2 = *(vec + pivotIndex);
+                    a3 = *(vec + hi);
+                    ai1 = *(vecIdx + lo);
+                    ai2 = *(vecIdx + pivotIndex);
+                    ai3 = *(vecIdx + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    *(vecIdx + pivotIndex) = *(vecIdx + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 > a2) {
+                        if (a1 > a3) {
+                            if (a3 > a2) {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a2;
+                                *(vec + lo + inc) = a3;
+                                *(vecIdx + hi) = ai1;
+                                *(vecIdx + lo) = ai2;
+                                *(vecIdx + lo + inc) = ai3;
+                            } else {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a3;
+                                *(vec + lo + inc) = a2;
+                                *(vecIdx + hi) = ai1;
+                                *(vecIdx + lo) = ai3;
+                                *(vecIdx + lo + inc) = ai2;
+                            }
+                        } else {
+                            *(vec + lo) = a2;
+                            *(vec + lo + inc) = a1;
+                            *(vecIdx + lo) = ai2;
+                            *(vecIdx + lo + inc) = ai1;
+                        }
+                    } else {
+                        if (a2 > a3) {
+                            *(vec + hi) = a2;
+                            *(vecIdx + hi) = ai2;
+                            if (a3 > a1) {
+                                *(vec + lo + inc) = a3;
+                                *(vecIdx + lo + inc) = ai3;
+                            } else {
+                                *(vec + lo + inc) = a1;
+                                *(vec + lo) = a3;
+                                *(vecIdx + lo + inc) = ai1;
+                                *(vecIdx + lo) = ai3;
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2;
+                            *(vecIdx + lo + inc) = ai2;
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi;
+                    pivotItem = *(vec + lo + inc);
+                    ai1 = *(vecIdx + lo + inc);
+                    for (; ; ) {
+                        do i += inc; while (*(vec + i) < pivotItem);
+                        do j -= inc; while (*(vec + j) > pivotItem);
+                        if (j < i) break;
+                        temp = *(vec + i);
+                        ai2 = *(vecIdx + i);
+                        *(vec + i) = *(vec + j);
+                        *(vec + j) = temp;
+                        *(vecIdx + i) = *(vecIdx + j);
+                        *(vecIdx + j) = ai2;
+                    }
+                    *(vec + lo + inc) = *(vec + j);
+                    *(vec + j) = pivotItem;
+                    *(vecIdx + lo + inc) = *(vecIdx + j);
+                    *(vecIdx + j) = ai1;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif
+                    if (hi - i + inc < j - lo) {
+                        if (s_threadCount < 100
+                                && (j - lo) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = i;
+                            data.hi = hi;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortAscIDX_ITMT_noNaN(vec, vecIdx, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = hi;
+                            s_quickSortStackMT[++s_quickSortStackPos] = i;
+                        }
+                        hi = j - inc;
+                    } else {
+                        if (s_threadCount < 100
+                            && (hi - i + inc) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = lo;
+                            data.hi = j - inc;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortAscIDX_ITMT_noNaN(vec, vecIdx, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = j - inc;
+                            s_quickSortStackMT[++s_quickSortStackPos] = lo;
+                        }
+                        lo = i;
+                    }
+                }
+                #endregion
+            }
+        }
+        unsafe private static void QuickSortDescIDX_ITMT_noNaN( Int16* vec, double* vecIdx, int lo, int hi, int inc) {
+           
+            Int16 temp, pivotItem;
+            int pivotIndex, j, i;
+            s_quickSortStackPos = -1;
+           
+            Int16 a1, a2, a3;
+           
+            double ai1, ai2, ai3;
+            for (; ; ) {
+                #region inner loop
+                if (hi - lo < (ILNumerics.Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        ai1 = *(vecIdx + j);
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp >= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                            *(vecIdx + i + inc) = *(vecIdx + i);
+                        }
+                        *(vec + i + inc) = pivotItem;
+                        *(vecIdx + i + inc) = ai1;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--];
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo);
+                    a2 = *(vec + pivotIndex);
+                    a3 = *(vec + hi);
+                    ai1 = *(vecIdx + lo);
+                    ai2 = *(vecIdx + pivotIndex);
+                    ai3 = *(vecIdx + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    *(vecIdx + pivotIndex) = *(vecIdx + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 < a2) {
+                        if (a1 < a3) {
+                            if (a3 < a2) {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a2;
+                                *(vec + lo + inc) = a3;
+                                *(vecIdx + hi) = ai1;
+                                *(vecIdx + lo) = ai2;
+                                *(vecIdx + lo + inc) = ai3;
+                            } else {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a3;
+                                *(vec + lo + inc) = a2;
+                                *(vecIdx + hi) = ai1;
+                                *(vecIdx + lo) = ai3;
+                                *(vecIdx + lo + inc) = ai2;
+                            }
+                        } else {
+                            *(vec + lo) = a2;
+                            *(vec + lo + inc) = a1;
+                            *(vecIdx + lo) = ai2;
+                            *(vecIdx + lo + inc) = ai1;
+                        }
+                    } else {
+                        if (a2 < a3) {
+                            *(vec + hi) = a2;
+                            *(vecIdx + hi) = ai2;
+                            if (a3 < a1) {
+                                *(vec + lo + inc) = a3;
+                                *(vecIdx + lo + inc) = ai3;
+                            } else {
+                                *(vec + lo + inc) = a1;
+                                *(vec + lo) = a3;
+                                *(vecIdx + lo + inc) = ai1;
+                                *(vecIdx + lo) = ai3;
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2;
+                            *(vecIdx + lo + inc) = ai2;
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi;
+                    pivotItem = *(vec + lo + inc);
+                    ai1 = *(vecIdx + lo + inc);
+                    for (; ; ) {
+                        do i += inc; while (*(vec + i) > pivotItem);
+                        do j -= inc; while (*(vec + j) < pivotItem);
+                        if (j < i) break;
+                        temp = *(vec + i);
+                        ai2 = *(vecIdx + i);
+                        *(vec + i) = *(vec + j);
+                        *(vec + j) = temp;
+                        *(vecIdx + i) = *(vecIdx + j);
+                        *(vecIdx + j) = ai2;
+                    }
+                    *(vec + lo + inc) = *(vec + j);
+                    *(vec + j) = pivotItem;
+                    *(vecIdx + lo + inc) = *(vecIdx + j);
+                    *(vecIdx + j) = ai1;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif
+                    if (hi - i + inc < j - lo) {
+                        if (s_threadCount < 100
+                                && (j - lo) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = i;
+                            data.hi = hi;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortDescIDX_ITMT_noNaN(vec, vecIdx, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = hi;
+                            s_quickSortStackMT[++s_quickSortStackPos] = i;
+                        }
+                        hi = j - inc;
+                    } else {
+                        if (s_threadCount < 100
+                            && (hi - i + inc) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = lo;
+                            data.hi = j - inc;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortDescIDX_ITMT_noNaN(vec, vecIdx, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = j - inc;
+                            s_quickSortStackMT[++s_quickSortStackPos] = lo;
+                        }
+                        lo = i;
+                    }
+                }
+                #endregion
+            }
+        }
+        #endregion 
+        
+
+        /// <summary>
+        /// inline one dimensional quick sort, ascending, arbitrary element spacing, multithreaded
+        /// </summary>
+        /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+        /// <param name="lo">lowest index of sorting range</param>
+        /// <param name="hi">highest index of sorting range</param>
+        /// <param name="inc">spacing between elements (dimension specifier)</param>
+        /// <remarks>
+        /// <para>This function provides a low level in-place implementation of the quicksort algorithm. It is used by the 
+        /// higher level sorting API provided by <see cref="M:ILNumerics.ILMath.sort"/>. It is recommended to use the overloads 
+        /// of <see cref="M:ILNumerics.ILMath.sort()"/> instead of this function. That way, the decision, which lower level function
+        /// is to be called is made by the library automatically.</para>
+        /// <para>A quicksort algorithm is used for ranges of minimum lengths specified by 
+        /// <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/> and above. 
+        /// Below that length, a simple insertion sort is used instead.</para>
+        /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+        /// memory is needed to perform the sorting. That 'stack' memory defaults to length 100. The stack array
+        /// is cached internally.</para>
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>This function internally parallelizes the sorting in a very efficient manner. It usually outperforms 
+        /// non-parallelized versions of the quicksort algorithm for larger arrays. For smaller arrays, it may be more 
+        /// efficient, to use the non parallelized version instead: <see cref="M:ILNumerics.ILMath.QuickSortAsc(double[], int, int, int)"/></para></remarks>
+        public static void QuickSortAscMT( float[] vecP, int lo, int hi, int inc) {
+            System.Diagnostics.Debug.Assert(vecP != null && vecP.Length > hi);
+            System.Diagnostics.Debug.Assert(lo <= hi);
+            System.Diagnostics.Debug.Assert(lo >= 0);
+            if (vecP.Length < 2) return;
+            unsafe {
+                fixed ( float* vec = vecP) {
+                    if (checkNaNAsc(lo,ref hi, inc, vec)) return;
+                    s_threadCount = 1;
+                    QuickSortAsc_ITMT_noNaN(vec, lo, hi, inc);
+
+                } // fixed
+            } // unsafe 
+            Interlocked.Decrement(ref s_threadCount);
+            SpinWait.SpinUntil(() => {
+                return s_threadCount <= 0;
+            });
+        }
+
+        /// <summary>
+        /// inline one dimensional quick sort, descending, arbitrary element spacing, multithreaded
+        /// </summary>
+        /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+        /// <param name="lo">lowest index of sorting range</param>
+        /// <param name="hi">highest index of sorting range</param>
+        /// <param name="inc">spacing between elements (dimension specifier)</param>
+        /// <remarks>        
+        /// <para>This function provides a low level in-place implementation of the quicksort algorithm. It is used by the 
+        /// higher level sorting API provided by <see cref="M:ILNumerics.ILMath.sort"/>. It is recommended to use the overloads 
+        /// of <see cref="M:ILNumerics.ILMath.sort()"/> instead of this function. That way, the decision, which lower level function
+        /// is to be called is made by the library automatically.</para>
+        /// <para>A quicksort algorithm is used for ranges of minimum lengths specified by 
+        /// <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/> and above. 
+        /// Below that length, a simple insertion sort is used instead.</para>
+        /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+        /// memory is needed to perform the sorting. That 'stack' memory defaults to length 100.</para>
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>This function internally parallelizes the sorting in a very efficient manner. It usually outperforms 
+        /// non-parallelized versions of the quicksort algorithm for larger arrays. For smaller arrays, it may be more 
+        /// efficient, to use the non parallelized version instead: <see cref="M:ILNumerics.ILMath.QuickSortAsc(double[], int, int, int)"/></para></remarks>
+        public static void QuickSortDescMT( float[] vecP, int lo, int hi, int inc) {
+            System.Diagnostics.Debug.Assert(vecP != null && vecP.Length > hi);
+            System.Diagnostics.Debug.Assert(lo <= hi);
+            System.Diagnostics.Debug.Assert(lo >= 0);
+            if (vecP.Length < 2) return;
+            unsafe {
+                fixed ( float* vec = vecP) {
+                    if (checkNaNDesc(lo,ref hi, inc, vec)) return;
+                    s_threadCount = 1;
+                    QuickSortDesc_ITMT_noNaN(vec, lo, hi, inc);
+
+                } // fixed
+            } // unsafe 
+            Interlocked.Decrement(ref s_threadCount);
+            SpinWait.SpinUntil(() => {
+                return s_threadCount <= 0;
+            });
+        }
+        /// <summary>
+        /// inline one dimensional quick sort, ascending, arbitrary element spacing, indices aware
+        /// </summary>
+        /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+        /// <param name="lo">lowest index of sorting range</param>
+        /// <param name="hi">highest index of sorting range</param>
+        /// <param name="idxP">indices vector, content will in-place be sorted along with <paramref name="vecP"/></param>
+        /// <param name="inc">spacing between elements (dimension specifier)</param>
+        /// <remarks>
+        /// <para>This function provides a low level in-place implementation of the quicksort algorithm. It is used by the 
+        /// higher level sorting API provided by <see cref="M:ILNumerics.ILMath.sort"/>. It is recommended to use the overloads 
+        /// of <see cref="M:ILNumerics.ILMath.sort()"/> instead of this function. That way, the decision, which lower level function
+        /// is to be called is made by the library automatically.</para>
+        /// <para>A quicksort algorithm is used for ranges of minimum lengths specified by 
+        /// <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/> and above. 
+        /// Below that length, a simple insertion sort is used instead.</para>
+        /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+        /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+        /// The size is determined by the value of 
+        /// <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/>.</para>
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>This function internally parallelizes the sorting in a very efficient manner. It usually outperforms 
+        /// non-parallelized versions of the quicksort algorithm for larger arrays. For smaller arrays, it may be more 
+        /// efficient, to use the non parallelized version instead: <see cref="M:ILNumerics.ILMath.QuickSortAsc(double[], int, int, int)"/></para></remarks>
+        public static void QuickSortAscIDXMT( float[] vecP,  double[] idxP, int lo, int hi, int inc) {
+            System.Diagnostics.Debug.Assert(vecP != null && vecP.Length > hi);
+            System.Diagnostics.Debug.Assert(idxP != null && idxP.Length > hi);
+            System.Diagnostics.Debug.Assert(lo <= hi);
+            System.Diagnostics.Debug.Assert(lo >= 0);
+            if (vecP.Length < 2) return;
+            int[] stack = ILMemoryPool.Pool.New<int>(ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth * 2);
+            unsafe {
+                fixed ( double* vecIdx = idxP)
+                fixed ( float* vec = vecP) {
+                    if (checkNaNIDXAsc(lo,ref hi, inc, vecIdx, vec)) return;
+                    s_threadCount = 1;
+                    QuickSortAscIDX_ITMT_noNaN(vec, vecIdx, lo, hi, inc);
+
+                } // fixed
+            } // unsafe 
+            Interlocked.Decrement(ref s_threadCount);
+            SpinWait.SpinUntil(() => {
+                return s_threadCount <= 0;
+            });
+        }
+
+        /// <summary>
+        /// inline one dimensional quick sort, descending, arbitrary element spacing, indices aware
+        /// </summary>
+        /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+        /// <param name="lo">lowest index of sorting range</param>
+        /// <param name="hi">highest index of sorting range</param>
+        /// <param name="idxP">indices vector, content will in-place be sorted along with <paramref name="vecP"/></param>
+        /// <param name="inc">spacing between elements (dimension specifier)</param>
+        /// <remarks>
+        /// <para>This function provides a low level in-place implementation of the quicksort algorithm. It is used by the 
+        /// higher level sorting API provided by <see cref="M:ILNumerics.ILMath.sort"/>. It is recommended to use the overloads 
+        /// of <see cref="M:ILNumerics.ILMath.sort()"/> instead of this function. That way, the decision, which lower level function
+        /// is to be called is made by the library automatically.</para>
+        /// <para>A quicksort algorithm is used for ranges of minimum lengths specified by 
+        /// <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/> and above. 
+        /// Below that length, a simple insertion sort is used instead.</para>
+        /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+        /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+        /// The size is determined by the value of 
+        /// <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/>.</para>
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>This function internally parallelizes the sorting in a very efficient manner. It usually outperforms 
+        /// non-parallelized versions of the quicksort algorithm for larger arrays. For smaller arrays, it may be more 
+        /// efficient, to use the non parallelized version instead: <see cref="M:ILNumerics.ILMath.QuickSortAsc(double[], int, int, int)"/></para></remarks>
+        public static void QuickSortDescIDXMT( float[] vecP,  double[] idxP, int lo, int hi, int inc) {
+            System.Diagnostics.Debug.Assert(vecP != null && vecP.Length > hi);
+            System.Diagnostics.Debug.Assert(idxP != null && idxP.Length > hi);
+            System.Diagnostics.Debug.Assert(lo <= hi);
+            System.Diagnostics.Debug.Assert(lo >= 0);
+           
+            if (vecP.Length < 2) return;
+            int[] stack = ILMemoryPool.Pool.New<int>(ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth * 2);
+            unsafe {
+                fixed ( double* vecIdx = idxP)
+                fixed ( float* vec = vecP) {
+                    if (checkNaNIDXDesc(lo,ref hi, inc, vecIdx, vec)) return;
+                    Interlocked.Increment(ref s_threadCount);
+                    QuickSortDescIDX_ITMT_noNaN(vec, vecIdx, lo, hi, inc);
+                } // fixed
+            } // unsafe 
+            Interlocked.Decrement(ref s_threadCount);
+            SpinWait.SpinUntil(() => {
+                return s_threadCount <= 0;
+            });
+        }
+
+        #region private functions
+        unsafe private static void QuickSortAsc_ITMT_noNaN( float* vec, int lo, int hi, int inc) {
+            int pivotIndex, i, j;
+            s_quickSortStackPos = -1;
+           
+            float a1, a2, a3;
+           
+            float temp, pivotItem;
+            for (; ; ) {
+                #region innerloop
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp <= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                        }
+                        *(vec + i + inc) = pivotItem;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--];
+                } else {
+                    #region quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo);
+                    a2 = *(vec + pivotIndex);
+                    a3 = *(vec + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 > a2) {
+                        if (a1 > a3) {
+                            if (a3 > a2) {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a2;
+                                *(vec + lo + inc) = a3;
+                            } else {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a3;
+                                *(vec + lo + inc) = a2;
+                            }
+                        } else {
+                            *(vec + lo) = a2;
+                            *(vec + lo + inc) = a1;
+                        }
+                    } else {
+                        if (a2 > a3) {
+                            *(vec + hi) = a2;
+                            if (a3 > a1) {
+                                *(vec + lo + inc) = a3;
+                            } else {
+                                *(vec + lo + inc) = a1;
+                                *(vec + lo) = a3;
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2;
+                        }
+                    }
+                    #endregion
+                   
+                    float* vecI = vec + lo + inc, vecJ = vec + hi;
+                    pivotItem = *vecI;
+                    for (; ; ) {
+                        do vecI += inc; while (*vecI < pivotItem);
+                        do vecJ -= inc; while (*vecJ > pivotItem);
+                        if (vecJ < vecI) break;
+                        temp = *vecI;
+                        *vecI = *vecJ;
+                        *vecJ = temp;
+                    }
+                    *(vec + lo + inc) = *vecJ;
+                    *vecJ = pivotItem;
+
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif
+                    #endregion
+                    i = (int)(vecI - vec);
+                    j = (int)(vecJ - vec);
+                    if (hi - i + inc < j - lo) {
+                        if (s_threadCount < 100
+                                && (j - lo) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = i;
+                            data.hi = hi;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortAsc_ITMT_noNaN(vec, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = hi;
+                            s_quickSortStackMT[++s_quickSortStackPos] = i;
+                        }
+                        hi = j - inc;
+                    } else {
+                        if (s_threadCount < 100
+                            && (hi - i + inc) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = lo;
+                            data.hi = j - inc;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                //Console.Out.WriteLine("Thread start: {0} ({1} - {2} Count:{3})", Thread.CurrentThread.ManagedThreadId, lo, hi, threadCount.ThreadCount);
+                                QuickSortAsc_ITMT_noNaN(vec, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = j - inc;
+                            s_quickSortStackMT[++s_quickSortStackPos] = lo;
+                        }
+                        lo = i;
+                    }
+                }
+                #endregion inner loop
+            }
+        }
+        unsafe private static void QuickSortDesc_ITMT_noNaN( float* vec, int lo, int hi, int inc) {
+            int pivotIndex, i, j;
+            s_quickSortStackPos = -1;
+           
+            float a1, a2, a3;
+           
+            float temp, pivotItem;
+            for (; ; ) {
+                #region innerloop
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp >= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                        }
+                        *(vec + i + inc) = pivotItem;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--];
+                } else {
+                    #region quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo);
+                    a2 = *(vec + pivotIndex);
+                    a3 = *(vec + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 < a2) {
+                        if (a1 < a3) {
+                            if (a3 < a2) {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a2;
+                                *(vec + lo + inc) = a3;
+                            } else {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a3;
+                                *(vec + lo + inc) = a2;
+                            }
+                        } else {
+                            *(vec + lo) = a2;
+                            *(vec + lo + inc) = a1;
+                        }
+                    } else {
+                        if (a2 < a3) {
+                            *(vec + hi) = a2;
+                            if (a3 < a1) {
+                                *(vec + lo + inc) = a3;
+                            } else {
+                                *(vec + lo + inc) = a1;
+                                *(vec + lo) = a3;
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2;
+                        }
+                    }
+                    #endregion
+                   
+                    float* vecI = vec + lo + inc, vecJ = vec + hi;
+                    pivotItem = *vecI;
+                    for (; ; ) {
+                        do vecI += inc; while (*vecI > pivotItem);
+                        do vecJ -= inc; while (*vecJ < pivotItem);
+                        if (vecJ < vecI) break;
+                        temp = *vecI;
+                        *vecI = *vecJ;
+                        *vecJ = temp;
+                    }
+                    *(vec + lo + inc) = *vecJ;
+                    *vecJ = pivotItem;
+
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif
+                    #endregion
+                    i = (int)(vecI - vec);
+                    j = (int)(vecJ - vec);
+                    if (hi - i + inc < j - lo) {
+                        if (s_threadCount < 100
+                                && (j - lo) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = i;
+                            data.hi = hi;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortDesc_ITMT_noNaN(vec, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = hi;
+                            s_quickSortStackMT[++s_quickSortStackPos] = i;
+                        }
+                        hi = j - inc;
+                    } else {
+                        if (s_threadCount < 100
+                            && (hi - i + inc) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = lo;
+                            data.hi = j - inc;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                //Console.Out.WriteLine("Thread start: {0} ({1} - {2} Count:{3})", Thread.CurrentThread.ManagedThreadId, lo, hi, threadCount.ThreadCount);
+                                QuickSortDesc_ITMT_noNaN(vec, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = j - inc;
+                            s_quickSortStackMT[++s_quickSortStackPos] = lo;
+                        }
+                        lo = i;
+                    }
+                }
+                #endregion inner loop
+            }
+        }
+        unsafe private static void QuickSortAscIDX_ITMT_noNaN( float* vec, double* vecIdx, int lo, int hi, int inc) {
+           
+            float temp, pivotItem;
+            int pivotIndex, j, i;
+            s_quickSortStackPos = -1;
+           
+            float a1, a2, a3;
+           
+            double ai1, ai2, ai3;
+            for (; ; ) {
+                #region inner loop
+                if (hi - lo < (ILNumerics.Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        ai1 = *(vecIdx + j);
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp <= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                            *(vecIdx + i + inc) = *(vecIdx + i);
+                        }
+                        *(vec + i + inc) = pivotItem;
+                        *(vecIdx + i + inc) = ai1;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--];
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo);
+                    a2 = *(vec + pivotIndex);
+                    a3 = *(vec + hi);
+                    ai1 = *(vecIdx + lo);
+                    ai2 = *(vecIdx + pivotIndex);
+                    ai3 = *(vecIdx + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    *(vecIdx + pivotIndex) = *(vecIdx + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 > a2) {
+                        if (a1 > a3) {
+                            if (a3 > a2) {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a2;
+                                *(vec + lo + inc) = a3;
+                                *(vecIdx + hi) = ai1;
+                                *(vecIdx + lo) = ai2;
+                                *(vecIdx + lo + inc) = ai3;
+                            } else {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a3;
+                                *(vec + lo + inc) = a2;
+                                *(vecIdx + hi) = ai1;
+                                *(vecIdx + lo) = ai3;
+                                *(vecIdx + lo + inc) = ai2;
+                            }
+                        } else {
+                            *(vec + lo) = a2;
+                            *(vec + lo + inc) = a1;
+                            *(vecIdx + lo) = ai2;
+                            *(vecIdx + lo + inc) = ai1;
+                        }
+                    } else {
+                        if (a2 > a3) {
+                            *(vec + hi) = a2;
+                            *(vecIdx + hi) = ai2;
+                            if (a3 > a1) {
+                                *(vec + lo + inc) = a3;
+                                *(vecIdx + lo + inc) = ai3;
+                            } else {
+                                *(vec + lo + inc) = a1;
+                                *(vec + lo) = a3;
+                                *(vecIdx + lo + inc) = ai1;
+                                *(vecIdx + lo) = ai3;
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2;
+                            *(vecIdx + lo + inc) = ai2;
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi;
+                    pivotItem = *(vec + lo + inc);
+                    ai1 = *(vecIdx + lo + inc);
+                    for (; ; ) {
+                        do i += inc; while (*(vec + i) < pivotItem);
+                        do j -= inc; while (*(vec + j) > pivotItem);
+                        if (j < i) break;
+                        temp = *(vec + i);
+                        ai2 = *(vecIdx + i);
+                        *(vec + i) = *(vec + j);
+                        *(vec + j) = temp;
+                        *(vecIdx + i) = *(vecIdx + j);
+                        *(vecIdx + j) = ai2;
+                    }
+                    *(vec + lo + inc) = *(vec + j);
+                    *(vec + j) = pivotItem;
+                    *(vecIdx + lo + inc) = *(vecIdx + j);
+                    *(vecIdx + j) = ai1;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif
+                    if (hi - i + inc < j - lo) {
+                        if (s_threadCount < 100
+                                && (j - lo) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = i;
+                            data.hi = hi;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortAscIDX_ITMT_noNaN(vec, vecIdx, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = hi;
+                            s_quickSortStackMT[++s_quickSortStackPos] = i;
+                        }
+                        hi = j - inc;
+                    } else {
+                        if (s_threadCount < 100
+                            && (hi - i + inc) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = lo;
+                            data.hi = j - inc;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortAscIDX_ITMT_noNaN(vec, vecIdx, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = j - inc;
+                            s_quickSortStackMT[++s_quickSortStackPos] = lo;
+                        }
+                        lo = i;
+                    }
+                }
+                #endregion
+            }
+        }
+        unsafe private static void QuickSortDescIDX_ITMT_noNaN( float* vec, double* vecIdx, int lo, int hi, int inc) {
+           
+            float temp, pivotItem;
+            int pivotIndex, j, i;
+            s_quickSortStackPos = -1;
+           
+            float a1, a2, a3;
+           
+            double ai1, ai2, ai3;
+            for (; ; ) {
+                #region inner loop
+                if (hi - lo < (ILNumerics.Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        ai1 = *(vecIdx + j);
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp >= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                            *(vecIdx + i + inc) = *(vecIdx + i);
+                        }
+                        *(vec + i + inc) = pivotItem;
+                        *(vecIdx + i + inc) = ai1;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--];
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo);
+                    a2 = *(vec + pivotIndex);
+                    a3 = *(vec + hi);
+                    ai1 = *(vecIdx + lo);
+                    ai2 = *(vecIdx + pivotIndex);
+                    ai3 = *(vecIdx + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    *(vecIdx + pivotIndex) = *(vecIdx + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 < a2) {
+                        if (a1 < a3) {
+                            if (a3 < a2) {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a2;
+                                *(vec + lo + inc) = a3;
+                                *(vecIdx + hi) = ai1;
+                                *(vecIdx + lo) = ai2;
+                                *(vecIdx + lo + inc) = ai3;
+                            } else {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a3;
+                                *(vec + lo + inc) = a2;
+                                *(vecIdx + hi) = ai1;
+                                *(vecIdx + lo) = ai3;
+                                *(vecIdx + lo + inc) = ai2;
+                            }
+                        } else {
+                            *(vec + lo) = a2;
+                            *(vec + lo + inc) = a1;
+                            *(vecIdx + lo) = ai2;
+                            *(vecIdx + lo + inc) = ai1;
+                        }
+                    } else {
+                        if (a2 < a3) {
+                            *(vec + hi) = a2;
+                            *(vecIdx + hi) = ai2;
+                            if (a3 < a1) {
+                                *(vec + lo + inc) = a3;
+                                *(vecIdx + lo + inc) = ai3;
+                            } else {
+                                *(vec + lo + inc) = a1;
+                                *(vec + lo) = a3;
+                                *(vecIdx + lo + inc) = ai1;
+                                *(vecIdx + lo) = ai3;
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2;
+                            *(vecIdx + lo + inc) = ai2;
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi;
+                    pivotItem = *(vec + lo + inc);
+                    ai1 = *(vecIdx + lo + inc);
+                    for (; ; ) {
+                        do i += inc; while (*(vec + i) > pivotItem);
+                        do j -= inc; while (*(vec + j) < pivotItem);
+                        if (j < i) break;
+                        temp = *(vec + i);
+                        ai2 = *(vecIdx + i);
+                        *(vec + i) = *(vec + j);
+                        *(vec + j) = temp;
+                        *(vecIdx + i) = *(vecIdx + j);
+                        *(vecIdx + j) = ai2;
+                    }
+                    *(vec + lo + inc) = *(vec + j);
+                    *(vec + j) = pivotItem;
+                    *(vecIdx + lo + inc) = *(vecIdx + j);
+                    *(vecIdx + j) = ai1;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif
+                    if (hi - i + inc < j - lo) {
+                        if (s_threadCount < 100
+                                && (j - lo) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = i;
+                            data.hi = hi;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortDescIDX_ITMT_noNaN(vec, vecIdx, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = hi;
+                            s_quickSortStackMT[++s_quickSortStackPos] = i;
+                        }
+                        hi = j - inc;
+                    } else {
+                        if (s_threadCount < 100
+                            && (hi - i + inc) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = lo;
+                            data.hi = j - inc;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortDescIDX_ITMT_noNaN(vec, vecIdx, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = j - inc;
+                            s_quickSortStackMT[++s_quickSortStackPos] = lo;
+                        }
+                        lo = i;
+                    }
+                }
+                #endregion
+            }
+        }
+        #endregion 
+        
+
+        /// <summary>
+        /// inline one dimensional quick sort, ascending, arbitrary element spacing, multithreaded
+        /// </summary>
+        /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+        /// <param name="lo">lowest index of sorting range</param>
+        /// <param name="hi">highest index of sorting range</param>
+        /// <param name="inc">spacing between elements (dimension specifier)</param>
+        /// <remarks>
+        /// <para>This function provides a low level in-place implementation of the quicksort algorithm. It is used by the 
+        /// higher level sorting API provided by <see cref="M:ILNumerics.ILMath.sort"/>. It is recommended to use the overloads 
+        /// of <see cref="M:ILNumerics.ILMath.sort()"/> instead of this function. That way, the decision, which lower level function
+        /// is to be called is made by the library automatically.</para>
+        /// <para>A quicksort algorithm is used for ranges of minimum lengths specified by 
+        /// <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/> and above. 
+        /// Below that length, a simple insertion sort is used instead.</para>
+        /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+        /// memory is needed to perform the sorting. That 'stack' memory defaults to length 100. The stack array
+        /// is cached internally.</para>
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>This function internally parallelizes the sorting in a very efficient manner. It usually outperforms 
+        /// non-parallelized versions of the quicksort algorithm for larger arrays. For smaller arrays, it may be more 
+        /// efficient, to use the non parallelized version instead: <see cref="M:ILNumerics.ILMath.QuickSortAsc(double[], int, int, int)"/></para></remarks>
+        public static void QuickSortAscMT( fcomplex[] vecP, int lo, int hi, int inc) {
+            System.Diagnostics.Debug.Assert(vecP != null && vecP.Length > hi);
+            System.Diagnostics.Debug.Assert(lo <= hi);
+            System.Diagnostics.Debug.Assert(lo >= 0);
+            if (vecP.Length < 2) return;
+            unsafe {
+                fixed ( fcomplex* vec = vecP) {
+                    if (checkNaNAsc(lo,ref hi, inc, vec)) return;
+                    s_threadCount = 1;
+                    QuickSortAsc_ITMT_noNaN(vec, lo, hi, inc);
+
+                } // fixed
+            } // unsafe 
+            Interlocked.Decrement(ref s_threadCount);
+            SpinWait.SpinUntil(() => {
+                return s_threadCount <= 0;
+            });
+        }
+
+        /// <summary>
+        /// inline one dimensional quick sort, descending, arbitrary element spacing, multithreaded
+        /// </summary>
+        /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+        /// <param name="lo">lowest index of sorting range</param>
+        /// <param name="hi">highest index of sorting range</param>
+        /// <param name="inc">spacing between elements (dimension specifier)</param>
+        /// <remarks>        
+        /// <para>This function provides a low level in-place implementation of the quicksort algorithm. It is used by the 
+        /// higher level sorting API provided by <see cref="M:ILNumerics.ILMath.sort"/>. It is recommended to use the overloads 
+        /// of <see cref="M:ILNumerics.ILMath.sort()"/> instead of this function. That way, the decision, which lower level function
+        /// is to be called is made by the library automatically.</para>
+        /// <para>A quicksort algorithm is used for ranges of minimum lengths specified by 
+        /// <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/> and above. 
+        /// Below that length, a simple insertion sort is used instead.</para>
+        /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+        /// memory is needed to perform the sorting. That 'stack' memory defaults to length 100.</para>
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>This function internally parallelizes the sorting in a very efficient manner. It usually outperforms 
+        /// non-parallelized versions of the quicksort algorithm for larger arrays. For smaller arrays, it may be more 
+        /// efficient, to use the non parallelized version instead: <see cref="M:ILNumerics.ILMath.QuickSortAsc(double[], int, int, int)"/></para></remarks>
+        public static void QuickSortDescMT( fcomplex[] vecP, int lo, int hi, int inc) {
+            System.Diagnostics.Debug.Assert(vecP != null && vecP.Length > hi);
+            System.Diagnostics.Debug.Assert(lo <= hi);
+            System.Diagnostics.Debug.Assert(lo >= 0);
+            if (vecP.Length < 2) return;
+            unsafe {
+                fixed ( fcomplex* vec = vecP) {
+                    if (checkNaNDesc(lo,ref hi, inc, vec)) return;
+                    s_threadCount = 1;
+                    QuickSortDesc_ITMT_noNaN(vec, lo, hi, inc);
+
+                } // fixed
+            } // unsafe 
+            Interlocked.Decrement(ref s_threadCount);
+            SpinWait.SpinUntil(() => {
+                return s_threadCount <= 0;
+            });
+        }
+        /// <summary>
+        /// inline one dimensional quick sort, ascending, arbitrary element spacing, indices aware
+        /// </summary>
+        /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+        /// <param name="lo">lowest index of sorting range</param>
+        /// <param name="hi">highest index of sorting range</param>
+        /// <param name="idxP">indices vector, content will in-place be sorted along with <paramref name="vecP"/></param>
+        /// <param name="inc">spacing between elements (dimension specifier)</param>
+        /// <remarks>
+        /// <para>This function provides a low level in-place implementation of the quicksort algorithm. It is used by the 
+        /// higher level sorting API provided by <see cref="M:ILNumerics.ILMath.sort"/>. It is recommended to use the overloads 
+        /// of <see cref="M:ILNumerics.ILMath.sort()"/> instead of this function. That way, the decision, which lower level function
+        /// is to be called is made by the library automatically.</para>
+        /// <para>A quicksort algorithm is used for ranges of minimum lengths specified by 
+        /// <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/> and above. 
+        /// Below that length, a simple insertion sort is used instead.</para>
+        /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+        /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+        /// The size is determined by the value of 
+        /// <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/>.</para>
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>This function internally parallelizes the sorting in a very efficient manner. It usually outperforms 
+        /// non-parallelized versions of the quicksort algorithm for larger arrays. For smaller arrays, it may be more 
+        /// efficient, to use the non parallelized version instead: <see cref="M:ILNumerics.ILMath.QuickSortAsc(double[], int, int, int)"/></para></remarks>
+        public static void QuickSortAscIDXMT( fcomplex[] vecP,  double[] idxP, int lo, int hi, int inc) {
+            System.Diagnostics.Debug.Assert(vecP != null && vecP.Length > hi);
+            System.Diagnostics.Debug.Assert(idxP != null && idxP.Length > hi);
+            System.Diagnostics.Debug.Assert(lo <= hi);
+            System.Diagnostics.Debug.Assert(lo >= 0);
+            if (vecP.Length < 2) return;
+            int[] stack = ILMemoryPool.Pool.New<int>(ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth * 2);
+            unsafe {
+                fixed ( double* vecIdx = idxP)
+                fixed ( fcomplex* vec = vecP) {
+                    if (checkNaNIDXAsc(lo,ref hi, inc, vecIdx, vec)) return;
+                    s_threadCount = 1;
+                    QuickSortAscIDX_ITMT_noNaN(vec, vecIdx, lo, hi, inc);
+
+                } // fixed
+            } // unsafe 
+            Interlocked.Decrement(ref s_threadCount);
+            SpinWait.SpinUntil(() => {
+                return s_threadCount <= 0;
+            });
+        }
+
+        /// <summary>
+        /// inline one dimensional quick sort, descending, arbitrary element spacing, indices aware
+        /// </summary>
+        /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+        /// <param name="lo">lowest index of sorting range</param>
+        /// <param name="hi">highest index of sorting range</param>
+        /// <param name="idxP">indices vector, content will in-place be sorted along with <paramref name="vecP"/></param>
+        /// <param name="inc">spacing between elements (dimension specifier)</param>
+        /// <remarks>
+        /// <para>This function provides a low level in-place implementation of the quicksort algorithm. It is used by the 
+        /// higher level sorting API provided by <see cref="M:ILNumerics.ILMath.sort"/>. It is recommended to use the overloads 
+        /// of <see cref="M:ILNumerics.ILMath.sort()"/> instead of this function. That way, the decision, which lower level function
+        /// is to be called is made by the library automatically.</para>
+        /// <para>A quicksort algorithm is used for ranges of minimum lengths specified by 
+        /// <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/> and above. 
+        /// Below that length, a simple insertion sort is used instead.</para>
+        /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+        /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+        /// The size is determined by the value of 
+        /// <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/>.</para>
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>This function internally parallelizes the sorting in a very efficient manner. It usually outperforms 
+        /// non-parallelized versions of the quicksort algorithm for larger arrays. For smaller arrays, it may be more 
+        /// efficient, to use the non parallelized version instead: <see cref="M:ILNumerics.ILMath.QuickSortAsc(double[], int, int, int)"/></para></remarks>
+        public static void QuickSortDescIDXMT( fcomplex[] vecP,  double[] idxP, int lo, int hi, int inc) {
+            System.Diagnostics.Debug.Assert(vecP != null && vecP.Length > hi);
+            System.Diagnostics.Debug.Assert(idxP != null && idxP.Length > hi);
+            System.Diagnostics.Debug.Assert(lo <= hi);
+            System.Diagnostics.Debug.Assert(lo >= 0);
+           
+            if (vecP.Length < 2) return;
+            int[] stack = ILMemoryPool.Pool.New<int>(ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth * 2);
+            unsafe {
+                fixed ( double* vecIdx = idxP)
+                fixed ( fcomplex* vec = vecP) {
+                    if (checkNaNIDXDesc(lo,ref hi, inc, vecIdx, vec)) return;
+                    Interlocked.Increment(ref s_threadCount);
+                    QuickSortDescIDX_ITMT_noNaN(vec, vecIdx, lo, hi, inc);
+                } // fixed
+            } // unsafe 
+            Interlocked.Decrement(ref s_threadCount);
+            SpinWait.SpinUntil(() => {
+                return s_threadCount <= 0;
+            });
+        }
+
+        #region private functions
+        unsafe private static void QuickSortAsc_ITMT_noNaN( fcomplex* vec, int lo, int hi, int inc) {
+            int pivotIndex, i, j;
+            s_quickSortStackPos = -1;
+           
+            fcomplex a1, a2, a3;
+           
+            fcomplex temp, pivotItem;
+            for (; ; ) {
+                #region innerloop
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp <= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                        }
+                        *(vec + i + inc) = pivotItem;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--];
+                } else {
+                    #region quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo);
+                    a2 = *(vec + pivotIndex);
+                    a3 = *(vec + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 > a2) {
+                        if (a1 > a3) {
+                            if (a3 > a2) {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a2;
+                                *(vec + lo + inc) = a3;
+                            } else {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a3;
+                                *(vec + lo + inc) = a2;
+                            }
+                        } else {
+                            *(vec + lo) = a2;
+                            *(vec + lo + inc) = a1;
+                        }
+                    } else {
+                        if (a2 > a3) {
+                            *(vec + hi) = a2;
+                            if (a3 > a1) {
+                                *(vec + lo + inc) = a3;
+                            } else {
+                                *(vec + lo + inc) = a1;
+                                *(vec + lo) = a3;
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2;
+                        }
+                    }
+                    #endregion
+                   
+                    fcomplex* vecI = vec + lo + inc, vecJ = vec + hi;
+                    pivotItem = *vecI;
+                    for (; ; ) {
+                        do vecI += inc; while (*vecI < pivotItem);
+                        do vecJ -= inc; while (*vecJ > pivotItem);
+                        if (vecJ < vecI) break;
+                        temp = *vecI;
+                        *vecI = *vecJ;
+                        *vecJ = temp;
+                    }
+                    *(vec + lo + inc) = *vecJ;
+                    *vecJ = pivotItem;
+
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif
+                    #endregion
+                    i = (int)(vecI - vec);
+                    j = (int)(vecJ - vec);
+                    if (hi - i + inc < j - lo) {
+                        if (s_threadCount < 100
+                                && (j - lo) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = i;
+                            data.hi = hi;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortAsc_ITMT_noNaN(vec, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = hi;
+                            s_quickSortStackMT[++s_quickSortStackPos] = i;
+                        }
+                        hi = j - inc;
+                    } else {
+                        if (s_threadCount < 100
+                            && (hi - i + inc) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = lo;
+                            data.hi = j - inc;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                //Console.Out.WriteLine("Thread start: {0} ({1} - {2} Count:{3})", Thread.CurrentThread.ManagedThreadId, lo, hi, threadCount.ThreadCount);
+                                QuickSortAsc_ITMT_noNaN(vec, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = j - inc;
+                            s_quickSortStackMT[++s_quickSortStackPos] = lo;
+                        }
+                        lo = i;
+                    }
+                }
+                #endregion inner loop
+            }
+        }
+        unsafe private static void QuickSortDesc_ITMT_noNaN( fcomplex* vec, int lo, int hi, int inc) {
+            int pivotIndex, i, j;
+            s_quickSortStackPos = -1;
+           
+            fcomplex a1, a2, a3;
+           
+            fcomplex temp, pivotItem;
+            for (; ; ) {
+                #region innerloop
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp >= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                        }
+                        *(vec + i + inc) = pivotItem;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--];
+                } else {
+                    #region quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo);
+                    a2 = *(vec + pivotIndex);
+                    a3 = *(vec + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 < a2) {
+                        if (a1 < a3) {
+                            if (a3 < a2) {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a2;
+                                *(vec + lo + inc) = a3;
+                            } else {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a3;
+                                *(vec + lo + inc) = a2;
+                            }
+                        } else {
+                            *(vec + lo) = a2;
+                            *(vec + lo + inc) = a1;
+                        }
+                    } else {
+                        if (a2 < a3) {
+                            *(vec + hi) = a2;
+                            if (a3 < a1) {
+                                *(vec + lo + inc) = a3;
+                            } else {
+                                *(vec + lo + inc) = a1;
+                                *(vec + lo) = a3;
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2;
+                        }
+                    }
+                    #endregion
+                   
+                    fcomplex* vecI = vec + lo + inc, vecJ = vec + hi;
+                    pivotItem = *vecI;
+                    for (; ; ) {
+                        do vecI += inc; while (*vecI > pivotItem);
+                        do vecJ -= inc; while (*vecJ < pivotItem);
+                        if (vecJ < vecI) break;
+                        temp = *vecI;
+                        *vecI = *vecJ;
+                        *vecJ = temp;
+                    }
+                    *(vec + lo + inc) = *vecJ;
+                    *vecJ = pivotItem;
+
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif
+                    #endregion
+                    i = (int)(vecI - vec);
+                    j = (int)(vecJ - vec);
+                    if (hi - i + inc < j - lo) {
+                        if (s_threadCount < 100
+                                && (j - lo) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = i;
+                            data.hi = hi;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortDesc_ITMT_noNaN(vec, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = hi;
+                            s_quickSortStackMT[++s_quickSortStackPos] = i;
+                        }
+                        hi = j - inc;
+                    } else {
+                        if (s_threadCount < 100
+                            && (hi - i + inc) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = lo;
+                            data.hi = j - inc;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                //Console.Out.WriteLine("Thread start: {0} ({1} - {2} Count:{3})", Thread.CurrentThread.ManagedThreadId, lo, hi, threadCount.ThreadCount);
+                                QuickSortDesc_ITMT_noNaN(vec, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = j - inc;
+                            s_quickSortStackMT[++s_quickSortStackPos] = lo;
+                        }
+                        lo = i;
+                    }
+                }
+                #endregion inner loop
+            }
+        }
+        unsafe private static void QuickSortAscIDX_ITMT_noNaN( fcomplex* vec, double* vecIdx, int lo, int hi, int inc) {
+           
+            fcomplex temp, pivotItem;
+            int pivotIndex, j, i;
+            s_quickSortStackPos = -1;
+           
+            fcomplex a1, a2, a3;
+           
+            double ai1, ai2, ai3;
+            for (; ; ) {
+                #region inner loop
+                if (hi - lo < (ILNumerics.Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        ai1 = *(vecIdx + j);
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp <= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                            *(vecIdx + i + inc) = *(vecIdx + i);
+                        }
+                        *(vec + i + inc) = pivotItem;
+                        *(vecIdx + i + inc) = ai1;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--];
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo);
+                    a2 = *(vec + pivotIndex);
+                    a3 = *(vec + hi);
+                    ai1 = *(vecIdx + lo);
+                    ai2 = *(vecIdx + pivotIndex);
+                    ai3 = *(vecIdx + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    *(vecIdx + pivotIndex) = *(vecIdx + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 > a2) {
+                        if (a1 > a3) {
+                            if (a3 > a2) {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a2;
+                                *(vec + lo + inc) = a3;
+                                *(vecIdx + hi) = ai1;
+                                *(vecIdx + lo) = ai2;
+                                *(vecIdx + lo + inc) = ai3;
+                            } else {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a3;
+                                *(vec + lo + inc) = a2;
+                                *(vecIdx + hi) = ai1;
+                                *(vecIdx + lo) = ai3;
+                                *(vecIdx + lo + inc) = ai2;
+                            }
+                        } else {
+                            *(vec + lo) = a2;
+                            *(vec + lo + inc) = a1;
+                            *(vecIdx + lo) = ai2;
+                            *(vecIdx + lo + inc) = ai1;
+                        }
+                    } else {
+                        if (a2 > a3) {
+                            *(vec + hi) = a2;
+                            *(vecIdx + hi) = ai2;
+                            if (a3 > a1) {
+                                *(vec + lo + inc) = a3;
+                                *(vecIdx + lo + inc) = ai3;
+                            } else {
+                                *(vec + lo + inc) = a1;
+                                *(vec + lo) = a3;
+                                *(vecIdx + lo + inc) = ai1;
+                                *(vecIdx + lo) = ai3;
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2;
+                            *(vecIdx + lo + inc) = ai2;
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi;
+                    pivotItem = *(vec + lo + inc);
+                    ai1 = *(vecIdx + lo + inc);
+                    for (; ; ) {
+                        do i += inc; while (*(vec + i) < pivotItem);
+                        do j -= inc; while (*(vec + j) > pivotItem);
+                        if (j < i) break;
+                        temp = *(vec + i);
+                        ai2 = *(vecIdx + i);
+                        *(vec + i) = *(vec + j);
+                        *(vec + j) = temp;
+                        *(vecIdx + i) = *(vecIdx + j);
+                        *(vecIdx + j) = ai2;
+                    }
+                    *(vec + lo + inc) = *(vec + j);
+                    *(vec + j) = pivotItem;
+                    *(vecIdx + lo + inc) = *(vecIdx + j);
+                    *(vecIdx + j) = ai1;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif
+                    if (hi - i + inc < j - lo) {
+                        if (s_threadCount < 100
+                                && (j - lo) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = i;
+                            data.hi = hi;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortAscIDX_ITMT_noNaN(vec, vecIdx, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = hi;
+                            s_quickSortStackMT[++s_quickSortStackPos] = i;
+                        }
+                        hi = j - inc;
+                    } else {
+                        if (s_threadCount < 100
+                            && (hi - i + inc) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = lo;
+                            data.hi = j - inc;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortAscIDX_ITMT_noNaN(vec, vecIdx, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = j - inc;
+                            s_quickSortStackMT[++s_quickSortStackPos] = lo;
+                        }
+                        lo = i;
+                    }
+                }
+                #endregion
+            }
+        }
+        unsafe private static void QuickSortDescIDX_ITMT_noNaN( fcomplex* vec, double* vecIdx, int lo, int hi, int inc) {
+           
+            fcomplex temp, pivotItem;
+            int pivotIndex, j, i;
+            s_quickSortStackPos = -1;
+           
+            fcomplex a1, a2, a3;
+           
+            double ai1, ai2, ai3;
+            for (; ; ) {
+                #region inner loop
+                if (hi - lo < (ILNumerics.Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        ai1 = *(vecIdx + j);
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp >= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                            *(vecIdx + i + inc) = *(vecIdx + i);
+                        }
+                        *(vec + i + inc) = pivotItem;
+                        *(vecIdx + i + inc) = ai1;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--];
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo);
+                    a2 = *(vec + pivotIndex);
+                    a3 = *(vec + hi);
+                    ai1 = *(vecIdx + lo);
+                    ai2 = *(vecIdx + pivotIndex);
+                    ai3 = *(vecIdx + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    *(vecIdx + pivotIndex) = *(vecIdx + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 < a2) {
+                        if (a1 < a3) {
+                            if (a3 < a2) {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a2;
+                                *(vec + lo + inc) = a3;
+                                *(vecIdx + hi) = ai1;
+                                *(vecIdx + lo) = ai2;
+                                *(vecIdx + lo + inc) = ai3;
+                            } else {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a3;
+                                *(vec + lo + inc) = a2;
+                                *(vecIdx + hi) = ai1;
+                                *(vecIdx + lo) = ai3;
+                                *(vecIdx + lo + inc) = ai2;
+                            }
+                        } else {
+                            *(vec + lo) = a2;
+                            *(vec + lo + inc) = a1;
+                            *(vecIdx + lo) = ai2;
+                            *(vecIdx + lo + inc) = ai1;
+                        }
+                    } else {
+                        if (a2 < a3) {
+                            *(vec + hi) = a2;
+                            *(vecIdx + hi) = ai2;
+                            if (a3 < a1) {
+                                *(vec + lo + inc) = a3;
+                                *(vecIdx + lo + inc) = ai3;
+                            } else {
+                                *(vec + lo + inc) = a1;
+                                *(vec + lo) = a3;
+                                *(vecIdx + lo + inc) = ai1;
+                                *(vecIdx + lo) = ai3;
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2;
+                            *(vecIdx + lo + inc) = ai2;
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi;
+                    pivotItem = *(vec + lo + inc);
+                    ai1 = *(vecIdx + lo + inc);
+                    for (; ; ) {
+                        do i += inc; while (*(vec + i) > pivotItem);
+                        do j -= inc; while (*(vec + j) < pivotItem);
+                        if (j < i) break;
+                        temp = *(vec + i);
+                        ai2 = *(vecIdx + i);
+                        *(vec + i) = *(vec + j);
+                        *(vec + j) = temp;
+                        *(vecIdx + i) = *(vecIdx + j);
+                        *(vecIdx + j) = ai2;
+                    }
+                    *(vec + lo + inc) = *(vec + j);
+                    *(vec + j) = pivotItem;
+                    *(vecIdx + lo + inc) = *(vecIdx + j);
+                    *(vecIdx + j) = ai1;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif
+                    if (hi - i + inc < j - lo) {
+                        if (s_threadCount < 100
+                                && (j - lo) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = i;
+                            data.hi = hi;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortDescIDX_ITMT_noNaN(vec, vecIdx, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = hi;
+                            s_quickSortStackMT[++s_quickSortStackPos] = i;
+                        }
+                        hi = j - inc;
+                    } else {
+                        if (s_threadCount < 100
+                            && (hi - i + inc) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = lo;
+                            data.hi = j - inc;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortDescIDX_ITMT_noNaN(vec, vecIdx, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = j - inc;
+                            s_quickSortStackMT[++s_quickSortStackPos] = lo;
+                        }
+                        lo = i;
+                    }
+                }
+                #endregion
+            }
+        }
+        #endregion 
+        
+
+        /// <summary>
+        /// inline one dimensional quick sort, ascending, arbitrary element spacing, multithreaded
+        /// </summary>
+        /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+        /// <param name="lo">lowest index of sorting range</param>
+        /// <param name="hi">highest index of sorting range</param>
+        /// <param name="inc">spacing between elements (dimension specifier)</param>
+        /// <remarks>
+        /// <para>This function provides a low level in-place implementation of the quicksort algorithm. It is used by the 
+        /// higher level sorting API provided by <see cref="M:ILNumerics.ILMath.sort"/>. It is recommended to use the overloads 
+        /// of <see cref="M:ILNumerics.ILMath.sort()"/> instead of this function. That way, the decision, which lower level function
+        /// is to be called is made by the library automatically.</para>
+        /// <para>A quicksort algorithm is used for ranges of minimum lengths specified by 
+        /// <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/> and above. 
+        /// Below that length, a simple insertion sort is used instead.</para>
+        /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+        /// memory is needed to perform the sorting. That 'stack' memory defaults to length 100. The stack array
+        /// is cached internally.</para>
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>This function internally parallelizes the sorting in a very efficient manner. It usually outperforms 
+        /// non-parallelized versions of the quicksort algorithm for larger arrays. For smaller arrays, it may be more 
+        /// efficient, to use the non parallelized version instead: <see cref="M:ILNumerics.ILMath.QuickSortAsc(double[], int, int, int)"/></para></remarks>
+        public static void QuickSortAscMT( complex[] vecP, int lo, int hi, int inc) {
+            System.Diagnostics.Debug.Assert(vecP != null && vecP.Length > hi);
+            System.Diagnostics.Debug.Assert(lo <= hi);
+            System.Diagnostics.Debug.Assert(lo >= 0);
+            if (vecP.Length < 2) return;
+            unsafe {
+                fixed ( complex* vec = vecP) {
+                    if (checkNaNAsc(lo,ref hi, inc, vec)) return;
+                    s_threadCount = 1;
+                    QuickSortAsc_ITMT_noNaN(vec, lo, hi, inc);
+
+                } // fixed
+            } // unsafe 
+            Interlocked.Decrement(ref s_threadCount);
+            SpinWait.SpinUntil(() => {
+                return s_threadCount <= 0;
+            });
+        }
+
+        /// <summary>
+        /// inline one dimensional quick sort, descending, arbitrary element spacing, multithreaded
+        /// </summary>
+        /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+        /// <param name="lo">lowest index of sorting range</param>
+        /// <param name="hi">highest index of sorting range</param>
+        /// <param name="inc">spacing between elements (dimension specifier)</param>
+        /// <remarks>        
+        /// <para>This function provides a low level in-place implementation of the quicksort algorithm. It is used by the 
+        /// higher level sorting API provided by <see cref="M:ILNumerics.ILMath.sort"/>. It is recommended to use the overloads 
+        /// of <see cref="M:ILNumerics.ILMath.sort()"/> instead of this function. That way, the decision, which lower level function
+        /// is to be called is made by the library automatically.</para>
+        /// <para>A quicksort algorithm is used for ranges of minimum lengths specified by 
+        /// <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/> and above. 
+        /// Below that length, a simple insertion sort is used instead.</para>
+        /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+        /// memory is needed to perform the sorting. That 'stack' memory defaults to length 100.</para>
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>This function internally parallelizes the sorting in a very efficient manner. It usually outperforms 
+        /// non-parallelized versions of the quicksort algorithm for larger arrays. For smaller arrays, it may be more 
+        /// efficient, to use the non parallelized version instead: <see cref="M:ILNumerics.ILMath.QuickSortAsc(double[], int, int, int)"/></para></remarks>
+        public static void QuickSortDescMT( complex[] vecP, int lo, int hi, int inc) {
+            System.Diagnostics.Debug.Assert(vecP != null && vecP.Length > hi);
+            System.Diagnostics.Debug.Assert(lo <= hi);
+            System.Diagnostics.Debug.Assert(lo >= 0);
+            if (vecP.Length < 2) return;
+            unsafe {
+                fixed ( complex* vec = vecP) {
+                    if (checkNaNDesc(lo,ref hi, inc, vec)) return;
+                    s_threadCount = 1;
+                    QuickSortDesc_ITMT_noNaN(vec, lo, hi, inc);
+
+                } // fixed
+            } // unsafe 
+            Interlocked.Decrement(ref s_threadCount);
+            SpinWait.SpinUntil(() => {
+                return s_threadCount <= 0;
+            });
+        }
+        /// <summary>
+        /// inline one dimensional quick sort, ascending, arbitrary element spacing, indices aware
+        /// </summary>
+        /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+        /// <param name="lo">lowest index of sorting range</param>
+        /// <param name="hi">highest index of sorting range</param>
+        /// <param name="idxP">indices vector, content will in-place be sorted along with <paramref name="vecP"/></param>
+        /// <param name="inc">spacing between elements (dimension specifier)</param>
+        /// <remarks>
+        /// <para>This function provides a low level in-place implementation of the quicksort algorithm. It is used by the 
+        /// higher level sorting API provided by <see cref="M:ILNumerics.ILMath.sort"/>. It is recommended to use the overloads 
+        /// of <see cref="M:ILNumerics.ILMath.sort()"/> instead of this function. That way, the decision, which lower level function
+        /// is to be called is made by the library automatically.</para>
+        /// <para>A quicksort algorithm is used for ranges of minimum lengths specified by 
+        /// <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/> and above. 
+        /// Below that length, a simple insertion sort is used instead.</para>
+        /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+        /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+        /// The size is determined by the value of 
+        /// <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/>.</para>
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>This function internally parallelizes the sorting in a very efficient manner. It usually outperforms 
+        /// non-parallelized versions of the quicksort algorithm for larger arrays. For smaller arrays, it may be more 
+        /// efficient, to use the non parallelized version instead: <see cref="M:ILNumerics.ILMath.QuickSortAsc(double[], int, int, int)"/></para></remarks>
+        public static void QuickSortAscIDXMT( complex[] vecP,  double[] idxP, int lo, int hi, int inc) {
+            System.Diagnostics.Debug.Assert(vecP != null && vecP.Length > hi);
+            System.Diagnostics.Debug.Assert(idxP != null && idxP.Length > hi);
+            System.Diagnostics.Debug.Assert(lo <= hi);
+            System.Diagnostics.Debug.Assert(lo >= 0);
+            if (vecP.Length < 2) return;
+            int[] stack = ILMemoryPool.Pool.New<int>(ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth * 2);
+            unsafe {
+                fixed ( double* vecIdx = idxP)
+                fixed ( complex* vec = vecP) {
+                    if (checkNaNIDXAsc(lo,ref hi, inc, vecIdx, vec)) return;
+                    s_threadCount = 1;
+                    QuickSortAscIDX_ITMT_noNaN(vec, vecIdx, lo, hi, inc);
+
+                } // fixed
+            } // unsafe 
+            Interlocked.Decrement(ref s_threadCount);
+            SpinWait.SpinUntil(() => {
+                return s_threadCount <= 0;
+            });
+        }
+
+        /// <summary>
+        /// inline one dimensional quick sort, descending, arbitrary element spacing, indices aware
+        /// </summary>
+        /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+        /// <param name="lo">lowest index of sorting range</param>
+        /// <param name="hi">highest index of sorting range</param>
+        /// <param name="idxP">indices vector, content will in-place be sorted along with <paramref name="vecP"/></param>
+        /// <param name="inc">spacing between elements (dimension specifier)</param>
+        /// <remarks>
+        /// <para>This function provides a low level in-place implementation of the quicksort algorithm. It is used by the 
+        /// higher level sorting API provided by <see cref="M:ILNumerics.ILMath.sort"/>. It is recommended to use the overloads 
+        /// of <see cref="M:ILNumerics.ILMath.sort()"/> instead of this function. That way, the decision, which lower level function
+        /// is to be called is made by the library automatically.</para>
+        /// <para>A quicksort algorithm is used for ranges of minimum lengths specified by 
+        /// <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/> and above. 
+        /// Below that length, a simple insertion sort is used instead.</para>
+        /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+        /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+        /// The size is determined by the value of 
+        /// <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/>.</para>
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>This function internally parallelizes the sorting in a very efficient manner. It usually outperforms 
+        /// non-parallelized versions of the quicksort algorithm for larger arrays. For smaller arrays, it may be more 
+        /// efficient, to use the non parallelized version instead: <see cref="M:ILNumerics.ILMath.QuickSortAsc(double[], int, int, int)"/></para></remarks>
+        public static void QuickSortDescIDXMT( complex[] vecP,  double[] idxP, int lo, int hi, int inc) {
+            System.Diagnostics.Debug.Assert(vecP != null && vecP.Length > hi);
+            System.Diagnostics.Debug.Assert(idxP != null && idxP.Length > hi);
+            System.Diagnostics.Debug.Assert(lo <= hi);
+            System.Diagnostics.Debug.Assert(lo >= 0);
+           
+            if (vecP.Length < 2) return;
+            int[] stack = ILMemoryPool.Pool.New<int>(ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth * 2);
+            unsafe {
+                fixed ( double* vecIdx = idxP)
+                fixed ( complex* vec = vecP) {
+                    if (checkNaNIDXDesc(lo,ref hi, inc, vecIdx, vec)) return;
+                    Interlocked.Increment(ref s_threadCount);
+                    QuickSortDescIDX_ITMT_noNaN(vec, vecIdx, lo, hi, inc);
+                } // fixed
+            } // unsafe 
+            Interlocked.Decrement(ref s_threadCount);
+            SpinWait.SpinUntil(() => {
+                return s_threadCount <= 0;
+            });
+        }
+
+        #region private functions
+        unsafe private static void QuickSortAsc_ITMT_noNaN( complex* vec, int lo, int hi, int inc) {
+            int pivotIndex, i, j;
+            s_quickSortStackPos = -1;
+           
+            complex a1, a2, a3;
+           
+            complex temp, pivotItem;
+            for (; ; ) {
+                #region innerloop
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp <= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                        }
+                        *(vec + i + inc) = pivotItem;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--];
+                } else {
+                    #region quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo);
+                    a2 = *(vec + pivotIndex);
+                    a3 = *(vec + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 > a2) {
+                        if (a1 > a3) {
+                            if (a3 > a2) {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a2;
+                                *(vec + lo + inc) = a3;
+                            } else {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a3;
+                                *(vec + lo + inc) = a2;
+                            }
+                        } else {
+                            *(vec + lo) = a2;
+                            *(vec + lo + inc) = a1;
+                        }
+                    } else {
+                        if (a2 > a3) {
+                            *(vec + hi) = a2;
+                            if (a3 > a1) {
+                                *(vec + lo + inc) = a3;
+                            } else {
+                                *(vec + lo + inc) = a1;
+                                *(vec + lo) = a3;
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2;
+                        }
+                    }
+                    #endregion
+                   
+                    complex* vecI = vec + lo + inc, vecJ = vec + hi;
+                    pivotItem = *vecI;
+                    for (; ; ) {
+                        do vecI += inc; while (*vecI < pivotItem);
+                        do vecJ -= inc; while (*vecJ > pivotItem);
+                        if (vecJ < vecI) break;
+                        temp = *vecI;
+                        *vecI = *vecJ;
+                        *vecJ = temp;
+                    }
+                    *(vec + lo + inc) = *vecJ;
+                    *vecJ = pivotItem;
+
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif
+                    #endregion
+                    i = (int)(vecI - vec);
+                    j = (int)(vecJ - vec);
+                    if (hi - i + inc < j - lo) {
+                        if (s_threadCount < 100
+                                && (j - lo) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = i;
+                            data.hi = hi;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortAsc_ITMT_noNaN(vec, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = hi;
+                            s_quickSortStackMT[++s_quickSortStackPos] = i;
+                        }
+                        hi = j - inc;
+                    } else {
+                        if (s_threadCount < 100
+                            && (hi - i + inc) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = lo;
+                            data.hi = j - inc;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                //Console.Out.WriteLine("Thread start: {0} ({1} - {2} Count:{3})", Thread.CurrentThread.ManagedThreadId, lo, hi, threadCount.ThreadCount);
+                                QuickSortAsc_ITMT_noNaN(vec, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = j - inc;
+                            s_quickSortStackMT[++s_quickSortStackPos] = lo;
+                        }
+                        lo = i;
+                    }
+                }
+                #endregion inner loop
+            }
+        }
+        unsafe private static void QuickSortDesc_ITMT_noNaN( complex* vec, int lo, int hi, int inc) {
+            int pivotIndex, i, j;
+            s_quickSortStackPos = -1;
+           
+            complex a1, a2, a3;
+           
+            complex temp, pivotItem;
+            for (; ; ) {
+                #region innerloop
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp >= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                        }
+                        *(vec + i + inc) = pivotItem;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--];
+                } else {
+                    #region quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo);
+                    a2 = *(vec + pivotIndex);
+                    a3 = *(vec + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 < a2) {
+                        if (a1 < a3) {
+                            if (a3 < a2) {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a2;
+                                *(vec + lo + inc) = a3;
+                            } else {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a3;
+                                *(vec + lo + inc) = a2;
+                            }
+                        } else {
+                            *(vec + lo) = a2;
+                            *(vec + lo + inc) = a1;
+                        }
+                    } else {
+                        if (a2 < a3) {
+                            *(vec + hi) = a2;
+                            if (a3 < a1) {
+                                *(vec + lo + inc) = a3;
+                            } else {
+                                *(vec + lo + inc) = a1;
+                                *(vec + lo) = a3;
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2;
+                        }
+                    }
+                    #endregion
+                   
+                    complex* vecI = vec + lo + inc, vecJ = vec + hi;
+                    pivotItem = *vecI;
+                    for (; ; ) {
+                        do vecI += inc; while (*vecI > pivotItem);
+                        do vecJ -= inc; while (*vecJ < pivotItem);
+                        if (vecJ < vecI) break;
+                        temp = *vecI;
+                        *vecI = *vecJ;
+                        *vecJ = temp;
+                    }
+                    *(vec + lo + inc) = *vecJ;
+                    *vecJ = pivotItem;
+
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif
+                    #endregion
+                    i = (int)(vecI - vec);
+                    j = (int)(vecJ - vec);
+                    if (hi - i + inc < j - lo) {
+                        if (s_threadCount < 100
+                                && (j - lo) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = i;
+                            data.hi = hi;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortDesc_ITMT_noNaN(vec, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = hi;
+                            s_quickSortStackMT[++s_quickSortStackPos] = i;
+                        }
+                        hi = j - inc;
+                    } else {
+                        if (s_threadCount < 100
+                            && (hi - i + inc) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = lo;
+                            data.hi = j - inc;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                //Console.Out.WriteLine("Thread start: {0} ({1} - {2} Count:{3})", Thread.CurrentThread.ManagedThreadId, lo, hi, threadCount.ThreadCount);
+                                QuickSortDesc_ITMT_noNaN(vec, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = j - inc;
+                            s_quickSortStackMT[++s_quickSortStackPos] = lo;
+                        }
+                        lo = i;
+                    }
+                }
+                #endregion inner loop
+            }
+        }
+        unsafe private static void QuickSortAscIDX_ITMT_noNaN( complex* vec, double* vecIdx, int lo, int hi, int inc) {
+           
+            complex temp, pivotItem;
+            int pivotIndex, j, i;
+            s_quickSortStackPos = -1;
+           
+            complex a1, a2, a3;
+           
+            double ai1, ai2, ai3;
+            for (; ; ) {
+                #region inner loop
+                if (hi - lo < (ILNumerics.Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        ai1 = *(vecIdx + j);
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp <= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                            *(vecIdx + i + inc) = *(vecIdx + i);
+                        }
+                        *(vec + i + inc) = pivotItem;
+                        *(vecIdx + i + inc) = ai1;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--];
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo);
+                    a2 = *(vec + pivotIndex);
+                    a3 = *(vec + hi);
+                    ai1 = *(vecIdx + lo);
+                    ai2 = *(vecIdx + pivotIndex);
+                    ai3 = *(vecIdx + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    *(vecIdx + pivotIndex) = *(vecIdx + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 > a2) {
+                        if (a1 > a3) {
+                            if (a3 > a2) {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a2;
+                                *(vec + lo + inc) = a3;
+                                *(vecIdx + hi) = ai1;
+                                *(vecIdx + lo) = ai2;
+                                *(vecIdx + lo + inc) = ai3;
+                            } else {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a3;
+                                *(vec + lo + inc) = a2;
+                                *(vecIdx + hi) = ai1;
+                                *(vecIdx + lo) = ai3;
+                                *(vecIdx + lo + inc) = ai2;
+                            }
+                        } else {
+                            *(vec + lo) = a2;
+                            *(vec + lo + inc) = a1;
+                            *(vecIdx + lo) = ai2;
+                            *(vecIdx + lo + inc) = ai1;
+                        }
+                    } else {
+                        if (a2 > a3) {
+                            *(vec + hi) = a2;
+                            *(vecIdx + hi) = ai2;
+                            if (a3 > a1) {
+                                *(vec + lo + inc) = a3;
+                                *(vecIdx + lo + inc) = ai3;
+                            } else {
+                                *(vec + lo + inc) = a1;
+                                *(vec + lo) = a3;
+                                *(vecIdx + lo + inc) = ai1;
+                                *(vecIdx + lo) = ai3;
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2;
+                            *(vecIdx + lo + inc) = ai2;
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi;
+                    pivotItem = *(vec + lo + inc);
+                    ai1 = *(vecIdx + lo + inc);
+                    for (; ; ) {
+                        do i += inc; while (*(vec + i) < pivotItem);
+                        do j -= inc; while (*(vec + j) > pivotItem);
+                        if (j < i) break;
+                        temp = *(vec + i);
+                        ai2 = *(vecIdx + i);
+                        *(vec + i) = *(vec + j);
+                        *(vec + j) = temp;
+                        *(vecIdx + i) = *(vecIdx + j);
+                        *(vecIdx + j) = ai2;
+                    }
+                    *(vec + lo + inc) = *(vec + j);
+                    *(vec + j) = pivotItem;
+                    *(vecIdx + lo + inc) = *(vecIdx + j);
+                    *(vecIdx + j) = ai1;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif
+                    if (hi - i + inc < j - lo) {
+                        if (s_threadCount < 100
+                                && (j - lo) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = i;
+                            data.hi = hi;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortAscIDX_ITMT_noNaN(vec, vecIdx, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = hi;
+                            s_quickSortStackMT[++s_quickSortStackPos] = i;
+                        }
+                        hi = j - inc;
+                    } else {
+                        if (s_threadCount < 100
+                            && (hi - i + inc) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = lo;
+                            data.hi = j - inc;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortAscIDX_ITMT_noNaN(vec, vecIdx, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = j - inc;
+                            s_quickSortStackMT[++s_quickSortStackPos] = lo;
+                        }
+                        lo = i;
+                    }
+                }
+                #endregion
+            }
+        }
+        unsafe private static void QuickSortDescIDX_ITMT_noNaN( complex* vec, double* vecIdx, int lo, int hi, int inc) {
+           
+            complex temp, pivotItem;
+            int pivotIndex, j, i;
+            s_quickSortStackPos = -1;
+           
+            complex a1, a2, a3;
+           
+            double ai1, ai2, ai3;
+            for (; ; ) {
+                #region inner loop
+                if (hi - lo < (ILNumerics.Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        ai1 = *(vecIdx + j);
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp >= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                            *(vecIdx + i + inc) = *(vecIdx + i);
+                        }
+                        *(vec + i + inc) = pivotItem;
+                        *(vecIdx + i + inc) = ai1;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--];
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo);
+                    a2 = *(vec + pivotIndex);
+                    a3 = *(vec + hi);
+                    ai1 = *(vecIdx + lo);
+                    ai2 = *(vecIdx + pivotIndex);
+                    ai3 = *(vecIdx + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    *(vecIdx + pivotIndex) = *(vecIdx + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 < a2) {
+                        if (a1 < a3) {
+                            if (a3 < a2) {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a2;
+                                *(vec + lo + inc) = a3;
+                                *(vecIdx + hi) = ai1;
+                                *(vecIdx + lo) = ai2;
+                                *(vecIdx + lo + inc) = ai3;
+                            } else {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a3;
+                                *(vec + lo + inc) = a2;
+                                *(vecIdx + hi) = ai1;
+                                *(vecIdx + lo) = ai3;
+                                *(vecIdx + lo + inc) = ai2;
+                            }
+                        } else {
+                            *(vec + lo) = a2;
+                            *(vec + lo + inc) = a1;
+                            *(vecIdx + lo) = ai2;
+                            *(vecIdx + lo + inc) = ai1;
+                        }
+                    } else {
+                        if (a2 < a3) {
+                            *(vec + hi) = a2;
+                            *(vecIdx + hi) = ai2;
+                            if (a3 < a1) {
+                                *(vec + lo + inc) = a3;
+                                *(vecIdx + lo + inc) = ai3;
+                            } else {
+                                *(vec + lo + inc) = a1;
+                                *(vec + lo) = a3;
+                                *(vecIdx + lo + inc) = ai1;
+                                *(vecIdx + lo) = ai3;
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2;
+                            *(vecIdx + lo + inc) = ai2;
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi;
+                    pivotItem = *(vec + lo + inc);
+                    ai1 = *(vecIdx + lo + inc);
+                    for (; ; ) {
+                        do i += inc; while (*(vec + i) > pivotItem);
+                        do j -= inc; while (*(vec + j) < pivotItem);
+                        if (j < i) break;
+                        temp = *(vec + i);
+                        ai2 = *(vecIdx + i);
+                        *(vec + i) = *(vec + j);
+                        *(vec + j) = temp;
+                        *(vecIdx + i) = *(vecIdx + j);
+                        *(vecIdx + j) = ai2;
+                    }
+                    *(vec + lo + inc) = *(vec + j);
+                    *(vec + j) = pivotItem;
+                    *(vecIdx + lo + inc) = *(vecIdx + j);
+                    *(vecIdx + j) = ai1;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif
+                    if (hi - i + inc < j - lo) {
+                        if (s_threadCount < 100
+                                && (j - lo) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = i;
+                            data.hi = hi;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortDescIDX_ITMT_noNaN(vec, vecIdx, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = hi;
+                            s_quickSortStackMT[++s_quickSortStackPos] = i;
+                        }
+                        hi = j - inc;
+                    } else {
+                        if (s_threadCount < 100
+                            && (hi - i + inc) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = lo;
+                            data.hi = j - inc;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortDescIDX_ITMT_noNaN(vec, vecIdx, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = j - inc;
+                            s_quickSortStackMT[++s_quickSortStackPos] = lo;
+                        }
+                        lo = i;
+                    }
+                }
+                #endregion
+            }
+        }
+        #endregion 
+        
+
+        /// <summary>
+        /// inline one dimensional quick sort, ascending, arbitrary element spacing, multithreaded
+        /// </summary>
+        /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+        /// <param name="lo">lowest index of sorting range</param>
+        /// <param name="hi">highest index of sorting range</param>
+        /// <param name="inc">spacing between elements (dimension specifier)</param>
+        /// <remarks>
+        /// <para>This function provides a low level in-place implementation of the quicksort algorithm. It is used by the 
+        /// higher level sorting API provided by <see cref="M:ILNumerics.ILMath.sort"/>. It is recommended to use the overloads 
+        /// of <see cref="M:ILNumerics.ILMath.sort()"/> instead of this function. That way, the decision, which lower level function
+        /// is to be called is made by the library automatically.</para>
+        /// <para>A quicksort algorithm is used for ranges of minimum lengths specified by 
+        /// <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/> and above. 
+        /// Below that length, a simple insertion sort is used instead.</para>
+        /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+        /// memory is needed to perform the sorting. That 'stack' memory defaults to length 100. The stack array
+        /// is cached internally.</para>
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>This function internally parallelizes the sorting in a very efficient manner. It usually outperforms 
+        /// non-parallelized versions of the quicksort algorithm for larger arrays. For smaller arrays, it may be more 
+        /// efficient, to use the non parallelized version instead: <see cref="M:ILNumerics.ILMath.QuickSortAsc(double[], int, int, int)"/></para></remarks>
+        public static void QuickSortAscMT( char[] vecP, int lo, int hi, int inc) {
+            System.Diagnostics.Debug.Assert(vecP != null && vecP.Length > hi);
+            System.Diagnostics.Debug.Assert(lo <= hi);
+            System.Diagnostics.Debug.Assert(lo >= 0);
+            if (vecP.Length < 2) return;
+            unsafe {
+                fixed ( char* vec = vecP) {
+                    
+                    s_threadCount = 1;
+                    QuickSortAsc_ITMT_noNaN(vec, lo, hi, inc);
+
+                } // fixed
+            } // unsafe 
+            Interlocked.Decrement(ref s_threadCount);
+            SpinWait.SpinUntil(() => {
+                return s_threadCount <= 0;
+            });
+        }
+
+        /// <summary>
+        /// inline one dimensional quick sort, descending, arbitrary element spacing, multithreaded
+        /// </summary>
+        /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+        /// <param name="lo">lowest index of sorting range</param>
+        /// <param name="hi">highest index of sorting range</param>
+        /// <param name="inc">spacing between elements (dimension specifier)</param>
+        /// <remarks>        
+        /// <para>This function provides a low level in-place implementation of the quicksort algorithm. It is used by the 
+        /// higher level sorting API provided by <see cref="M:ILNumerics.ILMath.sort"/>. It is recommended to use the overloads 
+        /// of <see cref="M:ILNumerics.ILMath.sort()"/> instead of this function. That way, the decision, which lower level function
+        /// is to be called is made by the library automatically.</para>
+        /// <para>A quicksort algorithm is used for ranges of minimum lengths specified by 
+        /// <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/> and above. 
+        /// Below that length, a simple insertion sort is used instead.</para>
+        /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+        /// memory is needed to perform the sorting. That 'stack' memory defaults to length 100.</para>
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>This function internally parallelizes the sorting in a very efficient manner. It usually outperforms 
+        /// non-parallelized versions of the quicksort algorithm for larger arrays. For smaller arrays, it may be more 
+        /// efficient, to use the non parallelized version instead: <see cref="M:ILNumerics.ILMath.QuickSortAsc(double[], int, int, int)"/></para></remarks>
+        public static void QuickSortDescMT( char[] vecP, int lo, int hi, int inc) {
+            System.Diagnostics.Debug.Assert(vecP != null && vecP.Length > hi);
+            System.Diagnostics.Debug.Assert(lo <= hi);
+            System.Diagnostics.Debug.Assert(lo >= 0);
+            if (vecP.Length < 2) return;
+            unsafe {
+                fixed ( char* vec = vecP) {
+                    
+                    s_threadCount = 1;
+                    QuickSortDesc_ITMT_noNaN(vec, lo, hi, inc);
+
+                } // fixed
+            } // unsafe 
+            Interlocked.Decrement(ref s_threadCount);
+            SpinWait.SpinUntil(() => {
+                return s_threadCount <= 0;
+            });
+        }
+        /// <summary>
+        /// inline one dimensional quick sort, ascending, arbitrary element spacing, indices aware
+        /// </summary>
+        /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+        /// <param name="lo">lowest index of sorting range</param>
+        /// <param name="hi">highest index of sorting range</param>
+        /// <param name="idxP">indices vector, content will in-place be sorted along with <paramref name="vecP"/></param>
+        /// <param name="inc">spacing between elements (dimension specifier)</param>
+        /// <remarks>
+        /// <para>This function provides a low level in-place implementation of the quicksort algorithm. It is used by the 
+        /// higher level sorting API provided by <see cref="M:ILNumerics.ILMath.sort"/>. It is recommended to use the overloads 
+        /// of <see cref="M:ILNumerics.ILMath.sort()"/> instead of this function. That way, the decision, which lower level function
+        /// is to be called is made by the library automatically.</para>
+        /// <para>A quicksort algorithm is used for ranges of minimum lengths specified by 
+        /// <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/> and above. 
+        /// Below that length, a simple insertion sort is used instead.</para>
+        /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+        /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+        /// The size is determined by the value of 
+        /// <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/>.</para>
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>This function internally parallelizes the sorting in a very efficient manner. It usually outperforms 
+        /// non-parallelized versions of the quicksort algorithm for larger arrays. For smaller arrays, it may be more 
+        /// efficient, to use the non parallelized version instead: <see cref="M:ILNumerics.ILMath.QuickSortAsc(double[], int, int, int)"/></para></remarks>
+        public static void QuickSortAscIDXMT( char[] vecP,  double[] idxP, int lo, int hi, int inc) {
+            System.Diagnostics.Debug.Assert(vecP != null && vecP.Length > hi);
+            System.Diagnostics.Debug.Assert(idxP != null && idxP.Length > hi);
+            System.Diagnostics.Debug.Assert(lo <= hi);
+            System.Diagnostics.Debug.Assert(lo >= 0);
+            if (vecP.Length < 2) return;
+            int[] stack = ILMemoryPool.Pool.New<int>(ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth * 2);
+            unsafe {
+                fixed ( double* vecIdx = idxP)
+                fixed ( char* vec = vecP) {
+                    
+                    s_threadCount = 1;
+                    QuickSortAscIDX_ITMT_noNaN(vec, vecIdx, lo, hi, inc);
+
+                } // fixed
+            } // unsafe 
+            Interlocked.Decrement(ref s_threadCount);
+            SpinWait.SpinUntil(() => {
+                return s_threadCount <= 0;
+            });
+        }
+
+        /// <summary>
+        /// inline one dimensional quick sort, descending, arbitrary element spacing, indices aware
+        /// </summary>
+        /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+        /// <param name="lo">lowest index of sorting range</param>
+        /// <param name="hi">highest index of sorting range</param>
+        /// <param name="idxP">indices vector, content will in-place be sorted along with <paramref name="vecP"/></param>
+        /// <param name="inc">spacing between elements (dimension specifier)</param>
+        /// <remarks>
+        /// <para>This function provides a low level in-place implementation of the quicksort algorithm. It is used by the 
+        /// higher level sorting API provided by <see cref="M:ILNumerics.ILMath.sort"/>. It is recommended to use the overloads 
+        /// of <see cref="M:ILNumerics.ILMath.sort()"/> instead of this function. That way, the decision, which lower level function
+        /// is to be called is made by the library automatically.</para>
+        /// <para>A quicksort algorithm is used for ranges of minimum lengths specified by 
+        /// <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/> and above. 
+        /// Below that length, a simple insertion sort is used instead.</para>
+        /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+        /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+        /// The size is determined by the value of 
+        /// <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/>.</para>
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>This function internally parallelizes the sorting in a very efficient manner. It usually outperforms 
+        /// non-parallelized versions of the quicksort algorithm for larger arrays. For smaller arrays, it may be more 
+        /// efficient, to use the non parallelized version instead: <see cref="M:ILNumerics.ILMath.QuickSortAsc(double[], int, int, int)"/></para></remarks>
+        public static void QuickSortDescIDXMT( char[] vecP,  double[] idxP, int lo, int hi, int inc) {
+            System.Diagnostics.Debug.Assert(vecP != null && vecP.Length > hi);
+            System.Diagnostics.Debug.Assert(idxP != null && idxP.Length > hi);
+            System.Diagnostics.Debug.Assert(lo <= hi);
+            System.Diagnostics.Debug.Assert(lo >= 0);
+           
+            if (vecP.Length < 2) return;
+            int[] stack = ILMemoryPool.Pool.New<int>(ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth * 2);
+            unsafe {
+                fixed ( double* vecIdx = idxP)
+                fixed ( char* vec = vecP) {
+                    
+                    Interlocked.Increment(ref s_threadCount);
+                    QuickSortDescIDX_ITMT_noNaN(vec, vecIdx, lo, hi, inc);
+                } // fixed
+            } // unsafe 
+            Interlocked.Decrement(ref s_threadCount);
+            SpinWait.SpinUntil(() => {
+                return s_threadCount <= 0;
+            });
+        }
+
+        #region private functions
+        unsafe private static void QuickSortAsc_ITMT_noNaN( char* vec, int lo, int hi, int inc) {
+            int pivotIndex, i, j;
+            s_quickSortStackPos = -1;
+           
+            char a1, a2, a3;
+           
+            char temp, pivotItem;
+            for (; ; ) {
+                #region innerloop
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp <= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                        }
+                        *(vec + i + inc) = pivotItem;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--];
+                } else {
+                    #region quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo);
+                    a2 = *(vec + pivotIndex);
+                    a3 = *(vec + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 > a2) {
+                        if (a1 > a3) {
+                            if (a3 > a2) {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a2;
+                                *(vec + lo + inc) = a3;
+                            } else {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a3;
+                                *(vec + lo + inc) = a2;
+                            }
+                        } else {
+                            *(vec + lo) = a2;
+                            *(vec + lo + inc) = a1;
+                        }
+                    } else {
+                        if (a2 > a3) {
+                            *(vec + hi) = a2;
+                            if (a3 > a1) {
+                                *(vec + lo + inc) = a3;
+                            } else {
+                                *(vec + lo + inc) = a1;
+                                *(vec + lo) = a3;
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2;
+                        }
+                    }
+                    #endregion
+                   
+                    char* vecI = vec + lo + inc, vecJ = vec + hi;
+                    pivotItem = *vecI;
+                    for (; ; ) {
+                        do vecI += inc; while (*vecI < pivotItem);
+                        do vecJ -= inc; while (*vecJ > pivotItem);
+                        if (vecJ < vecI) break;
+                        temp = *vecI;
+                        *vecI = *vecJ;
+                        *vecJ = temp;
+                    }
+                    *(vec + lo + inc) = *vecJ;
+                    *vecJ = pivotItem;
+
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif
+                    #endregion
+                    i = (int)(vecI - vec);
+                    j = (int)(vecJ - vec);
+                    if (hi - i + inc < j - lo) {
+                        if (s_threadCount < 100
+                                && (j - lo) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = i;
+                            data.hi = hi;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortAsc_ITMT_noNaN(vec, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = hi;
+                            s_quickSortStackMT[++s_quickSortStackPos] = i;
+                        }
+                        hi = j - inc;
+                    } else {
+                        if (s_threadCount < 100
+                            && (hi - i + inc) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = lo;
+                            data.hi = j - inc;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                //Console.Out.WriteLine("Thread start: {0} ({1} - {2} Count:{3})", Thread.CurrentThread.ManagedThreadId, lo, hi, threadCount.ThreadCount);
+                                QuickSortAsc_ITMT_noNaN(vec, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = j - inc;
+                            s_quickSortStackMT[++s_quickSortStackPos] = lo;
+                        }
+                        lo = i;
+                    }
+                }
+                #endregion inner loop
+            }
+        }
+        unsafe private static void QuickSortDesc_ITMT_noNaN( char* vec, int lo, int hi, int inc) {
+            int pivotIndex, i, j;
+            s_quickSortStackPos = -1;
+           
+            char a1, a2, a3;
+           
+            char temp, pivotItem;
+            for (; ; ) {
+                #region innerloop
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp >= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                        }
+                        *(vec + i + inc) = pivotItem;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--];
+                } else {
+                    #region quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo);
+                    a2 = *(vec + pivotIndex);
+                    a3 = *(vec + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 < a2) {
+                        if (a1 < a3) {
+                            if (a3 < a2) {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a2;
+                                *(vec + lo + inc) = a3;
+                            } else {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a3;
+                                *(vec + lo + inc) = a2;
+                            }
+                        } else {
+                            *(vec + lo) = a2;
+                            *(vec + lo + inc) = a1;
+                        }
+                    } else {
+                        if (a2 < a3) {
+                            *(vec + hi) = a2;
+                            if (a3 < a1) {
+                                *(vec + lo + inc) = a3;
+                            } else {
+                                *(vec + lo + inc) = a1;
+                                *(vec + lo) = a3;
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2;
+                        }
+                    }
+                    #endregion
+                   
+                    char* vecI = vec + lo + inc, vecJ = vec + hi;
+                    pivotItem = *vecI;
+                    for (; ; ) {
+                        do vecI += inc; while (*vecI > pivotItem);
+                        do vecJ -= inc; while (*vecJ < pivotItem);
+                        if (vecJ < vecI) break;
+                        temp = *vecI;
+                        *vecI = *vecJ;
+                        *vecJ = temp;
+                    }
+                    *(vec + lo + inc) = *vecJ;
+                    *vecJ = pivotItem;
+
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif
+                    #endregion
+                    i = (int)(vecI - vec);
+                    j = (int)(vecJ - vec);
+                    if (hi - i + inc < j - lo) {
+                        if (s_threadCount < 100
+                                && (j - lo) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = i;
+                            data.hi = hi;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortDesc_ITMT_noNaN(vec, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = hi;
+                            s_quickSortStackMT[++s_quickSortStackPos] = i;
+                        }
+                        hi = j - inc;
+                    } else {
+                        if (s_threadCount < 100
+                            && (hi - i + inc) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = lo;
+                            data.hi = j - inc;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                //Console.Out.WriteLine("Thread start: {0} ({1} - {2} Count:{3})", Thread.CurrentThread.ManagedThreadId, lo, hi, threadCount.ThreadCount);
+                                QuickSortDesc_ITMT_noNaN(vec, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = j - inc;
+                            s_quickSortStackMT[++s_quickSortStackPos] = lo;
+                        }
+                        lo = i;
+                    }
+                }
+                #endregion inner loop
+            }
+        }
+        unsafe private static void QuickSortAscIDX_ITMT_noNaN( char* vec, double* vecIdx, int lo, int hi, int inc) {
+           
+            char temp, pivotItem;
+            int pivotIndex, j, i;
+            s_quickSortStackPos = -1;
+           
+            char a1, a2, a3;
+           
+            double ai1, ai2, ai3;
+            for (; ; ) {
+                #region inner loop
+                if (hi - lo < (ILNumerics.Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        ai1 = *(vecIdx + j);
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp <= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                            *(vecIdx + i + inc) = *(vecIdx + i);
+                        }
+                        *(vec + i + inc) = pivotItem;
+                        *(vecIdx + i + inc) = ai1;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--];
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo);
+                    a2 = *(vec + pivotIndex);
+                    a3 = *(vec + hi);
+                    ai1 = *(vecIdx + lo);
+                    ai2 = *(vecIdx + pivotIndex);
+                    ai3 = *(vecIdx + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    *(vecIdx + pivotIndex) = *(vecIdx + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 > a2) {
+                        if (a1 > a3) {
+                            if (a3 > a2) {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a2;
+                                *(vec + lo + inc) = a3;
+                                *(vecIdx + hi) = ai1;
+                                *(vecIdx + lo) = ai2;
+                                *(vecIdx + lo + inc) = ai3;
+                            } else {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a3;
+                                *(vec + lo + inc) = a2;
+                                *(vecIdx + hi) = ai1;
+                                *(vecIdx + lo) = ai3;
+                                *(vecIdx + lo + inc) = ai2;
+                            }
+                        } else {
+                            *(vec + lo) = a2;
+                            *(vec + lo + inc) = a1;
+                            *(vecIdx + lo) = ai2;
+                            *(vecIdx + lo + inc) = ai1;
+                        }
+                    } else {
+                        if (a2 > a3) {
+                            *(vec + hi) = a2;
+                            *(vecIdx + hi) = ai2;
+                            if (a3 > a1) {
+                                *(vec + lo + inc) = a3;
+                                *(vecIdx + lo + inc) = ai3;
+                            } else {
+                                *(vec + lo + inc) = a1;
+                                *(vec + lo) = a3;
+                                *(vecIdx + lo + inc) = ai1;
+                                *(vecIdx + lo) = ai3;
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2;
+                            *(vecIdx + lo + inc) = ai2;
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi;
+                    pivotItem = *(vec + lo + inc);
+                    ai1 = *(vecIdx + lo + inc);
+                    for (; ; ) {
+                        do i += inc; while (*(vec + i) < pivotItem);
+                        do j -= inc; while (*(vec + j) > pivotItem);
+                        if (j < i) break;
+                        temp = *(vec + i);
+                        ai2 = *(vecIdx + i);
+                        *(vec + i) = *(vec + j);
+                        *(vec + j) = temp;
+                        *(vecIdx + i) = *(vecIdx + j);
+                        *(vecIdx + j) = ai2;
+                    }
+                    *(vec + lo + inc) = *(vec + j);
+                    *(vec + j) = pivotItem;
+                    *(vecIdx + lo + inc) = *(vecIdx + j);
+                    *(vecIdx + j) = ai1;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif
+                    if (hi - i + inc < j - lo) {
+                        if (s_threadCount < 100
+                                && (j - lo) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = i;
+                            data.hi = hi;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortAscIDX_ITMT_noNaN(vec, vecIdx, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = hi;
+                            s_quickSortStackMT[++s_quickSortStackPos] = i;
+                        }
+                        hi = j - inc;
+                    } else {
+                        if (s_threadCount < 100
+                            && (hi - i + inc) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = lo;
+                            data.hi = j - inc;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortAscIDX_ITMT_noNaN(vec, vecIdx, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = j - inc;
+                            s_quickSortStackMT[++s_quickSortStackPos] = lo;
+                        }
+                        lo = i;
+                    }
+                }
+                #endregion
+            }
+        }
+        unsafe private static void QuickSortDescIDX_ITMT_noNaN( char* vec, double* vecIdx, int lo, int hi, int inc) {
+           
+            char temp, pivotItem;
+            int pivotIndex, j, i;
+            s_quickSortStackPos = -1;
+           
+            char a1, a2, a3;
+           
+            double ai1, ai2, ai3;
+            for (; ; ) {
+                #region inner loop
+                if (hi - lo < (ILNumerics.Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        ai1 = *(vecIdx + j);
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp >= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                            *(vecIdx + i + inc) = *(vecIdx + i);
+                        }
+                        *(vec + i + inc) = pivotItem;
+                        *(vecIdx + i + inc) = ai1;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--];
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo);
+                    a2 = *(vec + pivotIndex);
+                    a3 = *(vec + hi);
+                    ai1 = *(vecIdx + lo);
+                    ai2 = *(vecIdx + pivotIndex);
+                    ai3 = *(vecIdx + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    *(vecIdx + pivotIndex) = *(vecIdx + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 < a2) {
+                        if (a1 < a3) {
+                            if (a3 < a2) {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a2;
+                                *(vec + lo + inc) = a3;
+                                *(vecIdx + hi) = ai1;
+                                *(vecIdx + lo) = ai2;
+                                *(vecIdx + lo + inc) = ai3;
+                            } else {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a3;
+                                *(vec + lo + inc) = a2;
+                                *(vecIdx + hi) = ai1;
+                                *(vecIdx + lo) = ai3;
+                                *(vecIdx + lo + inc) = ai2;
+                            }
+                        } else {
+                            *(vec + lo) = a2;
+                            *(vec + lo + inc) = a1;
+                            *(vecIdx + lo) = ai2;
+                            *(vecIdx + lo + inc) = ai1;
+                        }
+                    } else {
+                        if (a2 < a3) {
+                            *(vec + hi) = a2;
+                            *(vecIdx + hi) = ai2;
+                            if (a3 < a1) {
+                                *(vec + lo + inc) = a3;
+                                *(vecIdx + lo + inc) = ai3;
+                            } else {
+                                *(vec + lo + inc) = a1;
+                                *(vec + lo) = a3;
+                                *(vecIdx + lo + inc) = ai1;
+                                *(vecIdx + lo) = ai3;
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2;
+                            *(vecIdx + lo + inc) = ai2;
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi;
+                    pivotItem = *(vec + lo + inc);
+                    ai1 = *(vecIdx + lo + inc);
+                    for (; ; ) {
+                        do i += inc; while (*(vec + i) > pivotItem);
+                        do j -= inc; while (*(vec + j) < pivotItem);
+                        if (j < i) break;
+                        temp = *(vec + i);
+                        ai2 = *(vecIdx + i);
+                        *(vec + i) = *(vec + j);
+                        *(vec + j) = temp;
+                        *(vecIdx + i) = *(vecIdx + j);
+                        *(vecIdx + j) = ai2;
+                    }
+                    *(vec + lo + inc) = *(vec + j);
+                    *(vec + j) = pivotItem;
+                    *(vecIdx + lo + inc) = *(vecIdx + j);
+                    *(vecIdx + j) = ai1;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif
+                    if (hi - i + inc < j - lo) {
+                        if (s_threadCount < 100
+                                && (j - lo) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = i;
+                            data.hi = hi;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortDescIDX_ITMT_noNaN(vec, vecIdx, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = hi;
+                            s_quickSortStackMT[++s_quickSortStackPos] = i;
+                        }
+                        hi = j - inc;
+                    } else {
+                        if (s_threadCount < 100
+                            && (hi - i + inc) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = lo;
+                            data.hi = j - inc;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortDescIDX_ITMT_noNaN(vec, vecIdx, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = j - inc;
+                            s_quickSortStackMT[++s_quickSortStackPos] = lo;
+                        }
+                        lo = i;
+                    }
+                }
+                #endregion
+            }
+        }
+        #endregion 
+        
+
+        /// <summary>
+        /// inline one dimensional quick sort, ascending, arbitrary element spacing, multithreaded
+        /// </summary>
+        /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+        /// <param name="lo">lowest index of sorting range</param>
+        /// <param name="hi">highest index of sorting range</param>
+        /// <param name="inc">spacing between elements (dimension specifier)</param>
+        /// <remarks>
+        /// <para>This function provides a low level in-place implementation of the quicksort algorithm. It is used by the 
+        /// higher level sorting API provided by <see cref="M:ILNumerics.ILMath.sort"/>. It is recommended to use the overloads 
+        /// of <see cref="M:ILNumerics.ILMath.sort()"/> instead of this function. That way, the decision, which lower level function
+        /// is to be called is made by the library automatically.</para>
+        /// <para>A quicksort algorithm is used for ranges of minimum lengths specified by 
+        /// <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/> and above. 
+        /// Below that length, a simple insertion sort is used instead.</para>
+        /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+        /// memory is needed to perform the sorting. That 'stack' memory defaults to length 100. The stack array
+        /// is cached internally.</para>
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>This function internally parallelizes the sorting in a very efficient manner. It usually outperforms 
+        /// non-parallelized versions of the quicksort algorithm for larger arrays. For smaller arrays, it may be more 
+        /// efficient, to use the non parallelized version instead: <see cref="M:ILNumerics.ILMath.QuickSortAsc(double[], int, int, int)"/></para></remarks>
+        public static void QuickSortAscMT( byte[] vecP, int lo, int hi, int inc) {
+            System.Diagnostics.Debug.Assert(vecP != null && vecP.Length > hi);
+            System.Diagnostics.Debug.Assert(lo <= hi);
+            System.Diagnostics.Debug.Assert(lo >= 0);
+            if (vecP.Length < 2) return;
+            unsafe {
+                fixed ( byte* vec = vecP) {
+                    
+                    s_threadCount = 1;
+                    QuickSortAsc_ITMT_noNaN(vec, lo, hi, inc);
+
+                } // fixed
+            } // unsafe 
+            Interlocked.Decrement(ref s_threadCount);
+            SpinWait.SpinUntil(() => {
+                return s_threadCount <= 0;
+            });
+        }
+
+        /// <summary>
+        /// inline one dimensional quick sort, descending, arbitrary element spacing, multithreaded
+        /// </summary>
+        /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+        /// <param name="lo">lowest index of sorting range</param>
+        /// <param name="hi">highest index of sorting range</param>
+        /// <param name="inc">spacing between elements (dimension specifier)</param>
+        /// <remarks>        
+        /// <para>This function provides a low level in-place implementation of the quicksort algorithm. It is used by the 
+        /// higher level sorting API provided by <see cref="M:ILNumerics.ILMath.sort"/>. It is recommended to use the overloads 
+        /// of <see cref="M:ILNumerics.ILMath.sort()"/> instead of this function. That way, the decision, which lower level function
+        /// is to be called is made by the library automatically.</para>
+        /// <para>A quicksort algorithm is used for ranges of minimum lengths specified by 
+        /// <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/> and above. 
+        /// Below that length, a simple insertion sort is used instead.</para>
+        /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+        /// memory is needed to perform the sorting. That 'stack' memory defaults to length 100.</para>
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>This function internally parallelizes the sorting in a very efficient manner. It usually outperforms 
+        /// non-parallelized versions of the quicksort algorithm for larger arrays. For smaller arrays, it may be more 
+        /// efficient, to use the non parallelized version instead: <see cref="M:ILNumerics.ILMath.QuickSortAsc(double[], int, int, int)"/></para></remarks>
+        public static void QuickSortDescMT( byte[] vecP, int lo, int hi, int inc) {
+            System.Diagnostics.Debug.Assert(vecP != null && vecP.Length > hi);
+            System.Diagnostics.Debug.Assert(lo <= hi);
+            System.Diagnostics.Debug.Assert(lo >= 0);
+            if (vecP.Length < 2) return;
+            unsafe {
+                fixed ( byte* vec = vecP) {
+                    
+                    s_threadCount = 1;
+                    QuickSortDesc_ITMT_noNaN(vec, lo, hi, inc);
+
+                } // fixed
+            } // unsafe 
+            Interlocked.Decrement(ref s_threadCount);
+            SpinWait.SpinUntil(() => {
+                return s_threadCount <= 0;
+            });
+        }
+        /// <summary>
+        /// inline one dimensional quick sort, ascending, arbitrary element spacing, indices aware
+        /// </summary>
+        /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+        /// <param name="lo">lowest index of sorting range</param>
+        /// <param name="hi">highest index of sorting range</param>
+        /// <param name="idxP">indices vector, content will in-place be sorted along with <paramref name="vecP"/></param>
+        /// <param name="inc">spacing between elements (dimension specifier)</param>
+        /// <remarks>
+        /// <para>This function provides a low level in-place implementation of the quicksort algorithm. It is used by the 
+        /// higher level sorting API provided by <see cref="M:ILNumerics.ILMath.sort"/>. It is recommended to use the overloads 
+        /// of <see cref="M:ILNumerics.ILMath.sort()"/> instead of this function. That way, the decision, which lower level function
+        /// is to be called is made by the library automatically.</para>
+        /// <para>A quicksort algorithm is used for ranges of minimum lengths specified by 
+        /// <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/> and above. 
+        /// Below that length, a simple insertion sort is used instead.</para>
+        /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+        /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+        /// The size is determined by the value of 
+        /// <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/>.</para>
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>This function internally parallelizes the sorting in a very efficient manner. It usually outperforms 
+        /// non-parallelized versions of the quicksort algorithm for larger arrays. For smaller arrays, it may be more 
+        /// efficient, to use the non parallelized version instead: <see cref="M:ILNumerics.ILMath.QuickSortAsc(double[], int, int, int)"/></para></remarks>
+        public static void QuickSortAscIDXMT( byte[] vecP,  double[] idxP, int lo, int hi, int inc) {
+            System.Diagnostics.Debug.Assert(vecP != null && vecP.Length > hi);
+            System.Diagnostics.Debug.Assert(idxP != null && idxP.Length > hi);
+            System.Diagnostics.Debug.Assert(lo <= hi);
+            System.Diagnostics.Debug.Assert(lo >= 0);
+            if (vecP.Length < 2) return;
+            int[] stack = ILMemoryPool.Pool.New<int>(ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth * 2);
+            unsafe {
+                fixed ( double* vecIdx = idxP)
+                fixed ( byte* vec = vecP) {
+                    
+                    s_threadCount = 1;
+                    QuickSortAscIDX_ITMT_noNaN(vec, vecIdx, lo, hi, inc);
+
+                } // fixed
+            } // unsafe 
+            Interlocked.Decrement(ref s_threadCount);
+            SpinWait.SpinUntil(() => {
+                return s_threadCount <= 0;
+            });
+        }
+
+        /// <summary>
+        /// inline one dimensional quick sort, descending, arbitrary element spacing, indices aware
+        /// </summary>
+        /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+        /// <param name="lo">lowest index of sorting range</param>
+        /// <param name="hi">highest index of sorting range</param>
+        /// <param name="idxP">indices vector, content will in-place be sorted along with <paramref name="vecP"/></param>
+        /// <param name="inc">spacing between elements (dimension specifier)</param>
+        /// <remarks>
+        /// <para>This function provides a low level in-place implementation of the quicksort algorithm. It is used by the 
+        /// higher level sorting API provided by <see cref="M:ILNumerics.ILMath.sort"/>. It is recommended to use the overloads 
+        /// of <see cref="M:ILNumerics.ILMath.sort()"/> instead of this function. That way, the decision, which lower level function
+        /// is to be called is made by the library automatically.</para>
+        /// <para>A quicksort algorithm is used for ranges of minimum lengths specified by 
+        /// <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/> and above. 
+        /// Below that length, a simple insertion sort is used instead.</para>
+        /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+        /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+        /// The size is determined by the value of 
+        /// <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/>.</para>
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>This function internally parallelizes the sorting in a very efficient manner. It usually outperforms 
+        /// non-parallelized versions of the quicksort algorithm for larger arrays. For smaller arrays, it may be more 
+        /// efficient, to use the non parallelized version instead: <see cref="M:ILNumerics.ILMath.QuickSortAsc(double[], int, int, int)"/></para></remarks>
+        public static void QuickSortDescIDXMT( byte[] vecP,  double[] idxP, int lo, int hi, int inc) {
+            System.Diagnostics.Debug.Assert(vecP != null && vecP.Length > hi);
+            System.Diagnostics.Debug.Assert(idxP != null && idxP.Length > hi);
+            System.Diagnostics.Debug.Assert(lo <= hi);
+            System.Diagnostics.Debug.Assert(lo >= 0);
+           
+            if (vecP.Length < 2) return;
+            int[] stack = ILMemoryPool.Pool.New<int>(ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth * 2);
+            unsafe {
+                fixed ( double* vecIdx = idxP)
+                fixed ( byte* vec = vecP) {
+                    
+                    Interlocked.Increment(ref s_threadCount);
+                    QuickSortDescIDX_ITMT_noNaN(vec, vecIdx, lo, hi, inc);
+                } // fixed
+            } // unsafe 
+            Interlocked.Decrement(ref s_threadCount);
+            SpinWait.SpinUntil(() => {
+                return s_threadCount <= 0;
+            });
+        }
+
+        #region private functions
+        unsafe private static void QuickSortAsc_ITMT_noNaN( byte* vec, int lo, int hi, int inc) {
+            int pivotIndex, i, j;
+            s_quickSortStackPos = -1;
+           
+            byte a1, a2, a3;
+           
+            byte temp, pivotItem;
+            for (; ; ) {
+                #region innerloop
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp <= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                        }
+                        *(vec + i + inc) = pivotItem;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--];
+                } else {
+                    #region quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo);
+                    a2 = *(vec + pivotIndex);
+                    a3 = *(vec + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 > a2) {
+                        if (a1 > a3) {
+                            if (a3 > a2) {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a2;
+                                *(vec + lo + inc) = a3;
+                            } else {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a3;
+                                *(vec + lo + inc) = a2;
+                            }
+                        } else {
+                            *(vec + lo) = a2;
+                            *(vec + lo + inc) = a1;
+                        }
+                    } else {
+                        if (a2 > a3) {
+                            *(vec + hi) = a2;
+                            if (a3 > a1) {
+                                *(vec + lo + inc) = a3;
+                            } else {
+                                *(vec + lo + inc) = a1;
+                                *(vec + lo) = a3;
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2;
+                        }
+                    }
+                    #endregion
+                   
+                    byte* vecI = vec + lo + inc, vecJ = vec + hi;
+                    pivotItem = *vecI;
+                    for (; ; ) {
+                        do vecI += inc; while (*vecI < pivotItem);
+                        do vecJ -= inc; while (*vecJ > pivotItem);
+                        if (vecJ < vecI) break;
+                        temp = *vecI;
+                        *vecI = *vecJ;
+                        *vecJ = temp;
+                    }
+                    *(vec + lo + inc) = *vecJ;
+                    *vecJ = pivotItem;
+
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif
+                    #endregion
+                    i = (int)(vecI - vec);
+                    j = (int)(vecJ - vec);
+                    if (hi - i + inc < j - lo) {
+                        if (s_threadCount < 100
+                                && (j - lo) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = i;
+                            data.hi = hi;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortAsc_ITMT_noNaN(vec, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = hi;
+                            s_quickSortStackMT[++s_quickSortStackPos] = i;
+                        }
+                        hi = j - inc;
+                    } else {
+                        if (s_threadCount < 100
+                            && (hi - i + inc) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = lo;
+                            data.hi = j - inc;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                //Console.Out.WriteLine("Thread start: {0} ({1} - {2} Count:{3})", Thread.CurrentThread.ManagedThreadId, lo, hi, threadCount.ThreadCount);
+                                QuickSortAsc_ITMT_noNaN(vec, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = j - inc;
+                            s_quickSortStackMT[++s_quickSortStackPos] = lo;
+                        }
+                        lo = i;
+                    }
+                }
+                #endregion inner loop
+            }
+        }
+        unsafe private static void QuickSortDesc_ITMT_noNaN( byte* vec, int lo, int hi, int inc) {
+            int pivotIndex, i, j;
+            s_quickSortStackPos = -1;
+           
+            byte a1, a2, a3;
+           
+            byte temp, pivotItem;
+            for (; ; ) {
+                #region innerloop
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp >= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                        }
+                        *(vec + i + inc) = pivotItem;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--];
+                } else {
+                    #region quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo);
+                    a2 = *(vec + pivotIndex);
+                    a3 = *(vec + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 < a2) {
+                        if (a1 < a3) {
+                            if (a3 < a2) {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a2;
+                                *(vec + lo + inc) = a3;
+                            } else {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a3;
+                                *(vec + lo + inc) = a2;
+                            }
+                        } else {
+                            *(vec + lo) = a2;
+                            *(vec + lo + inc) = a1;
+                        }
+                    } else {
+                        if (a2 < a3) {
+                            *(vec + hi) = a2;
+                            if (a3 < a1) {
+                                *(vec + lo + inc) = a3;
+                            } else {
+                                *(vec + lo + inc) = a1;
+                                *(vec + lo) = a3;
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2;
+                        }
+                    }
+                    #endregion
+                   
+                    byte* vecI = vec + lo + inc, vecJ = vec + hi;
+                    pivotItem = *vecI;
+                    for (; ; ) {
+                        do vecI += inc; while (*vecI > pivotItem);
+                        do vecJ -= inc; while (*vecJ < pivotItem);
+                        if (vecJ < vecI) break;
+                        temp = *vecI;
+                        *vecI = *vecJ;
+                        *vecJ = temp;
+                    }
+                    *(vec + lo + inc) = *vecJ;
+                    *vecJ = pivotItem;
+
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif
+                    #endregion
+                    i = (int)(vecI - vec);
+                    j = (int)(vecJ - vec);
+                    if (hi - i + inc < j - lo) {
+                        if (s_threadCount < 100
+                                && (j - lo) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = i;
+                            data.hi = hi;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortDesc_ITMT_noNaN(vec, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = hi;
+                            s_quickSortStackMT[++s_quickSortStackPos] = i;
+                        }
+                        hi = j - inc;
+                    } else {
+                        if (s_threadCount < 100
+                            && (hi - i + inc) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = lo;
+                            data.hi = j - inc;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                //Console.Out.WriteLine("Thread start: {0} ({1} - {2} Count:{3})", Thread.CurrentThread.ManagedThreadId, lo, hi, threadCount.ThreadCount);
+                                QuickSortDesc_ITMT_noNaN(vec, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = j - inc;
+                            s_quickSortStackMT[++s_quickSortStackPos] = lo;
+                        }
+                        lo = i;
+                    }
+                }
+                #endregion inner loop
+            }
+        }
+        unsafe private static void QuickSortAscIDX_ITMT_noNaN( byte* vec, double* vecIdx, int lo, int hi, int inc) {
+           
+            byte temp, pivotItem;
+            int pivotIndex, j, i;
+            s_quickSortStackPos = -1;
+           
+            byte a1, a2, a3;
+           
+            double ai1, ai2, ai3;
+            for (; ; ) {
+                #region inner loop
+                if (hi - lo < (ILNumerics.Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        ai1 = *(vecIdx + j);
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp <= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                            *(vecIdx + i + inc) = *(vecIdx + i);
+                        }
+                        *(vec + i + inc) = pivotItem;
+                        *(vecIdx + i + inc) = ai1;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--];
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo);
+                    a2 = *(vec + pivotIndex);
+                    a3 = *(vec + hi);
+                    ai1 = *(vecIdx + lo);
+                    ai2 = *(vecIdx + pivotIndex);
+                    ai3 = *(vecIdx + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    *(vecIdx + pivotIndex) = *(vecIdx + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 > a2) {
+                        if (a1 > a3) {
+                            if (a3 > a2) {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a2;
+                                *(vec + lo + inc) = a3;
+                                *(vecIdx + hi) = ai1;
+                                *(vecIdx + lo) = ai2;
+                                *(vecIdx + lo + inc) = ai3;
+                            } else {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a3;
+                                *(vec + lo + inc) = a2;
+                                *(vecIdx + hi) = ai1;
+                                *(vecIdx + lo) = ai3;
+                                *(vecIdx + lo + inc) = ai2;
+                            }
+                        } else {
+                            *(vec + lo) = a2;
+                            *(vec + lo + inc) = a1;
+                            *(vecIdx + lo) = ai2;
+                            *(vecIdx + lo + inc) = ai1;
+                        }
+                    } else {
+                        if (a2 > a3) {
+                            *(vec + hi) = a2;
+                            *(vecIdx + hi) = ai2;
+                            if (a3 > a1) {
+                                *(vec + lo + inc) = a3;
+                                *(vecIdx + lo + inc) = ai3;
+                            } else {
+                                *(vec + lo + inc) = a1;
+                                *(vec + lo) = a3;
+                                *(vecIdx + lo + inc) = ai1;
+                                *(vecIdx + lo) = ai3;
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2;
+                            *(vecIdx + lo + inc) = ai2;
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi;
+                    pivotItem = *(vec + lo + inc);
+                    ai1 = *(vecIdx + lo + inc);
+                    for (; ; ) {
+                        do i += inc; while (*(vec + i) < pivotItem);
+                        do j -= inc; while (*(vec + j) > pivotItem);
+                        if (j < i) break;
+                        temp = *(vec + i);
+                        ai2 = *(vecIdx + i);
+                        *(vec + i) = *(vec + j);
+                        *(vec + j) = temp;
+                        *(vecIdx + i) = *(vecIdx + j);
+                        *(vecIdx + j) = ai2;
+                    }
+                    *(vec + lo + inc) = *(vec + j);
+                    *(vec + j) = pivotItem;
+                    *(vecIdx + lo + inc) = *(vecIdx + j);
+                    *(vecIdx + j) = ai1;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif
+                    if (hi - i + inc < j - lo) {
+                        if (s_threadCount < 100
+                                && (j - lo) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = i;
+                            data.hi = hi;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortAscIDX_ITMT_noNaN(vec, vecIdx, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = hi;
+                            s_quickSortStackMT[++s_quickSortStackPos] = i;
+                        }
+                        hi = j - inc;
+                    } else {
+                        if (s_threadCount < 100
+                            && (hi - i + inc) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = lo;
+                            data.hi = j - inc;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortAscIDX_ITMT_noNaN(vec, vecIdx, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = j - inc;
+                            s_quickSortStackMT[++s_quickSortStackPos] = lo;
+                        }
+                        lo = i;
+                    }
+                }
+                #endregion
+            }
+        }
+        unsafe private static void QuickSortDescIDX_ITMT_noNaN( byte* vec, double* vecIdx, int lo, int hi, int inc) {
+           
+            byte temp, pivotItem;
+            int pivotIndex, j, i;
+            s_quickSortStackPos = -1;
+           
+            byte a1, a2, a3;
+           
+            double ai1, ai2, ai3;
+            for (; ; ) {
+                #region inner loop
+                if (hi - lo < (ILNumerics.Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        ai1 = *(vecIdx + j);
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp >= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                            *(vecIdx + i + inc) = *(vecIdx + i);
+                        }
+                        *(vec + i + inc) = pivotItem;
+                        *(vecIdx + i + inc) = ai1;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--];
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo);
+                    a2 = *(vec + pivotIndex);
+                    a3 = *(vec + hi);
+                    ai1 = *(vecIdx + lo);
+                    ai2 = *(vecIdx + pivotIndex);
+                    ai3 = *(vecIdx + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    *(vecIdx + pivotIndex) = *(vecIdx + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 < a2) {
+                        if (a1 < a3) {
+                            if (a3 < a2) {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a2;
+                                *(vec + lo + inc) = a3;
+                                *(vecIdx + hi) = ai1;
+                                *(vecIdx + lo) = ai2;
+                                *(vecIdx + lo + inc) = ai3;
+                            } else {
+                                *(vec + hi) = a1;
+                                *(vec + lo) = a3;
+                                *(vec + lo + inc) = a2;
+                                *(vecIdx + hi) = ai1;
+                                *(vecIdx + lo) = ai3;
+                                *(vecIdx + lo + inc) = ai2;
+                            }
+                        } else {
+                            *(vec + lo) = a2;
+                            *(vec + lo + inc) = a1;
+                            *(vecIdx + lo) = ai2;
+                            *(vecIdx + lo + inc) = ai1;
+                        }
+                    } else {
+                        if (a2 < a3) {
+                            *(vec + hi) = a2;
+                            *(vecIdx + hi) = ai2;
+                            if (a3 < a1) {
+                                *(vec + lo + inc) = a3;
+                                *(vecIdx + lo + inc) = ai3;
+                            } else {
+                                *(vec + lo + inc) = a1;
+                                *(vec + lo) = a3;
+                                *(vecIdx + lo + inc) = ai1;
+                                *(vecIdx + lo) = ai3;
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2;
+                            *(vecIdx + lo + inc) = ai2;
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi;
+                    pivotItem = *(vec + lo + inc);
+                    ai1 = *(vecIdx + lo + inc);
+                    for (; ; ) {
+                        do i += inc; while (*(vec + i) > pivotItem);
+                        do j -= inc; while (*(vec + j) < pivotItem);
+                        if (j < i) break;
+                        temp = *(vec + i);
+                        ai2 = *(vecIdx + i);
+                        *(vec + i) = *(vec + j);
+                        *(vec + j) = temp;
+                        *(vecIdx + i) = *(vecIdx + j);
+                        *(vecIdx + j) = ai2;
+                    }
+                    *(vec + lo + inc) = *(vec + j);
+                    *(vec + j) = pivotItem;
+                    *(vecIdx + lo + inc) = *(vecIdx + j);
+                    *(vecIdx + j) = ai1;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif
+                    if (hi - i + inc < j - lo) {
+                        if (s_threadCount < 100
+                                && (j - lo) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = i;
+                            data.hi = hi;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortDescIDX_ITMT_noNaN(vec, vecIdx, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = hi;
+                            s_quickSortStackMT[++s_quickSortStackPos] = i;
+                        }
+                        hi = j - inc;
+                    } else {
+                        if (s_threadCount < 100
+                            && (hi - i + inc) / inc > Settings.s_minParallelElement2Count) {
+                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+                            Interlocked.Increment(ref s_threadCount);
+
+                            ILQuickSortQueueItemData data;
+                            data.lo = lo;
+                            data.hi = j - inc;
+                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+                                ILQuickSortQueueItemData d = (ILQuickSortQueueItemData)o;
+                                QuickSortDescIDX_ITMT_noNaN(vec, vecIdx, d.lo, d.hi, inc);
+                                Interlocked.Decrement(ref s_threadCount);
+                            }, data);
+                        } else {
+                            // TODO: in order to minimize the stack size, do smaller chunk now and put larger chunk into stack! 
+                            if (s_quickSortStackMT == null)
+                                s_quickSortStackMT = new int[100];
+                            s_quickSortStackMT[++s_quickSortStackPos] = j - inc;
+                            s_quickSortStackMT[++s_quickSortStackPos] = lo;
+                        }
+                        lo = i;
+                    }
+                }
+                #endregion
+            }
+        }
+        #endregion 
+        
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+
+
+        /// <summary>
+        /// sort nan elements to the end, test if the array is already sorted
+        /// </summary>
+        /// <returns>true, if already sorted</returns>
+        unsafe private static bool checkNaNIDXAsc(int lo, ref int hi, int inc, double* vecIdx, double* vec) {
+            double tempIdx;
+            bool isSorted = true;
+            for (; hi >= lo && double.IsNaN(*(vec + hi)); hi -= inc) ;
+            if (hi >= lo) {
+                
+                double lastVal = *(vec + hi), curVal;
+                for (int i = hi - inc; i >= lo; i -= inc) {
+                    curVal = *(vec + i);
+                    if (double.IsNaN(curVal)) {
+                        *(vec + i) = *(vec + hi);
+                        *(vec + hi) = double.NaN;
+                        tempIdx = *(vecIdx + hi);
+                        *(vecIdx + hi) = *(vecIdx + i);
+                        *(vecIdx + i) = tempIdx;
+                        hi -= inc;
+                    } else if (isSorted) {
+                        if (curVal > lastVal) {
+                            isSorted = false;
+                        } else {
+                            lastVal = curVal;
+                        }
+                    }
+                }
+            }
+            return isSorted;
+        }
+
+        /// <summary>
+        /// sort nan elements to the end, test if the array is already sorted
+        /// </summary>
+        /// <returns>true, if already sorted</returns>
+        unsafe private static bool checkNaNIDXDesc(int lo, ref int hi, int inc, double* vecIdx, double* vec) {
+            bool isSorted = true;
+            double tempIDX;
+            for (; hi >= lo && double.IsNaN(*(vec + hi)); hi -= inc) ;
+            if (hi >= lo) {
+                
+                double lastVal = *(vec + hi), curVal;
+                for (int i = hi - inc; i >= lo; i -= inc) {
+                    curVal = *(vec + i); 
+                    if (double.IsNaN(curVal)) {
+                        *(vec + i) = *(vec + hi);
+                        *(vec + hi) = double.NaN;
+                        tempIDX = *(vecIdx + hi);
+                        *(vecIdx + hi) = *(vecIdx + i);
+                        *(vecIdx + i) = tempIDX;
+                        hi -= inc;
+                    } else if (isSorted) {
+                        if (curVal < lastVal) {
+                            isSorted = false;
+                        } else {
+                            lastVal = curVal;
+                        }
+                    }
+                }
+            }
+            return isSorted;
+        }
+
+        /// <summary>
+        /// sort nan elements to the end, test if the array is already sorted
+        /// </summary>
+        /// <returns>true, if already sorted</returns>
+        unsafe private static bool checkNaNAsc(int lo, ref int hi, int inc, double* vec) {
+            bool isSorted = true; 
+            for (; hi >= lo && double.IsNaN(*(vec + hi)); hi -= inc) ;
+            if (hi >= lo) {
+                
+                double temp, lastVal = *(vec + hi);
+                for (int i = hi; i >= lo; i -= inc) { // SMA: Started at hi-inc, which would yield isSorted = true when all elements are in order but the last!
+                    temp = *(vec + i);
+                    if (double.IsNaN(temp)) {
+                        *(vec + i) = *(vec + hi);
+                        *(vec + hi) = double.NaN;
+                        hi -= inc;
+                    } else if (isSorted) {
+                        if (temp > lastVal) {
+                            isSorted = false;
+                        } else {
+                            lastVal = temp;
+                        }
+                    }
+                }
+            }
+            return isSorted; 
+        }
+        /// <summary>
+        /// sort nan elements to the end, test if the array is already sorted
+        /// </summary>
+        /// <returns>true, if already sorted</returns>
+        unsafe private static bool checkNaNDesc(int lo, ref int hi, int inc, double* vec) {
+            bool isSorted = true; 
+            for (; hi >= lo && double.IsNaN(*(vec + hi)); hi -= inc) ;
+            if (hi >= lo) {
+                
+                double temp, lastVal = *(vec + hi);
+                for (int i = hi; i >= lo; i -= inc) { // SMA: Started at hi-inc, which would yield isSorted = true when all elements are in order but the last!
+                    temp = *(vec + i);
+                    if (double.IsNaN(temp)) {
+                        *(vec + i) = *(vec + hi);
+                        *(vec + hi) = double.NaN;
+                        hi -= inc;
+                    } else if (isSorted) {
+                        if (temp < lastVal) {
+                            isSorted = false;
+                        } else {
+                            lastVal = temp;
+                        }
+                    }
+                }
+            }
+            return isSorted; 
+        }
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+
+        /// <summary>
+        /// sort nan elements to the end, test if the array is already sorted
+        /// </summary>
+        /// <returns>true, if already sorted</returns>
+        unsafe private static bool checkNaNIDXAsc(int lo, ref int hi, int inc, double* vecIdx, float* vec) {
+            double tempIdx;
+            bool isSorted = true;
+            for (; hi >= lo && float.IsNaN(*(vec + hi)); hi -= inc) ;
+            if (hi >= lo) {
+               
+                float lastVal = *(vec + hi), curVal;
+                for (int i = hi - inc; i >= lo; i -= inc) {
+                    curVal = *(vec + i);
+                    if (float.IsNaN(curVal)) {
+                        *(vec + i) = *(vec + hi);
+                        *(vec + hi) = float.NaN;
+                        tempIdx = *(vecIdx + hi);
+                        *(vecIdx + hi) = *(vecIdx + i);
+                        *(vecIdx + i) = tempIdx;
+                        hi -= inc;
+                    } else if (isSorted) {
+                        if (curVal > lastVal) {
+                            isSorted = false;
+                        } else {
+                            lastVal = curVal;
+                        }
+                    }
+                }
+            }
+            return isSorted;
+        }
+
+        /// <summary>
+        /// sort nan elements to the end, test if the array is already sorted
+        /// </summary>
+        /// <returns>true, if already sorted</returns>
+        unsafe private static bool checkNaNIDXDesc(int lo, ref int hi, int inc, double* vecIdx, float* vec) {
+            bool isSorted = true;
+            double tempIDX;
+            for (; hi >= lo && float.IsNaN(*(vec + hi)); hi -= inc) ;
+            if (hi >= lo) {
+               
+                float lastVal = *(vec + hi), curVal;
+                for (int i = hi - inc; i >= lo; i -= inc) {
+                    curVal = *(vec + i); 
+                    if (float.IsNaN(curVal)) {
+                        *(vec + i) = *(vec + hi);
+                        *(vec + hi) = float.NaN;
+                        tempIDX = *(vecIdx + hi);
+                        *(vecIdx + hi) = *(vecIdx + i);
+                        *(vecIdx + i) = tempIDX;
+                        hi -= inc;
+                    } else if (isSorted) {
+                        if (curVal < lastVal) {
+                            isSorted = false;
+                        } else {
+                            lastVal = curVal;
+                        }
+                    }
+                }
+            }
+            return isSorted;
+        }
+
+        /// <summary>
+        /// sort nan elements to the end, test if the array is already sorted
+        /// </summary>
+        /// <returns>true, if already sorted</returns>
+        unsafe private static bool checkNaNAsc(int lo, ref int hi, int inc, float* vec) {
+            bool isSorted = true; 
+            for (; hi >= lo && float.IsNaN(*(vec + hi)); hi -= inc) ;
+            if (hi >= lo) {
+               
+                float temp, lastVal = *(vec + hi);
+                for (int i = hi; i >= lo; i -= inc) { // SMA: Started at hi-inc, which would yield isSorted = true when all elements are in order but the last!
+                    temp = *(vec + i);
+                    if (float.IsNaN(temp)) {
+                        *(vec + i) = *(vec + hi);
+                        *(vec + hi) = float.NaN;
+                        hi -= inc;
+                    } else if (isSorted) {
+                        if (temp > lastVal) {
+                            isSorted = false;
+                        } else {
+                            lastVal = temp;
+                        }
+                    }
+                }
+            }
+            return isSorted; 
+        }
+        /// <summary>
+        /// sort nan elements to the end, test if the array is already sorted
+        /// </summary>
+        /// <returns>true, if already sorted</returns>
+        unsafe private static bool checkNaNDesc(int lo, ref int hi, int inc, float* vec) {
+            bool isSorted = true; 
+            for (; hi >= lo && float.IsNaN(*(vec + hi)); hi -= inc) ;
+            if (hi >= lo) {
+               
+                float temp, lastVal = *(vec + hi);
+                for (int i = hi; i >= lo; i -= inc) { // SMA: Started at hi-inc, which would yield isSorted = true when all elements are in order but the last!
+                    temp = *(vec + i);
+                    if (float.IsNaN(temp)) {
+                        *(vec + i) = *(vec + hi);
+                        *(vec + hi) = float.NaN;
+                        hi -= inc;
+                    } else if (isSorted) {
+                        if (temp < lastVal) {
+                            isSorted = false;
+                        } else {
+                            lastVal = temp;
+                        }
+                    }
+                }
+            }
+            return isSorted; 
+        }
+
+
+        /// <summary>
+        /// sort nan elements to the end, test if the array is already sorted
+        /// </summary>
+        /// <returns>true, if already sorted</returns>
+        unsafe private static bool checkNaNIDXAsc(int lo, ref int hi, int inc, double* vecIdx, fcomplex* vec) {
+            double tempIdx;
+            bool isSorted = true;
+            for (; hi >= lo && fcomplex.IsNaN(*(vec + hi)); hi -= inc) ;
+            if (hi >= lo) {
+               
+                fcomplex lastVal = *(vec + hi), curVal;
+                for (int i = hi - inc; i >= lo; i -= inc) {
+                    curVal = *(vec + i);
+                    if (fcomplex.IsNaN(curVal)) {
+                        *(vec + i) = *(vec + hi);
+                        *(vec + hi) = fcomplex.NaN;
+                        tempIdx = *(vecIdx + hi);
+                        *(vecIdx + hi) = *(vecIdx + i);
+                        *(vecIdx + i) = tempIdx;
+                        hi -= inc;
+                    } else if (isSorted) {
+                        if (curVal > lastVal) {
+                            isSorted = false;
+                        } else {
+                            lastVal = curVal;
+                        }
+                    }
+                }
+            }
+            return isSorted;
+        }
+
+        /// <summary>
+        /// sort nan elements to the end, test if the array is already sorted
+        /// </summary>
+        /// <returns>true, if already sorted</returns>
+        unsafe private static bool checkNaNIDXDesc(int lo, ref int hi, int inc, double* vecIdx, fcomplex* vec) {
+            bool isSorted = true;
+            double tempIDX;
+            for (; hi >= lo && fcomplex.IsNaN(*(vec + hi)); hi -= inc) ;
+            if (hi >= lo) {
+               
+                fcomplex lastVal = *(vec + hi), curVal;
+                for (int i = hi - inc; i >= lo; i -= inc) {
+                    curVal = *(vec + i); 
+                    if (fcomplex.IsNaN(curVal)) {
+                        *(vec + i) = *(vec + hi);
+                        *(vec + hi) = fcomplex.NaN;
+                        tempIDX = *(vecIdx + hi);
+                        *(vecIdx + hi) = *(vecIdx + i);
+                        *(vecIdx + i) = tempIDX;
+                        hi -= inc;
+                    } else if (isSorted) {
+                        if (curVal < lastVal) {
+                            isSorted = false;
+                        } else {
+                            lastVal = curVal;
+                        }
+                    }
+                }
+            }
+            return isSorted;
+        }
+
+        /// <summary>
+        /// sort nan elements to the end, test if the array is already sorted
+        /// </summary>
+        /// <returns>true, if already sorted</returns>
+        unsafe private static bool checkNaNAsc(int lo, ref int hi, int inc, fcomplex* vec) {
+            bool isSorted = true; 
+            for (; hi >= lo && fcomplex.IsNaN(*(vec + hi)); hi -= inc) ;
+            if (hi >= lo) {
+               
+                fcomplex temp, lastVal = *(vec + hi);
+                for (int i = hi; i >= lo; i -= inc) { // SMA: Started at hi-inc, which would yield isSorted = true when all elements are in order but the last!
+                    temp = *(vec + i);
+                    if (fcomplex.IsNaN(temp)) {
+                        *(vec + i) = *(vec + hi);
+                        *(vec + hi) = fcomplex.NaN;
+                        hi -= inc;
+                    } else if (isSorted) {
+                        if (temp > lastVal) {
+                            isSorted = false;
+                        } else {
+                            lastVal = temp;
+                        }
+                    }
+                }
+            }
+            return isSorted; 
+        }
+        /// <summary>
+        /// sort nan elements to the end, test if the array is already sorted
+        /// </summary>
+        /// <returns>true, if already sorted</returns>
+        unsafe private static bool checkNaNDesc(int lo, ref int hi, int inc, fcomplex* vec) {
+            bool isSorted = true; 
+            for (; hi >= lo && fcomplex.IsNaN(*(vec + hi)); hi -= inc) ;
+            if (hi >= lo) {
+               
+                fcomplex temp, lastVal = *(vec + hi);
+                for (int i = hi; i >= lo; i -= inc) { // SMA: Started at hi-inc, which would yield isSorted = true when all elements are in order but the last!
+                    temp = *(vec + i);
+                    if (fcomplex.IsNaN(temp)) {
+                        *(vec + i) = *(vec + hi);
+                        *(vec + hi) = fcomplex.NaN;
+                        hi -= inc;
+                    } else if (isSorted) {
+                        if (temp < lastVal) {
+                            isSorted = false;
+                        } else {
+                            lastVal = temp;
+                        }
+                    }
+                }
+            }
+            return isSorted; 
+        }
+
+
+        /// <summary>
+        /// sort nan elements to the end, test if the array is already sorted
+        /// </summary>
+        /// <returns>true, if already sorted</returns>
+        unsafe private static bool checkNaNIDXAsc(int lo, ref int hi, int inc, double* vecIdx, complex* vec) {
+            double tempIdx;
+            bool isSorted = true;
+            for (; hi >= lo && complex.IsNaN(*(vec + hi)); hi -= inc) ;
+            if (hi >= lo) {
+               
+                complex lastVal = *(vec + hi), curVal;
+                for (int i = hi - inc; i >= lo; i -= inc) {
+                    curVal = *(vec + i);
+                    if (complex.IsNaN(curVal)) {
+                        *(vec + i) = *(vec + hi);
+                        *(vec + hi) = complex.NaN;
+                        tempIdx = *(vecIdx + hi);
+                        *(vecIdx + hi) = *(vecIdx + i);
+                        *(vecIdx + i) = tempIdx;
+                        hi -= inc;
+                    } else if (isSorted) {
+                        if (curVal > lastVal) {
+                            isSorted = false;
+                        } else {
+                            lastVal = curVal;
+                        }
+                    }
+                }
+            }
+            return isSorted;
+        }
+
+        /// <summary>
+        /// sort nan elements to the end, test if the array is already sorted
+        /// </summary>
+        /// <returns>true, if already sorted</returns>
+        unsafe private static bool checkNaNIDXDesc(int lo, ref int hi, int inc, double* vecIdx, complex* vec) {
+            bool isSorted = true;
+            double tempIDX;
+            for (; hi >= lo && complex.IsNaN(*(vec + hi)); hi -= inc) ;
+            if (hi >= lo) {
+               
+                complex lastVal = *(vec + hi), curVal;
+                for (int i = hi - inc; i >= lo; i -= inc) {
+                    curVal = *(vec + i); 
+                    if (complex.IsNaN(curVal)) {
+                        *(vec + i) = *(vec + hi);
+                        *(vec + hi) = complex.NaN;
+                        tempIDX = *(vecIdx + hi);
+                        *(vecIdx + hi) = *(vecIdx + i);
+                        *(vecIdx + i) = tempIDX;
+                        hi -= inc;
+                    } else if (isSorted) {
+                        if (curVal < lastVal) {
+                            isSorted = false;
+                        } else {
+                            lastVal = curVal;
+                        }
+                    }
+                }
+            }
+            return isSorted;
+        }
+
+        /// <summary>
+        /// sort nan elements to the end, test if the array is already sorted
+        /// </summary>
+        /// <returns>true, if already sorted</returns>
+        unsafe private static bool checkNaNAsc(int lo, ref int hi, int inc, complex* vec) {
+            bool isSorted = true; 
+            for (; hi >= lo && complex.IsNaN(*(vec + hi)); hi -= inc) ;
+            if (hi >= lo) {
+               
+                complex temp, lastVal = *(vec + hi);
+                for (int i = hi; i >= lo; i -= inc) { // SMA: Started at hi-inc, which would yield isSorted = true when all elements are in order but the last!
+                    temp = *(vec + i);
+                    if (complex.IsNaN(temp)) {
+                        *(vec + i) = *(vec + hi);
+                        *(vec + hi) = complex.NaN;
+                        hi -= inc;
+                    } else if (isSorted) {
+                        if (temp > lastVal) {
+                            isSorted = false;
+                        } else {
+                            lastVal = temp;
+                        }
+                    }
+                }
+            }
+            return isSorted; 
+        }
+        /// <summary>
+        /// sort nan elements to the end, test if the array is already sorted
+        /// </summary>
+        /// <returns>true, if already sorted</returns>
+        unsafe private static bool checkNaNDesc(int lo, ref int hi, int inc, complex* vec) {
+            bool isSorted = true; 
+            for (; hi >= lo && complex.IsNaN(*(vec + hi)); hi -= inc) ;
+            if (hi >= lo) {
+               
+                complex temp, lastVal = *(vec + hi);
+                for (int i = hi; i >= lo; i -= inc) { // SMA: Started at hi-inc, which would yield isSorted = true when all elements are in order but the last!
+                    temp = *(vec + i);
+                    if (complex.IsNaN(temp)) {
+                        *(vec + i) = *(vec + hi);
+                        *(vec + hi) = complex.NaN;
+                        hi -= inc;
+                    } else if (isSorted) {
+                        if (temp < lastVal) {
+                            isSorted = false;
+                        } else {
+                            lastVal = temp;
+                        }
+                    }
+                }
+            }
+            return isSorted; 
+        }
+
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+        // FOLLOWING ATTEMPT TO REPLACE INT POINTER INCREMENTS WITH RUNNING POINTERs WAS YET BUGGY, BUT MAY BRING FURTHER INCREASE OF SPEED
+        //        unsafe private static void QuickSortAsc_ITMT_noNaN( double* vecLo,  double* vecHi, int inc) {
+        //            
+        //            double* veci, vecj, pivotIndex;
+        //            s_quickSortStackPos = -1;
+        //            
+        //            double a1, a2, a3;
+        //            
+        //            double temp, pivotItem;
+        //            //System.Diagnostics.Debug.WriteLine(@"Thread:{0} len:{1} lo:{2} hi:{3}", System.Threading.Thread.CurrentThread.ManagedThreadId, vecP.Length, lo, hi);
+
+        //            for (; ; ) {
+        //                #region innerloop
+        //                if (vecHi - vecLo < (Settings.s_minimumQuicksortLength * inc)) {
+        //                    #region small array: insertion sort
+        //                    for (vecj = vecLo + inc; vecj <= vecHi; vecj += inc) {
+        //                        pivotItem = *vecj;
+        //                        for (veci = vecj - inc; veci >= vecLo; veci -= inc) {
+        //                            temp = *veci;
+        //                            if (temp <= pivotItem)
+        //                                break;
+        //                            *(veci + inc) = temp;
+        //                        }
+        //                        *(veci + inc) = pivotItem;
+        //                    }
+        //                    #endregion
+        //                    if (s_quickSortStackPos < 0) break;
+        //                    vecLo = ( double*)QuickSortStack[s_quickSortStackPos--];
+        //                    vecHi = ( double*)QuickSortStack[s_quickSortStackPos--];
+        //                } else {
+        //                    #region quick sort
+        //                    pivotIndex = vecLo + (int)((vecHi - vecLo) / inc / 2) * inc;
+        //                    a1 = *vecLo;
+        //                    a2 = *pivotIndex;
+        //                    a3 = *vecHi;
+        //                    *pivotIndex = *(vecLo + inc);
+        //                    #region pivoting bring lo, lo+inc, hi in order
+        //                    // by explicitely stepping through all possible paths,
+        //                    // we save some assignments and comparisons
+        //                    if (a1 > a2) {
+        //                        if (a1 > a3) {
+        //                            if (a3 > a2) {
+        //                                *vecHi = a1;
+        //                                *vecLo = a2;
+        //                                *(vecLo + inc) = a3;
+        //                            } else {
+        //                                *vecHi = a1;
+        //                                *vecLo = a3;
+        //                                *(vecLo + inc) = a2;
+        //                            }
+        //                        } else {
+        //                            *vecLo = a2;
+        //                            *(vecLo + inc) = a1;
+        //                        }
+        //                    } else {
+        //                        if (a2 > a3) {
+        //                            *vecHi = a2;
+        //                            if (a3 > a1) {
+        //                                *(vecLo + inc) = a3;
+        //                            } else {
+        //                                *(vecLo + inc) = a1;
+        //                                *vecLo = a3;
+        //                            }
+        //                        } else {
+        //                            *(vecLo + inc) = a2;
+        //                        }
+        //                    }
+        //                    #endregion
+        //                    veci = vecLo + inc; vecj = vecHi;
+        //                    pivotItem = *veci;
+        //                    for (; ; ) {
+        //                        do veci += inc; while (*veci < pivotItem);
+        //                        do vecj -= inc; while (*vecj > pivotItem);
+        //                        if (vecj < veci) break;
+        //                        temp = *veci;
+        //                        *veci = *vecj;
+        //                        *vecj = temp;
+        //                    }
+        //                    *(vecLo + inc) = *vecj;
+        //                    *vecj = pivotItem;
+
+        //#if DEBUG
+        //                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+        //#endif
+        //                    #endregion
+        //                    if (vecHi - veci + inc < vecj - vecLo) {
+        //                        if (s_threadCount < int.MaxValue //ILSettings.s_maxNumberThreads
+        //                                && (vecj - vecLo) / inc > ILSettings.s_minParallelElement2Count) {
+        //                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+        //                            Interlocked.Increment(ref s_threadCount);
+        //                            //s_threadCount++;
+        //                            ILQuickSortQueueItemDataIntPtr data;
+        //                            data.lo = (IntPtr)veci;
+        //                            data.hi = (IntPtr)vecHi;
+        //                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+        //                                ILQuickSortQueueItemDataIntPtr d = (ILQuickSortQueueItemDataIntPtr)o;
+        //                                QuickSortAsc_ITMT_noNaN(( double*)d.lo, ( double*)d.hi, inc);
+        //                                Interlocked.Decrement(ref s_threadCount);
+        //                                //s_threadCount--;
+        //                            }, data);
+        //                            vecHi = vecj - inc;
+        //                        } else {
+        //                            // smaller chunk now, bigger chunk to stack
+        //                            if (QuickSortStack == null)
+        //                                QuickSortStack = new IntPtr[50];
+        //                            QuickSortStack[++s_quickSortStackPos] = (IntPtr) (vecj - inc);
+        //                            QuickSortStack[++s_quickSortStackPos] = (IntPtr)vecLo;
+        //                            vecLo = veci; 
+        //                        }
+        //                    } else {
+        //                        if (s_threadCount < int.MaxValue //ILSettings.s_maxNumberThreads
+        //                            && (vecHi - veci + inc) / inc > ILSettings.s_minParallelElement2Count) {
+        //                            // do parallel: bigger chunk now, deliver smaller chunk to new thread 
+        //                            Interlocked.Increment(ref s_threadCount);
+        //                            //s_threadCount++;
+        //                            ILQuickSortQueueItemDataIntPtr data;
+        //                            data.lo = (IntPtr)vecLo;
+        //                            data.hi = (IntPtr)(vecj - inc);
+        //                            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o) {
+        //                                ILQuickSortQueueItemDataIntPtr d = (ILQuickSortQueueItemDataIntPtr)o;
+        //                                //Console.Out.WriteLine("Thread start: {0} ({1} - {2} Count:{3})", Thread.CurrentThread.ManagedThreadId, lo, hi, threadCount.ThreadCount);
+        //                                QuickSortAsc_ITMT_noNaN(( double*)d.lo, ( double*)d.hi, inc);
+        //                                Interlocked.Decrement(ref s_threadCount);
+        //                                //s_threadCount--;
+        //                            }, data);
+        //                            vecLo = veci;
+        //                        } else {
+        //                            if (QuickSortStack == null)
+        //                                QuickSortStack = new IntPtr[50];
+        //                            QuickSortStack[++s_quickSortStackPos] = (IntPtr)vecHi;
+        //                            QuickSortStack[++s_quickSortStackPos] = (IntPtr)veci;
+        //                            vecHi = vecj - inc;
+        //                        }
+        //                    }
+        //                }
+        //                #endregion inner loop
+        //            }
+        //        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Algorithms/Sorting/ILQuickSortST.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Algorithms/Sorting/ILQuickSortST.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Algorithms/Sorting/ILQuickSortST.cs	(revision 9102)
@@ -0,0 +1,6773 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Algorithms; 
+using ILNumerics.Exceptions;
+using ILNumerics; 
+using ILNumerics.Misc;
+
+
+namespace ILNumerics.Algorithms {
+
+    /// <summary>
+    /// the class provides a number of one dimensional quicksort implementations for several datatypes/ properties
+    /// </summary>
+    internal partial class ILQuickSort {
+
+
+
+    /// <summary>
+    /// inline one dimensional quick sort, ascending, arbitrary element spacing
+    /// </summary>
+    /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+    /// <param name="lo">lowest index of sorting range</param>
+    /// <param name="hi">highest index of sorting range</param>
+    /// <param name="inc">spacing between elements (dimension specifier)</param>
+    /// <remarks><para>Quick sort algorithm is used for ranges of minimum lengths specified by 
+    /// <see cref="P:ILNumerics.Settings.MinimumQuicksortLength"/> and above. 
+    /// Below that length, a simple insertion sort is used instead.</para>
+    /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+    /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+    /// The size is determined by the value of 
+    /// <see cref="P:ILNumerics.Settings.MaxSafeQuicksortRecursionDepth"/>.</para>
+    /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+    /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para></remarks>
+    public static void QuickSortAscST( double [] vecP, int lo, int hi, int inc) {
+        System.Diagnostics.Debug.Assert(vecP != null); 
+        System.Diagnostics.Debug.Assert(lo <= hi);
+        System.Diagnostics.Debug.Assert(lo >= 0);
+        //int loSwap, hiSwap;
+        int pivotIndex, i, j;
+        if (vecP.Length < 2) return; 
+        int[] s_quickSortStackMT = ILMemoryPool.Pool.New<int>(Settings.s_maxSafeQuicksortRecursionDepth * 2);
+        s_quickSortStackPos = -1;
+         double a1, a2, a3; 
+        unsafe {
+        fixed (
+             double * vec = vecP) {
+             double temp, pivotItem;
+            
+            if (checkNaNAsc(lo, ref hi, inc, vec)) return;
+
+            for (; ; ) {
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp <= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                        }
+                        *(vec + i + inc) = pivotItem;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--]; 
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo); 
+                    a2 = *(vec + pivotIndex); 
+                    a3 = *(vec + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 > a2) {
+                        if (a1 > a3) {
+                            if (a3 > a2) {
+                                *(vec + hi) = a1; 
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a3; 
+                            } else {
+                                *(vec + hi) = a1; 
+                                *(vec + lo) = a3; 
+                                *(vec + lo + inc) = a2; 
+                            }
+                        } else {
+                            *(vec + lo) = a2; 
+                            *(vec + lo + inc) = a1; 
+                        }
+                    } else {
+                        if (a2 > a3) {
+                            *(vec + hi) = a2; 
+                            if (a3 > a1) {
+                                *(vec + lo + inc) = a3; 
+                            } else {
+                                *(vec + lo + inc) = a1; 
+                                *(vec + lo) = a3; 
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2; 
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi; 
+                    pivotItem = *(vec + lo + inc);
+                    for (;;) {
+                        do i += inc; while (*(vec + i) < pivotItem); 
+                        do j -= inc; while (*(vec + j) > pivotItem); 
+                        if (j < i) break; 
+                        temp = *(vec + i); 
+                        *(vec + i) = *(vec + j); 
+                        *(vec + j) = temp; 
+                    }
+                    *(vec + lo + inc) = *(vec + j); 
+                    *(vec + j) = pivotItem;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif 
+                    if (hi - i + inc >= j - lo) {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = hi; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = i; 
+                        hi = j - inc; 
+                    } else {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = j - inc; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = lo; 
+                        lo = i; 
+                    }
+                }
+            }
+        } // fixed
+        } // unsafe 
+    }
+    /// <summary>
+    /// inline one dimensional quick sort, descending, arbitrary element spacing
+    /// </summary>
+    /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+    /// <param name="lo">lowest index of sorting range</param>
+    /// <param name="hi">highest index of sorting range</param>
+    /// <param name="inc">spacing between elements (dimension specifier)</param>
+    /// <remarks><para>Quick sort algorithm is used for ranges of minimum lengths specified by 
+    /// <see cref="P:ILNumerics.Settings.MinimumQuicksortLength"/> and above. 
+    /// Below that length, a simple insertion sort is used instead.</para>
+    /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+    /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+    /// The size is determined by the value of 
+    /// <see cref="P:ILNumerics.Settings.MaxSafeQuicksortRecursionDepth"/>.</para>
+    /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+    /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para></remarks>
+    public static void QuickSortDescST( double [] vecP, int lo, int hi, int inc) {
+        System.Diagnostics.Debug.Assert(vecP != null); 
+        System.Diagnostics.Debug.Assert(lo <= hi);
+        System.Diagnostics.Debug.Assert(lo >= 0);
+        //int loSwap, hiSwap;
+        int pivotIndex, i, j;
+        if (vecP.Length < 2) return;
+        s_quickSortStackPos = -1;
+         double a1, a2, a3; 
+        unsafe {
+        fixed (
+             double * vec = vecP) {
+             double temp, pivotItem;                
+             
+            if (checkNaNDesc(lo, ref hi, inc, vec)) return;
+            for (; ; ) {
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp >= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                        }
+                        *(vec + i + inc) = pivotItem;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--]; 
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo); 
+                    a2 = *(vec + pivotIndex); 
+                    a3 = *(vec + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 < a2) {
+                        if (a2 < a3) {
+                            *(vec + hi) = a1; 
+                            *(vec + lo) = a3; 
+                            *(vec + lo + inc) = a2; 
+                        } else {
+                            if (a1 < a3) {
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a3; 
+                                *(vec + hi) = a1; 
+                            } else {
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a1; 
+                                //*(vec + hi) = a3; 
+                            }
+                        }
+                    } else {
+                        if (a2 < a3) {
+                            if (a1 < a3) {
+                                *(vec + lo) = a3; 
+                                *(vec + hi) = a2; 
+                                *(vec + lo + inc) = a1; 
+                            } else {
+                                //*(vec + lo) = a1; 
+                                *(vec + hi) = a2; 
+                                *(vec + lo + inc) = a3; 
+                            }
+                        } else {
+                            //*(vec + lo) = a1; 
+                            //*(vec + hi) = a3; 
+                            *(vec + lo + inc) = a2; 
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi; 
+                    pivotItem = *(vec + lo + inc);
+                    for (;;) {
+                        do i += inc; while (*(vec + i) > pivotItem); 
+                        do j -= inc; while (*(vec + j) < pivotItem); 
+                        if (j < i) break; 
+                        temp = *(vec + i); 
+                        *(vec + i) = *(vec + j); 
+                        *(vec + j) = temp; 
+                    }
+                    *(vec + lo + inc) = *(vec + j); 
+                    *(vec + j) = pivotItem;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4D(vecP,lo,hi,j,inc)); 
+#endif 
+                    if (hi - i + inc >= j - lo) {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = hi; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = i; 
+                        hi = j - inc; 
+                    } else {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = j - inc; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = lo; 
+                        lo = i; 
+                    }
+                }
+            }
+        } // fixed
+        } // unsafe 
+    }
+    /// <summary>
+    /// inline 1 dimensional quick sort, ascending, arbitrary element spacing, indices aware
+    /// </summary>
+    /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+    /// <param name="lo">lowest index of sorting range</param>
+    /// <param name="hi">highest index of sorting range</param>
+    /// <param name="idxP">indices vector, content will in-place be sorted along with <paramref name="vecP"/></param>
+    /// <param name="inc">spacing between elements (dimension specifier)</param>
+    /// <remarks><para>Quick sort algorithm is used for ranges of minimum lengths specified by 
+    /// <see cref="P:ILNumerics.Settings.MminimumQuicksortLength"/> and above. 
+    /// Below that length, a simple insertion sort is used instead.</para>
+    /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+    /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+    /// The size is determined by the value of 
+    /// <see cref="P:ILNumerics.Settings.MaxSafeQuicksortRecursionDepth"/>.</para>
+    /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+    /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para></remarks>
+    public static void QuickSortAscIDXST( double [] vecP,  double [] idxP, int lo, int hi, int inc) {
+        System.Diagnostics.Debug.Assert(vecP != null); 
+        System.Diagnostics.Debug.Assert(lo <= hi);
+        System.Diagnostics.Debug.Assert(lo >= 0);
+        //int loSwap, hiSwap;
+        int pivotIndex, i, j;
+        if (vecP.Length < 2) return;
+        s_quickSortStackPos = -1; 
+         double a1, a2, a3; 
+         double ai1, ai2, ai3; 
+        unsafe {
+        fixed ( double * vecIdx = idxP)
+        fixed (
+             double * vec = vecP) {
+             double temp, pivotItem;                
+              
+            if (checkNaNIDXAsc(lo, ref hi, inc, vecIdx, vec)) return; 
+            for (; ; ) {
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        ai1 = *(vecIdx + j); 
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp <= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                            *(vecIdx + i + inc) = *(vecIdx + i);
+                        }
+                        *(vec + i + inc) = pivotItem;
+                        *(vecIdx + i + inc) = ai1;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--]; 
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo); 
+                    a2 = *(vec + pivotIndex); 
+                    a3 = *(vec + hi);
+                    ai1 = *(vecIdx + lo); 
+                    ai2 = *(vecIdx + pivotIndex); 
+                    ai3 = *(vecIdx + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    *(vecIdx + pivotIndex) = *(vecIdx + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 > a2) {
+                        if (a1 > a3) {
+                            if (a3 > a2) {
+                                *(vec + hi) = a1; 
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a3; 
+                                *(vecIdx + hi) = ai1; 
+                                *(vecIdx + lo) = ai2; 
+                                *(vecIdx + lo + inc) = ai3; 
+                            } else {
+                                *(vec + hi) = a1; 
+                                *(vec + lo) = a3; 
+                                *(vec + lo + inc) = a2; 
+                                *(vecIdx + hi) = ai1;  
+                                *(vecIdx + lo) = ai3; 
+                                *(vecIdx + lo + inc) = ai2; 
+                            }
+                        } else {
+                            *(vec + lo) = a2; 
+                            *(vec + lo + inc) = a1; 
+                            *(vecIdx + lo) = ai2; 
+                            *(vecIdx + lo + inc) = ai1; 
+                        }
+                    } else {
+                        if (a2 > a3) {
+                            *(vec + hi) = a2; 
+                            *(vecIdx + hi) = ai2; 
+                            if (a3 > a1) {
+                                *(vec + lo + inc) = a3; 
+                                *(vecIdx + lo + inc) = ai3; 
+                            } else {
+                                *(vec + lo + inc) = a1; 
+                                *(vec + lo) = a3; 
+                                *(vecIdx + lo + inc) = ai1; 
+                                *(vecIdx + lo) = ai3; 
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2; 
+                            *(vecIdx + lo + inc) = ai2; 
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi; 
+                    pivotItem = *(vec + lo + inc);
+                    ai1 = *(vecIdx + lo + inc);
+                    for (;;) {
+                        do i += inc; while (*(vec + i) < pivotItem); 
+                        do j -= inc; while (*(vec + j) > pivotItem); 
+                        if (j < i) break; 
+                        temp = *(vec + i); 
+                        ai2 = *(vecIdx + i); 
+                        *(vec + i) = *(vec + j); 
+                        *(vec + j) = temp; 
+                        *(vecIdx + i) = *(vecIdx + j); 
+                        *(vecIdx + j) = ai2; 
+                    }
+                    *(vec + lo + inc) = *(vec + j); 
+                    *(vec + j) = pivotItem;
+                    *(vecIdx + lo + inc) = *(vecIdx + j); 
+                    *(vecIdx + j) = ai1;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif 
+                    if (hi - i + inc >= j - lo) {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = hi; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = i; 
+                        hi = j - inc; 
+                    } else {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = j - inc; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = lo; 
+                        lo = i; 
+                    }
+                }
+            }
+        } // fixed
+        } // unsafe 
+    }
+    /// <summary>
+    /// inline 1 dimensional quick sort, descending, arbitrary element spacing, indices aware
+    /// </summary>
+    /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+    /// <param name="lo">lowest index of sorting range</param>
+    /// <param name="hi">highest index of sorting range</param>
+    /// <param name="idxP">indices vector, content will in-place be sorted along with <paramref name="vecP"/></param>
+    /// <param name="inc">spacing between elements (dimension specifier)</param>
+    /// <remarks><para>Quick sort algorithm is used for ranges of minimum lengths specified by 
+    /// <see cref="P:ILNumerics.Settings.MinimumQuicksortLength"/> and above. 
+    /// Below that length, a simple insertion sort is used instead.</para>
+    /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+    /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+    /// The size is determined by the value of 
+    /// <see cref="P:ILNumerics.Settings.MaxSafeQuicksortRecursionDepth"/>.</para>
+    /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+    /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para></remarks>
+    public static void QuickSortDescIDXST( double [] vecP,  double [] idxP, int lo, int hi, int inc) {
+        System.Diagnostics.Debug.Assert(vecP != null); 
+        System.Diagnostics.Debug.Assert(lo <= hi);
+        System.Diagnostics.Debug.Assert(lo >= 0);
+        //int loSwap, hiSwap;
+        int pivotIndex, i, j;
+        if (vecP.Length < 2) return;
+        
+        s_quickSortStackPos = -1;
+         double a1, a2, a3; 
+         double ai1, ai2, ai3; 
+        unsafe {
+        fixed ( double * vecIdx = idxP)
+        fixed (
+             double * vec = vecP) {
+             double temp, pivotItem;
+            
+            if (checkNaNIDXDesc(lo, ref hi, inc, vecIdx, vec)) return;
+            for (; ; ) {
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        ai1 = *(vecIdx + j); 
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp >= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                            *(vecIdx + i + inc) = *(vecIdx + i);
+                        }
+                        *(vec + i + inc) = pivotItem;
+                        *(vecIdx + i + inc) = ai1;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--]; 
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo); 
+                    a2 = *(vec + pivotIndex); 
+                    a3 = *(vec + hi);
+                    ai1 = *(vecIdx + lo); 
+                    ai2 = *(vecIdx + pivotIndex); 
+                    ai3 = *(vecIdx + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    *(vecIdx + pivotIndex) = *(vecIdx + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 < a2) {
+                        if (a2 < a3) {
+                            *(vec + hi) = a1; 
+                            *(vec + lo) = a3; 
+                            *(vec + lo + inc) = a2; 
+                            *(vecIdx + hi) = ai1; 
+                            *(vecIdx + lo) = ai3; 
+                            *(vecIdx + lo + inc) = ai2; 
+                        } else {
+                            if (a1 < a3) {
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a3; 
+                                *(vec + hi) = a1; 
+                                *(vecIdx + lo) = ai2; 
+                                *(vecIdx + lo + inc) = ai3; 
+                                *(vecIdx + hi) = ai1; 
+                            } else {
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a1; 
+                                //*(vec + hi) = a3; 
+                                *(vecIdx + lo) = ai2; 
+                                *(vecIdx + lo + inc) = ai1; 
+                                //*(vecIdx + hi) = ai3; 
+                            }
+                        }
+                    } else {
+                        if (a2 < a3) {
+                            if (a1 < a3) {
+                                *(vec + lo) = a3; 
+                                *(vec + hi) = a2; 
+                                *(vec + lo + inc) = a1; 
+                                *(vecIdx + lo) = ai3; 
+                                *(vecIdx + hi) = ai2; 
+                                *(vecIdx + lo + inc) = ai1; 
+                            } else {
+                                //*(vec + lo) = a1; 
+                                *(vec + hi) = a2; 
+                                *(vec + lo + inc) = a3; 
+                                //*(vecIdx + lo) = ai1; 
+                                *(vecIdx + hi) = ai2; 
+                                *(vecIdx + lo + inc) = ai3; 
+                            }
+                        } else {
+                            //*(vec + lo) = a1; 
+                            //*(vec + hi) = a3; 
+                            *(vec + lo + inc) = a2; 
+                            //*(vecIdx + lo) = ai1; 
+                            //*(vecIdx + hi) = ai3; 
+                            *(vecIdx + lo + inc) = ai2; 
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi; 
+                    pivotItem = *(vec + lo + inc);
+                    ai1 = *(vecIdx + lo + inc);
+                    for (;;) {
+                        do i += inc; while (*(vec + i) > pivotItem); 
+                        do j -= inc; while (*(vec + j) < pivotItem); 
+                        if (j < i) break; 
+                        temp = *(vec + i); 
+                        ai2 = *(vecIdx + i); 
+                        *(vec + i) = *(vec + j); 
+                        *(vec + j) = temp; 
+                        *(vecIdx + i) = *(vecIdx + j); 
+                        *(vecIdx + j) = ai2; 
+                    }
+                    *(vec + lo + inc) = *(vec + j); 
+                    *(vec + j) = pivotItem;
+                    *(vecIdx + lo + inc) = *(vecIdx + j); 
+                    *(vecIdx + j) = ai1;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif 
+                    if (hi - i + inc >= j - lo) {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = hi; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = i; 
+                        hi = j - inc; 
+                    } else {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = j - inc; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = lo; 
+                        lo = i; 
+                    }
+                }
+            }
+        } // fixed
+        } // unsafe 
+    }
+
+#region HYCALPER AUTO GENERATED CODE
+
+
+    /// <summary>
+    /// inline one dimensional quick sort, ascending, arbitrary element spacing
+    /// </summary>
+    /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+    /// <param name="lo">lowest index of sorting range</param>
+    /// <param name="hi">highest index of sorting range</param>
+    /// <param name="inc">spacing between elements (dimension specifier)</param>
+    /// <remarks><para>Quick sort algorithm is used for ranges of minimum lengths specified by 
+    /// <see cref="P:ILNumerics.Settings.MinimumQuicksortLength"/> and above. 
+    /// Below that length, a simple insertion sort is used instead.</para>
+    /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+    /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+    /// The size is determined by the value of 
+    /// <see cref="P:ILNumerics.Settings.MaxSafeQuicksortRecursionDepth"/>.</para>
+    /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+    /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para></remarks>
+    public static void QuickSortAscST( UInt64 [] vecP, int lo, int hi, int inc) {
+        System.Diagnostics.Debug.Assert(vecP != null); 
+        System.Diagnostics.Debug.Assert(lo <= hi);
+        System.Diagnostics.Debug.Assert(lo >= 0);
+        //int loSwap, hiSwap;
+        int pivotIndex, i, j;
+        if (vecP.Length < 2) return; 
+        int[] s_quickSortStackMT = ILMemoryPool.Pool.New<int>(Settings.s_maxSafeQuicksortRecursionDepth * 2);
+        s_quickSortStackPos = -1;
+        UInt64 a1, a2, a3; 
+        unsafe {
+        fixed (
+            UInt64 * vec = vecP) {
+            UInt64 temp, pivotItem;
+            
+
+            for (; ; ) {
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp <= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                        }
+                        *(vec + i + inc) = pivotItem;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--]; 
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo); 
+                    a2 = *(vec + pivotIndex); 
+                    a3 = *(vec + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 > a2) {
+                        if (a1 > a3) {
+                            if (a3 > a2) {
+                                *(vec + hi) = a1; 
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a3; 
+                            } else {
+                                *(vec + hi) = a1; 
+                                *(vec + lo) = a3; 
+                                *(vec + lo + inc) = a2; 
+                            }
+                        } else {
+                            *(vec + lo) = a2; 
+                            *(vec + lo + inc) = a1; 
+                        }
+                    } else {
+                        if (a2 > a3) {
+                            *(vec + hi) = a2; 
+                            if (a3 > a1) {
+                                *(vec + lo + inc) = a3; 
+                            } else {
+                                *(vec + lo + inc) = a1; 
+                                *(vec + lo) = a3; 
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2; 
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi; 
+                    pivotItem = *(vec + lo + inc);
+                    for (;;) {
+                        do i += inc; while (*(vec + i) < pivotItem); 
+                        do j -= inc; while (*(vec + j) > pivotItem); 
+                        if (j < i) break; 
+                        temp = *(vec + i); 
+                        *(vec + i) = *(vec + j); 
+                        *(vec + j) = temp; 
+                    }
+                    *(vec + lo + inc) = *(vec + j); 
+                    *(vec + j) = pivotItem;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif 
+                    if (hi - i + inc >= j - lo) {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = hi; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = i; 
+                        hi = j - inc; 
+                    } else {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = j - inc; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = lo; 
+                        lo = i; 
+                    }
+                }
+            }
+        } // fixed
+        } // unsafe 
+    }
+    /// <summary>
+    /// inline one dimensional quick sort, descending, arbitrary element spacing
+    /// </summary>
+    /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+    /// <param name="lo">lowest index of sorting range</param>
+    /// <param name="hi">highest index of sorting range</param>
+    /// <param name="inc">spacing between elements (dimension specifier)</param>
+    /// <remarks><para>Quick sort algorithm is used for ranges of minimum lengths specified by 
+    /// <see cref="P:ILNumerics.Settings.MinimumQuicksortLength"/> and above. 
+    /// Below that length, a simple insertion sort is used instead.</para>
+    /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+    /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+    /// The size is determined by the value of 
+    /// <see cref="P:ILNumerics.Settings.MaxSafeQuicksortRecursionDepth"/>.</para>
+    /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+    /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para></remarks>
+    public static void QuickSortDescST( UInt64 [] vecP, int lo, int hi, int inc) {
+        System.Diagnostics.Debug.Assert(vecP != null); 
+        System.Diagnostics.Debug.Assert(lo <= hi);
+        System.Diagnostics.Debug.Assert(lo >= 0);
+        //int loSwap, hiSwap;
+        int pivotIndex, i, j;
+        if (vecP.Length < 2) return;
+        s_quickSortStackPos = -1;
+        UInt64 a1, a2, a3; 
+        unsafe {
+        fixed (
+            UInt64 * vec = vecP) {
+            UInt64 temp, pivotItem;                
+            
+            for (; ; ) {
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp >= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                        }
+                        *(vec + i + inc) = pivotItem;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--]; 
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo); 
+                    a2 = *(vec + pivotIndex); 
+                    a3 = *(vec + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 < a2) {
+                        if (a2 < a3) {
+                            *(vec + hi) = a1; 
+                            *(vec + lo) = a3; 
+                            *(vec + lo + inc) = a2; 
+                        } else {
+                            if (a1 < a3) {
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a3; 
+                                *(vec + hi) = a1; 
+                            } else {
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a1; 
+                                //*(vec + hi) = a3; 
+                            }
+                        }
+                    } else {
+                        if (a2 < a3) {
+                            if (a1 < a3) {
+                                *(vec + lo) = a3; 
+                                *(vec + hi) = a2; 
+                                *(vec + lo + inc) = a1; 
+                            } else {
+                                //*(vec + lo) = a1; 
+                                *(vec + hi) = a2; 
+                                *(vec + lo + inc) = a3; 
+                            }
+                        } else {
+                            //*(vec + lo) = a1; 
+                            //*(vec + hi) = a3; 
+                            *(vec + lo + inc) = a2; 
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi; 
+                    pivotItem = *(vec + lo + inc);
+                    for (;;) {
+                        do i += inc; while (*(vec + i) > pivotItem); 
+                        do j -= inc; while (*(vec + j) < pivotItem); 
+                        if (j < i) break; 
+                        temp = *(vec + i); 
+                        *(vec + i) = *(vec + j); 
+                        *(vec + j) = temp; 
+                    }
+                    *(vec + lo + inc) = *(vec + j); 
+                    *(vec + j) = pivotItem;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4D(vecP,lo,hi,j,inc)); 
+#endif 
+                    if (hi - i + inc >= j - lo) {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = hi; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = i; 
+                        hi = j - inc; 
+                    } else {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = j - inc; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = lo; 
+                        lo = i; 
+                    }
+                }
+            }
+        } // fixed
+        } // unsafe 
+    }
+    /// <summary>
+    /// inline 1 dimensional quick sort, ascending, arbitrary element spacing, indices aware
+    /// </summary>
+    /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+    /// <param name="lo">lowest index of sorting range</param>
+    /// <param name="hi">highest index of sorting range</param>
+    /// <param name="idxP">indices vector, content will in-place be sorted along with <paramref name="vecP"/></param>
+    /// <param name="inc">spacing between elements (dimension specifier)</param>
+    /// <remarks><para>Quick sort algorithm is used for ranges of minimum lengths specified by 
+    /// <see cref="P:ILNumerics.Settings.MminimumQuicksortLength"/> and above. 
+    /// Below that length, a simple insertion sort is used instead.</para>
+    /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+    /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+    /// The size is determined by the value of 
+    /// <see cref="P:ILNumerics.Settings.MaxSafeQuicksortRecursionDepth"/>.</para>
+    /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+    /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para></remarks>
+    public static void QuickSortAscIDXST( UInt64 [] vecP,  double [] idxP, int lo, int hi, int inc) {
+        System.Diagnostics.Debug.Assert(vecP != null); 
+        System.Diagnostics.Debug.Assert(lo <= hi);
+        System.Diagnostics.Debug.Assert(lo >= 0);
+        //int loSwap, hiSwap;
+        int pivotIndex, i, j;
+        if (vecP.Length < 2) return;
+        s_quickSortStackPos = -1; 
+        UInt64 a1, a2, a3; 
+        double ai1, ai2, ai3; 
+        unsafe {
+        fixed ( double * vecIdx = idxP)
+        fixed (
+            UInt64 * vec = vecP) {
+            UInt64 temp, pivotItem;                
+            
+            for (; ; ) {
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        ai1 = *(vecIdx + j); 
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp <= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                            *(vecIdx + i + inc) = *(vecIdx + i);
+                        }
+                        *(vec + i + inc) = pivotItem;
+                        *(vecIdx + i + inc) = ai1;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--]; 
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo); 
+                    a2 = *(vec + pivotIndex); 
+                    a3 = *(vec + hi);
+                    ai1 = *(vecIdx + lo); 
+                    ai2 = *(vecIdx + pivotIndex); 
+                    ai3 = *(vecIdx + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    *(vecIdx + pivotIndex) = *(vecIdx + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 > a2) {
+                        if (a1 > a3) {
+                            if (a3 > a2) {
+                                *(vec + hi) = a1; 
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a3; 
+                                *(vecIdx + hi) = ai1; 
+                                *(vecIdx + lo) = ai2; 
+                                *(vecIdx + lo + inc) = ai3; 
+                            } else {
+                                *(vec + hi) = a1; 
+                                *(vec + lo) = a3; 
+                                *(vec + lo + inc) = a2; 
+                                *(vecIdx + hi) = ai1;  
+                                *(vecIdx + lo) = ai3; 
+                                *(vecIdx + lo + inc) = ai2; 
+                            }
+                        } else {
+                            *(vec + lo) = a2; 
+                            *(vec + lo + inc) = a1; 
+                            *(vecIdx + lo) = ai2; 
+                            *(vecIdx + lo + inc) = ai1; 
+                        }
+                    } else {
+                        if (a2 > a3) {
+                            *(vec + hi) = a2; 
+                            *(vecIdx + hi) = ai2; 
+                            if (a3 > a1) {
+                                *(vec + lo + inc) = a3; 
+                                *(vecIdx + lo + inc) = ai3; 
+                            } else {
+                                *(vec + lo + inc) = a1; 
+                                *(vec + lo) = a3; 
+                                *(vecIdx + lo + inc) = ai1; 
+                                *(vecIdx + lo) = ai3; 
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2; 
+                            *(vecIdx + lo + inc) = ai2; 
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi; 
+                    pivotItem = *(vec + lo + inc);
+                    ai1 = *(vecIdx + lo + inc);
+                    for (;;) {
+                        do i += inc; while (*(vec + i) < pivotItem); 
+                        do j -= inc; while (*(vec + j) > pivotItem); 
+                        if (j < i) break; 
+                        temp = *(vec + i); 
+                        ai2 = *(vecIdx + i); 
+                        *(vec + i) = *(vec + j); 
+                        *(vec + j) = temp; 
+                        *(vecIdx + i) = *(vecIdx + j); 
+                        *(vecIdx + j) = ai2; 
+                    }
+                    *(vec + lo + inc) = *(vec + j); 
+                    *(vec + j) = pivotItem;
+                    *(vecIdx + lo + inc) = *(vecIdx + j); 
+                    *(vecIdx + j) = ai1;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif 
+                    if (hi - i + inc >= j - lo) {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = hi; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = i; 
+                        hi = j - inc; 
+                    } else {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = j - inc; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = lo; 
+                        lo = i; 
+                    }
+                }
+            }
+        } // fixed
+        } // unsafe 
+    }
+    /// <summary>
+    /// inline 1 dimensional quick sort, descending, arbitrary element spacing, indices aware
+    /// </summary>
+    /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+    /// <param name="lo">lowest index of sorting range</param>
+    /// <param name="hi">highest index of sorting range</param>
+    /// <param name="idxP">indices vector, content will in-place be sorted along with <paramref name="vecP"/></param>
+    /// <param name="inc">spacing between elements (dimension specifier)</param>
+    /// <remarks><para>Quick sort algorithm is used for ranges of minimum lengths specified by 
+    /// <see cref="P:ILNumerics.Settings.MinimumQuicksortLength"/> and above. 
+    /// Below that length, a simple insertion sort is used instead.</para>
+    /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+    /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+    /// The size is determined by the value of 
+    /// <see cref="P:ILNumerics.Settings.MaxSafeQuicksortRecursionDepth"/>.</para>
+    /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+    /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para></remarks>
+    public static void QuickSortDescIDXST( UInt64 [] vecP,  double [] idxP, int lo, int hi, int inc) {
+        System.Diagnostics.Debug.Assert(vecP != null); 
+        System.Diagnostics.Debug.Assert(lo <= hi);
+        System.Diagnostics.Debug.Assert(lo >= 0);
+        //int loSwap, hiSwap;
+        int pivotIndex, i, j;
+        if (vecP.Length < 2) return;
+        
+        s_quickSortStackPos = -1;
+        UInt64 a1, a2, a3; 
+        double ai1, ai2, ai3; 
+        unsafe {
+        fixed ( double * vecIdx = idxP)
+        fixed (
+            UInt64 * vec = vecP) {
+            UInt64 temp, pivotItem;
+            
+            for (; ; ) {
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        ai1 = *(vecIdx + j); 
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp >= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                            *(vecIdx + i + inc) = *(vecIdx + i);
+                        }
+                        *(vec + i + inc) = pivotItem;
+                        *(vecIdx + i + inc) = ai1;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--]; 
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo); 
+                    a2 = *(vec + pivotIndex); 
+                    a3 = *(vec + hi);
+                    ai1 = *(vecIdx + lo); 
+                    ai2 = *(vecIdx + pivotIndex); 
+                    ai3 = *(vecIdx + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    *(vecIdx + pivotIndex) = *(vecIdx + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 < a2) {
+                        if (a2 < a3) {
+                            *(vec + hi) = a1; 
+                            *(vec + lo) = a3; 
+                            *(vec + lo + inc) = a2; 
+                            *(vecIdx + hi) = ai1; 
+                            *(vecIdx + lo) = ai3; 
+                            *(vecIdx + lo + inc) = ai2; 
+                        } else {
+                            if (a1 < a3) {
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a3; 
+                                *(vec + hi) = a1; 
+                                *(vecIdx + lo) = ai2; 
+                                *(vecIdx + lo + inc) = ai3; 
+                                *(vecIdx + hi) = ai1; 
+                            } else {
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a1; 
+                                //*(vec + hi) = a3; 
+                                *(vecIdx + lo) = ai2; 
+                                *(vecIdx + lo + inc) = ai1; 
+                                //*(vecIdx + hi) = ai3; 
+                            }
+                        }
+                    } else {
+                        if (a2 < a3) {
+                            if (a1 < a3) {
+                                *(vec + lo) = a3; 
+                                *(vec + hi) = a2; 
+                                *(vec + lo + inc) = a1; 
+                                *(vecIdx + lo) = ai3; 
+                                *(vecIdx + hi) = ai2; 
+                                *(vecIdx + lo + inc) = ai1; 
+                            } else {
+                                //*(vec + lo) = a1; 
+                                *(vec + hi) = a2; 
+                                *(vec + lo + inc) = a3; 
+                                //*(vecIdx + lo) = ai1; 
+                                *(vecIdx + hi) = ai2; 
+                                *(vecIdx + lo + inc) = ai3; 
+                            }
+                        } else {
+                            //*(vec + lo) = a1; 
+                            //*(vec + hi) = a3; 
+                            *(vec + lo + inc) = a2; 
+                            //*(vecIdx + lo) = ai1; 
+                            //*(vecIdx + hi) = ai3; 
+                            *(vecIdx + lo + inc) = ai2; 
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi; 
+                    pivotItem = *(vec + lo + inc);
+                    ai1 = *(vecIdx + lo + inc);
+                    for (;;) {
+                        do i += inc; while (*(vec + i) > pivotItem); 
+                        do j -= inc; while (*(vec + j) < pivotItem); 
+                        if (j < i) break; 
+                        temp = *(vec + i); 
+                        ai2 = *(vecIdx + i); 
+                        *(vec + i) = *(vec + j); 
+                        *(vec + j) = temp; 
+                        *(vecIdx + i) = *(vecIdx + j); 
+                        *(vecIdx + j) = ai2; 
+                    }
+                    *(vec + lo + inc) = *(vec + j); 
+                    *(vec + j) = pivotItem;
+                    *(vecIdx + lo + inc) = *(vecIdx + j); 
+                    *(vecIdx + j) = ai1;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif 
+                    if (hi - i + inc >= j - lo) {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = hi; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = i; 
+                        hi = j - inc; 
+                    } else {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = j - inc; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = lo; 
+                        lo = i; 
+                    }
+                }
+            }
+        } // fixed
+        } // unsafe 
+    }
+
+    /// <summary>
+    /// inline one dimensional quick sort, ascending, arbitrary element spacing
+    /// </summary>
+    /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+    /// <param name="lo">lowest index of sorting range</param>
+    /// <param name="hi">highest index of sorting range</param>
+    /// <param name="inc">spacing between elements (dimension specifier)</param>
+    /// <remarks><para>Quick sort algorithm is used for ranges of minimum lengths specified by 
+    /// <see cref="P:ILNumerics.Settings.MinimumQuicksortLength"/> and above. 
+    /// Below that length, a simple insertion sort is used instead.</para>
+    /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+    /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+    /// The size is determined by the value of 
+    /// <see cref="P:ILNumerics.Settings.MaxSafeQuicksortRecursionDepth"/>.</para>
+    /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+    /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para></remarks>
+    public static void QuickSortAscST( UInt32 [] vecP, int lo, int hi, int inc) {
+        System.Diagnostics.Debug.Assert(vecP != null); 
+        System.Diagnostics.Debug.Assert(lo <= hi);
+        System.Diagnostics.Debug.Assert(lo >= 0);
+        //int loSwap, hiSwap;
+        int pivotIndex, i, j;
+        if (vecP.Length < 2) return; 
+        int[] s_quickSortStackMT = ILMemoryPool.Pool.New<int>(Settings.s_maxSafeQuicksortRecursionDepth * 2);
+        s_quickSortStackPos = -1;
+        UInt32 a1, a2, a3; 
+        unsafe {
+        fixed (
+            UInt32 * vec = vecP) {
+            UInt32 temp, pivotItem;
+            
+
+            for (; ; ) {
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp <= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                        }
+                        *(vec + i + inc) = pivotItem;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--]; 
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo); 
+                    a2 = *(vec + pivotIndex); 
+                    a3 = *(vec + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 > a2) {
+                        if (a1 > a3) {
+                            if (a3 > a2) {
+                                *(vec + hi) = a1; 
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a3; 
+                            } else {
+                                *(vec + hi) = a1; 
+                                *(vec + lo) = a3; 
+                                *(vec + lo + inc) = a2; 
+                            }
+                        } else {
+                            *(vec + lo) = a2; 
+                            *(vec + lo + inc) = a1; 
+                        }
+                    } else {
+                        if (a2 > a3) {
+                            *(vec + hi) = a2; 
+                            if (a3 > a1) {
+                                *(vec + lo + inc) = a3; 
+                            } else {
+                                *(vec + lo + inc) = a1; 
+                                *(vec + lo) = a3; 
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2; 
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi; 
+                    pivotItem = *(vec + lo + inc);
+                    for (;;) {
+                        do i += inc; while (*(vec + i) < pivotItem); 
+                        do j -= inc; while (*(vec + j) > pivotItem); 
+                        if (j < i) break; 
+                        temp = *(vec + i); 
+                        *(vec + i) = *(vec + j); 
+                        *(vec + j) = temp; 
+                    }
+                    *(vec + lo + inc) = *(vec + j); 
+                    *(vec + j) = pivotItem;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif 
+                    if (hi - i + inc >= j - lo) {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = hi; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = i; 
+                        hi = j - inc; 
+                    } else {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = j - inc; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = lo; 
+                        lo = i; 
+                    }
+                }
+            }
+        } // fixed
+        } // unsafe 
+    }
+    /// <summary>
+    /// inline one dimensional quick sort, descending, arbitrary element spacing
+    /// </summary>
+    /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+    /// <param name="lo">lowest index of sorting range</param>
+    /// <param name="hi">highest index of sorting range</param>
+    /// <param name="inc">spacing between elements (dimension specifier)</param>
+    /// <remarks><para>Quick sort algorithm is used for ranges of minimum lengths specified by 
+    /// <see cref="P:ILNumerics.Settings.MinimumQuicksortLength"/> and above. 
+    /// Below that length, a simple insertion sort is used instead.</para>
+    /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+    /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+    /// The size is determined by the value of 
+    /// <see cref="P:ILNumerics.Settings.MaxSafeQuicksortRecursionDepth"/>.</para>
+    /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+    /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para></remarks>
+    public static void QuickSortDescST( UInt32 [] vecP, int lo, int hi, int inc) {
+        System.Diagnostics.Debug.Assert(vecP != null); 
+        System.Diagnostics.Debug.Assert(lo <= hi);
+        System.Diagnostics.Debug.Assert(lo >= 0);
+        //int loSwap, hiSwap;
+        int pivotIndex, i, j;
+        if (vecP.Length < 2) return;
+        s_quickSortStackPos = -1;
+        UInt32 a1, a2, a3; 
+        unsafe {
+        fixed (
+            UInt32 * vec = vecP) {
+            UInt32 temp, pivotItem;                
+            
+            for (; ; ) {
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp >= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                        }
+                        *(vec + i + inc) = pivotItem;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--]; 
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo); 
+                    a2 = *(vec + pivotIndex); 
+                    a3 = *(vec + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 < a2) {
+                        if (a2 < a3) {
+                            *(vec + hi) = a1; 
+                            *(vec + lo) = a3; 
+                            *(vec + lo + inc) = a2; 
+                        } else {
+                            if (a1 < a3) {
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a3; 
+                                *(vec + hi) = a1; 
+                            } else {
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a1; 
+                                //*(vec + hi) = a3; 
+                            }
+                        }
+                    } else {
+                        if (a2 < a3) {
+                            if (a1 < a3) {
+                                *(vec + lo) = a3; 
+                                *(vec + hi) = a2; 
+                                *(vec + lo + inc) = a1; 
+                            } else {
+                                //*(vec + lo) = a1; 
+                                *(vec + hi) = a2; 
+                                *(vec + lo + inc) = a3; 
+                            }
+                        } else {
+                            //*(vec + lo) = a1; 
+                            //*(vec + hi) = a3; 
+                            *(vec + lo + inc) = a2; 
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi; 
+                    pivotItem = *(vec + lo + inc);
+                    for (;;) {
+                        do i += inc; while (*(vec + i) > pivotItem); 
+                        do j -= inc; while (*(vec + j) < pivotItem); 
+                        if (j < i) break; 
+                        temp = *(vec + i); 
+                        *(vec + i) = *(vec + j); 
+                        *(vec + j) = temp; 
+                    }
+                    *(vec + lo + inc) = *(vec + j); 
+                    *(vec + j) = pivotItem;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4D(vecP,lo,hi,j,inc)); 
+#endif 
+                    if (hi - i + inc >= j - lo) {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = hi; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = i; 
+                        hi = j - inc; 
+                    } else {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = j - inc; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = lo; 
+                        lo = i; 
+                    }
+                }
+            }
+        } // fixed
+        } // unsafe 
+    }
+    /// <summary>
+    /// inline 1 dimensional quick sort, ascending, arbitrary element spacing, indices aware
+    /// </summary>
+    /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+    /// <param name="lo">lowest index of sorting range</param>
+    /// <param name="hi">highest index of sorting range</param>
+    /// <param name="idxP">indices vector, content will in-place be sorted along with <paramref name="vecP"/></param>
+    /// <param name="inc">spacing between elements (dimension specifier)</param>
+    /// <remarks><para>Quick sort algorithm is used for ranges of minimum lengths specified by 
+    /// <see cref="P:ILNumerics.Settings.MminimumQuicksortLength"/> and above. 
+    /// Below that length, a simple insertion sort is used instead.</para>
+    /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+    /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+    /// The size is determined by the value of 
+    /// <see cref="P:ILNumerics.Settings.MaxSafeQuicksortRecursionDepth"/>.</para>
+    /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+    /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para></remarks>
+    public static void QuickSortAscIDXST( UInt32 [] vecP,  double [] idxP, int lo, int hi, int inc) {
+        System.Diagnostics.Debug.Assert(vecP != null); 
+        System.Diagnostics.Debug.Assert(lo <= hi);
+        System.Diagnostics.Debug.Assert(lo >= 0);
+        //int loSwap, hiSwap;
+        int pivotIndex, i, j;
+        if (vecP.Length < 2) return;
+        s_quickSortStackPos = -1; 
+        UInt32 a1, a2, a3; 
+        double ai1, ai2, ai3; 
+        unsafe {
+        fixed ( double * vecIdx = idxP)
+        fixed (
+            UInt32 * vec = vecP) {
+            UInt32 temp, pivotItem;                
+            
+            for (; ; ) {
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        ai1 = *(vecIdx + j); 
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp <= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                            *(vecIdx + i + inc) = *(vecIdx + i);
+                        }
+                        *(vec + i + inc) = pivotItem;
+                        *(vecIdx + i + inc) = ai1;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--]; 
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo); 
+                    a2 = *(vec + pivotIndex); 
+                    a3 = *(vec + hi);
+                    ai1 = *(vecIdx + lo); 
+                    ai2 = *(vecIdx + pivotIndex); 
+                    ai3 = *(vecIdx + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    *(vecIdx + pivotIndex) = *(vecIdx + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 > a2) {
+                        if (a1 > a3) {
+                            if (a3 > a2) {
+                                *(vec + hi) = a1; 
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a3; 
+                                *(vecIdx + hi) = ai1; 
+                                *(vecIdx + lo) = ai2; 
+                                *(vecIdx + lo + inc) = ai3; 
+                            } else {
+                                *(vec + hi) = a1; 
+                                *(vec + lo) = a3; 
+                                *(vec + lo + inc) = a2; 
+                                *(vecIdx + hi) = ai1;  
+                                *(vecIdx + lo) = ai3; 
+                                *(vecIdx + lo + inc) = ai2; 
+                            }
+                        } else {
+                            *(vec + lo) = a2; 
+                            *(vec + lo + inc) = a1; 
+                            *(vecIdx + lo) = ai2; 
+                            *(vecIdx + lo + inc) = ai1; 
+                        }
+                    } else {
+                        if (a2 > a3) {
+                            *(vec + hi) = a2; 
+                            *(vecIdx + hi) = ai2; 
+                            if (a3 > a1) {
+                                *(vec + lo + inc) = a3; 
+                                *(vecIdx + lo + inc) = ai3; 
+                            } else {
+                                *(vec + lo + inc) = a1; 
+                                *(vec + lo) = a3; 
+                                *(vecIdx + lo + inc) = ai1; 
+                                *(vecIdx + lo) = ai3; 
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2; 
+                            *(vecIdx + lo + inc) = ai2; 
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi; 
+                    pivotItem = *(vec + lo + inc);
+                    ai1 = *(vecIdx + lo + inc);
+                    for (;;) {
+                        do i += inc; while (*(vec + i) < pivotItem); 
+                        do j -= inc; while (*(vec + j) > pivotItem); 
+                        if (j < i) break; 
+                        temp = *(vec + i); 
+                        ai2 = *(vecIdx + i); 
+                        *(vec + i) = *(vec + j); 
+                        *(vec + j) = temp; 
+                        *(vecIdx + i) = *(vecIdx + j); 
+                        *(vecIdx + j) = ai2; 
+                    }
+                    *(vec + lo + inc) = *(vec + j); 
+                    *(vec + j) = pivotItem;
+                    *(vecIdx + lo + inc) = *(vecIdx + j); 
+                    *(vecIdx + j) = ai1;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif 
+                    if (hi - i + inc >= j - lo) {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = hi; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = i; 
+                        hi = j - inc; 
+                    } else {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = j - inc; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = lo; 
+                        lo = i; 
+                    }
+                }
+            }
+        } // fixed
+        } // unsafe 
+    }
+    /// <summary>
+    /// inline 1 dimensional quick sort, descending, arbitrary element spacing, indices aware
+    /// </summary>
+    /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+    /// <param name="lo">lowest index of sorting range</param>
+    /// <param name="hi">highest index of sorting range</param>
+    /// <param name="idxP">indices vector, content will in-place be sorted along with <paramref name="vecP"/></param>
+    /// <param name="inc">spacing between elements (dimension specifier)</param>
+    /// <remarks><para>Quick sort algorithm is used for ranges of minimum lengths specified by 
+    /// <see cref="P:ILNumerics.Settings.MinimumQuicksortLength"/> and above. 
+    /// Below that length, a simple insertion sort is used instead.</para>
+    /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+    /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+    /// The size is determined by the value of 
+    /// <see cref="P:ILNumerics.Settings.MaxSafeQuicksortRecursionDepth"/>.</para>
+    /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+    /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para></remarks>
+    public static void QuickSortDescIDXST( UInt32 [] vecP,  double [] idxP, int lo, int hi, int inc) {
+        System.Diagnostics.Debug.Assert(vecP != null); 
+        System.Diagnostics.Debug.Assert(lo <= hi);
+        System.Diagnostics.Debug.Assert(lo >= 0);
+        //int loSwap, hiSwap;
+        int pivotIndex, i, j;
+        if (vecP.Length < 2) return;
+        
+        s_quickSortStackPos = -1;
+        UInt32 a1, a2, a3; 
+        double ai1, ai2, ai3; 
+        unsafe {
+        fixed ( double * vecIdx = idxP)
+        fixed (
+            UInt32 * vec = vecP) {
+            UInt32 temp, pivotItem;
+            
+            for (; ; ) {
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        ai1 = *(vecIdx + j); 
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp >= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                            *(vecIdx + i + inc) = *(vecIdx + i);
+                        }
+                        *(vec + i + inc) = pivotItem;
+                        *(vecIdx + i + inc) = ai1;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--]; 
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo); 
+                    a2 = *(vec + pivotIndex); 
+                    a3 = *(vec + hi);
+                    ai1 = *(vecIdx + lo); 
+                    ai2 = *(vecIdx + pivotIndex); 
+                    ai3 = *(vecIdx + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    *(vecIdx + pivotIndex) = *(vecIdx + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 < a2) {
+                        if (a2 < a3) {
+                            *(vec + hi) = a1; 
+                            *(vec + lo) = a3; 
+                            *(vec + lo + inc) = a2; 
+                            *(vecIdx + hi) = ai1; 
+                            *(vecIdx + lo) = ai3; 
+                            *(vecIdx + lo + inc) = ai2; 
+                        } else {
+                            if (a1 < a3) {
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a3; 
+                                *(vec + hi) = a1; 
+                                *(vecIdx + lo) = ai2; 
+                                *(vecIdx + lo + inc) = ai3; 
+                                *(vecIdx + hi) = ai1; 
+                            } else {
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a1; 
+                                //*(vec + hi) = a3; 
+                                *(vecIdx + lo) = ai2; 
+                                *(vecIdx + lo + inc) = ai1; 
+                                //*(vecIdx + hi) = ai3; 
+                            }
+                        }
+                    } else {
+                        if (a2 < a3) {
+                            if (a1 < a3) {
+                                *(vec + lo) = a3; 
+                                *(vec + hi) = a2; 
+                                *(vec + lo + inc) = a1; 
+                                *(vecIdx + lo) = ai3; 
+                                *(vecIdx + hi) = ai2; 
+                                *(vecIdx + lo + inc) = ai1; 
+                            } else {
+                                //*(vec + lo) = a1; 
+                                *(vec + hi) = a2; 
+                                *(vec + lo + inc) = a3; 
+                                //*(vecIdx + lo) = ai1; 
+                                *(vecIdx + hi) = ai2; 
+                                *(vecIdx + lo + inc) = ai3; 
+                            }
+                        } else {
+                            //*(vec + lo) = a1; 
+                            //*(vec + hi) = a3; 
+                            *(vec + lo + inc) = a2; 
+                            //*(vecIdx + lo) = ai1; 
+                            //*(vecIdx + hi) = ai3; 
+                            *(vecIdx + lo + inc) = ai2; 
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi; 
+                    pivotItem = *(vec + lo + inc);
+                    ai1 = *(vecIdx + lo + inc);
+                    for (;;) {
+                        do i += inc; while (*(vec + i) > pivotItem); 
+                        do j -= inc; while (*(vec + j) < pivotItem); 
+                        if (j < i) break; 
+                        temp = *(vec + i); 
+                        ai2 = *(vecIdx + i); 
+                        *(vec + i) = *(vec + j); 
+                        *(vec + j) = temp; 
+                        *(vecIdx + i) = *(vecIdx + j); 
+                        *(vecIdx + j) = ai2; 
+                    }
+                    *(vec + lo + inc) = *(vec + j); 
+                    *(vec + j) = pivotItem;
+                    *(vecIdx + lo + inc) = *(vecIdx + j); 
+                    *(vecIdx + j) = ai1;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif 
+                    if (hi - i + inc >= j - lo) {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = hi; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = i; 
+                        hi = j - inc; 
+                    } else {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = j - inc; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = lo; 
+                        lo = i; 
+                    }
+                }
+            }
+        } // fixed
+        } // unsafe 
+    }
+
+    /// <summary>
+    /// inline one dimensional quick sort, ascending, arbitrary element spacing
+    /// </summary>
+    /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+    /// <param name="lo">lowest index of sorting range</param>
+    /// <param name="hi">highest index of sorting range</param>
+    /// <param name="inc">spacing between elements (dimension specifier)</param>
+    /// <remarks><para>Quick sort algorithm is used for ranges of minimum lengths specified by 
+    /// <see cref="P:ILNumerics.Settings.MinimumQuicksortLength"/> and above. 
+    /// Below that length, a simple insertion sort is used instead.</para>
+    /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+    /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+    /// The size is determined by the value of 
+    /// <see cref="P:ILNumerics.Settings.MaxSafeQuicksortRecursionDepth"/>.</para>
+    /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+    /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para></remarks>
+    public static void QuickSortAscST( UInt16 [] vecP, int lo, int hi, int inc) {
+        System.Diagnostics.Debug.Assert(vecP != null); 
+        System.Diagnostics.Debug.Assert(lo <= hi);
+        System.Diagnostics.Debug.Assert(lo >= 0);
+        //int loSwap, hiSwap;
+        int pivotIndex, i, j;
+        if (vecP.Length < 2) return; 
+        int[] s_quickSortStackMT = ILMemoryPool.Pool.New<int>(Settings.s_maxSafeQuicksortRecursionDepth * 2);
+        s_quickSortStackPos = -1;
+        UInt16 a1, a2, a3; 
+        unsafe {
+        fixed (
+            UInt16 * vec = vecP) {
+            UInt16 temp, pivotItem;
+            
+
+            for (; ; ) {
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp <= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                        }
+                        *(vec + i + inc) = pivotItem;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--]; 
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo); 
+                    a2 = *(vec + pivotIndex); 
+                    a3 = *(vec + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 > a2) {
+                        if (a1 > a3) {
+                            if (a3 > a2) {
+                                *(vec + hi) = a1; 
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a3; 
+                            } else {
+                                *(vec + hi) = a1; 
+                                *(vec + lo) = a3; 
+                                *(vec + lo + inc) = a2; 
+                            }
+                        } else {
+                            *(vec + lo) = a2; 
+                            *(vec + lo + inc) = a1; 
+                        }
+                    } else {
+                        if (a2 > a3) {
+                            *(vec + hi) = a2; 
+                            if (a3 > a1) {
+                                *(vec + lo + inc) = a3; 
+                            } else {
+                                *(vec + lo + inc) = a1; 
+                                *(vec + lo) = a3; 
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2; 
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi; 
+                    pivotItem = *(vec + lo + inc);
+                    for (;;) {
+                        do i += inc; while (*(vec + i) < pivotItem); 
+                        do j -= inc; while (*(vec + j) > pivotItem); 
+                        if (j < i) break; 
+                        temp = *(vec + i); 
+                        *(vec + i) = *(vec + j); 
+                        *(vec + j) = temp; 
+                    }
+                    *(vec + lo + inc) = *(vec + j); 
+                    *(vec + j) = pivotItem;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif 
+                    if (hi - i + inc >= j - lo) {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = hi; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = i; 
+                        hi = j - inc; 
+                    } else {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = j - inc; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = lo; 
+                        lo = i; 
+                    }
+                }
+            }
+        } // fixed
+        } // unsafe 
+    }
+    /// <summary>
+    /// inline one dimensional quick sort, descending, arbitrary element spacing
+    /// </summary>
+    /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+    /// <param name="lo">lowest index of sorting range</param>
+    /// <param name="hi">highest index of sorting range</param>
+    /// <param name="inc">spacing between elements (dimension specifier)</param>
+    /// <remarks><para>Quick sort algorithm is used for ranges of minimum lengths specified by 
+    /// <see cref="P:ILNumerics.Settings.MinimumQuicksortLength"/> and above. 
+    /// Below that length, a simple insertion sort is used instead.</para>
+    /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+    /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+    /// The size is determined by the value of 
+    /// <see cref="P:ILNumerics.Settings.MaxSafeQuicksortRecursionDepth"/>.</para>
+    /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+    /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para></remarks>
+    public static void QuickSortDescST( UInt16 [] vecP, int lo, int hi, int inc) {
+        System.Diagnostics.Debug.Assert(vecP != null); 
+        System.Diagnostics.Debug.Assert(lo <= hi);
+        System.Diagnostics.Debug.Assert(lo >= 0);
+        //int loSwap, hiSwap;
+        int pivotIndex, i, j;
+        if (vecP.Length < 2) return;
+        s_quickSortStackPos = -1;
+        UInt16 a1, a2, a3; 
+        unsafe {
+        fixed (
+            UInt16 * vec = vecP) {
+            UInt16 temp, pivotItem;                
+            
+            for (; ; ) {
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp >= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                        }
+                        *(vec + i + inc) = pivotItem;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--]; 
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo); 
+                    a2 = *(vec + pivotIndex); 
+                    a3 = *(vec + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 < a2) {
+                        if (a2 < a3) {
+                            *(vec + hi) = a1; 
+                            *(vec + lo) = a3; 
+                            *(vec + lo + inc) = a2; 
+                        } else {
+                            if (a1 < a3) {
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a3; 
+                                *(vec + hi) = a1; 
+                            } else {
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a1; 
+                                //*(vec + hi) = a3; 
+                            }
+                        }
+                    } else {
+                        if (a2 < a3) {
+                            if (a1 < a3) {
+                                *(vec + lo) = a3; 
+                                *(vec + hi) = a2; 
+                                *(vec + lo + inc) = a1; 
+                            } else {
+                                //*(vec + lo) = a1; 
+                                *(vec + hi) = a2; 
+                                *(vec + lo + inc) = a3; 
+                            }
+                        } else {
+                            //*(vec + lo) = a1; 
+                            //*(vec + hi) = a3; 
+                            *(vec + lo + inc) = a2; 
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi; 
+                    pivotItem = *(vec + lo + inc);
+                    for (;;) {
+                        do i += inc; while (*(vec + i) > pivotItem); 
+                        do j -= inc; while (*(vec + j) < pivotItem); 
+                        if (j < i) break; 
+                        temp = *(vec + i); 
+                        *(vec + i) = *(vec + j); 
+                        *(vec + j) = temp; 
+                    }
+                    *(vec + lo + inc) = *(vec + j); 
+                    *(vec + j) = pivotItem;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4D(vecP,lo,hi,j,inc)); 
+#endif 
+                    if (hi - i + inc >= j - lo) {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = hi; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = i; 
+                        hi = j - inc; 
+                    } else {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = j - inc; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = lo; 
+                        lo = i; 
+                    }
+                }
+            }
+        } // fixed
+        } // unsafe 
+    }
+    /// <summary>
+    /// inline 1 dimensional quick sort, ascending, arbitrary element spacing, indices aware
+    /// </summary>
+    /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+    /// <param name="lo">lowest index of sorting range</param>
+    /// <param name="hi">highest index of sorting range</param>
+    /// <param name="idxP">indices vector, content will in-place be sorted along with <paramref name="vecP"/></param>
+    /// <param name="inc">spacing between elements (dimension specifier)</param>
+    /// <remarks><para>Quick sort algorithm is used for ranges of minimum lengths specified by 
+    /// <see cref="P:ILNumerics.Settings.MminimumQuicksortLength"/> and above. 
+    /// Below that length, a simple insertion sort is used instead.</para>
+    /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+    /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+    /// The size is determined by the value of 
+    /// <see cref="P:ILNumerics.Settings.MaxSafeQuicksortRecursionDepth"/>.</para>
+    /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+    /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para></remarks>
+    public static void QuickSortAscIDXST( UInt16 [] vecP,  double [] idxP, int lo, int hi, int inc) {
+        System.Diagnostics.Debug.Assert(vecP != null); 
+        System.Diagnostics.Debug.Assert(lo <= hi);
+        System.Diagnostics.Debug.Assert(lo >= 0);
+        //int loSwap, hiSwap;
+        int pivotIndex, i, j;
+        if (vecP.Length < 2) return;
+        s_quickSortStackPos = -1; 
+        UInt16 a1, a2, a3; 
+        double ai1, ai2, ai3; 
+        unsafe {
+        fixed ( double * vecIdx = idxP)
+        fixed (
+            UInt16 * vec = vecP) {
+            UInt16 temp, pivotItem;                
+            
+            for (; ; ) {
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        ai1 = *(vecIdx + j); 
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp <= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                            *(vecIdx + i + inc) = *(vecIdx + i);
+                        }
+                        *(vec + i + inc) = pivotItem;
+                        *(vecIdx + i + inc) = ai1;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--]; 
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo); 
+                    a2 = *(vec + pivotIndex); 
+                    a3 = *(vec + hi);
+                    ai1 = *(vecIdx + lo); 
+                    ai2 = *(vecIdx + pivotIndex); 
+                    ai3 = *(vecIdx + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    *(vecIdx + pivotIndex) = *(vecIdx + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 > a2) {
+                        if (a1 > a3) {
+                            if (a3 > a2) {
+                                *(vec + hi) = a1; 
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a3; 
+                                *(vecIdx + hi) = ai1; 
+                                *(vecIdx + lo) = ai2; 
+                                *(vecIdx + lo + inc) = ai3; 
+                            } else {
+                                *(vec + hi) = a1; 
+                                *(vec + lo) = a3; 
+                                *(vec + lo + inc) = a2; 
+                                *(vecIdx + hi) = ai1;  
+                                *(vecIdx + lo) = ai3; 
+                                *(vecIdx + lo + inc) = ai2; 
+                            }
+                        } else {
+                            *(vec + lo) = a2; 
+                            *(vec + lo + inc) = a1; 
+                            *(vecIdx + lo) = ai2; 
+                            *(vecIdx + lo + inc) = ai1; 
+                        }
+                    } else {
+                        if (a2 > a3) {
+                            *(vec + hi) = a2; 
+                            *(vecIdx + hi) = ai2; 
+                            if (a3 > a1) {
+                                *(vec + lo + inc) = a3; 
+                                *(vecIdx + lo + inc) = ai3; 
+                            } else {
+                                *(vec + lo + inc) = a1; 
+                                *(vec + lo) = a3; 
+                                *(vecIdx + lo + inc) = ai1; 
+                                *(vecIdx + lo) = ai3; 
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2; 
+                            *(vecIdx + lo + inc) = ai2; 
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi; 
+                    pivotItem = *(vec + lo + inc);
+                    ai1 = *(vecIdx + lo + inc);
+                    for (;;) {
+                        do i += inc; while (*(vec + i) < pivotItem); 
+                        do j -= inc; while (*(vec + j) > pivotItem); 
+                        if (j < i) break; 
+                        temp = *(vec + i); 
+                        ai2 = *(vecIdx + i); 
+                        *(vec + i) = *(vec + j); 
+                        *(vec + j) = temp; 
+                        *(vecIdx + i) = *(vecIdx + j); 
+                        *(vecIdx + j) = ai2; 
+                    }
+                    *(vec + lo + inc) = *(vec + j); 
+                    *(vec + j) = pivotItem;
+                    *(vecIdx + lo + inc) = *(vecIdx + j); 
+                    *(vecIdx + j) = ai1;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif 
+                    if (hi - i + inc >= j - lo) {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = hi; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = i; 
+                        hi = j - inc; 
+                    } else {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = j - inc; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = lo; 
+                        lo = i; 
+                    }
+                }
+            }
+        } // fixed
+        } // unsafe 
+    }
+    /// <summary>
+    /// inline 1 dimensional quick sort, descending, arbitrary element spacing, indices aware
+    /// </summary>
+    /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+    /// <param name="lo">lowest index of sorting range</param>
+    /// <param name="hi">highest index of sorting range</param>
+    /// <param name="idxP">indices vector, content will in-place be sorted along with <paramref name="vecP"/></param>
+    /// <param name="inc">spacing between elements (dimension specifier)</param>
+    /// <remarks><para>Quick sort algorithm is used for ranges of minimum lengths specified by 
+    /// <see cref="P:ILNumerics.Settings.MinimumQuicksortLength"/> and above. 
+    /// Below that length, a simple insertion sort is used instead.</para>
+    /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+    /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+    /// The size is determined by the value of 
+    /// <see cref="P:ILNumerics.Settings.MaxSafeQuicksortRecursionDepth"/>.</para>
+    /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+    /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para></remarks>
+    public static void QuickSortDescIDXST( UInt16 [] vecP,  double [] idxP, int lo, int hi, int inc) {
+        System.Diagnostics.Debug.Assert(vecP != null); 
+        System.Diagnostics.Debug.Assert(lo <= hi);
+        System.Diagnostics.Debug.Assert(lo >= 0);
+        //int loSwap, hiSwap;
+        int pivotIndex, i, j;
+        if (vecP.Length < 2) return;
+        
+        s_quickSortStackPos = -1;
+        UInt16 a1, a2, a3; 
+        double ai1, ai2, ai3; 
+        unsafe {
+        fixed ( double * vecIdx = idxP)
+        fixed (
+            UInt16 * vec = vecP) {
+            UInt16 temp, pivotItem;
+            
+            for (; ; ) {
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        ai1 = *(vecIdx + j); 
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp >= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                            *(vecIdx + i + inc) = *(vecIdx + i);
+                        }
+                        *(vec + i + inc) = pivotItem;
+                        *(vecIdx + i + inc) = ai1;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--]; 
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo); 
+                    a2 = *(vec + pivotIndex); 
+                    a3 = *(vec + hi);
+                    ai1 = *(vecIdx + lo); 
+                    ai2 = *(vecIdx + pivotIndex); 
+                    ai3 = *(vecIdx + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    *(vecIdx + pivotIndex) = *(vecIdx + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 < a2) {
+                        if (a2 < a3) {
+                            *(vec + hi) = a1; 
+                            *(vec + lo) = a3; 
+                            *(vec + lo + inc) = a2; 
+                            *(vecIdx + hi) = ai1; 
+                            *(vecIdx + lo) = ai3; 
+                            *(vecIdx + lo + inc) = ai2; 
+                        } else {
+                            if (a1 < a3) {
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a3; 
+                                *(vec + hi) = a1; 
+                                *(vecIdx + lo) = ai2; 
+                                *(vecIdx + lo + inc) = ai3; 
+                                *(vecIdx + hi) = ai1; 
+                            } else {
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a1; 
+                                //*(vec + hi) = a3; 
+                                *(vecIdx + lo) = ai2; 
+                                *(vecIdx + lo + inc) = ai1; 
+                                //*(vecIdx + hi) = ai3; 
+                            }
+                        }
+                    } else {
+                        if (a2 < a3) {
+                            if (a1 < a3) {
+                                *(vec + lo) = a3; 
+                                *(vec + hi) = a2; 
+                                *(vec + lo + inc) = a1; 
+                                *(vecIdx + lo) = ai3; 
+                                *(vecIdx + hi) = ai2; 
+                                *(vecIdx + lo + inc) = ai1; 
+                            } else {
+                                //*(vec + lo) = a1; 
+                                *(vec + hi) = a2; 
+                                *(vec + lo + inc) = a3; 
+                                //*(vecIdx + lo) = ai1; 
+                                *(vecIdx + hi) = ai2; 
+                                *(vecIdx + lo + inc) = ai3; 
+                            }
+                        } else {
+                            //*(vec + lo) = a1; 
+                            //*(vec + hi) = a3; 
+                            *(vec + lo + inc) = a2; 
+                            //*(vecIdx + lo) = ai1; 
+                            //*(vecIdx + hi) = ai3; 
+                            *(vecIdx + lo + inc) = ai2; 
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi; 
+                    pivotItem = *(vec + lo + inc);
+                    ai1 = *(vecIdx + lo + inc);
+                    for (;;) {
+                        do i += inc; while (*(vec + i) > pivotItem); 
+                        do j -= inc; while (*(vec + j) < pivotItem); 
+                        if (j < i) break; 
+                        temp = *(vec + i); 
+                        ai2 = *(vecIdx + i); 
+                        *(vec + i) = *(vec + j); 
+                        *(vec + j) = temp; 
+                        *(vecIdx + i) = *(vecIdx + j); 
+                        *(vecIdx + j) = ai2; 
+                    }
+                    *(vec + lo + inc) = *(vec + j); 
+                    *(vec + j) = pivotItem;
+                    *(vecIdx + lo + inc) = *(vecIdx + j); 
+                    *(vecIdx + j) = ai1;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif 
+                    if (hi - i + inc >= j - lo) {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = hi; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = i; 
+                        hi = j - inc; 
+                    } else {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = j - inc; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = lo; 
+                        lo = i; 
+                    }
+                }
+            }
+        } // fixed
+        } // unsafe 
+    }
+
+    /// <summary>
+    /// inline one dimensional quick sort, ascending, arbitrary element spacing
+    /// </summary>
+    /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+    /// <param name="lo">lowest index of sorting range</param>
+    /// <param name="hi">highest index of sorting range</param>
+    /// <param name="inc">spacing between elements (dimension specifier)</param>
+    /// <remarks><para>Quick sort algorithm is used for ranges of minimum lengths specified by 
+    /// <see cref="P:ILNumerics.Settings.MinimumQuicksortLength"/> and above. 
+    /// Below that length, a simple insertion sort is used instead.</para>
+    /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+    /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+    /// The size is determined by the value of 
+    /// <see cref="P:ILNumerics.Settings.MaxSafeQuicksortRecursionDepth"/>.</para>
+    /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+    /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para></remarks>
+    public static void QuickSortAscST( Int64 [] vecP, int lo, int hi, int inc) {
+        System.Diagnostics.Debug.Assert(vecP != null); 
+        System.Diagnostics.Debug.Assert(lo <= hi);
+        System.Diagnostics.Debug.Assert(lo >= 0);
+        //int loSwap, hiSwap;
+        int pivotIndex, i, j;
+        if (vecP.Length < 2) return; 
+        int[] s_quickSortStackMT = ILMemoryPool.Pool.New<int>(Settings.s_maxSafeQuicksortRecursionDepth * 2);
+        s_quickSortStackPos = -1;
+        Int64 a1, a2, a3; 
+        unsafe {
+        fixed (
+            Int64 * vec = vecP) {
+            Int64 temp, pivotItem;
+            
+
+            for (; ; ) {
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp <= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                        }
+                        *(vec + i + inc) = pivotItem;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--]; 
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo); 
+                    a2 = *(vec + pivotIndex); 
+                    a3 = *(vec + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 > a2) {
+                        if (a1 > a3) {
+                            if (a3 > a2) {
+                                *(vec + hi) = a1; 
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a3; 
+                            } else {
+                                *(vec + hi) = a1; 
+                                *(vec + lo) = a3; 
+                                *(vec + lo + inc) = a2; 
+                            }
+                        } else {
+                            *(vec + lo) = a2; 
+                            *(vec + lo + inc) = a1; 
+                        }
+                    } else {
+                        if (a2 > a3) {
+                            *(vec + hi) = a2; 
+                            if (a3 > a1) {
+                                *(vec + lo + inc) = a3; 
+                            } else {
+                                *(vec + lo + inc) = a1; 
+                                *(vec + lo) = a3; 
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2; 
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi; 
+                    pivotItem = *(vec + lo + inc);
+                    for (;;) {
+                        do i += inc; while (*(vec + i) < pivotItem); 
+                        do j -= inc; while (*(vec + j) > pivotItem); 
+                        if (j < i) break; 
+                        temp = *(vec + i); 
+                        *(vec + i) = *(vec + j); 
+                        *(vec + j) = temp; 
+                    }
+                    *(vec + lo + inc) = *(vec + j); 
+                    *(vec + j) = pivotItem;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif 
+                    if (hi - i + inc >= j - lo) {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = hi; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = i; 
+                        hi = j - inc; 
+                    } else {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = j - inc; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = lo; 
+                        lo = i; 
+                    }
+                }
+            }
+        } // fixed
+        } // unsafe 
+    }
+    /// <summary>
+    /// inline one dimensional quick sort, descending, arbitrary element spacing
+    /// </summary>
+    /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+    /// <param name="lo">lowest index of sorting range</param>
+    /// <param name="hi">highest index of sorting range</param>
+    /// <param name="inc">spacing between elements (dimension specifier)</param>
+    /// <remarks><para>Quick sort algorithm is used for ranges of minimum lengths specified by 
+    /// <see cref="P:ILNumerics.Settings.MinimumQuicksortLength"/> and above. 
+    /// Below that length, a simple insertion sort is used instead.</para>
+    /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+    /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+    /// The size is determined by the value of 
+    /// <see cref="P:ILNumerics.Settings.MaxSafeQuicksortRecursionDepth"/>.</para>
+    /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+    /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para></remarks>
+    public static void QuickSortDescST( Int64 [] vecP, int lo, int hi, int inc) {
+        System.Diagnostics.Debug.Assert(vecP != null); 
+        System.Diagnostics.Debug.Assert(lo <= hi);
+        System.Diagnostics.Debug.Assert(lo >= 0);
+        //int loSwap, hiSwap;
+        int pivotIndex, i, j;
+        if (vecP.Length < 2) return;
+        s_quickSortStackPos = -1;
+        Int64 a1, a2, a3; 
+        unsafe {
+        fixed (
+            Int64 * vec = vecP) {
+            Int64 temp, pivotItem;                
+            
+            for (; ; ) {
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp >= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                        }
+                        *(vec + i + inc) = pivotItem;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--]; 
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo); 
+                    a2 = *(vec + pivotIndex); 
+                    a3 = *(vec + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 < a2) {
+                        if (a2 < a3) {
+                            *(vec + hi) = a1; 
+                            *(vec + lo) = a3; 
+                            *(vec + lo + inc) = a2; 
+                        } else {
+                            if (a1 < a3) {
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a3; 
+                                *(vec + hi) = a1; 
+                            } else {
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a1; 
+                                //*(vec + hi) = a3; 
+                            }
+                        }
+                    } else {
+                        if (a2 < a3) {
+                            if (a1 < a3) {
+                                *(vec + lo) = a3; 
+                                *(vec + hi) = a2; 
+                                *(vec + lo + inc) = a1; 
+                            } else {
+                                //*(vec + lo) = a1; 
+                                *(vec + hi) = a2; 
+                                *(vec + lo + inc) = a3; 
+                            }
+                        } else {
+                            //*(vec + lo) = a1; 
+                            //*(vec + hi) = a3; 
+                            *(vec + lo + inc) = a2; 
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi; 
+                    pivotItem = *(vec + lo + inc);
+                    for (;;) {
+                        do i += inc; while (*(vec + i) > pivotItem); 
+                        do j -= inc; while (*(vec + j) < pivotItem); 
+                        if (j < i) break; 
+                        temp = *(vec + i); 
+                        *(vec + i) = *(vec + j); 
+                        *(vec + j) = temp; 
+                    }
+                    *(vec + lo + inc) = *(vec + j); 
+                    *(vec + j) = pivotItem;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4D(vecP,lo,hi,j,inc)); 
+#endif 
+                    if (hi - i + inc >= j - lo) {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = hi; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = i; 
+                        hi = j - inc; 
+                    } else {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = j - inc; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = lo; 
+                        lo = i; 
+                    }
+                }
+            }
+        } // fixed
+        } // unsafe 
+    }
+    /// <summary>
+    /// inline 1 dimensional quick sort, ascending, arbitrary element spacing, indices aware
+    /// </summary>
+    /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+    /// <param name="lo">lowest index of sorting range</param>
+    /// <param name="hi">highest index of sorting range</param>
+    /// <param name="idxP">indices vector, content will in-place be sorted along with <paramref name="vecP"/></param>
+    /// <param name="inc">spacing between elements (dimension specifier)</param>
+    /// <remarks><para>Quick sort algorithm is used for ranges of minimum lengths specified by 
+    /// <see cref="P:ILNumerics.Settings.MminimumQuicksortLength"/> and above. 
+    /// Below that length, a simple insertion sort is used instead.</para>
+    /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+    /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+    /// The size is determined by the value of 
+    /// <see cref="P:ILNumerics.Settings.MaxSafeQuicksortRecursionDepth"/>.</para>
+    /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+    /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para></remarks>
+    public static void QuickSortAscIDXST( Int64 [] vecP,  double [] idxP, int lo, int hi, int inc) {
+        System.Diagnostics.Debug.Assert(vecP != null); 
+        System.Diagnostics.Debug.Assert(lo <= hi);
+        System.Diagnostics.Debug.Assert(lo >= 0);
+        //int loSwap, hiSwap;
+        int pivotIndex, i, j;
+        if (vecP.Length < 2) return;
+        s_quickSortStackPos = -1; 
+        Int64 a1, a2, a3; 
+        double ai1, ai2, ai3; 
+        unsafe {
+        fixed ( double * vecIdx = idxP)
+        fixed (
+            Int64 * vec = vecP) {
+            Int64 temp, pivotItem;                
+            
+            for (; ; ) {
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        ai1 = *(vecIdx + j); 
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp <= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                            *(vecIdx + i + inc) = *(vecIdx + i);
+                        }
+                        *(vec + i + inc) = pivotItem;
+                        *(vecIdx + i + inc) = ai1;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--]; 
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo); 
+                    a2 = *(vec + pivotIndex); 
+                    a3 = *(vec + hi);
+                    ai1 = *(vecIdx + lo); 
+                    ai2 = *(vecIdx + pivotIndex); 
+                    ai3 = *(vecIdx + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    *(vecIdx + pivotIndex) = *(vecIdx + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 > a2) {
+                        if (a1 > a3) {
+                            if (a3 > a2) {
+                                *(vec + hi) = a1; 
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a3; 
+                                *(vecIdx + hi) = ai1; 
+                                *(vecIdx + lo) = ai2; 
+                                *(vecIdx + lo + inc) = ai3; 
+                            } else {
+                                *(vec + hi) = a1; 
+                                *(vec + lo) = a3; 
+                                *(vec + lo + inc) = a2; 
+                                *(vecIdx + hi) = ai1;  
+                                *(vecIdx + lo) = ai3; 
+                                *(vecIdx + lo + inc) = ai2; 
+                            }
+                        } else {
+                            *(vec + lo) = a2; 
+                            *(vec + lo + inc) = a1; 
+                            *(vecIdx + lo) = ai2; 
+                            *(vecIdx + lo + inc) = ai1; 
+                        }
+                    } else {
+                        if (a2 > a3) {
+                            *(vec + hi) = a2; 
+                            *(vecIdx + hi) = ai2; 
+                            if (a3 > a1) {
+                                *(vec + lo + inc) = a3; 
+                                *(vecIdx + lo + inc) = ai3; 
+                            } else {
+                                *(vec + lo + inc) = a1; 
+                                *(vec + lo) = a3; 
+                                *(vecIdx + lo + inc) = ai1; 
+                                *(vecIdx + lo) = ai3; 
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2; 
+                            *(vecIdx + lo + inc) = ai2; 
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi; 
+                    pivotItem = *(vec + lo + inc);
+                    ai1 = *(vecIdx + lo + inc);
+                    for (;;) {
+                        do i += inc; while (*(vec + i) < pivotItem); 
+                        do j -= inc; while (*(vec + j) > pivotItem); 
+                        if (j < i) break; 
+                        temp = *(vec + i); 
+                        ai2 = *(vecIdx + i); 
+                        *(vec + i) = *(vec + j); 
+                        *(vec + j) = temp; 
+                        *(vecIdx + i) = *(vecIdx + j); 
+                        *(vecIdx + j) = ai2; 
+                    }
+                    *(vec + lo + inc) = *(vec + j); 
+                    *(vec + j) = pivotItem;
+                    *(vecIdx + lo + inc) = *(vecIdx + j); 
+                    *(vecIdx + j) = ai1;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif 
+                    if (hi - i + inc >= j - lo) {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = hi; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = i; 
+                        hi = j - inc; 
+                    } else {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = j - inc; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = lo; 
+                        lo = i; 
+                    }
+                }
+            }
+        } // fixed
+        } // unsafe 
+    }
+    /// <summary>
+    /// inline 1 dimensional quick sort, descending, arbitrary element spacing, indices aware
+    /// </summary>
+    /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+    /// <param name="lo">lowest index of sorting range</param>
+    /// <param name="hi">highest index of sorting range</param>
+    /// <param name="idxP">indices vector, content will in-place be sorted along with <paramref name="vecP"/></param>
+    /// <param name="inc">spacing between elements (dimension specifier)</param>
+    /// <remarks><para>Quick sort algorithm is used for ranges of minimum lengths specified by 
+    /// <see cref="P:ILNumerics.Settings.MinimumQuicksortLength"/> and above. 
+    /// Below that length, a simple insertion sort is used instead.</para>
+    /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+    /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+    /// The size is determined by the value of 
+    /// <see cref="P:ILNumerics.Settings.MaxSafeQuicksortRecursionDepth"/>.</para>
+    /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+    /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para></remarks>
+    public static void QuickSortDescIDXST( Int64 [] vecP,  double [] idxP, int lo, int hi, int inc) {
+        System.Diagnostics.Debug.Assert(vecP != null); 
+        System.Diagnostics.Debug.Assert(lo <= hi);
+        System.Diagnostics.Debug.Assert(lo >= 0);
+        //int loSwap, hiSwap;
+        int pivotIndex, i, j;
+        if (vecP.Length < 2) return;
+        
+        s_quickSortStackPos = -1;
+        Int64 a1, a2, a3; 
+        double ai1, ai2, ai3; 
+        unsafe {
+        fixed ( double * vecIdx = idxP)
+        fixed (
+            Int64 * vec = vecP) {
+            Int64 temp, pivotItem;
+            
+            for (; ; ) {
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        ai1 = *(vecIdx + j); 
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp >= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                            *(vecIdx + i + inc) = *(vecIdx + i);
+                        }
+                        *(vec + i + inc) = pivotItem;
+                        *(vecIdx + i + inc) = ai1;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--]; 
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo); 
+                    a2 = *(vec + pivotIndex); 
+                    a3 = *(vec + hi);
+                    ai1 = *(vecIdx + lo); 
+                    ai2 = *(vecIdx + pivotIndex); 
+                    ai3 = *(vecIdx + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    *(vecIdx + pivotIndex) = *(vecIdx + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 < a2) {
+                        if (a2 < a3) {
+                            *(vec + hi) = a1; 
+                            *(vec + lo) = a3; 
+                            *(vec + lo + inc) = a2; 
+                            *(vecIdx + hi) = ai1; 
+                            *(vecIdx + lo) = ai3; 
+                            *(vecIdx + lo + inc) = ai2; 
+                        } else {
+                            if (a1 < a3) {
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a3; 
+                                *(vec + hi) = a1; 
+                                *(vecIdx + lo) = ai2; 
+                                *(vecIdx + lo + inc) = ai3; 
+                                *(vecIdx + hi) = ai1; 
+                            } else {
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a1; 
+                                //*(vec + hi) = a3; 
+                                *(vecIdx + lo) = ai2; 
+                                *(vecIdx + lo + inc) = ai1; 
+                                //*(vecIdx + hi) = ai3; 
+                            }
+                        }
+                    } else {
+                        if (a2 < a3) {
+                            if (a1 < a3) {
+                                *(vec + lo) = a3; 
+                                *(vec + hi) = a2; 
+                                *(vec + lo + inc) = a1; 
+                                *(vecIdx + lo) = ai3; 
+                                *(vecIdx + hi) = ai2; 
+                                *(vecIdx + lo + inc) = ai1; 
+                            } else {
+                                //*(vec + lo) = a1; 
+                                *(vec + hi) = a2; 
+                                *(vec + lo + inc) = a3; 
+                                //*(vecIdx + lo) = ai1; 
+                                *(vecIdx + hi) = ai2; 
+                                *(vecIdx + lo + inc) = ai3; 
+                            }
+                        } else {
+                            //*(vec + lo) = a1; 
+                            //*(vec + hi) = a3; 
+                            *(vec + lo + inc) = a2; 
+                            //*(vecIdx + lo) = ai1; 
+                            //*(vecIdx + hi) = ai3; 
+                            *(vecIdx + lo + inc) = ai2; 
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi; 
+                    pivotItem = *(vec + lo + inc);
+                    ai1 = *(vecIdx + lo + inc);
+                    for (;;) {
+                        do i += inc; while (*(vec + i) > pivotItem); 
+                        do j -= inc; while (*(vec + j) < pivotItem); 
+                        if (j < i) break; 
+                        temp = *(vec + i); 
+                        ai2 = *(vecIdx + i); 
+                        *(vec + i) = *(vec + j); 
+                        *(vec + j) = temp; 
+                        *(vecIdx + i) = *(vecIdx + j); 
+                        *(vecIdx + j) = ai2; 
+                    }
+                    *(vec + lo + inc) = *(vec + j); 
+                    *(vec + j) = pivotItem;
+                    *(vecIdx + lo + inc) = *(vecIdx + j); 
+                    *(vecIdx + j) = ai1;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif 
+                    if (hi - i + inc >= j - lo) {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = hi; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = i; 
+                        hi = j - inc; 
+                    } else {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = j - inc; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = lo; 
+                        lo = i; 
+                    }
+                }
+            }
+        } // fixed
+        } // unsafe 
+    }
+
+    /// <summary>
+    /// inline one dimensional quick sort, ascending, arbitrary element spacing
+    /// </summary>
+    /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+    /// <param name="lo">lowest index of sorting range</param>
+    /// <param name="hi">highest index of sorting range</param>
+    /// <param name="inc">spacing between elements (dimension specifier)</param>
+    /// <remarks><para>Quick sort algorithm is used for ranges of minimum lengths specified by 
+    /// <see cref="P:ILNumerics.Settings.MinimumQuicksortLength"/> and above. 
+    /// Below that length, a simple insertion sort is used instead.</para>
+    /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+    /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+    /// The size is determined by the value of 
+    /// <see cref="P:ILNumerics.Settings.MaxSafeQuicksortRecursionDepth"/>.</para>
+    /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+    /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para></remarks>
+    public static void QuickSortAscST( Int32 [] vecP, int lo, int hi, int inc) {
+        System.Diagnostics.Debug.Assert(vecP != null); 
+        System.Diagnostics.Debug.Assert(lo <= hi);
+        System.Diagnostics.Debug.Assert(lo >= 0);
+        //int loSwap, hiSwap;
+        int pivotIndex, i, j;
+        if (vecP.Length < 2) return; 
+        int[] s_quickSortStackMT = ILMemoryPool.Pool.New<int>(Settings.s_maxSafeQuicksortRecursionDepth * 2);
+        s_quickSortStackPos = -1;
+        Int32 a1, a2, a3; 
+        unsafe {
+        fixed (
+            Int32 * vec = vecP) {
+            Int32 temp, pivotItem;
+            
+
+            for (; ; ) {
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp <= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                        }
+                        *(vec + i + inc) = pivotItem;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--]; 
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo); 
+                    a2 = *(vec + pivotIndex); 
+                    a3 = *(vec + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 > a2) {
+                        if (a1 > a3) {
+                            if (a3 > a2) {
+                                *(vec + hi) = a1; 
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a3; 
+                            } else {
+                                *(vec + hi) = a1; 
+                                *(vec + lo) = a3; 
+                                *(vec + lo + inc) = a2; 
+                            }
+                        } else {
+                            *(vec + lo) = a2; 
+                            *(vec + lo + inc) = a1; 
+                        }
+                    } else {
+                        if (a2 > a3) {
+                            *(vec + hi) = a2; 
+                            if (a3 > a1) {
+                                *(vec + lo + inc) = a3; 
+                            } else {
+                                *(vec + lo + inc) = a1; 
+                                *(vec + lo) = a3; 
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2; 
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi; 
+                    pivotItem = *(vec + lo + inc);
+                    for (;;) {
+                        do i += inc; while (*(vec + i) < pivotItem); 
+                        do j -= inc; while (*(vec + j) > pivotItem); 
+                        if (j < i) break; 
+                        temp = *(vec + i); 
+                        *(vec + i) = *(vec + j); 
+                        *(vec + j) = temp; 
+                    }
+                    *(vec + lo + inc) = *(vec + j); 
+                    *(vec + j) = pivotItem;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif 
+                    if (hi - i + inc >= j - lo) {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = hi; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = i; 
+                        hi = j - inc; 
+                    } else {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = j - inc; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = lo; 
+                        lo = i; 
+                    }
+                }
+            }
+        } // fixed
+        } // unsafe 
+    }
+    /// <summary>
+    /// inline one dimensional quick sort, descending, arbitrary element spacing
+    /// </summary>
+    /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+    /// <param name="lo">lowest index of sorting range</param>
+    /// <param name="hi">highest index of sorting range</param>
+    /// <param name="inc">spacing between elements (dimension specifier)</param>
+    /// <remarks><para>Quick sort algorithm is used for ranges of minimum lengths specified by 
+    /// <see cref="P:ILNumerics.Settings.MinimumQuicksortLength"/> and above. 
+    /// Below that length, a simple insertion sort is used instead.</para>
+    /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+    /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+    /// The size is determined by the value of 
+    /// <see cref="P:ILNumerics.Settings.MaxSafeQuicksortRecursionDepth"/>.</para>
+    /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+    /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para></remarks>
+    public static void QuickSortDescST( Int32 [] vecP, int lo, int hi, int inc) {
+        System.Diagnostics.Debug.Assert(vecP != null); 
+        System.Diagnostics.Debug.Assert(lo <= hi);
+        System.Diagnostics.Debug.Assert(lo >= 0);
+        //int loSwap, hiSwap;
+        int pivotIndex, i, j;
+        if (vecP.Length < 2) return;
+        s_quickSortStackPos = -1;
+        Int32 a1, a2, a3; 
+        unsafe {
+        fixed (
+            Int32 * vec = vecP) {
+            Int32 temp, pivotItem;                
+            
+            for (; ; ) {
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp >= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                        }
+                        *(vec + i + inc) = pivotItem;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--]; 
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo); 
+                    a2 = *(vec + pivotIndex); 
+                    a3 = *(vec + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 < a2) {
+                        if (a2 < a3) {
+                            *(vec + hi) = a1; 
+                            *(vec + lo) = a3; 
+                            *(vec + lo + inc) = a2; 
+                        } else {
+                            if (a1 < a3) {
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a3; 
+                                *(vec + hi) = a1; 
+                            } else {
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a1; 
+                                //*(vec + hi) = a3; 
+                            }
+                        }
+                    } else {
+                        if (a2 < a3) {
+                            if (a1 < a3) {
+                                *(vec + lo) = a3; 
+                                *(vec + hi) = a2; 
+                                *(vec + lo + inc) = a1; 
+                            } else {
+                                //*(vec + lo) = a1; 
+                                *(vec + hi) = a2; 
+                                *(vec + lo + inc) = a3; 
+                            }
+                        } else {
+                            //*(vec + lo) = a1; 
+                            //*(vec + hi) = a3; 
+                            *(vec + lo + inc) = a2; 
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi; 
+                    pivotItem = *(vec + lo + inc);
+                    for (;;) {
+                        do i += inc; while (*(vec + i) > pivotItem); 
+                        do j -= inc; while (*(vec + j) < pivotItem); 
+                        if (j < i) break; 
+                        temp = *(vec + i); 
+                        *(vec + i) = *(vec + j); 
+                        *(vec + j) = temp; 
+                    }
+                    *(vec + lo + inc) = *(vec + j); 
+                    *(vec + j) = pivotItem;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4D(vecP,lo,hi,j,inc)); 
+#endif 
+                    if (hi - i + inc >= j - lo) {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = hi; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = i; 
+                        hi = j - inc; 
+                    } else {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = j - inc; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = lo; 
+                        lo = i; 
+                    }
+                }
+            }
+        } // fixed
+        } // unsafe 
+    }
+    /// <summary>
+    /// inline 1 dimensional quick sort, ascending, arbitrary element spacing, indices aware
+    /// </summary>
+    /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+    /// <param name="lo">lowest index of sorting range</param>
+    /// <param name="hi">highest index of sorting range</param>
+    /// <param name="idxP">indices vector, content will in-place be sorted along with <paramref name="vecP"/></param>
+    /// <param name="inc">spacing between elements (dimension specifier)</param>
+    /// <remarks><para>Quick sort algorithm is used for ranges of minimum lengths specified by 
+    /// <see cref="P:ILNumerics.Settings.MminimumQuicksortLength"/> and above. 
+    /// Below that length, a simple insertion sort is used instead.</para>
+    /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+    /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+    /// The size is determined by the value of 
+    /// <see cref="P:ILNumerics.Settings.MaxSafeQuicksortRecursionDepth"/>.</para>
+    /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+    /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para></remarks>
+    public static void QuickSortAscIDXST( Int32 [] vecP,  double [] idxP, int lo, int hi, int inc) {
+        System.Diagnostics.Debug.Assert(vecP != null); 
+        System.Diagnostics.Debug.Assert(lo <= hi);
+        System.Diagnostics.Debug.Assert(lo >= 0);
+        //int loSwap, hiSwap;
+        int pivotIndex, i, j;
+        if (vecP.Length < 2) return;
+        s_quickSortStackPos = -1; 
+        Int32 a1, a2, a3; 
+        double ai1, ai2, ai3; 
+        unsafe {
+        fixed ( double * vecIdx = idxP)
+        fixed (
+            Int32 * vec = vecP) {
+            Int32 temp, pivotItem;                
+            
+            for (; ; ) {
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        ai1 = *(vecIdx + j); 
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp <= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                            *(vecIdx + i + inc) = *(vecIdx + i);
+                        }
+                        *(vec + i + inc) = pivotItem;
+                        *(vecIdx + i + inc) = ai1;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--]; 
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo); 
+                    a2 = *(vec + pivotIndex); 
+                    a3 = *(vec + hi);
+                    ai1 = *(vecIdx + lo); 
+                    ai2 = *(vecIdx + pivotIndex); 
+                    ai3 = *(vecIdx + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    *(vecIdx + pivotIndex) = *(vecIdx + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 > a2) {
+                        if (a1 > a3) {
+                            if (a3 > a2) {
+                                *(vec + hi) = a1; 
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a3; 
+                                *(vecIdx + hi) = ai1; 
+                                *(vecIdx + lo) = ai2; 
+                                *(vecIdx + lo + inc) = ai3; 
+                            } else {
+                                *(vec + hi) = a1; 
+                                *(vec + lo) = a3; 
+                                *(vec + lo + inc) = a2; 
+                                *(vecIdx + hi) = ai1;  
+                                *(vecIdx + lo) = ai3; 
+                                *(vecIdx + lo + inc) = ai2; 
+                            }
+                        } else {
+                            *(vec + lo) = a2; 
+                            *(vec + lo + inc) = a1; 
+                            *(vecIdx + lo) = ai2; 
+                            *(vecIdx + lo + inc) = ai1; 
+                        }
+                    } else {
+                        if (a2 > a3) {
+                            *(vec + hi) = a2; 
+                            *(vecIdx + hi) = ai2; 
+                            if (a3 > a1) {
+                                *(vec + lo + inc) = a3; 
+                                *(vecIdx + lo + inc) = ai3; 
+                            } else {
+                                *(vec + lo + inc) = a1; 
+                                *(vec + lo) = a3; 
+                                *(vecIdx + lo + inc) = ai1; 
+                                *(vecIdx + lo) = ai3; 
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2; 
+                            *(vecIdx + lo + inc) = ai2; 
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi; 
+                    pivotItem = *(vec + lo + inc);
+                    ai1 = *(vecIdx + lo + inc);
+                    for (;;) {
+                        do i += inc; while (*(vec + i) < pivotItem); 
+                        do j -= inc; while (*(vec + j) > pivotItem); 
+                        if (j < i) break; 
+                        temp = *(vec + i); 
+                        ai2 = *(vecIdx + i); 
+                        *(vec + i) = *(vec + j); 
+                        *(vec + j) = temp; 
+                        *(vecIdx + i) = *(vecIdx + j); 
+                        *(vecIdx + j) = ai2; 
+                    }
+                    *(vec + lo + inc) = *(vec + j); 
+                    *(vec + j) = pivotItem;
+                    *(vecIdx + lo + inc) = *(vecIdx + j); 
+                    *(vecIdx + j) = ai1;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif 
+                    if (hi - i + inc >= j - lo) {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = hi; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = i; 
+                        hi = j - inc; 
+                    } else {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = j - inc; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = lo; 
+                        lo = i; 
+                    }
+                }
+            }
+        } // fixed
+        } // unsafe 
+    }
+    /// <summary>
+    /// inline 1 dimensional quick sort, descending, arbitrary element spacing, indices aware
+    /// </summary>
+    /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+    /// <param name="lo">lowest index of sorting range</param>
+    /// <param name="hi">highest index of sorting range</param>
+    /// <param name="idxP">indices vector, content will in-place be sorted along with <paramref name="vecP"/></param>
+    /// <param name="inc">spacing between elements (dimension specifier)</param>
+    /// <remarks><para>Quick sort algorithm is used for ranges of minimum lengths specified by 
+    /// <see cref="P:ILNumerics.Settings.MinimumQuicksortLength"/> and above. 
+    /// Below that length, a simple insertion sort is used instead.</para>
+    /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+    /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+    /// The size is determined by the value of 
+    /// <see cref="P:ILNumerics.Settings.MaxSafeQuicksortRecursionDepth"/>.</para>
+    /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+    /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para></remarks>
+    public static void QuickSortDescIDXST( Int32 [] vecP,  double [] idxP, int lo, int hi, int inc) {
+        System.Diagnostics.Debug.Assert(vecP != null); 
+        System.Diagnostics.Debug.Assert(lo <= hi);
+        System.Diagnostics.Debug.Assert(lo >= 0);
+        //int loSwap, hiSwap;
+        int pivotIndex, i, j;
+        if (vecP.Length < 2) return;
+        
+        s_quickSortStackPos = -1;
+        Int32 a1, a2, a3; 
+        double ai1, ai2, ai3; 
+        unsafe {
+        fixed ( double * vecIdx = idxP)
+        fixed (
+            Int32 * vec = vecP) {
+            Int32 temp, pivotItem;
+            
+            for (; ; ) {
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        ai1 = *(vecIdx + j); 
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp >= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                            *(vecIdx + i + inc) = *(vecIdx + i);
+                        }
+                        *(vec + i + inc) = pivotItem;
+                        *(vecIdx + i + inc) = ai1;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--]; 
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo); 
+                    a2 = *(vec + pivotIndex); 
+                    a3 = *(vec + hi);
+                    ai1 = *(vecIdx + lo); 
+                    ai2 = *(vecIdx + pivotIndex); 
+                    ai3 = *(vecIdx + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    *(vecIdx + pivotIndex) = *(vecIdx + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 < a2) {
+                        if (a2 < a3) {
+                            *(vec + hi) = a1; 
+                            *(vec + lo) = a3; 
+                            *(vec + lo + inc) = a2; 
+                            *(vecIdx + hi) = ai1; 
+                            *(vecIdx + lo) = ai3; 
+                            *(vecIdx + lo + inc) = ai2; 
+                        } else {
+                            if (a1 < a3) {
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a3; 
+                                *(vec + hi) = a1; 
+                                *(vecIdx + lo) = ai2; 
+                                *(vecIdx + lo + inc) = ai3; 
+                                *(vecIdx + hi) = ai1; 
+                            } else {
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a1; 
+                                //*(vec + hi) = a3; 
+                                *(vecIdx + lo) = ai2; 
+                                *(vecIdx + lo + inc) = ai1; 
+                                //*(vecIdx + hi) = ai3; 
+                            }
+                        }
+                    } else {
+                        if (a2 < a3) {
+                            if (a1 < a3) {
+                                *(vec + lo) = a3; 
+                                *(vec + hi) = a2; 
+                                *(vec + lo + inc) = a1; 
+                                *(vecIdx + lo) = ai3; 
+                                *(vecIdx + hi) = ai2; 
+                                *(vecIdx + lo + inc) = ai1; 
+                            } else {
+                                //*(vec + lo) = a1; 
+                                *(vec + hi) = a2; 
+                                *(vec + lo + inc) = a3; 
+                                //*(vecIdx + lo) = ai1; 
+                                *(vecIdx + hi) = ai2; 
+                                *(vecIdx + lo + inc) = ai3; 
+                            }
+                        } else {
+                            //*(vec + lo) = a1; 
+                            //*(vec + hi) = a3; 
+                            *(vec + lo + inc) = a2; 
+                            //*(vecIdx + lo) = ai1; 
+                            //*(vecIdx + hi) = ai3; 
+                            *(vecIdx + lo + inc) = ai2; 
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi; 
+                    pivotItem = *(vec + lo + inc);
+                    ai1 = *(vecIdx + lo + inc);
+                    for (;;) {
+                        do i += inc; while (*(vec + i) > pivotItem); 
+                        do j -= inc; while (*(vec + j) < pivotItem); 
+                        if (j < i) break; 
+                        temp = *(vec + i); 
+                        ai2 = *(vecIdx + i); 
+                        *(vec + i) = *(vec + j); 
+                        *(vec + j) = temp; 
+                        *(vecIdx + i) = *(vecIdx + j); 
+                        *(vecIdx + j) = ai2; 
+                    }
+                    *(vec + lo + inc) = *(vec + j); 
+                    *(vec + j) = pivotItem;
+                    *(vecIdx + lo + inc) = *(vecIdx + j); 
+                    *(vecIdx + j) = ai1;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif 
+                    if (hi - i + inc >= j - lo) {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = hi; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = i; 
+                        hi = j - inc; 
+                    } else {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = j - inc; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = lo; 
+                        lo = i; 
+                    }
+                }
+            }
+        } // fixed
+        } // unsafe 
+    }
+
+    /// <summary>
+    /// inline one dimensional quick sort, ascending, arbitrary element spacing
+    /// </summary>
+    /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+    /// <param name="lo">lowest index of sorting range</param>
+    /// <param name="hi">highest index of sorting range</param>
+    /// <param name="inc">spacing between elements (dimension specifier)</param>
+    /// <remarks><para>Quick sort algorithm is used for ranges of minimum lengths specified by 
+    /// <see cref="P:ILNumerics.Settings.MinimumQuicksortLength"/> and above. 
+    /// Below that length, a simple insertion sort is used instead.</para>
+    /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+    /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+    /// The size is determined by the value of 
+    /// <see cref="P:ILNumerics.Settings.MaxSafeQuicksortRecursionDepth"/>.</para>
+    /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+    /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para></remarks>
+    public static void QuickSortAscST( Int16 [] vecP, int lo, int hi, int inc) {
+        System.Diagnostics.Debug.Assert(vecP != null); 
+        System.Diagnostics.Debug.Assert(lo <= hi);
+        System.Diagnostics.Debug.Assert(lo >= 0);
+        //int loSwap, hiSwap;
+        int pivotIndex, i, j;
+        if (vecP.Length < 2) return; 
+        int[] s_quickSortStackMT = ILMemoryPool.Pool.New<int>(Settings.s_maxSafeQuicksortRecursionDepth * 2);
+        s_quickSortStackPos = -1;
+        Int16 a1, a2, a3; 
+        unsafe {
+        fixed (
+            Int16 * vec = vecP) {
+            Int16 temp, pivotItem;
+            
+
+            for (; ; ) {
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp <= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                        }
+                        *(vec + i + inc) = pivotItem;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--]; 
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo); 
+                    a2 = *(vec + pivotIndex); 
+                    a3 = *(vec + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 > a2) {
+                        if (a1 > a3) {
+                            if (a3 > a2) {
+                                *(vec + hi) = a1; 
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a3; 
+                            } else {
+                                *(vec + hi) = a1; 
+                                *(vec + lo) = a3; 
+                                *(vec + lo + inc) = a2; 
+                            }
+                        } else {
+                            *(vec + lo) = a2; 
+                            *(vec + lo + inc) = a1; 
+                        }
+                    } else {
+                        if (a2 > a3) {
+                            *(vec + hi) = a2; 
+                            if (a3 > a1) {
+                                *(vec + lo + inc) = a3; 
+                            } else {
+                                *(vec + lo + inc) = a1; 
+                                *(vec + lo) = a3; 
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2; 
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi; 
+                    pivotItem = *(vec + lo + inc);
+                    for (;;) {
+                        do i += inc; while (*(vec + i) < pivotItem); 
+                        do j -= inc; while (*(vec + j) > pivotItem); 
+                        if (j < i) break; 
+                        temp = *(vec + i); 
+                        *(vec + i) = *(vec + j); 
+                        *(vec + j) = temp; 
+                    }
+                    *(vec + lo + inc) = *(vec + j); 
+                    *(vec + j) = pivotItem;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif 
+                    if (hi - i + inc >= j - lo) {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = hi; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = i; 
+                        hi = j - inc; 
+                    } else {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = j - inc; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = lo; 
+                        lo = i; 
+                    }
+                }
+            }
+        } // fixed
+        } // unsafe 
+    }
+    /// <summary>
+    /// inline one dimensional quick sort, descending, arbitrary element spacing
+    /// </summary>
+    /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+    /// <param name="lo">lowest index of sorting range</param>
+    /// <param name="hi">highest index of sorting range</param>
+    /// <param name="inc">spacing between elements (dimension specifier)</param>
+    /// <remarks><para>Quick sort algorithm is used for ranges of minimum lengths specified by 
+    /// <see cref="P:ILNumerics.Settings.MinimumQuicksortLength"/> and above. 
+    /// Below that length, a simple insertion sort is used instead.</para>
+    /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+    /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+    /// The size is determined by the value of 
+    /// <see cref="P:ILNumerics.Settings.MaxSafeQuicksortRecursionDepth"/>.</para>
+    /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+    /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para></remarks>
+    public static void QuickSortDescST( Int16 [] vecP, int lo, int hi, int inc) {
+        System.Diagnostics.Debug.Assert(vecP != null); 
+        System.Diagnostics.Debug.Assert(lo <= hi);
+        System.Diagnostics.Debug.Assert(lo >= 0);
+        //int loSwap, hiSwap;
+        int pivotIndex, i, j;
+        if (vecP.Length < 2) return;
+        s_quickSortStackPos = -1;
+        Int16 a1, a2, a3; 
+        unsafe {
+        fixed (
+            Int16 * vec = vecP) {
+            Int16 temp, pivotItem;                
+            
+            for (; ; ) {
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp >= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                        }
+                        *(vec + i + inc) = pivotItem;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--]; 
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo); 
+                    a2 = *(vec + pivotIndex); 
+                    a3 = *(vec + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 < a2) {
+                        if (a2 < a3) {
+                            *(vec + hi) = a1; 
+                            *(vec + lo) = a3; 
+                            *(vec + lo + inc) = a2; 
+                        } else {
+                            if (a1 < a3) {
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a3; 
+                                *(vec + hi) = a1; 
+                            } else {
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a1; 
+                                //*(vec + hi) = a3; 
+                            }
+                        }
+                    } else {
+                        if (a2 < a3) {
+                            if (a1 < a3) {
+                                *(vec + lo) = a3; 
+                                *(vec + hi) = a2; 
+                                *(vec + lo + inc) = a1; 
+                            } else {
+                                //*(vec + lo) = a1; 
+                                *(vec + hi) = a2; 
+                                *(vec + lo + inc) = a3; 
+                            }
+                        } else {
+                            //*(vec + lo) = a1; 
+                            //*(vec + hi) = a3; 
+                            *(vec + lo + inc) = a2; 
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi; 
+                    pivotItem = *(vec + lo + inc);
+                    for (;;) {
+                        do i += inc; while (*(vec + i) > pivotItem); 
+                        do j -= inc; while (*(vec + j) < pivotItem); 
+                        if (j < i) break; 
+                        temp = *(vec + i); 
+                        *(vec + i) = *(vec + j); 
+                        *(vec + j) = temp; 
+                    }
+                    *(vec + lo + inc) = *(vec + j); 
+                    *(vec + j) = pivotItem;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4D(vecP,lo,hi,j,inc)); 
+#endif 
+                    if (hi - i + inc >= j - lo) {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = hi; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = i; 
+                        hi = j - inc; 
+                    } else {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = j - inc; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = lo; 
+                        lo = i; 
+                    }
+                }
+            }
+        } // fixed
+        } // unsafe 
+    }
+    /// <summary>
+    /// inline 1 dimensional quick sort, ascending, arbitrary element spacing, indices aware
+    /// </summary>
+    /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+    /// <param name="lo">lowest index of sorting range</param>
+    /// <param name="hi">highest index of sorting range</param>
+    /// <param name="idxP">indices vector, content will in-place be sorted along with <paramref name="vecP"/></param>
+    /// <param name="inc">spacing between elements (dimension specifier)</param>
+    /// <remarks><para>Quick sort algorithm is used for ranges of minimum lengths specified by 
+    /// <see cref="P:ILNumerics.Settings.MminimumQuicksortLength"/> and above. 
+    /// Below that length, a simple insertion sort is used instead.</para>
+    /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+    /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+    /// The size is determined by the value of 
+    /// <see cref="P:ILNumerics.Settings.MaxSafeQuicksortRecursionDepth"/>.</para>
+    /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+    /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para></remarks>
+    public static void QuickSortAscIDXST( Int16 [] vecP,  double [] idxP, int lo, int hi, int inc) {
+        System.Diagnostics.Debug.Assert(vecP != null); 
+        System.Diagnostics.Debug.Assert(lo <= hi);
+        System.Diagnostics.Debug.Assert(lo >= 0);
+        //int loSwap, hiSwap;
+        int pivotIndex, i, j;
+        if (vecP.Length < 2) return;
+        s_quickSortStackPos = -1; 
+        Int16 a1, a2, a3; 
+        double ai1, ai2, ai3; 
+        unsafe {
+        fixed ( double * vecIdx = idxP)
+        fixed (
+            Int16 * vec = vecP) {
+            Int16 temp, pivotItem;                
+            
+            for (; ; ) {
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        ai1 = *(vecIdx + j); 
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp <= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                            *(vecIdx + i + inc) = *(vecIdx + i);
+                        }
+                        *(vec + i + inc) = pivotItem;
+                        *(vecIdx + i + inc) = ai1;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--]; 
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo); 
+                    a2 = *(vec + pivotIndex); 
+                    a3 = *(vec + hi);
+                    ai1 = *(vecIdx + lo); 
+                    ai2 = *(vecIdx + pivotIndex); 
+                    ai3 = *(vecIdx + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    *(vecIdx + pivotIndex) = *(vecIdx + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 > a2) {
+                        if (a1 > a3) {
+                            if (a3 > a2) {
+                                *(vec + hi) = a1; 
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a3; 
+                                *(vecIdx + hi) = ai1; 
+                                *(vecIdx + lo) = ai2; 
+                                *(vecIdx + lo + inc) = ai3; 
+                            } else {
+                                *(vec + hi) = a1; 
+                                *(vec + lo) = a3; 
+                                *(vec + lo + inc) = a2; 
+                                *(vecIdx + hi) = ai1;  
+                                *(vecIdx + lo) = ai3; 
+                                *(vecIdx + lo + inc) = ai2; 
+                            }
+                        } else {
+                            *(vec + lo) = a2; 
+                            *(vec + lo + inc) = a1; 
+                            *(vecIdx + lo) = ai2; 
+                            *(vecIdx + lo + inc) = ai1; 
+                        }
+                    } else {
+                        if (a2 > a3) {
+                            *(vec + hi) = a2; 
+                            *(vecIdx + hi) = ai2; 
+                            if (a3 > a1) {
+                                *(vec + lo + inc) = a3; 
+                                *(vecIdx + lo + inc) = ai3; 
+                            } else {
+                                *(vec + lo + inc) = a1; 
+                                *(vec + lo) = a3; 
+                                *(vecIdx + lo + inc) = ai1; 
+                                *(vecIdx + lo) = ai3; 
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2; 
+                            *(vecIdx + lo + inc) = ai2; 
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi; 
+                    pivotItem = *(vec + lo + inc);
+                    ai1 = *(vecIdx + lo + inc);
+                    for (;;) {
+                        do i += inc; while (*(vec + i) < pivotItem); 
+                        do j -= inc; while (*(vec + j) > pivotItem); 
+                        if (j < i) break; 
+                        temp = *(vec + i); 
+                        ai2 = *(vecIdx + i); 
+                        *(vec + i) = *(vec + j); 
+                        *(vec + j) = temp; 
+                        *(vecIdx + i) = *(vecIdx + j); 
+                        *(vecIdx + j) = ai2; 
+                    }
+                    *(vec + lo + inc) = *(vec + j); 
+                    *(vec + j) = pivotItem;
+                    *(vecIdx + lo + inc) = *(vecIdx + j); 
+                    *(vecIdx + j) = ai1;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif 
+                    if (hi - i + inc >= j - lo) {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = hi; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = i; 
+                        hi = j - inc; 
+                    } else {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = j - inc; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = lo; 
+                        lo = i; 
+                    }
+                }
+            }
+        } // fixed
+        } // unsafe 
+    }
+    /// <summary>
+    /// inline 1 dimensional quick sort, descending, arbitrary element spacing, indices aware
+    /// </summary>
+    /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+    /// <param name="lo">lowest index of sorting range</param>
+    /// <param name="hi">highest index of sorting range</param>
+    /// <param name="idxP">indices vector, content will in-place be sorted along with <paramref name="vecP"/></param>
+    /// <param name="inc">spacing between elements (dimension specifier)</param>
+    /// <remarks><para>Quick sort algorithm is used for ranges of minimum lengths specified by 
+    /// <see cref="P:ILNumerics.Settings.MinimumQuicksortLength"/> and above. 
+    /// Below that length, a simple insertion sort is used instead.</para>
+    /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+    /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+    /// The size is determined by the value of 
+    /// <see cref="P:ILNumerics.Settings.MaxSafeQuicksortRecursionDepth"/>.</para>
+    /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+    /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para></remarks>
+    public static void QuickSortDescIDXST( Int16 [] vecP,  double [] idxP, int lo, int hi, int inc) {
+        System.Diagnostics.Debug.Assert(vecP != null); 
+        System.Diagnostics.Debug.Assert(lo <= hi);
+        System.Diagnostics.Debug.Assert(lo >= 0);
+        //int loSwap, hiSwap;
+        int pivotIndex, i, j;
+        if (vecP.Length < 2) return;
+        
+        s_quickSortStackPos = -1;
+        Int16 a1, a2, a3; 
+        double ai1, ai2, ai3; 
+        unsafe {
+        fixed ( double * vecIdx = idxP)
+        fixed (
+            Int16 * vec = vecP) {
+            Int16 temp, pivotItem;
+            
+            for (; ; ) {
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        ai1 = *(vecIdx + j); 
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp >= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                            *(vecIdx + i + inc) = *(vecIdx + i);
+                        }
+                        *(vec + i + inc) = pivotItem;
+                        *(vecIdx + i + inc) = ai1;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--]; 
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo); 
+                    a2 = *(vec + pivotIndex); 
+                    a3 = *(vec + hi);
+                    ai1 = *(vecIdx + lo); 
+                    ai2 = *(vecIdx + pivotIndex); 
+                    ai3 = *(vecIdx + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    *(vecIdx + pivotIndex) = *(vecIdx + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 < a2) {
+                        if (a2 < a3) {
+                            *(vec + hi) = a1; 
+                            *(vec + lo) = a3; 
+                            *(vec + lo + inc) = a2; 
+                            *(vecIdx + hi) = ai1; 
+                            *(vecIdx + lo) = ai3; 
+                            *(vecIdx + lo + inc) = ai2; 
+                        } else {
+                            if (a1 < a3) {
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a3; 
+                                *(vec + hi) = a1; 
+                                *(vecIdx + lo) = ai2; 
+                                *(vecIdx + lo + inc) = ai3; 
+                                *(vecIdx + hi) = ai1; 
+                            } else {
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a1; 
+                                //*(vec + hi) = a3; 
+                                *(vecIdx + lo) = ai2; 
+                                *(vecIdx + lo + inc) = ai1; 
+                                //*(vecIdx + hi) = ai3; 
+                            }
+                        }
+                    } else {
+                        if (a2 < a3) {
+                            if (a1 < a3) {
+                                *(vec + lo) = a3; 
+                                *(vec + hi) = a2; 
+                                *(vec + lo + inc) = a1; 
+                                *(vecIdx + lo) = ai3; 
+                                *(vecIdx + hi) = ai2; 
+                                *(vecIdx + lo + inc) = ai1; 
+                            } else {
+                                //*(vec + lo) = a1; 
+                                *(vec + hi) = a2; 
+                                *(vec + lo + inc) = a3; 
+                                //*(vecIdx + lo) = ai1; 
+                                *(vecIdx + hi) = ai2; 
+                                *(vecIdx + lo + inc) = ai3; 
+                            }
+                        } else {
+                            //*(vec + lo) = a1; 
+                            //*(vec + hi) = a3; 
+                            *(vec + lo + inc) = a2; 
+                            //*(vecIdx + lo) = ai1; 
+                            //*(vecIdx + hi) = ai3; 
+                            *(vecIdx + lo + inc) = ai2; 
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi; 
+                    pivotItem = *(vec + lo + inc);
+                    ai1 = *(vecIdx + lo + inc);
+                    for (;;) {
+                        do i += inc; while (*(vec + i) > pivotItem); 
+                        do j -= inc; while (*(vec + j) < pivotItem); 
+                        if (j < i) break; 
+                        temp = *(vec + i); 
+                        ai2 = *(vecIdx + i); 
+                        *(vec + i) = *(vec + j); 
+                        *(vec + j) = temp; 
+                        *(vecIdx + i) = *(vecIdx + j); 
+                        *(vecIdx + j) = ai2; 
+                    }
+                    *(vec + lo + inc) = *(vec + j); 
+                    *(vec + j) = pivotItem;
+                    *(vecIdx + lo + inc) = *(vecIdx + j); 
+                    *(vecIdx + j) = ai1;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif 
+                    if (hi - i + inc >= j - lo) {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = hi; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = i; 
+                        hi = j - inc; 
+                    } else {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = j - inc; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = lo; 
+                        lo = i; 
+                    }
+                }
+            }
+        } // fixed
+        } // unsafe 
+    }
+
+    /// <summary>
+    /// inline one dimensional quick sort, ascending, arbitrary element spacing
+    /// </summary>
+    /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+    /// <param name="lo">lowest index of sorting range</param>
+    /// <param name="hi">highest index of sorting range</param>
+    /// <param name="inc">spacing between elements (dimension specifier)</param>
+    /// <remarks><para>Quick sort algorithm is used for ranges of minimum lengths specified by 
+    /// <see cref="P:ILNumerics.Settings.MinimumQuicksortLength"/> and above. 
+    /// Below that length, a simple insertion sort is used instead.</para>
+    /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+    /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+    /// The size is determined by the value of 
+    /// <see cref="P:ILNumerics.Settings.MaxSafeQuicksortRecursionDepth"/>.</para>
+    /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+    /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para></remarks>
+    public static void QuickSortAscST( float [] vecP, int lo, int hi, int inc) {
+        System.Diagnostics.Debug.Assert(vecP != null); 
+        System.Diagnostics.Debug.Assert(lo <= hi);
+        System.Diagnostics.Debug.Assert(lo >= 0);
+        //int loSwap, hiSwap;
+        int pivotIndex, i, j;
+        if (vecP.Length < 2) return; 
+        int[] s_quickSortStackMT = ILMemoryPool.Pool.New<int>(Settings.s_maxSafeQuicksortRecursionDepth * 2);
+        s_quickSortStackPos = -1;
+        float a1, a2, a3; 
+        unsafe {
+        fixed (
+            float * vec = vecP) {
+            float temp, pivotItem;
+            if (checkNaNAsc(lo, ref hi, inc, vec)) return;
+
+            for (; ; ) {
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp <= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                        }
+                        *(vec + i + inc) = pivotItem;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--]; 
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo); 
+                    a2 = *(vec + pivotIndex); 
+                    a3 = *(vec + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 > a2) {
+                        if (a1 > a3) {
+                            if (a3 > a2) {
+                                *(vec + hi) = a1; 
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a3; 
+                            } else {
+                                *(vec + hi) = a1; 
+                                *(vec + lo) = a3; 
+                                *(vec + lo + inc) = a2; 
+                            }
+                        } else {
+                            *(vec + lo) = a2; 
+                            *(vec + lo + inc) = a1; 
+                        }
+                    } else {
+                        if (a2 > a3) {
+                            *(vec + hi) = a2; 
+                            if (a3 > a1) {
+                                *(vec + lo + inc) = a3; 
+                            } else {
+                                *(vec + lo + inc) = a1; 
+                                *(vec + lo) = a3; 
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2; 
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi; 
+                    pivotItem = *(vec + lo + inc);
+                    for (;;) {
+                        do i += inc; while (*(vec + i) < pivotItem); 
+                        do j -= inc; while (*(vec + j) > pivotItem); 
+                        if (j < i) break; 
+                        temp = *(vec + i); 
+                        *(vec + i) = *(vec + j); 
+                        *(vec + j) = temp; 
+                    }
+                    *(vec + lo + inc) = *(vec + j); 
+                    *(vec + j) = pivotItem;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif 
+                    if (hi - i + inc >= j - lo) {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = hi; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = i; 
+                        hi = j - inc; 
+                    } else {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = j - inc; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = lo; 
+                        lo = i; 
+                    }
+                }
+            }
+        } // fixed
+        } // unsafe 
+    }
+    /// <summary>
+    /// inline one dimensional quick sort, descending, arbitrary element spacing
+    /// </summary>
+    /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+    /// <param name="lo">lowest index of sorting range</param>
+    /// <param name="hi">highest index of sorting range</param>
+    /// <param name="inc">spacing between elements (dimension specifier)</param>
+    /// <remarks><para>Quick sort algorithm is used for ranges of minimum lengths specified by 
+    /// <see cref="P:ILNumerics.Settings.MinimumQuicksortLength"/> and above. 
+    /// Below that length, a simple insertion sort is used instead.</para>
+    /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+    /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+    /// The size is determined by the value of 
+    /// <see cref="P:ILNumerics.Settings.MaxSafeQuicksortRecursionDepth"/>.</para>
+    /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+    /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para></remarks>
+    public static void QuickSortDescST( float [] vecP, int lo, int hi, int inc) {
+        System.Diagnostics.Debug.Assert(vecP != null); 
+        System.Diagnostics.Debug.Assert(lo <= hi);
+        System.Diagnostics.Debug.Assert(lo >= 0);
+        //int loSwap, hiSwap;
+        int pivotIndex, i, j;
+        if (vecP.Length < 2) return;
+        s_quickSortStackPos = -1;
+        float a1, a2, a3; 
+        unsafe {
+        fixed (
+            float * vec = vecP) {
+            float temp, pivotItem;                
+            if (checkNaNDesc(lo, ref hi, inc, vec)) return;
+            for (; ; ) {
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp >= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                        }
+                        *(vec + i + inc) = pivotItem;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--]; 
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo); 
+                    a2 = *(vec + pivotIndex); 
+                    a3 = *(vec + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 < a2) {
+                        if (a2 < a3) {
+                            *(vec + hi) = a1; 
+                            *(vec + lo) = a3; 
+                            *(vec + lo + inc) = a2; 
+                        } else {
+                            if (a1 < a3) {
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a3; 
+                                *(vec + hi) = a1; 
+                            } else {
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a1; 
+                                //*(vec + hi) = a3; 
+                            }
+                        }
+                    } else {
+                        if (a2 < a3) {
+                            if (a1 < a3) {
+                                *(vec + lo) = a3; 
+                                *(vec + hi) = a2; 
+                                *(vec + lo + inc) = a1; 
+                            } else {
+                                //*(vec + lo) = a1; 
+                                *(vec + hi) = a2; 
+                                *(vec + lo + inc) = a3; 
+                            }
+                        } else {
+                            //*(vec + lo) = a1; 
+                            //*(vec + hi) = a3; 
+                            *(vec + lo + inc) = a2; 
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi; 
+                    pivotItem = *(vec + lo + inc);
+                    for (;;) {
+                        do i += inc; while (*(vec + i) > pivotItem); 
+                        do j -= inc; while (*(vec + j) < pivotItem); 
+                        if (j < i) break; 
+                        temp = *(vec + i); 
+                        *(vec + i) = *(vec + j); 
+                        *(vec + j) = temp; 
+                    }
+                    *(vec + lo + inc) = *(vec + j); 
+                    *(vec + j) = pivotItem;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4D(vecP,lo,hi,j,inc)); 
+#endif 
+                    if (hi - i + inc >= j - lo) {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = hi; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = i; 
+                        hi = j - inc; 
+                    } else {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = j - inc; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = lo; 
+                        lo = i; 
+                    }
+                }
+            }
+        } // fixed
+        } // unsafe 
+    }
+    /// <summary>
+    /// inline 1 dimensional quick sort, ascending, arbitrary element spacing, indices aware
+    /// </summary>
+    /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+    /// <param name="lo">lowest index of sorting range</param>
+    /// <param name="hi">highest index of sorting range</param>
+    /// <param name="idxP">indices vector, content will in-place be sorted along with <paramref name="vecP"/></param>
+    /// <param name="inc">spacing between elements (dimension specifier)</param>
+    /// <remarks><para>Quick sort algorithm is used for ranges of minimum lengths specified by 
+    /// <see cref="P:ILNumerics.Settings.MminimumQuicksortLength"/> and above. 
+    /// Below that length, a simple insertion sort is used instead.</para>
+    /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+    /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+    /// The size is determined by the value of 
+    /// <see cref="P:ILNumerics.Settings.MaxSafeQuicksortRecursionDepth"/>.</para>
+    /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+    /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para></remarks>
+    public static void QuickSortAscIDXST( float [] vecP,  double [] idxP, int lo, int hi, int inc) {
+        System.Diagnostics.Debug.Assert(vecP != null); 
+        System.Diagnostics.Debug.Assert(lo <= hi);
+        System.Diagnostics.Debug.Assert(lo >= 0);
+        //int loSwap, hiSwap;
+        int pivotIndex, i, j;
+        if (vecP.Length < 2) return;
+        s_quickSortStackPos = -1; 
+        float a1, a2, a3; 
+        double ai1, ai2, ai3; 
+        unsafe {
+        fixed ( double * vecIdx = idxP)
+        fixed (
+            float * vec = vecP) {
+            float temp, pivotItem;                
+            if (checkNaNIDXAsc(lo, ref hi, inc, vecIdx, vec)) return;
+            for (; ; ) {
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        ai1 = *(vecIdx + j); 
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp <= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                            *(vecIdx + i + inc) = *(vecIdx + i);
+                        }
+                        *(vec + i + inc) = pivotItem;
+                        *(vecIdx + i + inc) = ai1;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--]; 
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo); 
+                    a2 = *(vec + pivotIndex); 
+                    a3 = *(vec + hi);
+                    ai1 = *(vecIdx + lo); 
+                    ai2 = *(vecIdx + pivotIndex); 
+                    ai3 = *(vecIdx + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    *(vecIdx + pivotIndex) = *(vecIdx + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 > a2) {
+                        if (a1 > a3) {
+                            if (a3 > a2) {
+                                *(vec + hi) = a1; 
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a3; 
+                                *(vecIdx + hi) = ai1; 
+                                *(vecIdx + lo) = ai2; 
+                                *(vecIdx + lo + inc) = ai3; 
+                            } else {
+                                *(vec + hi) = a1; 
+                                *(vec + lo) = a3; 
+                                *(vec + lo + inc) = a2; 
+                                *(vecIdx + hi) = ai1;  
+                                *(vecIdx + lo) = ai3; 
+                                *(vecIdx + lo + inc) = ai2; 
+                            }
+                        } else {
+                            *(vec + lo) = a2; 
+                            *(vec + lo + inc) = a1; 
+                            *(vecIdx + lo) = ai2; 
+                            *(vecIdx + lo + inc) = ai1; 
+                        }
+                    } else {
+                        if (a2 > a3) {
+                            *(vec + hi) = a2; 
+                            *(vecIdx + hi) = ai2; 
+                            if (a3 > a1) {
+                                *(vec + lo + inc) = a3; 
+                                *(vecIdx + lo + inc) = ai3; 
+                            } else {
+                                *(vec + lo + inc) = a1; 
+                                *(vec + lo) = a3; 
+                                *(vecIdx + lo + inc) = ai1; 
+                                *(vecIdx + lo) = ai3; 
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2; 
+                            *(vecIdx + lo + inc) = ai2; 
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi; 
+                    pivotItem = *(vec + lo + inc);
+                    ai1 = *(vecIdx + lo + inc);
+                    for (;;) {
+                        do i += inc; while (*(vec + i) < pivotItem); 
+                        do j -= inc; while (*(vec + j) > pivotItem); 
+                        if (j < i) break; 
+                        temp = *(vec + i); 
+                        ai2 = *(vecIdx + i); 
+                        *(vec + i) = *(vec + j); 
+                        *(vec + j) = temp; 
+                        *(vecIdx + i) = *(vecIdx + j); 
+                        *(vecIdx + j) = ai2; 
+                    }
+                    *(vec + lo + inc) = *(vec + j); 
+                    *(vec + j) = pivotItem;
+                    *(vecIdx + lo + inc) = *(vecIdx + j); 
+                    *(vecIdx + j) = ai1;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif 
+                    if (hi - i + inc >= j - lo) {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = hi; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = i; 
+                        hi = j - inc; 
+                    } else {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = j - inc; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = lo; 
+                        lo = i; 
+                    }
+                }
+            }
+        } // fixed
+        } // unsafe 
+    }
+    /// <summary>
+    /// inline 1 dimensional quick sort, descending, arbitrary element spacing, indices aware
+    /// </summary>
+    /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+    /// <param name="lo">lowest index of sorting range</param>
+    /// <param name="hi">highest index of sorting range</param>
+    /// <param name="idxP">indices vector, content will in-place be sorted along with <paramref name="vecP"/></param>
+    /// <param name="inc">spacing between elements (dimension specifier)</param>
+    /// <remarks><para>Quick sort algorithm is used for ranges of minimum lengths specified by 
+    /// <see cref="P:ILNumerics.Settings.MinimumQuicksortLength"/> and above. 
+    /// Below that length, a simple insertion sort is used instead.</para>
+    /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+    /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+    /// The size is determined by the value of 
+    /// <see cref="P:ILNumerics.Settings.MaxSafeQuicksortRecursionDepth"/>.</para>
+    /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+    /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para></remarks>
+    public static void QuickSortDescIDXST( float [] vecP,  double [] idxP, int lo, int hi, int inc) {
+        System.Diagnostics.Debug.Assert(vecP != null); 
+        System.Diagnostics.Debug.Assert(lo <= hi);
+        System.Diagnostics.Debug.Assert(lo >= 0);
+        //int loSwap, hiSwap;
+        int pivotIndex, i, j;
+        if (vecP.Length < 2) return;
+        
+        s_quickSortStackPos = -1;
+        float a1, a2, a3; 
+        double ai1, ai2, ai3; 
+        unsafe {
+        fixed ( double * vecIdx = idxP)
+        fixed (
+            float * vec = vecP) {
+            float temp, pivotItem;
+            if (checkNaNIDXDesc(lo, ref hi, inc, vecIdx, vec)) return;
+            for (; ; ) {
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        ai1 = *(vecIdx + j); 
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp >= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                            *(vecIdx + i + inc) = *(vecIdx + i);
+                        }
+                        *(vec + i + inc) = pivotItem;
+                        *(vecIdx + i + inc) = ai1;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--]; 
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo); 
+                    a2 = *(vec + pivotIndex); 
+                    a3 = *(vec + hi);
+                    ai1 = *(vecIdx + lo); 
+                    ai2 = *(vecIdx + pivotIndex); 
+                    ai3 = *(vecIdx + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    *(vecIdx + pivotIndex) = *(vecIdx + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 < a2) {
+                        if (a2 < a3) {
+                            *(vec + hi) = a1; 
+                            *(vec + lo) = a3; 
+                            *(vec + lo + inc) = a2; 
+                            *(vecIdx + hi) = ai1; 
+                            *(vecIdx + lo) = ai3; 
+                            *(vecIdx + lo + inc) = ai2; 
+                        } else {
+                            if (a1 < a3) {
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a3; 
+                                *(vec + hi) = a1; 
+                                *(vecIdx + lo) = ai2; 
+                                *(vecIdx + lo + inc) = ai3; 
+                                *(vecIdx + hi) = ai1; 
+                            } else {
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a1; 
+                                //*(vec + hi) = a3; 
+                                *(vecIdx + lo) = ai2; 
+                                *(vecIdx + lo + inc) = ai1; 
+                                //*(vecIdx + hi) = ai3; 
+                            }
+                        }
+                    } else {
+                        if (a2 < a3) {
+                            if (a1 < a3) {
+                                *(vec + lo) = a3; 
+                                *(vec + hi) = a2; 
+                                *(vec + lo + inc) = a1; 
+                                *(vecIdx + lo) = ai3; 
+                                *(vecIdx + hi) = ai2; 
+                                *(vecIdx + lo + inc) = ai1; 
+                            } else {
+                                //*(vec + lo) = a1; 
+                                *(vec + hi) = a2; 
+                                *(vec + lo + inc) = a3; 
+                                //*(vecIdx + lo) = ai1; 
+                                *(vecIdx + hi) = ai2; 
+                                *(vecIdx + lo + inc) = ai3; 
+                            }
+                        } else {
+                            //*(vec + lo) = a1; 
+                            //*(vec + hi) = a3; 
+                            *(vec + lo + inc) = a2; 
+                            //*(vecIdx + lo) = ai1; 
+                            //*(vecIdx + hi) = ai3; 
+                            *(vecIdx + lo + inc) = ai2; 
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi; 
+                    pivotItem = *(vec + lo + inc);
+                    ai1 = *(vecIdx + lo + inc);
+                    for (;;) {
+                        do i += inc; while (*(vec + i) > pivotItem); 
+                        do j -= inc; while (*(vec + j) < pivotItem); 
+                        if (j < i) break; 
+                        temp = *(vec + i); 
+                        ai2 = *(vecIdx + i); 
+                        *(vec + i) = *(vec + j); 
+                        *(vec + j) = temp; 
+                        *(vecIdx + i) = *(vecIdx + j); 
+                        *(vecIdx + j) = ai2; 
+                    }
+                    *(vec + lo + inc) = *(vec + j); 
+                    *(vec + j) = pivotItem;
+                    *(vecIdx + lo + inc) = *(vecIdx + j); 
+                    *(vecIdx + j) = ai1;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif 
+                    if (hi - i + inc >= j - lo) {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = hi; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = i; 
+                        hi = j - inc; 
+                    } else {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = j - inc; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = lo; 
+                        lo = i; 
+                    }
+                }
+            }
+        } // fixed
+        } // unsafe 
+    }
+
+    /// <summary>
+    /// inline one dimensional quick sort, ascending, arbitrary element spacing
+    /// </summary>
+    /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+    /// <param name="lo">lowest index of sorting range</param>
+    /// <param name="hi">highest index of sorting range</param>
+    /// <param name="inc">spacing between elements (dimension specifier)</param>
+    /// <remarks><para>Quick sort algorithm is used for ranges of minimum lengths specified by 
+    /// <see cref="P:ILNumerics.Settings.MinimumQuicksortLength"/> and above. 
+    /// Below that length, a simple insertion sort is used instead.</para>
+    /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+    /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+    /// The size is determined by the value of 
+    /// <see cref="P:ILNumerics.Settings.MaxSafeQuicksortRecursionDepth"/>.</para>
+    /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+    /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para></remarks>
+    public static void QuickSortAscST( fcomplex [] vecP, int lo, int hi, int inc) {
+        System.Diagnostics.Debug.Assert(vecP != null); 
+        System.Diagnostics.Debug.Assert(lo <= hi);
+        System.Diagnostics.Debug.Assert(lo >= 0);
+        //int loSwap, hiSwap;
+        int pivotIndex, i, j;
+        if (vecP.Length < 2) return; 
+        int[] s_quickSortStackMT = ILMemoryPool.Pool.New<int>(Settings.s_maxSafeQuicksortRecursionDepth * 2);
+        s_quickSortStackPos = -1;
+        fcomplex a1, a2, a3; 
+        unsafe {
+        fixed (
+            fcomplex * vec = vecP) {
+            fcomplex temp, pivotItem;
+            if (checkNaNAsc(lo, ref hi, inc, vec)) return;
+
+            for (; ; ) {
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp <= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                        }
+                        *(vec + i + inc) = pivotItem;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--]; 
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo); 
+                    a2 = *(vec + pivotIndex); 
+                    a3 = *(vec + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 > a2) {
+                        if (a1 > a3) {
+                            if (a3 > a2) {
+                                *(vec + hi) = a1; 
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a3; 
+                            } else {
+                                *(vec + hi) = a1; 
+                                *(vec + lo) = a3; 
+                                *(vec + lo + inc) = a2; 
+                            }
+                        } else {
+                            *(vec + lo) = a2; 
+                            *(vec + lo + inc) = a1; 
+                        }
+                    } else {
+                        if (a2 > a3) {
+                            *(vec + hi) = a2; 
+                            if (a3 > a1) {
+                                *(vec + lo + inc) = a3; 
+                            } else {
+                                *(vec + lo + inc) = a1; 
+                                *(vec + lo) = a3; 
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2; 
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi; 
+                    pivotItem = *(vec + lo + inc);
+                    for (;;) {
+                        do i += inc; while (*(vec + i) < pivotItem); 
+                        do j -= inc; while (*(vec + j) > pivotItem); 
+                        if (j < i) break; 
+                        temp = *(vec + i); 
+                        *(vec + i) = *(vec + j); 
+                        *(vec + j) = temp; 
+                    }
+                    *(vec + lo + inc) = *(vec + j); 
+                    *(vec + j) = pivotItem;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif 
+                    if (hi - i + inc >= j - lo) {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = hi; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = i; 
+                        hi = j - inc; 
+                    } else {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = j - inc; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = lo; 
+                        lo = i; 
+                    }
+                }
+            }
+        } // fixed
+        } // unsafe 
+    }
+    /// <summary>
+    /// inline one dimensional quick sort, descending, arbitrary element spacing
+    /// </summary>
+    /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+    /// <param name="lo">lowest index of sorting range</param>
+    /// <param name="hi">highest index of sorting range</param>
+    /// <param name="inc">spacing between elements (dimension specifier)</param>
+    /// <remarks><para>Quick sort algorithm is used for ranges of minimum lengths specified by 
+    /// <see cref="P:ILNumerics.Settings.MinimumQuicksortLength"/> and above. 
+    /// Below that length, a simple insertion sort is used instead.</para>
+    /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+    /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+    /// The size is determined by the value of 
+    /// <see cref="P:ILNumerics.Settings.MaxSafeQuicksortRecursionDepth"/>.</para>
+    /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+    /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para></remarks>
+    public static void QuickSortDescST( fcomplex [] vecP, int lo, int hi, int inc) {
+        System.Diagnostics.Debug.Assert(vecP != null); 
+        System.Diagnostics.Debug.Assert(lo <= hi);
+        System.Diagnostics.Debug.Assert(lo >= 0);
+        //int loSwap, hiSwap;
+        int pivotIndex, i, j;
+        if (vecP.Length < 2) return;
+        s_quickSortStackPos = -1;
+        fcomplex a1, a2, a3; 
+        unsafe {
+        fixed (
+            fcomplex * vec = vecP) {
+            fcomplex temp, pivotItem;                
+            if (checkNaNDesc(lo, ref hi, inc, vec)) return;
+            for (; ; ) {
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp >= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                        }
+                        *(vec + i + inc) = pivotItem;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--]; 
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo); 
+                    a2 = *(vec + pivotIndex); 
+                    a3 = *(vec + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 < a2) {
+                        if (a2 < a3) {
+                            *(vec + hi) = a1; 
+                            *(vec + lo) = a3; 
+                            *(vec + lo + inc) = a2; 
+                        } else {
+                            if (a1 < a3) {
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a3; 
+                                *(vec + hi) = a1; 
+                            } else {
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a1; 
+                                //*(vec + hi) = a3; 
+                            }
+                        }
+                    } else {
+                        if (a2 < a3) {
+                            if (a1 < a3) {
+                                *(vec + lo) = a3; 
+                                *(vec + hi) = a2; 
+                                *(vec + lo + inc) = a1; 
+                            } else {
+                                //*(vec + lo) = a1; 
+                                *(vec + hi) = a2; 
+                                *(vec + lo + inc) = a3; 
+                            }
+                        } else {
+                            //*(vec + lo) = a1; 
+                            //*(vec + hi) = a3; 
+                            *(vec + lo + inc) = a2; 
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi; 
+                    pivotItem = *(vec + lo + inc);
+                    for (;;) {
+                        do i += inc; while (*(vec + i) > pivotItem); 
+                        do j -= inc; while (*(vec + j) < pivotItem); 
+                        if (j < i) break; 
+                        temp = *(vec + i); 
+                        *(vec + i) = *(vec + j); 
+                        *(vec + j) = temp; 
+                    }
+                    *(vec + lo + inc) = *(vec + j); 
+                    *(vec + j) = pivotItem;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4D(vecP,lo,hi,j,inc)); 
+#endif 
+                    if (hi - i + inc >= j - lo) {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = hi; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = i; 
+                        hi = j - inc; 
+                    } else {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = j - inc; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = lo; 
+                        lo = i; 
+                    }
+                }
+            }
+        } // fixed
+        } // unsafe 
+    }
+    /// <summary>
+    /// inline 1 dimensional quick sort, ascending, arbitrary element spacing, indices aware
+    /// </summary>
+    /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+    /// <param name="lo">lowest index of sorting range</param>
+    /// <param name="hi">highest index of sorting range</param>
+    /// <param name="idxP">indices vector, content will in-place be sorted along with <paramref name="vecP"/></param>
+    /// <param name="inc">spacing between elements (dimension specifier)</param>
+    /// <remarks><para>Quick sort algorithm is used for ranges of minimum lengths specified by 
+    /// <see cref="P:ILNumerics.Settings.MminimumQuicksortLength"/> and above. 
+    /// Below that length, a simple insertion sort is used instead.</para>
+    /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+    /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+    /// The size is determined by the value of 
+    /// <see cref="P:ILNumerics.Settings.MaxSafeQuicksortRecursionDepth"/>.</para>
+    /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+    /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para></remarks>
+    public static void QuickSortAscIDXST( fcomplex [] vecP,  double [] idxP, int lo, int hi, int inc) {
+        System.Diagnostics.Debug.Assert(vecP != null); 
+        System.Diagnostics.Debug.Assert(lo <= hi);
+        System.Diagnostics.Debug.Assert(lo >= 0);
+        //int loSwap, hiSwap;
+        int pivotIndex, i, j;
+        if (vecP.Length < 2) return;
+        s_quickSortStackPos = -1; 
+        fcomplex a1, a2, a3; 
+        double ai1, ai2, ai3; 
+        unsafe {
+        fixed ( double * vecIdx = idxP)
+        fixed (
+            fcomplex * vec = vecP) {
+            fcomplex temp, pivotItem;                
+            if (checkNaNIDXAsc(lo, ref hi, inc, vecIdx, vec)) return;
+            for (; ; ) {
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        ai1 = *(vecIdx + j); 
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp <= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                            *(vecIdx + i + inc) = *(vecIdx + i);
+                        }
+                        *(vec + i + inc) = pivotItem;
+                        *(vecIdx + i + inc) = ai1;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--]; 
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo); 
+                    a2 = *(vec + pivotIndex); 
+                    a3 = *(vec + hi);
+                    ai1 = *(vecIdx + lo); 
+                    ai2 = *(vecIdx + pivotIndex); 
+                    ai3 = *(vecIdx + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    *(vecIdx + pivotIndex) = *(vecIdx + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 > a2) {
+                        if (a1 > a3) {
+                            if (a3 > a2) {
+                                *(vec + hi) = a1; 
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a3; 
+                                *(vecIdx + hi) = ai1; 
+                                *(vecIdx + lo) = ai2; 
+                                *(vecIdx + lo + inc) = ai3; 
+                            } else {
+                                *(vec + hi) = a1; 
+                                *(vec + lo) = a3; 
+                                *(vec + lo + inc) = a2; 
+                                *(vecIdx + hi) = ai1;  
+                                *(vecIdx + lo) = ai3; 
+                                *(vecIdx + lo + inc) = ai2; 
+                            }
+                        } else {
+                            *(vec + lo) = a2; 
+                            *(vec + lo + inc) = a1; 
+                            *(vecIdx + lo) = ai2; 
+                            *(vecIdx + lo + inc) = ai1; 
+                        }
+                    } else {
+                        if (a2 > a3) {
+                            *(vec + hi) = a2; 
+                            *(vecIdx + hi) = ai2; 
+                            if (a3 > a1) {
+                                *(vec + lo + inc) = a3; 
+                                *(vecIdx + lo + inc) = ai3; 
+                            } else {
+                                *(vec + lo + inc) = a1; 
+                                *(vec + lo) = a3; 
+                                *(vecIdx + lo + inc) = ai1; 
+                                *(vecIdx + lo) = ai3; 
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2; 
+                            *(vecIdx + lo + inc) = ai2; 
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi; 
+                    pivotItem = *(vec + lo + inc);
+                    ai1 = *(vecIdx + lo + inc);
+                    for (;;) {
+                        do i += inc; while (*(vec + i) < pivotItem); 
+                        do j -= inc; while (*(vec + j) > pivotItem); 
+                        if (j < i) break; 
+                        temp = *(vec + i); 
+                        ai2 = *(vecIdx + i); 
+                        *(vec + i) = *(vec + j); 
+                        *(vec + j) = temp; 
+                        *(vecIdx + i) = *(vecIdx + j); 
+                        *(vecIdx + j) = ai2; 
+                    }
+                    *(vec + lo + inc) = *(vec + j); 
+                    *(vec + j) = pivotItem;
+                    *(vecIdx + lo + inc) = *(vecIdx + j); 
+                    *(vecIdx + j) = ai1;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif 
+                    if (hi - i + inc >= j - lo) {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = hi; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = i; 
+                        hi = j - inc; 
+                    } else {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = j - inc; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = lo; 
+                        lo = i; 
+                    }
+                }
+            }
+        } // fixed
+        } // unsafe 
+    }
+    /// <summary>
+    /// inline 1 dimensional quick sort, descending, arbitrary element spacing, indices aware
+    /// </summary>
+    /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+    /// <param name="lo">lowest index of sorting range</param>
+    /// <param name="hi">highest index of sorting range</param>
+    /// <param name="idxP">indices vector, content will in-place be sorted along with <paramref name="vecP"/></param>
+    /// <param name="inc">spacing between elements (dimension specifier)</param>
+    /// <remarks><para>Quick sort algorithm is used for ranges of minimum lengths specified by 
+    /// <see cref="P:ILNumerics.Settings.MinimumQuicksortLength"/> and above. 
+    /// Below that length, a simple insertion sort is used instead.</para>
+    /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+    /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+    /// The size is determined by the value of 
+    /// <see cref="P:ILNumerics.Settings.MaxSafeQuicksortRecursionDepth"/>.</para>
+    /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+    /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para></remarks>
+    public static void QuickSortDescIDXST( fcomplex [] vecP,  double [] idxP, int lo, int hi, int inc) {
+        System.Diagnostics.Debug.Assert(vecP != null); 
+        System.Diagnostics.Debug.Assert(lo <= hi);
+        System.Diagnostics.Debug.Assert(lo >= 0);
+        //int loSwap, hiSwap;
+        int pivotIndex, i, j;
+        if (vecP.Length < 2) return;
+        
+        s_quickSortStackPos = -1;
+        fcomplex a1, a2, a3; 
+        double ai1, ai2, ai3; 
+        unsafe {
+        fixed ( double * vecIdx = idxP)
+        fixed (
+            fcomplex * vec = vecP) {
+            fcomplex temp, pivotItem;
+            if (checkNaNIDXDesc(lo, ref hi, inc, vecIdx, vec)) return;
+            for (; ; ) {
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        ai1 = *(vecIdx + j); 
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp >= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                            *(vecIdx + i + inc) = *(vecIdx + i);
+                        }
+                        *(vec + i + inc) = pivotItem;
+                        *(vecIdx + i + inc) = ai1;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--]; 
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo); 
+                    a2 = *(vec + pivotIndex); 
+                    a3 = *(vec + hi);
+                    ai1 = *(vecIdx + lo); 
+                    ai2 = *(vecIdx + pivotIndex); 
+                    ai3 = *(vecIdx + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    *(vecIdx + pivotIndex) = *(vecIdx + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 < a2) {
+                        if (a2 < a3) {
+                            *(vec + hi) = a1; 
+                            *(vec + lo) = a3; 
+                            *(vec + lo + inc) = a2; 
+                            *(vecIdx + hi) = ai1; 
+                            *(vecIdx + lo) = ai3; 
+                            *(vecIdx + lo + inc) = ai2; 
+                        } else {
+                            if (a1 < a3) {
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a3; 
+                                *(vec + hi) = a1; 
+                                *(vecIdx + lo) = ai2; 
+                                *(vecIdx + lo + inc) = ai3; 
+                                *(vecIdx + hi) = ai1; 
+                            } else {
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a1; 
+                                //*(vec + hi) = a3; 
+                                *(vecIdx + lo) = ai2; 
+                                *(vecIdx + lo + inc) = ai1; 
+                                //*(vecIdx + hi) = ai3; 
+                            }
+                        }
+                    } else {
+                        if (a2 < a3) {
+                            if (a1 < a3) {
+                                *(vec + lo) = a3; 
+                                *(vec + hi) = a2; 
+                                *(vec + lo + inc) = a1; 
+                                *(vecIdx + lo) = ai3; 
+                                *(vecIdx + hi) = ai2; 
+                                *(vecIdx + lo + inc) = ai1; 
+                            } else {
+                                //*(vec + lo) = a1; 
+                                *(vec + hi) = a2; 
+                                *(vec + lo + inc) = a3; 
+                                //*(vecIdx + lo) = ai1; 
+                                *(vecIdx + hi) = ai2; 
+                                *(vecIdx + lo + inc) = ai3; 
+                            }
+                        } else {
+                            //*(vec + lo) = a1; 
+                            //*(vec + hi) = a3; 
+                            *(vec + lo + inc) = a2; 
+                            //*(vecIdx + lo) = ai1; 
+                            //*(vecIdx + hi) = ai3; 
+                            *(vecIdx + lo + inc) = ai2; 
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi; 
+                    pivotItem = *(vec + lo + inc);
+                    ai1 = *(vecIdx + lo + inc);
+                    for (;;) {
+                        do i += inc; while (*(vec + i) > pivotItem); 
+                        do j -= inc; while (*(vec + j) < pivotItem); 
+                        if (j < i) break; 
+                        temp = *(vec + i); 
+                        ai2 = *(vecIdx + i); 
+                        *(vec + i) = *(vec + j); 
+                        *(vec + j) = temp; 
+                        *(vecIdx + i) = *(vecIdx + j); 
+                        *(vecIdx + j) = ai2; 
+                    }
+                    *(vec + lo + inc) = *(vec + j); 
+                    *(vec + j) = pivotItem;
+                    *(vecIdx + lo + inc) = *(vecIdx + j); 
+                    *(vecIdx + j) = ai1;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif 
+                    if (hi - i + inc >= j - lo) {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = hi; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = i; 
+                        hi = j - inc; 
+                    } else {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = j - inc; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = lo; 
+                        lo = i; 
+                    }
+                }
+            }
+        } // fixed
+        } // unsafe 
+    }
+
+    /// <summary>
+    /// inline one dimensional quick sort, ascending, arbitrary element spacing
+    /// </summary>
+    /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+    /// <param name="lo">lowest index of sorting range</param>
+    /// <param name="hi">highest index of sorting range</param>
+    /// <param name="inc">spacing between elements (dimension specifier)</param>
+    /// <remarks><para>Quick sort algorithm is used for ranges of minimum lengths specified by 
+    /// <see cref="P:ILNumerics.Settings.MinimumQuicksortLength"/> and above. 
+    /// Below that length, a simple insertion sort is used instead.</para>
+    /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+    /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+    /// The size is determined by the value of 
+    /// <see cref="P:ILNumerics.Settings.MaxSafeQuicksortRecursionDepth"/>.</para>
+    /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+    /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para></remarks>
+    public static void QuickSortAscST( complex [] vecP, int lo, int hi, int inc) {
+        System.Diagnostics.Debug.Assert(vecP != null); 
+        System.Diagnostics.Debug.Assert(lo <= hi);
+        System.Diagnostics.Debug.Assert(lo >= 0);
+        //int loSwap, hiSwap;
+        int pivotIndex, i, j;
+        if (vecP.Length < 2) return; 
+        int[] s_quickSortStackMT = ILMemoryPool.Pool.New<int>(Settings.s_maxSafeQuicksortRecursionDepth * 2);
+        s_quickSortStackPos = -1;
+        complex a1, a2, a3; 
+        unsafe {
+        fixed (
+            complex * vec = vecP) {
+            complex temp, pivotItem;
+            if (checkNaNAsc(lo, ref hi, inc, vec)) return;
+
+            for (; ; ) {
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp <= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                        }
+                        *(vec + i + inc) = pivotItem;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--]; 
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo); 
+                    a2 = *(vec + pivotIndex); 
+                    a3 = *(vec + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 > a2) {
+                        if (a1 > a3) {
+                            if (a3 > a2) {
+                                *(vec + hi) = a1; 
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a3; 
+                            } else {
+                                *(vec + hi) = a1; 
+                                *(vec + lo) = a3; 
+                                *(vec + lo + inc) = a2; 
+                            }
+                        } else {
+                            *(vec + lo) = a2; 
+                            *(vec + lo + inc) = a1; 
+                        }
+                    } else {
+                        if (a2 > a3) {
+                            *(vec + hi) = a2; 
+                            if (a3 > a1) {
+                                *(vec + lo + inc) = a3; 
+                            } else {
+                                *(vec + lo + inc) = a1; 
+                                *(vec + lo) = a3; 
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2; 
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi; 
+                    pivotItem = *(vec + lo + inc);
+                    for (;;) {
+                        do i += inc; while (*(vec + i) < pivotItem); 
+                        do j -= inc; while (*(vec + j) > pivotItem); 
+                        if (j < i) break; 
+                        temp = *(vec + i); 
+                        *(vec + i) = *(vec + j); 
+                        *(vec + j) = temp; 
+                    }
+                    *(vec + lo + inc) = *(vec + j); 
+                    *(vec + j) = pivotItem;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif 
+                    if (hi - i + inc >= j - lo) {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = hi; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = i; 
+                        hi = j - inc; 
+                    } else {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = j - inc; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = lo; 
+                        lo = i; 
+                    }
+                }
+            }
+        } // fixed
+        } // unsafe 
+    }
+    /// <summary>
+    /// inline one dimensional quick sort, descending, arbitrary element spacing
+    /// </summary>
+    /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+    /// <param name="lo">lowest index of sorting range</param>
+    /// <param name="hi">highest index of sorting range</param>
+    /// <param name="inc">spacing between elements (dimension specifier)</param>
+    /// <remarks><para>Quick sort algorithm is used for ranges of minimum lengths specified by 
+    /// <see cref="P:ILNumerics.Settings.MinimumQuicksortLength"/> and above. 
+    /// Below that length, a simple insertion sort is used instead.</para>
+    /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+    /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+    /// The size is determined by the value of 
+    /// <see cref="P:ILNumerics.Settings.MaxSafeQuicksortRecursionDepth"/>.</para>
+    /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+    /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para></remarks>
+    public static void QuickSortDescST( complex [] vecP, int lo, int hi, int inc) {
+        System.Diagnostics.Debug.Assert(vecP != null); 
+        System.Diagnostics.Debug.Assert(lo <= hi);
+        System.Diagnostics.Debug.Assert(lo >= 0);
+        //int loSwap, hiSwap;
+        int pivotIndex, i, j;
+        if (vecP.Length < 2) return;
+        s_quickSortStackPos = -1;
+        complex a1, a2, a3; 
+        unsafe {
+        fixed (
+            complex * vec = vecP) {
+            complex temp, pivotItem;                
+            if (checkNaNDesc(lo, ref hi, inc, vec)) return;
+            for (; ; ) {
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp >= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                        }
+                        *(vec + i + inc) = pivotItem;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--]; 
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo); 
+                    a2 = *(vec + pivotIndex); 
+                    a3 = *(vec + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 < a2) {
+                        if (a2 < a3) {
+                            *(vec + hi) = a1; 
+                            *(vec + lo) = a3; 
+                            *(vec + lo + inc) = a2; 
+                        } else {
+                            if (a1 < a3) {
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a3; 
+                                *(vec + hi) = a1; 
+                            } else {
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a1; 
+                                //*(vec + hi) = a3; 
+                            }
+                        }
+                    } else {
+                        if (a2 < a3) {
+                            if (a1 < a3) {
+                                *(vec + lo) = a3; 
+                                *(vec + hi) = a2; 
+                                *(vec + lo + inc) = a1; 
+                            } else {
+                                //*(vec + lo) = a1; 
+                                *(vec + hi) = a2; 
+                                *(vec + lo + inc) = a3; 
+                            }
+                        } else {
+                            //*(vec + lo) = a1; 
+                            //*(vec + hi) = a3; 
+                            *(vec + lo + inc) = a2; 
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi; 
+                    pivotItem = *(vec + lo + inc);
+                    for (;;) {
+                        do i += inc; while (*(vec + i) > pivotItem); 
+                        do j -= inc; while (*(vec + j) < pivotItem); 
+                        if (j < i) break; 
+                        temp = *(vec + i); 
+                        *(vec + i) = *(vec + j); 
+                        *(vec + j) = temp; 
+                    }
+                    *(vec + lo + inc) = *(vec + j); 
+                    *(vec + j) = pivotItem;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4D(vecP,lo,hi,j,inc)); 
+#endif 
+                    if (hi - i + inc >= j - lo) {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = hi; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = i; 
+                        hi = j - inc; 
+                    } else {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = j - inc; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = lo; 
+                        lo = i; 
+                    }
+                }
+            }
+        } // fixed
+        } // unsafe 
+    }
+    /// <summary>
+    /// inline 1 dimensional quick sort, ascending, arbitrary element spacing, indices aware
+    /// </summary>
+    /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+    /// <param name="lo">lowest index of sorting range</param>
+    /// <param name="hi">highest index of sorting range</param>
+    /// <param name="idxP">indices vector, content will in-place be sorted along with <paramref name="vecP"/></param>
+    /// <param name="inc">spacing between elements (dimension specifier)</param>
+    /// <remarks><para>Quick sort algorithm is used for ranges of minimum lengths specified by 
+    /// <see cref="P:ILNumerics.Settings.MminimumQuicksortLength"/> and above. 
+    /// Below that length, a simple insertion sort is used instead.</para>
+    /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+    /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+    /// The size is determined by the value of 
+    /// <see cref="P:ILNumerics.Settings.MaxSafeQuicksortRecursionDepth"/>.</para>
+    /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+    /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para></remarks>
+    public static void QuickSortAscIDXST( complex [] vecP,  double [] idxP, int lo, int hi, int inc) {
+        System.Diagnostics.Debug.Assert(vecP != null); 
+        System.Diagnostics.Debug.Assert(lo <= hi);
+        System.Diagnostics.Debug.Assert(lo >= 0);
+        //int loSwap, hiSwap;
+        int pivotIndex, i, j;
+        if (vecP.Length < 2) return;
+        s_quickSortStackPos = -1; 
+        complex a1, a2, a3; 
+        double ai1, ai2, ai3; 
+        unsafe {
+        fixed ( double * vecIdx = idxP)
+        fixed (
+            complex * vec = vecP) {
+            complex temp, pivotItem;                
+            if (checkNaNIDXAsc(lo, ref hi, inc, vecIdx, vec)) return;
+            for (; ; ) {
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        ai1 = *(vecIdx + j); 
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp <= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                            *(vecIdx + i + inc) = *(vecIdx + i);
+                        }
+                        *(vec + i + inc) = pivotItem;
+                        *(vecIdx + i + inc) = ai1;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--]; 
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo); 
+                    a2 = *(vec + pivotIndex); 
+                    a3 = *(vec + hi);
+                    ai1 = *(vecIdx + lo); 
+                    ai2 = *(vecIdx + pivotIndex); 
+                    ai3 = *(vecIdx + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    *(vecIdx + pivotIndex) = *(vecIdx + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 > a2) {
+                        if (a1 > a3) {
+                            if (a3 > a2) {
+                                *(vec + hi) = a1; 
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a3; 
+                                *(vecIdx + hi) = ai1; 
+                                *(vecIdx + lo) = ai2; 
+                                *(vecIdx + lo + inc) = ai3; 
+                            } else {
+                                *(vec + hi) = a1; 
+                                *(vec + lo) = a3; 
+                                *(vec + lo + inc) = a2; 
+                                *(vecIdx + hi) = ai1;  
+                                *(vecIdx + lo) = ai3; 
+                                *(vecIdx + lo + inc) = ai2; 
+                            }
+                        } else {
+                            *(vec + lo) = a2; 
+                            *(vec + lo + inc) = a1; 
+                            *(vecIdx + lo) = ai2; 
+                            *(vecIdx + lo + inc) = ai1; 
+                        }
+                    } else {
+                        if (a2 > a3) {
+                            *(vec + hi) = a2; 
+                            *(vecIdx + hi) = ai2; 
+                            if (a3 > a1) {
+                                *(vec + lo + inc) = a3; 
+                                *(vecIdx + lo + inc) = ai3; 
+                            } else {
+                                *(vec + lo + inc) = a1; 
+                                *(vec + lo) = a3; 
+                                *(vecIdx + lo + inc) = ai1; 
+                                *(vecIdx + lo) = ai3; 
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2; 
+                            *(vecIdx + lo + inc) = ai2; 
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi; 
+                    pivotItem = *(vec + lo + inc);
+                    ai1 = *(vecIdx + lo + inc);
+                    for (;;) {
+                        do i += inc; while (*(vec + i) < pivotItem); 
+                        do j -= inc; while (*(vec + j) > pivotItem); 
+                        if (j < i) break; 
+                        temp = *(vec + i); 
+                        ai2 = *(vecIdx + i); 
+                        *(vec + i) = *(vec + j); 
+                        *(vec + j) = temp; 
+                        *(vecIdx + i) = *(vecIdx + j); 
+                        *(vecIdx + j) = ai2; 
+                    }
+                    *(vec + lo + inc) = *(vec + j); 
+                    *(vec + j) = pivotItem;
+                    *(vecIdx + lo + inc) = *(vecIdx + j); 
+                    *(vecIdx + j) = ai1;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif 
+                    if (hi - i + inc >= j - lo) {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = hi; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = i; 
+                        hi = j - inc; 
+                    } else {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = j - inc; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = lo; 
+                        lo = i; 
+                    }
+                }
+            }
+        } // fixed
+        } // unsafe 
+    }
+    /// <summary>
+    /// inline 1 dimensional quick sort, descending, arbitrary element spacing, indices aware
+    /// </summary>
+    /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+    /// <param name="lo">lowest index of sorting range</param>
+    /// <param name="hi">highest index of sorting range</param>
+    /// <param name="idxP">indices vector, content will in-place be sorted along with <paramref name="vecP"/></param>
+    /// <param name="inc">spacing between elements (dimension specifier)</param>
+    /// <remarks><para>Quick sort algorithm is used for ranges of minimum lengths specified by 
+    /// <see cref="P:ILNumerics.Settings.MinimumQuicksortLength"/> and above. 
+    /// Below that length, a simple insertion sort is used instead.</para>
+    /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+    /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+    /// The size is determined by the value of 
+    /// <see cref="P:ILNumerics.Settings.MaxSafeQuicksortRecursionDepth"/>.</para>
+    /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+    /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para></remarks>
+    public static void QuickSortDescIDXST( complex [] vecP,  double [] idxP, int lo, int hi, int inc) {
+        System.Diagnostics.Debug.Assert(vecP != null); 
+        System.Diagnostics.Debug.Assert(lo <= hi);
+        System.Diagnostics.Debug.Assert(lo >= 0);
+        //int loSwap, hiSwap;
+        int pivotIndex, i, j;
+        if (vecP.Length < 2) return;
+        
+        s_quickSortStackPos = -1;
+        complex a1, a2, a3; 
+        double ai1, ai2, ai3; 
+        unsafe {
+        fixed ( double * vecIdx = idxP)
+        fixed (
+            complex * vec = vecP) {
+            complex temp, pivotItem;
+            if (checkNaNIDXDesc(lo, ref hi, inc, vecIdx, vec)) return;
+            for (; ; ) {
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        ai1 = *(vecIdx + j); 
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp >= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                            *(vecIdx + i + inc) = *(vecIdx + i);
+                        }
+                        *(vec + i + inc) = pivotItem;
+                        *(vecIdx + i + inc) = ai1;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--]; 
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo); 
+                    a2 = *(vec + pivotIndex); 
+                    a3 = *(vec + hi);
+                    ai1 = *(vecIdx + lo); 
+                    ai2 = *(vecIdx + pivotIndex); 
+                    ai3 = *(vecIdx + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    *(vecIdx + pivotIndex) = *(vecIdx + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 < a2) {
+                        if (a2 < a3) {
+                            *(vec + hi) = a1; 
+                            *(vec + lo) = a3; 
+                            *(vec + lo + inc) = a2; 
+                            *(vecIdx + hi) = ai1; 
+                            *(vecIdx + lo) = ai3; 
+                            *(vecIdx + lo + inc) = ai2; 
+                        } else {
+                            if (a1 < a3) {
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a3; 
+                                *(vec + hi) = a1; 
+                                *(vecIdx + lo) = ai2; 
+                                *(vecIdx + lo + inc) = ai3; 
+                                *(vecIdx + hi) = ai1; 
+                            } else {
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a1; 
+                                //*(vec + hi) = a3; 
+                                *(vecIdx + lo) = ai2; 
+                                *(vecIdx + lo + inc) = ai1; 
+                                //*(vecIdx + hi) = ai3; 
+                            }
+                        }
+                    } else {
+                        if (a2 < a3) {
+                            if (a1 < a3) {
+                                *(vec + lo) = a3; 
+                                *(vec + hi) = a2; 
+                                *(vec + lo + inc) = a1; 
+                                *(vecIdx + lo) = ai3; 
+                                *(vecIdx + hi) = ai2; 
+                                *(vecIdx + lo + inc) = ai1; 
+                            } else {
+                                //*(vec + lo) = a1; 
+                                *(vec + hi) = a2; 
+                                *(vec + lo + inc) = a3; 
+                                //*(vecIdx + lo) = ai1; 
+                                *(vecIdx + hi) = ai2; 
+                                *(vecIdx + lo + inc) = ai3; 
+                            }
+                        } else {
+                            //*(vec + lo) = a1; 
+                            //*(vec + hi) = a3; 
+                            *(vec + lo + inc) = a2; 
+                            //*(vecIdx + lo) = ai1; 
+                            //*(vecIdx + hi) = ai3; 
+                            *(vecIdx + lo + inc) = ai2; 
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi; 
+                    pivotItem = *(vec + lo + inc);
+                    ai1 = *(vecIdx + lo + inc);
+                    for (;;) {
+                        do i += inc; while (*(vec + i) > pivotItem); 
+                        do j -= inc; while (*(vec + j) < pivotItem); 
+                        if (j < i) break; 
+                        temp = *(vec + i); 
+                        ai2 = *(vecIdx + i); 
+                        *(vec + i) = *(vec + j); 
+                        *(vec + j) = temp; 
+                        *(vecIdx + i) = *(vecIdx + j); 
+                        *(vecIdx + j) = ai2; 
+                    }
+                    *(vec + lo + inc) = *(vec + j); 
+                    *(vec + j) = pivotItem;
+                    *(vecIdx + lo + inc) = *(vecIdx + j); 
+                    *(vecIdx + j) = ai1;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif 
+                    if (hi - i + inc >= j - lo) {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = hi; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = i; 
+                        hi = j - inc; 
+                    } else {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = j - inc; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = lo; 
+                        lo = i; 
+                    }
+                }
+            }
+        } // fixed
+        } // unsafe 
+    }
+
+    /// <summary>
+    /// inline one dimensional quick sort, ascending, arbitrary element spacing
+    /// </summary>
+    /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+    /// <param name="lo">lowest index of sorting range</param>
+    /// <param name="hi">highest index of sorting range</param>
+    /// <param name="inc">spacing between elements (dimension specifier)</param>
+    /// <remarks><para>Quick sort algorithm is used for ranges of minimum lengths specified by 
+    /// <see cref="P:ILNumerics.Settings.MinimumQuicksortLength"/> and above. 
+    /// Below that length, a simple insertion sort is used instead.</para>
+    /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+    /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+    /// The size is determined by the value of 
+    /// <see cref="P:ILNumerics.Settings.MaxSafeQuicksortRecursionDepth"/>.</para>
+    /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+    /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para></remarks>
+    public static void QuickSortAscST( char [] vecP, int lo, int hi, int inc) {
+        System.Diagnostics.Debug.Assert(vecP != null); 
+        System.Diagnostics.Debug.Assert(lo <= hi);
+        System.Diagnostics.Debug.Assert(lo >= 0);
+        //int loSwap, hiSwap;
+        int pivotIndex, i, j;
+        if (vecP.Length < 2) return; 
+        int[] s_quickSortStackMT = ILMemoryPool.Pool.New<int>(Settings.s_maxSafeQuicksortRecursionDepth * 2);
+        s_quickSortStackPos = -1;
+        char a1, a2, a3; 
+        unsafe {
+        fixed (
+            char * vec = vecP) {
+            char temp, pivotItem;
+            
+
+            for (; ; ) {
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp <= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                        }
+                        *(vec + i + inc) = pivotItem;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--]; 
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo); 
+                    a2 = *(vec + pivotIndex); 
+                    a3 = *(vec + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 > a2) {
+                        if (a1 > a3) {
+                            if (a3 > a2) {
+                                *(vec + hi) = a1; 
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a3; 
+                            } else {
+                                *(vec + hi) = a1; 
+                                *(vec + lo) = a3; 
+                                *(vec + lo + inc) = a2; 
+                            }
+                        } else {
+                            *(vec + lo) = a2; 
+                            *(vec + lo + inc) = a1; 
+                        }
+                    } else {
+                        if (a2 > a3) {
+                            *(vec + hi) = a2; 
+                            if (a3 > a1) {
+                                *(vec + lo + inc) = a3; 
+                            } else {
+                                *(vec + lo + inc) = a1; 
+                                *(vec + lo) = a3; 
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2; 
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi; 
+                    pivotItem = *(vec + lo + inc);
+                    for (;;) {
+                        do i += inc; while (*(vec + i) < pivotItem); 
+                        do j -= inc; while (*(vec + j) > pivotItem); 
+                        if (j < i) break; 
+                        temp = *(vec + i); 
+                        *(vec + i) = *(vec + j); 
+                        *(vec + j) = temp; 
+                    }
+                    *(vec + lo + inc) = *(vec + j); 
+                    *(vec + j) = pivotItem;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif 
+                    if (hi - i + inc >= j - lo) {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = hi; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = i; 
+                        hi = j - inc; 
+                    } else {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = j - inc; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = lo; 
+                        lo = i; 
+                    }
+                }
+            }
+        } // fixed
+        } // unsafe 
+    }
+    /// <summary>
+    /// inline one dimensional quick sort, descending, arbitrary element spacing
+    /// </summary>
+    /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+    /// <param name="lo">lowest index of sorting range</param>
+    /// <param name="hi">highest index of sorting range</param>
+    /// <param name="inc">spacing between elements (dimension specifier)</param>
+    /// <remarks><para>Quick sort algorithm is used for ranges of minimum lengths specified by 
+    /// <see cref="P:ILNumerics.Settings.MinimumQuicksortLength"/> and above. 
+    /// Below that length, a simple insertion sort is used instead.</para>
+    /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+    /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+    /// The size is determined by the value of 
+    /// <see cref="P:ILNumerics.Settings.MaxSafeQuicksortRecursionDepth"/>.</para>
+    /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+    /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para></remarks>
+    public static void QuickSortDescST( char [] vecP, int lo, int hi, int inc) {
+        System.Diagnostics.Debug.Assert(vecP != null); 
+        System.Diagnostics.Debug.Assert(lo <= hi);
+        System.Diagnostics.Debug.Assert(lo >= 0);
+        //int loSwap, hiSwap;
+        int pivotIndex, i, j;
+        if (vecP.Length < 2) return;
+        s_quickSortStackPos = -1;
+        char a1, a2, a3; 
+        unsafe {
+        fixed (
+            char * vec = vecP) {
+            char temp, pivotItem;                
+            
+            for (; ; ) {
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp >= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                        }
+                        *(vec + i + inc) = pivotItem;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--]; 
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo); 
+                    a2 = *(vec + pivotIndex); 
+                    a3 = *(vec + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 < a2) {
+                        if (a2 < a3) {
+                            *(vec + hi) = a1; 
+                            *(vec + lo) = a3; 
+                            *(vec + lo + inc) = a2; 
+                        } else {
+                            if (a1 < a3) {
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a3; 
+                                *(vec + hi) = a1; 
+                            } else {
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a1; 
+                                //*(vec + hi) = a3; 
+                            }
+                        }
+                    } else {
+                        if (a2 < a3) {
+                            if (a1 < a3) {
+                                *(vec + lo) = a3; 
+                                *(vec + hi) = a2; 
+                                *(vec + lo + inc) = a1; 
+                            } else {
+                                //*(vec + lo) = a1; 
+                                *(vec + hi) = a2; 
+                                *(vec + lo + inc) = a3; 
+                            }
+                        } else {
+                            //*(vec + lo) = a1; 
+                            //*(vec + hi) = a3; 
+                            *(vec + lo + inc) = a2; 
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi; 
+                    pivotItem = *(vec + lo + inc);
+                    for (;;) {
+                        do i += inc; while (*(vec + i) > pivotItem); 
+                        do j -= inc; while (*(vec + j) < pivotItem); 
+                        if (j < i) break; 
+                        temp = *(vec + i); 
+                        *(vec + i) = *(vec + j); 
+                        *(vec + j) = temp; 
+                    }
+                    *(vec + lo + inc) = *(vec + j); 
+                    *(vec + j) = pivotItem;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4D(vecP,lo,hi,j,inc)); 
+#endif 
+                    if (hi - i + inc >= j - lo) {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = hi; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = i; 
+                        hi = j - inc; 
+                    } else {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = j - inc; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = lo; 
+                        lo = i; 
+                    }
+                }
+            }
+        } // fixed
+        } // unsafe 
+    }
+    /// <summary>
+    /// inline 1 dimensional quick sort, ascending, arbitrary element spacing, indices aware
+    /// </summary>
+    /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+    /// <param name="lo">lowest index of sorting range</param>
+    /// <param name="hi">highest index of sorting range</param>
+    /// <param name="idxP">indices vector, content will in-place be sorted along with <paramref name="vecP"/></param>
+    /// <param name="inc">spacing between elements (dimension specifier)</param>
+    /// <remarks><para>Quick sort algorithm is used for ranges of minimum lengths specified by 
+    /// <see cref="P:ILNumerics.Settings.MminimumQuicksortLength"/> and above. 
+    /// Below that length, a simple insertion sort is used instead.</para>
+    /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+    /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+    /// The size is determined by the value of 
+    /// <see cref="P:ILNumerics.Settings.MaxSafeQuicksortRecursionDepth"/>.</para>
+    /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+    /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para></remarks>
+    public static void QuickSortAscIDXST( char [] vecP,  double [] idxP, int lo, int hi, int inc) {
+        System.Diagnostics.Debug.Assert(vecP != null); 
+        System.Diagnostics.Debug.Assert(lo <= hi);
+        System.Diagnostics.Debug.Assert(lo >= 0);
+        //int loSwap, hiSwap;
+        int pivotIndex, i, j;
+        if (vecP.Length < 2) return;
+        s_quickSortStackPos = -1; 
+        char a1, a2, a3; 
+        double ai1, ai2, ai3; 
+        unsafe {
+        fixed ( double * vecIdx = idxP)
+        fixed (
+            char * vec = vecP) {
+            char temp, pivotItem;                
+            
+            for (; ; ) {
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        ai1 = *(vecIdx + j); 
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp <= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                            *(vecIdx + i + inc) = *(vecIdx + i);
+                        }
+                        *(vec + i + inc) = pivotItem;
+                        *(vecIdx + i + inc) = ai1;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--]; 
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo); 
+                    a2 = *(vec + pivotIndex); 
+                    a3 = *(vec + hi);
+                    ai1 = *(vecIdx + lo); 
+                    ai2 = *(vecIdx + pivotIndex); 
+                    ai3 = *(vecIdx + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    *(vecIdx + pivotIndex) = *(vecIdx + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 > a2) {
+                        if (a1 > a3) {
+                            if (a3 > a2) {
+                                *(vec + hi) = a1; 
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a3; 
+                                *(vecIdx + hi) = ai1; 
+                                *(vecIdx + lo) = ai2; 
+                                *(vecIdx + lo + inc) = ai3; 
+                            } else {
+                                *(vec + hi) = a1; 
+                                *(vec + lo) = a3; 
+                                *(vec + lo + inc) = a2; 
+                                *(vecIdx + hi) = ai1;  
+                                *(vecIdx + lo) = ai3; 
+                                *(vecIdx + lo + inc) = ai2; 
+                            }
+                        } else {
+                            *(vec + lo) = a2; 
+                            *(vec + lo + inc) = a1; 
+                            *(vecIdx + lo) = ai2; 
+                            *(vecIdx + lo + inc) = ai1; 
+                        }
+                    } else {
+                        if (a2 > a3) {
+                            *(vec + hi) = a2; 
+                            *(vecIdx + hi) = ai2; 
+                            if (a3 > a1) {
+                                *(vec + lo + inc) = a3; 
+                                *(vecIdx + lo + inc) = ai3; 
+                            } else {
+                                *(vec + lo + inc) = a1; 
+                                *(vec + lo) = a3; 
+                                *(vecIdx + lo + inc) = ai1; 
+                                *(vecIdx + lo) = ai3; 
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2; 
+                            *(vecIdx + lo + inc) = ai2; 
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi; 
+                    pivotItem = *(vec + lo + inc);
+                    ai1 = *(vecIdx + lo + inc);
+                    for (;;) {
+                        do i += inc; while (*(vec + i) < pivotItem); 
+                        do j -= inc; while (*(vec + j) > pivotItem); 
+                        if (j < i) break; 
+                        temp = *(vec + i); 
+                        ai2 = *(vecIdx + i); 
+                        *(vec + i) = *(vec + j); 
+                        *(vec + j) = temp; 
+                        *(vecIdx + i) = *(vecIdx + j); 
+                        *(vecIdx + j) = ai2; 
+                    }
+                    *(vec + lo + inc) = *(vec + j); 
+                    *(vec + j) = pivotItem;
+                    *(vecIdx + lo + inc) = *(vecIdx + j); 
+                    *(vecIdx + j) = ai1;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif 
+                    if (hi - i + inc >= j - lo) {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = hi; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = i; 
+                        hi = j - inc; 
+                    } else {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = j - inc; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = lo; 
+                        lo = i; 
+                    }
+                }
+            }
+        } // fixed
+        } // unsafe 
+    }
+    /// <summary>
+    /// inline 1 dimensional quick sort, descending, arbitrary element spacing, indices aware
+    /// </summary>
+    /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+    /// <param name="lo">lowest index of sorting range</param>
+    /// <param name="hi">highest index of sorting range</param>
+    /// <param name="idxP">indices vector, content will in-place be sorted along with <paramref name="vecP"/></param>
+    /// <param name="inc">spacing between elements (dimension specifier)</param>
+    /// <remarks><para>Quick sort algorithm is used for ranges of minimum lengths specified by 
+    /// <see cref="P:ILNumerics.Settings.MinimumQuicksortLength"/> and above. 
+    /// Below that length, a simple insertion sort is used instead.</para>
+    /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+    /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+    /// The size is determined by the value of 
+    /// <see cref="P:ILNumerics.Settings.MaxSafeQuicksortRecursionDepth"/>.</para>
+    /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+    /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para></remarks>
+    public static void QuickSortDescIDXST( char [] vecP,  double [] idxP, int lo, int hi, int inc) {
+        System.Diagnostics.Debug.Assert(vecP != null); 
+        System.Diagnostics.Debug.Assert(lo <= hi);
+        System.Diagnostics.Debug.Assert(lo >= 0);
+        //int loSwap, hiSwap;
+        int pivotIndex, i, j;
+        if (vecP.Length < 2) return;
+        
+        s_quickSortStackPos = -1;
+        char a1, a2, a3; 
+        double ai1, ai2, ai3; 
+        unsafe {
+        fixed ( double * vecIdx = idxP)
+        fixed (
+            char * vec = vecP) {
+            char temp, pivotItem;
+            
+            for (; ; ) {
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        ai1 = *(vecIdx + j); 
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp >= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                            *(vecIdx + i + inc) = *(vecIdx + i);
+                        }
+                        *(vec + i + inc) = pivotItem;
+                        *(vecIdx + i + inc) = ai1;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--]; 
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo); 
+                    a2 = *(vec + pivotIndex); 
+                    a3 = *(vec + hi);
+                    ai1 = *(vecIdx + lo); 
+                    ai2 = *(vecIdx + pivotIndex); 
+                    ai3 = *(vecIdx + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    *(vecIdx + pivotIndex) = *(vecIdx + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 < a2) {
+                        if (a2 < a3) {
+                            *(vec + hi) = a1; 
+                            *(vec + lo) = a3; 
+                            *(vec + lo + inc) = a2; 
+                            *(vecIdx + hi) = ai1; 
+                            *(vecIdx + lo) = ai3; 
+                            *(vecIdx + lo + inc) = ai2; 
+                        } else {
+                            if (a1 < a3) {
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a3; 
+                                *(vec + hi) = a1; 
+                                *(vecIdx + lo) = ai2; 
+                                *(vecIdx + lo + inc) = ai3; 
+                                *(vecIdx + hi) = ai1; 
+                            } else {
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a1; 
+                                //*(vec + hi) = a3; 
+                                *(vecIdx + lo) = ai2; 
+                                *(vecIdx + lo + inc) = ai1; 
+                                //*(vecIdx + hi) = ai3; 
+                            }
+                        }
+                    } else {
+                        if (a2 < a3) {
+                            if (a1 < a3) {
+                                *(vec + lo) = a3; 
+                                *(vec + hi) = a2; 
+                                *(vec + lo + inc) = a1; 
+                                *(vecIdx + lo) = ai3; 
+                                *(vecIdx + hi) = ai2; 
+                                *(vecIdx + lo + inc) = ai1; 
+                            } else {
+                                //*(vec + lo) = a1; 
+                                *(vec + hi) = a2; 
+                                *(vec + lo + inc) = a3; 
+                                //*(vecIdx + lo) = ai1; 
+                                *(vecIdx + hi) = ai2; 
+                                *(vecIdx + lo + inc) = ai3; 
+                            }
+                        } else {
+                            //*(vec + lo) = a1; 
+                            //*(vec + hi) = a3; 
+                            *(vec + lo + inc) = a2; 
+                            //*(vecIdx + lo) = ai1; 
+                            //*(vecIdx + hi) = ai3; 
+                            *(vecIdx + lo + inc) = ai2; 
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi; 
+                    pivotItem = *(vec + lo + inc);
+                    ai1 = *(vecIdx + lo + inc);
+                    for (;;) {
+                        do i += inc; while (*(vec + i) > pivotItem); 
+                        do j -= inc; while (*(vec + j) < pivotItem); 
+                        if (j < i) break; 
+                        temp = *(vec + i); 
+                        ai2 = *(vecIdx + i); 
+                        *(vec + i) = *(vec + j); 
+                        *(vec + j) = temp; 
+                        *(vecIdx + i) = *(vecIdx + j); 
+                        *(vecIdx + j) = ai2; 
+                    }
+                    *(vec + lo + inc) = *(vec + j); 
+                    *(vec + j) = pivotItem;
+                    *(vecIdx + lo + inc) = *(vecIdx + j); 
+                    *(vecIdx + j) = ai1;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif 
+                    if (hi - i + inc >= j - lo) {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = hi; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = i; 
+                        hi = j - inc; 
+                    } else {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = j - inc; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = lo; 
+                        lo = i; 
+                    }
+                }
+            }
+        } // fixed
+        } // unsafe 
+    }
+
+    /// <summary>
+    /// inline one dimensional quick sort, ascending, arbitrary element spacing
+    /// </summary>
+    /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+    /// <param name="lo">lowest index of sorting range</param>
+    /// <param name="hi">highest index of sorting range</param>
+    /// <param name="inc">spacing between elements (dimension specifier)</param>
+    /// <remarks><para>Quick sort algorithm is used for ranges of minimum lengths specified by 
+    /// <see cref="P:ILNumerics.Settings.MinimumQuicksortLength"/> and above. 
+    /// Below that length, a simple insertion sort is used instead.</para>
+    /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+    /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+    /// The size is determined by the value of 
+    /// <see cref="P:ILNumerics.Settings.MaxSafeQuicksortRecursionDepth"/>.</para>
+    /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+    /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para></remarks>
+    public static void QuickSortAscST( byte [] vecP, int lo, int hi, int inc) {
+        System.Diagnostics.Debug.Assert(vecP != null); 
+        System.Diagnostics.Debug.Assert(lo <= hi);
+        System.Diagnostics.Debug.Assert(lo >= 0);
+        //int loSwap, hiSwap;
+        int pivotIndex, i, j;
+        if (vecP.Length < 2) return; 
+        int[] s_quickSortStackMT = ILMemoryPool.Pool.New<int>(Settings.s_maxSafeQuicksortRecursionDepth * 2);
+        s_quickSortStackPos = -1;
+        byte a1, a2, a3; 
+        unsafe {
+        fixed (
+            byte * vec = vecP) {
+            byte temp, pivotItem;
+            
+
+            for (; ; ) {
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp <= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                        }
+                        *(vec + i + inc) = pivotItem;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--]; 
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo); 
+                    a2 = *(vec + pivotIndex); 
+                    a3 = *(vec + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 > a2) {
+                        if (a1 > a3) {
+                            if (a3 > a2) {
+                                *(vec + hi) = a1; 
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a3; 
+                            } else {
+                                *(vec + hi) = a1; 
+                                *(vec + lo) = a3; 
+                                *(vec + lo + inc) = a2; 
+                            }
+                        } else {
+                            *(vec + lo) = a2; 
+                            *(vec + lo + inc) = a1; 
+                        }
+                    } else {
+                        if (a2 > a3) {
+                            *(vec + hi) = a2; 
+                            if (a3 > a1) {
+                                *(vec + lo + inc) = a3; 
+                            } else {
+                                *(vec + lo + inc) = a1; 
+                                *(vec + lo) = a3; 
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2; 
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi; 
+                    pivotItem = *(vec + lo + inc);
+                    for (;;) {
+                        do i += inc; while (*(vec + i) < pivotItem); 
+                        do j -= inc; while (*(vec + j) > pivotItem); 
+                        if (j < i) break; 
+                        temp = *(vec + i); 
+                        *(vec + i) = *(vec + j); 
+                        *(vec + j) = temp; 
+                    }
+                    *(vec + lo + inc) = *(vec + j); 
+                    *(vec + j) = pivotItem;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif 
+                    if (hi - i + inc >= j - lo) {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = hi; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = i; 
+                        hi = j - inc; 
+                    } else {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = j - inc; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = lo; 
+                        lo = i; 
+                    }
+                }
+            }
+        } // fixed
+        } // unsafe 
+    }
+    /// <summary>
+    /// inline one dimensional quick sort, descending, arbitrary element spacing
+    /// </summary>
+    /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+    /// <param name="lo">lowest index of sorting range</param>
+    /// <param name="hi">highest index of sorting range</param>
+    /// <param name="inc">spacing between elements (dimension specifier)</param>
+    /// <remarks><para>Quick sort algorithm is used for ranges of minimum lengths specified by 
+    /// <see cref="P:ILNumerics.Settings.MinimumQuicksortLength"/> and above. 
+    /// Below that length, a simple insertion sort is used instead.</para>
+    /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+    /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+    /// The size is determined by the value of 
+    /// <see cref="P:ILNumerics.Settings.MaxSafeQuicksortRecursionDepth"/>.</para>
+    /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+    /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para></remarks>
+    public static void QuickSortDescST( byte [] vecP, int lo, int hi, int inc) {
+        System.Diagnostics.Debug.Assert(vecP != null); 
+        System.Diagnostics.Debug.Assert(lo <= hi);
+        System.Diagnostics.Debug.Assert(lo >= 0);
+        //int loSwap, hiSwap;
+        int pivotIndex, i, j;
+        if (vecP.Length < 2) return;
+        s_quickSortStackPos = -1;
+        byte a1, a2, a3; 
+        unsafe {
+        fixed (
+            byte * vec = vecP) {
+            byte temp, pivotItem;                
+            
+            for (; ; ) {
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp >= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                        }
+                        *(vec + i + inc) = pivotItem;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--]; 
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo); 
+                    a2 = *(vec + pivotIndex); 
+                    a3 = *(vec + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 < a2) {
+                        if (a2 < a3) {
+                            *(vec + hi) = a1; 
+                            *(vec + lo) = a3; 
+                            *(vec + lo + inc) = a2; 
+                        } else {
+                            if (a1 < a3) {
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a3; 
+                                *(vec + hi) = a1; 
+                            } else {
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a1; 
+                                //*(vec + hi) = a3; 
+                            }
+                        }
+                    } else {
+                        if (a2 < a3) {
+                            if (a1 < a3) {
+                                *(vec + lo) = a3; 
+                                *(vec + hi) = a2; 
+                                *(vec + lo + inc) = a1; 
+                            } else {
+                                //*(vec + lo) = a1; 
+                                *(vec + hi) = a2; 
+                                *(vec + lo + inc) = a3; 
+                            }
+                        } else {
+                            //*(vec + lo) = a1; 
+                            //*(vec + hi) = a3; 
+                            *(vec + lo + inc) = a2; 
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi; 
+                    pivotItem = *(vec + lo + inc);
+                    for (;;) {
+                        do i += inc; while (*(vec + i) > pivotItem); 
+                        do j -= inc; while (*(vec + j) < pivotItem); 
+                        if (j < i) break; 
+                        temp = *(vec + i); 
+                        *(vec + i) = *(vec + j); 
+                        *(vec + j) = temp; 
+                    }
+                    *(vec + lo + inc) = *(vec + j); 
+                    *(vec + j) = pivotItem;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4D(vecP,lo,hi,j,inc)); 
+#endif 
+                    if (hi - i + inc >= j - lo) {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = hi; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = i; 
+                        hi = j - inc; 
+                    } else {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = j - inc; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = lo; 
+                        lo = i; 
+                    }
+                }
+            }
+        } // fixed
+        } // unsafe 
+    }
+    /// <summary>
+    /// inline 1 dimensional quick sort, ascending, arbitrary element spacing, indices aware
+    /// </summary>
+    /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+    /// <param name="lo">lowest index of sorting range</param>
+    /// <param name="hi">highest index of sorting range</param>
+    /// <param name="idxP">indices vector, content will in-place be sorted along with <paramref name="vecP"/></param>
+    /// <param name="inc">spacing between elements (dimension specifier)</param>
+    /// <remarks><para>Quick sort algorithm is used for ranges of minimum lengths specified by 
+    /// <see cref="P:ILNumerics.Settings.MminimumQuicksortLength"/> and above. 
+    /// Below that length, a simple insertion sort is used instead.</para>
+    /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+    /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+    /// The size is determined by the value of 
+    /// <see cref="P:ILNumerics.Settings.MaxSafeQuicksortRecursionDepth"/>.</para>
+    /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+    /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para></remarks>
+    public static void QuickSortAscIDXST( byte [] vecP,  double [] idxP, int lo, int hi, int inc) {
+        System.Diagnostics.Debug.Assert(vecP != null); 
+        System.Diagnostics.Debug.Assert(lo <= hi);
+        System.Diagnostics.Debug.Assert(lo >= 0);
+        //int loSwap, hiSwap;
+        int pivotIndex, i, j;
+        if (vecP.Length < 2) return;
+        s_quickSortStackPos = -1; 
+        byte a1, a2, a3; 
+        double ai1, ai2, ai3; 
+        unsafe {
+        fixed ( double * vecIdx = idxP)
+        fixed (
+            byte * vec = vecP) {
+            byte temp, pivotItem;                
+            
+            for (; ; ) {
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        ai1 = *(vecIdx + j); 
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp <= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                            *(vecIdx + i + inc) = *(vecIdx + i);
+                        }
+                        *(vec + i + inc) = pivotItem;
+                        *(vecIdx + i + inc) = ai1;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--]; 
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo); 
+                    a2 = *(vec + pivotIndex); 
+                    a3 = *(vec + hi);
+                    ai1 = *(vecIdx + lo); 
+                    ai2 = *(vecIdx + pivotIndex); 
+                    ai3 = *(vecIdx + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    *(vecIdx + pivotIndex) = *(vecIdx + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 > a2) {
+                        if (a1 > a3) {
+                            if (a3 > a2) {
+                                *(vec + hi) = a1; 
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a3; 
+                                *(vecIdx + hi) = ai1; 
+                                *(vecIdx + lo) = ai2; 
+                                *(vecIdx + lo + inc) = ai3; 
+                            } else {
+                                *(vec + hi) = a1; 
+                                *(vec + lo) = a3; 
+                                *(vec + lo + inc) = a2; 
+                                *(vecIdx + hi) = ai1;  
+                                *(vecIdx + lo) = ai3; 
+                                *(vecIdx + lo + inc) = ai2; 
+                            }
+                        } else {
+                            *(vec + lo) = a2; 
+                            *(vec + lo + inc) = a1; 
+                            *(vecIdx + lo) = ai2; 
+                            *(vecIdx + lo + inc) = ai1; 
+                        }
+                    } else {
+                        if (a2 > a3) {
+                            *(vec + hi) = a2; 
+                            *(vecIdx + hi) = ai2; 
+                            if (a3 > a1) {
+                                *(vec + lo + inc) = a3; 
+                                *(vecIdx + lo + inc) = ai3; 
+                            } else {
+                                *(vec + lo + inc) = a1; 
+                                *(vec + lo) = a3; 
+                                *(vecIdx + lo + inc) = ai1; 
+                                *(vecIdx + lo) = ai3; 
+                            }
+                        } else {
+                            *(vec + lo + inc) = a2; 
+                            *(vecIdx + lo + inc) = ai2; 
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi; 
+                    pivotItem = *(vec + lo + inc);
+                    ai1 = *(vecIdx + lo + inc);
+                    for (;;) {
+                        do i += inc; while (*(vec + i) < pivotItem); 
+                        do j -= inc; while (*(vec + j) > pivotItem); 
+                        if (j < i) break; 
+                        temp = *(vec + i); 
+                        ai2 = *(vecIdx + i); 
+                        *(vec + i) = *(vec + j); 
+                        *(vec + j) = temp; 
+                        *(vecIdx + i) = *(vecIdx + j); 
+                        *(vecIdx + j) = ai2; 
+                    }
+                    *(vec + lo + inc) = *(vec + j); 
+                    *(vec + j) = pivotItem;
+                    *(vecIdx + lo + inc) = *(vecIdx + j); 
+                    *(vecIdx + j) = ai1;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif 
+                    if (hi - i + inc >= j - lo) {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = hi; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = i; 
+                        hi = j - inc; 
+                    } else {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = j - inc; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = lo; 
+                        lo = i; 
+                    }
+                }
+            }
+        } // fixed
+        } // unsafe 
+    }
+    /// <summary>
+    /// inline 1 dimensional quick sort, descending, arbitrary element spacing, indices aware
+    /// </summary>
+    /// <param name="vecP">data array, 1dim, replaced on output with sorted values</param>
+    /// <param name="lo">lowest index of sorting range</param>
+    /// <param name="hi">highest index of sorting range</param>
+    /// <param name="idxP">indices vector, content will in-place be sorted along with <paramref name="vecP"/></param>
+    /// <param name="inc">spacing between elements (dimension specifier)</param>
+    /// <remarks><para>Quick sort algorithm is used for ranges of minimum lengths specified by 
+    /// <see cref="P:ILNumerics.Settings.MinimumQuicksortLength"/> and above. 
+    /// Below that length, a simple insertion sort is used instead.</para>
+    /// <para>The algorithm implements a non-recursive quicksort variant. Therefore a small amount of 
+    /// memory is needed to perform the sorting. That 'stack' memory is preserved from the ILMemoryPool. 
+    /// The size is determined by the value of 
+    /// <see cref="P:ILNumerics.Settings.MaxSafeQuicksortRecursionDepth"/>.</para>
+    /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+    /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para></remarks>
+    public static void QuickSortDescIDXST( byte [] vecP,  double [] idxP, int lo, int hi, int inc) {
+        System.Diagnostics.Debug.Assert(vecP != null); 
+        System.Diagnostics.Debug.Assert(lo <= hi);
+        System.Diagnostics.Debug.Assert(lo >= 0);
+        //int loSwap, hiSwap;
+        int pivotIndex, i, j;
+        if (vecP.Length < 2) return;
+        
+        s_quickSortStackPos = -1;
+        byte a1, a2, a3; 
+        double ai1, ai2, ai3; 
+        unsafe {
+        fixed ( double * vecIdx = idxP)
+        fixed (
+            byte * vec = vecP) {
+            byte temp, pivotItem;
+            
+            for (; ; ) {
+                if (hi - lo < (Settings.s_minimumQuicksortLength * inc)) {
+                    #region small array: insertion sort
+                    for (j = lo + inc; j <= hi; j += inc) {
+                        pivotItem = (*(vec + j));
+                        ai1 = *(vecIdx + j); 
+                        for (i = j - inc; i >= lo; i -= inc) {
+                            temp = *(vec + i);
+                            if (temp >= pivotItem)
+                                break;
+                            *(vec + i + inc) = temp;
+                            *(vecIdx + i + inc) = *(vecIdx + i);
+                        }
+                        *(vec + i + inc) = pivotItem;
+                        *(vecIdx + i + inc) = ai1;
+                    }
+                    #endregion
+                    if (s_quickSortStackPos < 0) break;
+                    lo = s_quickSortStackMT[s_quickSortStackPos--];
+                    hi = s_quickSortStackMT[s_quickSortStackPos--]; 
+                } else {
+                    // quicksort
+                    pivotIndex = lo + (int)((hi - lo) / inc / 2) * inc;
+                    a1 = *(vec + lo); 
+                    a2 = *(vec + pivotIndex); 
+                    a3 = *(vec + hi);
+                    ai1 = *(vecIdx + lo); 
+                    ai2 = *(vecIdx + pivotIndex); 
+                    ai3 = *(vecIdx + hi);
+                    *(vec + pivotIndex) = *(vec + lo + inc);
+                    *(vecIdx + pivotIndex) = *(vecIdx + lo + inc);
+                    #region bring lo, lo+inc, hi in order
+                    // by explicitely stepping through all possible paths,
+                    // we save some assignments and comparisons
+                    if (a1 < a2) {
+                        if (a2 < a3) {
+                            *(vec + hi) = a1; 
+                            *(vec + lo) = a3; 
+                            *(vec + lo + inc) = a2; 
+                            *(vecIdx + hi) = ai1; 
+                            *(vecIdx + lo) = ai3; 
+                            *(vecIdx + lo + inc) = ai2; 
+                        } else {
+                            if (a1 < a3) {
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a3; 
+                                *(vec + hi) = a1; 
+                                *(vecIdx + lo) = ai2; 
+                                *(vecIdx + lo + inc) = ai3; 
+                                *(vecIdx + hi) = ai1; 
+                            } else {
+                                *(vec + lo) = a2; 
+                                *(vec + lo + inc) = a1; 
+                                //*(vec + hi) = a3; 
+                                *(vecIdx + lo) = ai2; 
+                                *(vecIdx + lo + inc) = ai1; 
+                                //*(vecIdx + hi) = ai3; 
+                            }
+                        }
+                    } else {
+                        if (a2 < a3) {
+                            if (a1 < a3) {
+                                *(vec + lo) = a3; 
+                                *(vec + hi) = a2; 
+                                *(vec + lo + inc) = a1; 
+                                *(vecIdx + lo) = ai3; 
+                                *(vecIdx + hi) = ai2; 
+                                *(vecIdx + lo + inc) = ai1; 
+                            } else {
+                                //*(vec + lo) = a1; 
+                                *(vec + hi) = a2; 
+                                *(vec + lo + inc) = a3; 
+                                //*(vecIdx + lo) = ai1; 
+                                *(vecIdx + hi) = ai2; 
+                                *(vecIdx + lo + inc) = ai3; 
+                            }
+                        } else {
+                            //*(vec + lo) = a1; 
+                            //*(vec + hi) = a3; 
+                            *(vec + lo + inc) = a2; 
+                            //*(vecIdx + lo) = ai1; 
+                            //*(vecIdx + hi) = ai3; 
+                            *(vecIdx + lo + inc) = ai2; 
+                        }
+                    }
+                    #endregion
+                    i = lo + inc; j = hi; 
+                    pivotItem = *(vec + lo + inc);
+                    ai1 = *(vecIdx + lo + inc);
+                    for (;;) {
+                        do i += inc; while (*(vec + i) > pivotItem); 
+                        do j -= inc; while (*(vec + j) < pivotItem); 
+                        if (j < i) break; 
+                        temp = *(vec + i); 
+                        ai2 = *(vecIdx + i); 
+                        *(vec + i) = *(vec + j); 
+                        *(vec + j) = temp; 
+                        *(vecIdx + i) = *(vecIdx + j); 
+                        *(vecIdx + j) = ai2; 
+                    }
+                    *(vec + lo + inc) = *(vec + j); 
+                    *(vec + j) = pivotItem;
+                    *(vecIdx + lo + inc) = *(vecIdx + j); 
+                    *(vecIdx + j) = ai1;
+#if DEBUG
+                    //System.Diagnostics.Debug.Assert(Check4A(vecP,lo,hi,j,inc)); 
+#endif 
+                    if (hi - i + inc >= j - lo) {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = hi; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = i; 
+                        hi = j - inc; 
+                    } else {
+                        if (s_quickSortStackMT == null)
+                            s_quickSortStackMT = new int[100];
+                        s_quickSortStackMT[++s_quickSortStackPos] = j - inc; 
+                        s_quickSortStackMT[++s_quickSortStackPos] = lo; 
+                        lo = i; 
+                    }
+                }
+            }
+        } // fixed
+        } // unsafe 
+    }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+#region Debug assertion checks
+        private static bool Check4A<T>(T[] vec, int lo, int hi, int pivIndex, int inc) {
+            double piv = Convert.ToDouble(vec[pivIndex].ToString()); 
+            for (int i = lo; i <= pivIndex; i += inc) {
+                if (Convert.ToDouble(vec[i].ToString()) > piv) {
+                    return false; 
+                }
+            }
+            for (int i = hi; i >= pivIndex; i -= inc) {
+                if (Convert.ToDouble(vec[i].ToString()) < piv) {
+                    return false; 
+                }
+            }
+            return true; 
+        }
+        private static bool Check4D<T>(T[] vec, int lo, int hi, int pivIndex, int inc) {
+            double piv = Convert.ToDouble(vec[pivIndex].ToString()); 
+            for (int i = lo; i <= pivIndex; i += inc) {
+                if (Convert.ToDouble(vec[i].ToString()) < piv) {
+                    return false; 
+                }
+            }
+            for (int i = hi; i >= pivIndex; i -= inc) {
+                if (Convert.ToDouble(vec[i].ToString()) > piv) {
+                    return false; 
+                }
+            }
+            return true; 
+        }
+        private static bool Check3(double[] vec, int hiBound, int loBound, int loSwap, int hiSwap, double pivotItem) {
+            for (int i = loBound; i < loSwap - 1; i++) {
+                if (!(vec[i] <= pivotItem)) {
+                    return false; 
+                }
+            }
+            for (int i = hiSwap + 1; i < hiBound; i++) {
+                if (!(vec[i] > pivotItem)) {
+                    return false; 
+                }
+            }
+            if (loSwap < hiSwap) {
+                if (!(vec[loSwap] <= pivotItem && pivotItem < vec[hiSwap])) {
+                    return false; 
+                }
+            } else {
+                if (!(vec[hiSwap] <= pivotItem && (loBound <= loSwap) && (loSwap <= hiSwap + 1) && (hiSwap + 1 <= hiBound + 1))) {
+                    return false; 
+                }
+            }
+            return true; 
+        }
+        private static bool Check1(double[] vec, int loBound, int loSwap, int hiSwap, double pivotItem) {
+            for (int i = loBound + 1; i < loSwap - 1; i++) {
+                if (!(vec[i] <= pivotItem && loSwap <= hiSwap + 1)) {
+                    return false; 
+                }
+            }
+            return true; 
+        }
+        private static bool Check2(double[] vec, int hiBound, int loSwap, int hiSwap, double pivotItem) {
+            for (int i = hiSwap + 1; i < hiBound; i++) {
+                if (!(vec[i] > pivotItem && loSwap <= hiSwap + 1)) {
+                    return false; 
+                }
+            }
+            return true;
+        }
+#endregion 
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Algorithms/Special/ILSpecialData.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Algorithms/Special/ILSpecialData.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Algorithms/Special/ILSpecialData.cs	(revision 9102)
@@ -0,0 +1,197 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics;
+
+namespace ILNumerics {
+    /// <summary>
+    /// A helper class that can be used to generate various simple yet non-trivial test data sets
+    /// </summary>
+    public class ILSpecialData : ILMath {
+        /// <summary>
+        /// Generate sinc function in 2D, useful for plotting examples
+        /// </summary>
+        /// <param name="rows">Number of rows</param>
+        /// <param name="cols">Number of columns</param>
+        /// <param name="periods">Influences the number of periods to be drawn in both directions. 1 will result in 4 zero crossings, higher values result in more, lower values in less zero crossings.</param>
+        /// <returns>Matrix with sinc data in 2 dimensions</returns>
+        public static ILRetArray<double> sinc (int rows, int cols, float periods) {
+            using (ILScope.Enter()) {
+                ILArray<double> X = repmat<double>(vec<double>(-cols,2.0,cols-1).T,rows,1) / cols*pi*2*periods;  
+                ILArray<double> Y = repmat<double>(vec<double>(-rows,2.0,rows-1),1,cols) / rows*pi*2*periods; 
+                ILArray<double> ret = sqrt(X * X + Y * Y);
+                ret[ret == 0.0] = MachineParameterDouble.eps; 
+                ret.a = sin(ret)/ret; 
+                return ret; 
+            }
+        }
+        /// <summary>
+        /// Generate sinc function in 2D, useful for plotting examples
+        /// </summary>
+        /// <param name="rows">Number of rows</param>
+        /// <param name="cols">Number of columns</param>
+        /// <returns>Matrix with sinc data in 2 dimensions</returns>
+        /// <remarks>The function generates 4 zero crossings in each direction</remarks>
+        public static ILRetArray<double> sinc(int rows, int cols) {
+            return sinc(rows, cols, 1.0f);
+        }
+        /// <summary>
+        /// Generate sinc function in 2D, single precision, useful for plotting examples
+        /// </summary>
+        /// <param name="rows">Number of rows</param>
+        /// <param name="cols">Number of columns</param>
+        /// <returns>Matrix with sinc data in 2 dimensions</returns>
+        /// <remarks>The function generates 4 zero crossings in each direction</remarks>
+        public static ILRetArray<float> sincf(int rows, int cols) {
+            return tosingle(sinc(rows, cols, 1.0f));
+        }
+        /// <summary>
+        /// Generate sinc function in 2D, useful for plotting examples
+        /// </summary>
+        /// <param name="rows">Number of rows</param>
+        /// <param name="cols">Number of columns</param>
+        /// <param name="periods">Influences the number of periods to be drawn in both directions. 1 will result in 4 zero crossings, higher values result in more, lower values in less zero crossings.</param>
+        /// <returns>Matrix with sinc data in 2 dimensions</returns>
+        public static ILRetArray<float> sincf(int rows, int cols, float periods) {
+            return tosingle(sinc(rows,cols,periods)); 
+        }
+
+        /// <summary>
+        /// Create specified periods of sine and cosine data
+        /// </summary>
+        /// <param name="numSamples">Number of samples</param>
+        /// <param name="periods">Number of (full) periods to be generated, must be &gt; 0</param>
+        /// <returns>Matrix with sine data in first column, cosine data in second column</returns>
+        public static ILRetArray<double> sincos1D(int numSamples, double periods) {
+            using (ILScope.Enter()) {
+                ILArray<double> t = linspace(0.0, 2 * pi * periods, numSamples);
+                return horzcat(sin(t).T, cos(t).T);
+            }
+        }
+        /// <summary>
+        /// Create specified periods of sine and cosine data, single precision
+        /// </summary>
+        /// <param name="numSamples">Number of samples</param>
+        /// <param name="periods">Number of (full) periods to be generated, must be &gt; 0</param>
+        /// <returns>Matrix with sine data in first column, cosine data in second column</returns>
+        public static ILRetArray<float> sincos1Df(int numSamples, double periods) {
+            using (ILScope.Enter()) {
+                ILArray<float> t = linspace<float>(0, 2 * pi * periods, numSamples);
+                return horzcat(sin(t).T, cos(t).T);
+            }
+        }
+        /// <summary>
+        /// Create demo data for surface plots looking like a waterfall
+        /// </summary>
+        /// <param name="rows">Number of rows</param>
+        /// <param name="cols">Number of columns</param>
+        /// <returns>Matrix with data showing a waterfall terrain. </returns>
+        public static ILRetArray<double> waterfall(int rows, int cols) {
+            using (ILScope.Enter()) {
+                ILArray<double> a = rand(rows, cols);
+                ILArray<double> bord = rand(1, cols) * 3 + (rows / 2);
+                for (int c = 0; c < cols; c++) {
+                    int b = (int)(bord[c] - sin(c / cols * pi) * cols / 5);
+                    a[vec(0.0, b), c] = a[vec(0.0, b), c] + 2.0;
+                }
+                return a;
+            }
+        }
+
+        /// <summary>
+        /// Create demo data for surface plots looking like a waterfall
+        /// </summary>
+        /// <param name="rows">Number of rows</param>
+        /// <param name="cols">Number of columns</param>
+        /// <returns>Matrix with data showing a waterfall terrain. </returns>
+        public static ILRetArray<float> waterfallf(int rows, int cols) {
+            using (ILScope.Enter()) {
+                ILArray<double> a = rand(rows, cols);
+                ILArray<double> bord = rand(1, cols) * 3 + (rows / 2);
+                for (int c = 0; c < cols; c++) {
+                    int b = (int)(bord[c] - sin(c / cols * pi) * cols / 5);
+                    a[vec(0.0, b), c] = a[vec(0.0, b), c] + 2.0;
+                }
+                return tosingle(a);
+            }
+        }
+
+        /// <summary>
+        /// Create surface data of a sphere
+        /// </summary>
+        /// <param name="n">Number of facettes per angle</param>
+        /// <param name="X">[Output] X coords</param>
+        /// <param name="Y">[Output] Y coords</param>
+        /// <param name="Z">[Output] Z coords</param>
+        public static void sphere(int n, ILOutArray<double> X, ILOutArray<double> Y, ILOutArray<double> Z) {
+            using (ILScope.Enter()) {
+                ILArray<double> phi = repmat(linspace(-pi, pi, n).T, 1, n);
+                ILArray<double> rho = repmat(linspace(0, pi, n), n, 1);
+                Y.a = sin(phi) * sin(rho);
+                X.a = cos(phi) * sin(rho);
+                Z.a = cos(rho);
+            }
+        }
+        /// <summary>
+        /// Create surface data for a Mï¿œbius strip 
+        /// </summary>
+        /// <param name="n">Granularity (number of facettes)</param>
+        /// <param name="w">Width</param>
+        /// <param name="R">Radius</param>
+        /// <param name="X">[Output] X coords</param>
+        /// <param name="Y">[Output] Y coords</param>
+        /// <param name="Z">[Output] Z coords</param>
+        /// <remarks>Mï¿œbius strip is a surfcae, crated by cutting a regular strip, twisting one end by 180 deg and glueing 
+        /// both ends together again.</remarks>
+        public static void moebius(int n, double w, double R, ILOutArray<double> X, ILOutArray<double> Y, ILOutArray<double> Z) {
+            using (ILScope.Enter()) {
+                ILArray<double> s = repmat(linspace(-w, w, n), n, 1);
+                ILArray<double> t = repmat(linspace(0, 2 * pi, n).T, 1, n);
+                X.a = (R + s * cos(0.5 * t)) * cos(t);
+                Y.a = (R + s * cos(0.5 * t)) * sin(t);
+                Z.a = s * sin(0.5 * t);
+            }
+        }
+
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILArray.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILArray.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILArray.cs	(revision 9102)
@@ -0,0 +1,474 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.IO; 
+using System.Runtime.Serialization; 
+using System.Runtime.CompilerServices;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions;
+
+
+
+namespace ILNumerics {
+    /// <summary>
+    /// The main rectangular array to be used in algorithms 
+    /// </summary>
+    /// <typeparam name="ElementType">Inner type. This will mostly be a system numeric type or a 
+    /// complex floating point type.</typeparam>
+    /// <remarks>This class serves as the main rectangular array, holding arbitrary elements (usually numeric types) 
+    /// in arbitrary dimensions.
+    /// <para>Arrays of this type may use any type as generic element. However, common mathematical functions and operators 
+    /// are defined for a limited number of inner types only. All binary operations (+,-,*,/,<![CDATA[<,>,<=]]>,etc.) are 
+    /// defined for two arrays with the same <i>numeric type</i>, would it be from the <c>System</c> namespace (<c>double</c>, 
+    /// <c>int</c>,...) or <c>ILNumerics.complex</c>/ <c>ILNumerics.fcomplex</c>. Most algebraic functions require floating point 
+    /// types. See the <see cref="ILNumerics.ILMath"/> class for a list of all computational functions.</para>
+    /// <para>Arrays are capable of creating flexible <a href="http://ilnumerics.net/$Subarray0.html" target="ILMain">subarrays</a> 
+    /// and to get altered at runtime. Read about all details of ILNumerics arrays in the 
+    /// <a href="http://ilnumerics.net/$Arrays.html" target="ILMain">ILNumerics Array documentation</a>.</para>
+    /// <para>Arrays of this type are dense arrays. Cloning arrays is done as lazy 
+    /// copy on write, i.e. clones do only use new memory, if attempting to write on them. Arrays integrate into the memory 
+    /// management of ILNumerics. Read about the most <a href="http://ilnumerics.net/$GeneralRules.html" target="ILMain">important 
+    /// simple rules</a>, for using arrays in custom computational functions.</para>
+    /// <para>Arrays come with overloaded mathematical operators, allowing for a convenient syntax. A 
+    /// sophisticated memory management in the back will make sure, that as little memory as needed is used, even in 
+    /// expressions like: a + c * 2 / abs(sin(c) * -b / log(a)). Here all arrays are of the same size. Evaluating 
+    /// this expression does only need the memory of twice the size of one array. Memory gets collected and reused 
+    /// for every subexpression evaluation. Further optimization options exist, as described in 
+    /// <a href="http://ilnumerics.net/$PerfMemoryOpt.html" target="ILMain">Optimizing Algorithm Performance</a>.</para>
+    /// </remarks>
+    /// <example><para>A simple example demonstrating some uses of arrays in a very simple application:</para>
+    /// <code>using System;
+    ///using System.Collections.Generic;
+    ///using System.Linq;
+    ///using System.Text;
+    ///using ILNumerics; 
+    ///
+    ///
+    ///namespace ConsoleApplication1 {
+    ///    class Program : ILMath {
+    ///        static void Main(string[] args) {
+    ///            ILArray&lt;double> A = rand(10,20);
+    ///            ILArray&lt;double> B = A * 30 + 100; 
+    ///            ILLogical C = any(multiply(B,B.T)); 
+    ///            Console.Out.Write(-B); 
+    ///            Console.ReadKey(); 
+    ///        }
+    ///    }
+    ///}
+    ///</code>
+    /// </example>
+    /// <seealso cref="ILNumerics.ILLogical"/>
+    /// <seealso cref="ILNumerics.ILCell"/>
+    [Serializable]
+    public sealed class ILArray<ElementType> : ILDenseArray<ElementType> {
+
+        private static bool s_isTempArray = false; 
+
+        #region constructors
+        /// <summary>
+        /// Create new ILArray, specify (dense) storage
+        /// </summary>
+        /// <param name="storage"></param>
+        internal ILArray(ILDenseStorage<ElementType> storage)
+            : base(storage, s_isTempArray) {
+        }
+        /// <summary>
+        /// create new ILArray, specify dimensions
+        /// </summary>
+        /// <param name="dimensions"></param>
+        private ILArray(ILSize dimensions)
+            : base(new ILDenseStorage<ElementType>(dimensions), s_isTempArray) {
+        }
+        
+        /// <summary>
+        /// create new ILArray, specify storage and if the new array should be disposed automatically
+        /// </summary>
+        /// <param name="storage"></param>
+        /// <param name="registerForDisposal"></param>
+        internal ILArray(ILDenseStorage<ElementType> storage, bool registerForDisposal)
+            : base(storage, s_isTempArray) {
+            if (registerForDisposal) 
+                ILScope.Context.RegisterArray(this);
+        }
+        /// <summary>
+        /// create new ILArray, specify dimensions
+        /// </summary>
+        /// <param name="dimensions"></param>
+        /// <param name="registerForDisposal"></param>
+        private ILArray(ILSize dimensions, bool registerForDisposal)
+            : base(new ILDenseStorage<ElementType>(dimensions), s_isTempArray) {
+            if (registerForDisposal) 
+                ILScope.Context.RegisterArray(this);
+        }
+        /// <summary>
+        /// create new ILArray from System.Array
+        /// </summary>
+        /// <param name="elements">System.Array</param>
+        /// <param name="size">dimension specifier</param>
+        internal ILArray(ElementType[] elements, ILSize size) :
+            base(new ILDenseStorage<ElementType>(elements, size), s_isTempArray) {
+        }
+        /// <summary>
+        /// create new ILArray from System.Array, optionally register the array for disposal 
+        /// </summary>
+        /// <param name="elements">System.Array</param>
+        /// <param name="registerForDisposal">if true, the array will be disposed once the current scope is closed</param>
+        /// <param name="size">dimension specifier</param>
+        internal ILArray(ElementType[] elements, ILSize size, bool registerForDisposal) :
+            base(new ILDenseStorage<ElementType>(elements, size), s_isTempArray) {
+                if (registerForDisposal)
+                    ILScope.Context.RegisterArray(this);
+        }
+        /// <summary>
+        /// create new ILArray from System.Array
+        /// </summary>
+        /// <param name="elements">System.Array</param>
+        /// <param name="size">dimension specifier</param>
+        internal ILArray(ElementType[] elements, params int[] size) :
+            base(new ILDenseStorage<ElementType>(elements, new ILSize(size)), s_isTempArray) {
+        }
+        /// <summary>
+        /// create new ILArray from System.Array
+        /// </summary>
+        /// <param name="elements">variable length System.Array</param>
+        internal ILArray(params ElementType[] elements) :
+            base(new ILDenseStorage<ElementType>(elements, new ILSize(1, elements.Length)), s_isTempArray) {
+        }
+
+
+        /// <summary>
+        /// [deprecated] Create empty array of arbitrary size
+        /// </summary>
+        /// <param name="size">Dimension sizes</param>
+        /// <returns>New empty array</returns>
+        /// <remarks>This function is markes as deprecated and only included for compatibility reasons.
+        /// It will be removed in a future version. Use <see cref="ILNumerics.ILMath.empty{T}()"/> instead.</remarks>
+        [Obsolete("Use ILNumerics.ILMath.empty{T}() instead")]
+        public static ILRetArray<ElementType> empty(params int[] size) {
+            if (size == null || size.Length == 0) 
+                return new ILArray<ElementType>(ILSize.Empty00); 
+            ILArray<ElementType> ret = new ILArray<ElementType>(new ILSize(size)); 
+            if (!ret.IsEmpty) 
+                throw new ILArgumentException("'size' must specify the size of an empty array"); 
+            return ret; 
+        }
+        /// <summary>
+        /// [deprecated] Create empty array of arbitrary size
+        /// </summary>
+        /// <param name="size">Dimension sizes</param>
+        /// <returns>New empty array</returns>
+        /// <remarks>This function is markes as deprecated and only included for compatibility reasons.
+        /// It will be removed in a future version. Use <see cref="ILNumerics.ILMath.empty{T}()"/> instead.</remarks>
+        [Obsolete("Use ILNumerics.ILMath.empty{T}() instead")]
+        public static ILRetArray<ElementType> empty(ILSize size) {
+            ILArray<ElementType> ret = new ILArray<ElementType>(size); 
+            if (!ret.IsEmpty)
+                throw new ILArgumentException("'size' must specify the size of an empty array"); 
+            return ret; 
+        }
+        #endregion
+
+        #region implicit cast operators
+        
+        #region constructional operators
+        /// <summary>
+        /// Implicitly convert scalar to array of size 1x1 (scalar).
+        /// </summary>
+        /// <param name="val">System type of size scalar</param>
+        /// <returns>New ILArray of type ILArray <![CDATA[<typeof(val)>]]> of size 1x1 
+        /// holding the only element with value of val.
+        /// </returns>
+        public static implicit operator ILArray<ElementType> (ElementType val) {
+            ILArray<ElementType> ret = new ILArray<ElementType>(
+                        new ILDenseStorage<ElementType>(
+                            new ElementType[1] {val}, 
+                            new ILSize(1,1)));
+            return ret; 
+        }
+        /// <summary>
+        /// Implicitly cast one dimensional System.Array to ILNumerics array (vector)
+        /// </summary>
+        /// <param name="A">1-dimensional system array, arbitrary type</param>
+        /// <returns>ILNumerics array of same element type as elements of A. If A is null: empty array.</returns>
+        /// <remarks><para>The System.Array A will directly be used for the new ILNumerics array! 
+        /// No copy will be done! Make sure, not to reference A after this conversion</para>
+        /// <para>The size of the result depends on the global option <c>Settings.CreateRowVectorByDefault</c></para></remarks>
+        /// <seealso cref="Settings.CreateRowVectorsByDefault"/>
+        public static implicit operator ILArray<ElementType> (ElementType[] A) {
+            if (A == null) 
+                return null;
+            ILArray<ElementType> ret; 
+            if (Settings.CreateRowVectorsByDefault) {
+                ret = new ILArray<ElementType>(A, 1, A.Length);
+            } else {
+                ret = new ILArray<ElementType>(A, A.Length, 1);
+            }
+            ILScope.Context.RegisterArray(ret); 
+            return ret; 
+        }
+        /// <summary>
+        /// Implicitly convert n-dimensional System.Array to ILNumerics array
+        /// </summary>
+        /// <param name="A">Arbitrarily sized System.Array</param>
+        /// <returns>If A is null: empty array. Else: new ILNumerics array of the same size as A</returns>
+        /// <remarks>The inner type of input array <paramref name="A"/> must match the requested type
+        /// <typeparamref name="ElementType"/>. The resulting ILArray will reflect all dimensions of 
+        /// A. Elements of A will get copied to elements of the output array (shallow copy).</remarks>
+        /// <seealso cref="Settings.CreateRowVectorsByDefault"/>
+        /// <exception cref="ILNumerics.Exceptions.ILCastException">If type of input does not match 
+        /// ElementType</exception>
+        public static implicit operator ILArray<ElementType> (Array A) {
+            if (A == null) 
+                return null; 
+            if (A.Length == 0) {
+                return new ILArray<ElementType>(ILSize.Empty00);
+            }
+            if (A.GetType().GetElementType() != typeof(ElementType)) 
+                throw new ILCastException("inner type of System.Array must match"); 
+            int [] dims = new int[A.Rank]; 
+            ElementType [] retArr = ILMemoryPool.Pool.New<ElementType>(A.Length);
+            int posArr = 0; 
+            for (int i = 0; i < dims.Length; i++) {
+                dims[i] = A.GetLength(dims.Length-i-1);
+            }
+            if (dims.Length == 1 && Settings.CreateRowVectorsByDefault) {
+                dims = new int[2] {1, dims[0]}; 
+            }
+            foreach (ElementType item in A) 
+                retArr[posArr++] = item; 
+            ILArray<ElementType> ret = new ILArray<ElementType>(retArr,dims);
+            ILScope.Context.RegisterArray(ret);
+            return ret; 
+        }
+        /// <summary>
+        /// Implicitly cast two dimensional System.Array to ILNumerics array
+        /// </summary>
+        /// <param name="A">2-dimensional System.Array</param>
+        /// <returns>If A is null: empty array. ILNumerics array of same size and type as A otherwise.</returns>
+        public static implicit operator ILArray<ElementType>(ElementType[,] A) {
+            if (A == null) 
+                return null; 
+            if (A.Length == 0) {
+                return new ILArray<ElementType>(ILSize.Empty00);
+            }
+            int[] dims = new int[2];
+            ElementType[] retArr = ILMemoryPool.Pool.New<ElementType>(A.Length);
+            int posArr = 0;
+            for (int i = 0; i < 2; i++) {
+                dims[i] = A.GetLength(dims.Length - i - 1);
+            }
+            foreach (ElementType item in A)
+                retArr[posArr++] = item;
+            ILArray<ElementType> ret = new ILArray<ElementType>(retArr, dims);
+            ILScope.Context.RegisterArray(ret);
+            return ret; 
+        }
+        /// <summary>
+        /// Implicitly cast three dimensional System.Array to ILNumerics array
+        /// </summary>
+        /// <param name="A">3-dimensional System.Array</param>
+        /// <returns>If A is null: empty array. ILNumerics array of same size and type as A otherwise.</returns>
+        public static implicit operator ILArray<ElementType>(ElementType[,,] A) {
+            if (A == null)
+                return null;
+            if (A.Length == 0) {
+                return new ILArray<ElementType>(ILSize.Empty00);
+            }
+            int[] dims = new int[3];
+            ElementType[] retArr = ILMemoryPool.Pool.New<ElementType>(A.Length);
+            int posArr = 0;
+            for (int i = 0; i < 3; i++) {
+                dims[i] = A.GetLength(dims.Length - i - 1);
+            }
+            foreach (ElementType item in A)
+                retArr[posArr++] = item;
+            ILArray<ElementType> ret = new ILArray<ElementType>(retArr, dims);
+            ILScope.Context.RegisterArray(ret);
+            return ret; 
+        }
+        #endregion 
+
+        #region conversional operators
+        /// <summary>
+        /// "Persistence cast" make a steady array out of a temp array
+        /// </summary>
+        /// <param name="A">Temporary array</param>
+        /// <returns>Steady ILArray, will survive multiple usages</returns>
+        /// <remarks>This is one of the most important casts in the ILNumerics framework. It changes temporary 
+        /// arrays from temporary state to ('steady') ILArrays and persistent state. The inner storage is kept and used for 
+        /// the new array. The new arrays can than get used multiple times in any function. In contrast to
+        /// that, ILRetArrays are disposed off after first use.</remarks>
+        public static implicit operator ILArray<ElementType>(ILRetArray<ElementType> A) {
+            if (object.Equals(A, null))
+                return null;
+            ILArray<ElementType> ret = new ILArray<ElementType>(A.GiveStorageAwayOrClone());
+            ILScope.Context.RegisterArray(ret); 
+            return ret; 
+        }
+        /// <summary>
+        /// "Persistence cast" make a steady array out of an input array
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Steady ILArray, will survive multiple usages</returns>
+        /// <remarks>This is one of the most important casts in the ILNumerics framework. It changes temporary 
+        /// arrays from temporary state to ('steady') ILArrays and persistent state. The inner storage is kept and used for 
+        /// the new array. The new arrays can than get used multiple times in any function. In contrast to
+        /// that, ILRetArrays are disposed off after first use.</remarks>
+        public static implicit operator ILArray<ElementType>(ILInArray<ElementType> A) {
+            if (object.Equals(A, null))
+                return null;
+            ILArray < ElementType > ret = new ILArray<ElementType>(new ILDenseStorage<ElementType>(
+                A.Storage.GetDataArray(), A.Size));
+            ILScope.Context.RegisterArray(ret);
+            return ret;
+        }
+        /// <summary>
+        /// "Persistence cast" make a steady array out of an input array
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Steady ILArray, will survive multiple usages</returns>
+        /// <remarks>This is one of the most important casts in the ILNumerics framework. It changes temporary 
+        /// arrays from temporary state to ('steady') ILArrays and persistent state. The inner storage is kept and used for 
+        /// the new array. The new arrays can than get used multiple times in any function. In contrast to
+        /// that, ILRetArrays are disposed off after first use.</remarks>
+        public static implicit operator ILArray<ElementType>(ILOutArray<ElementType> A) {
+            if (object.Equals(A, null))
+                return null;
+            ILArray<ElementType> ret = new ILArray<ElementType>(new ILDenseStorage<ElementType>(
+                A.Storage.GetDataArray(), A.Size));
+            ILScope.Context.RegisterArray(ret);
+            return ret;
+        }
+        /// <summary>
+        /// Convert dense array to scalar temporary cell 
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Scalar cell having the only element with a clone of array</returns>
+        public static implicit operator ILRetCell(ILArray<ElementType> A) {
+            using (ILScope.Enter(A)) {
+                ILRetCell ret = new ILRetCell(ILSize.Scalar1_1, A.Storage);
+                ret.Storage.FromImplicitCast = true; 
+                return ret; 
+            }
+        }
+        #endregion
+        #endregion
+
+        #region memory management
+        /// <summary>
+        /// Assign another array to this array variable. This is an optional, yet more efficient alternative to using '='
+        /// </summary>
+        /// <param name="value">New array</param>
+        /// <remarks>By assigning to this property, this array is immediately released to the memory pool and replaced by the new array. In difference to that, 
+        /// by using the common '=' assignment operator, the array is released only at the time, the current 
+        /// <see cref="ILNumerics.ILScope.Enter"/> block  is left. Therefeore, prefere this method, if a 
+        /// smaller memory pool is crucial. However, for variables of type <c>ILArray</c>, regular assignments are allowed as well.</remarks>
+        /// <seealso cref="ILNumerics.ILOutArray{T}.Assign"/>
+        public ILRetArray<ElementType> a {
+            set { Assign(value); }
+            get { return this.C; }
+        }
+        /// <summary>
+        /// Assign another array to this array variable. This is an optional, yet more efficient alternative to '='
+        /// </summary>
+        /// <param name="value">New array</param>
+        /// <remarks>By using this method, this array is immediately released to the memory pool and replaced by the new array. In difference to that, 
+        /// by using the common '=' assignment operator, the array is released only at the time, the current 
+        /// <see cref="ILNumerics.ILScope.Enter"/> block  is left. Therefeore, prefere this method, if a 
+        /// smaller memory pool is crucial.</remarks>
+        /// <seealso cref="ILNumerics.ILOutArray{T}.Assign"/>
+        public void Assign(ILRetArray<ElementType> value) {
+            if (!IsDisposed)
+                Storage.Dispose();
+            m_storage = value.GiveStorageAwayOrClone();
+            //ILScope.Context.RegisterArray(this);  
+        }
+        internal override bool EnterScope() {
+            return false; 
+        }
+        #endregion
+
+        #region mutability + indexer 
+        /// <summary>
+        /// Set single value to element at index specified
+        /// </summary>
+        /// <param name="value">New value</param>
+        /// <param name="idx">Index of element to be altered</param>
+        public void SetValue(ElementType value, params int[] idx) {
+            Storage.SetValueTyped(value, idx);
+        }
+
+        /// <summary>
+        /// Alter range of this array
+        /// </summary>
+        /// <param name="value">Array with new values</param>
+        /// <param name="range">Range specification</param>
+        public void SetRange(ILInArray<ElementType> value, params ILBaseArray[] range) {
+            using (ILScope.Enter(value)) 
+            using (ILScope.Enter(range)) {
+                if (object.Equals(value, null)) {
+                    Storage.IndexSubrange(null, range);
+                } else {
+                    Storage.IndexSubrange(value.Storage, range);
+                }
+            }
+        }
+        /// <summary>
+        /// Subarray creation/ manipulation/ deletion
+        /// </summary>
+        /// <param name="range">Range specification, defining the size of the subarray</param>
+        /// <returns>Subarray as copy of this array</returns>
+        public ILRetArray<ElementType> this[params ILBaseArray[] range] {
+            get {
+                using (ILScope.Enter(range))
+                    return new ILRetArray<ElementType>(Storage.Subarray(range));
+            }
+            set {
+                SetRange(value, range); 
+            }
+        }
+
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILBaseArray.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILBaseArray.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILBaseArray.cs	(revision 9102)
@@ -0,0 +1,392 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using ILNumerics;
+using ILNumerics.Misc;
+using ILNumerics.Storage;
+using ILNumerics.Native; 
+using System.Runtime.Serialization;
+using System.Runtime.Serialization.Formatters.Binary;
+using System.IO;
+using System.Text;
+using System.Collections.Generic;
+using System.Collections; 
+
+namespace ILNumerics {
+    /// <summary>
+    /// Base type for all arrays in ILNumerics
+    /// </summary>
+    /// <remarks>All numerical arrays derive from ILBaseArray. ILBaseArrays itself 
+    /// cannot be instantiated. Currently, only ILArray<![CDATA[<>]]> exist, which describe 
+    /// a rectangular array as full (solid) or referencing array. There are plans to 
+    /// extend the collection of derived types to encompass triangular, diagonal and sparse arrays. 
+    /// </remarks>
+    [Serializable]
+    public abstract class ILBaseArray : IDisposable {
+
+        #region attributes
+        /// <summary>
+        /// Name of this array
+        /// </summary>
+        protected String m_name = "";
+        internal ILStorage m_storage; 
+        internal int m_scopeCounter = 0;
+        internal bool m_isTempArray;
+        #endregion
+
+        #region properties
+        internal int ScopeID {
+            get { return m_scopeCounter; }
+
+        }
+        internal bool IsDisposed {
+            get { return m_storage == null || m_storage.IsDisposed; }
+        }
+
+        internal ILStorage Storage {
+            get { return m_storage; }
+        }
+
+        /// <summary>
+        /// Size descriptor specification
+        /// </summary>
+        public virtual ILSize Size {
+            get {
+                return Storage.Size;
+            }
+        }
+        /// <summary>
+        /// [deprecated] Use 'Size' as size descriptor!
+        /// </summary>
+        [Obsolete("Use 'Size' instead!")]
+        public ILSize Dimensions {
+            get {
+                return Size;
+            }
+        }
+        /// <summary>
+        /// Size descriptor shortcut
+        /// </summary>
+        public virtual ILSize S {
+            get {
+                return Storage.Size;
+            }
+        }
+        /// <summary>
+        /// [deprecated] Use 'S' as size descriptor!
+        /// </summary>
+        [Obsolete("Use S instead!")]
+        public virtual ILSize D {
+            get {
+                return S;
+            }
+        }
+        /// <summary>
+        /// Length of the longest dimension of this instance
+        /// </summary>
+        /// <remarks>This property is readonly.</remarks>
+        public virtual int Length {
+            get {
+                return Size.Longest;
+            }
+        }
+        /// <summary>
+        /// Gets the name of this array or sets it
+        /// </summary>
+        public String Name {
+            get {
+                return m_name;
+            }
+            set {
+                m_name = value;
+            }
+        }
+        /// <summary>
+        /// Test if this instance is a scalar
+        /// </summary>
+        /// <remarks>This attribute is readonly. It returns: Size.NumberOfElements == 1.</remarks>
+        public virtual bool IsScalar {
+            get {
+                return Size.NumberOfElements == 1;
+            }
+        }
+        /// <summary>
+        /// Test if this instance is a matrix
+        /// </summary>
+        /// <remarks>In order for an array to be a matrix the number of <b>non singleton</b> 
+        /// dimensions must equal 2. This attribute is readonly.</remarks>
+        public virtual bool IsMatrix {
+            get {
+                if (Size.NumberOfDimensions == 2) 
+                    return true;
+                return (Size.Squeeze().NumberOfDimensions == 2); 
+            }
+        }
+        /// <summary>
+        /// Test if this array is a vector
+        /// </summary>
+        /// <remarks>In order for an array to be a vector the number of <b>non singleton</b> 
+        /// dimensions must equal 1. Keep in mind that all ILArrays have at least 2 dimensions. Therefore 
+        /// it is not sufficient to test for the number of dimensions, but to take the number of 
+        /// <b>non singleton</b> dimensions into account. This attribute is readonly.</remarks>
+        public virtual bool IsVector {
+            get {
+                return (Size[0] == 1 || Size[1] == 1) && Size.NumberOfDimensions == 2;
+            }
+        }
+        /// <summary>
+        /// Test if this array instance is a row vector
+        /// </summary>
+        public virtual bool IsRowVector {
+            get {
+                return Size[0] == 1 && Size.NumberOfDimensions == 2;
+            }
+        }
+        /// <summary>
+        /// Test if this array instance is a column vector
+        /// </summary>
+        public virtual bool IsColumnVector {
+            get {
+                return Size[1] == 1 && Size.NumberOfDimensions == 2;; 
+            }
+        }
+        /// <summary>
+        /// Test if this instance is an empty array (number of elements stored = 0)
+        /// </summary>
+        public virtual bool IsEmpty {
+            get {
+                return Size.NumberOfElements == 0;
+            }
+        }
+        #endregion
+
+        #region constructors
+        internal ILBaseArray(ILStorage storage, bool isTempArray) { 
+            m_storage = storage;
+            m_isTempArray = isTempArray; 
+        }
+        /// <summary>
+        /// Implicit cast from scalar of typeof(a) to <c>ILRetArray&lt;typeof(A)&gt;</c>
+        /// </summary>
+        /// <param name="a">Input scalar</param>
+        /// <returns>A ILRetArray of same type as <paramref name="a"/> and size 1x1</returns>
+        public static implicit operator ILBaseArray(double a) {
+            return new ILRetArray<double>(new double[] { a }, ILSize.Scalar1_1);  
+        }
+        /// <summary>
+        /// Implicit cast from scalar of typeof(A) to ILRetArray&lt;typeof(A)&gt;
+        /// </summary>
+        /// <param name="a">Input scalar</param>
+        /// <returns>A ILRetArray of same type as <paramref name="a"/> ans size 1x1</returns>
+        public static implicit operator ILBaseArray(complex a) {
+            return new ILRetArray<complex>(new complex[] { a, 0 }, ILSize.Scalar1_1);  
+        }
+        /// <summary>
+        /// Implicit cast from scalar of typeof(A) to ILRetArray&lt;typeof(A)&gt;
+        /// </summary>
+        /// <param name="a">Input scalar</param>
+        /// <returns>A ILRetArray of same type as <paramref name="a"/> ans size 1x1</returns>
+        public static implicit operator ILBaseArray(fcomplex a) {
+            return new ILRetArray<fcomplex>(new fcomplex[] { a, 0 }, ILSize.Scalar1_1);  
+        }
+        /// <summary>
+        /// Implicit cast from scalar of typeof(A) to ILRetArray&lt;typeof(A)&gt;
+        /// </summary>
+        /// <param name="s">Input scalar</param>
+        /// <returns>A ILRetArray of same type as <paramref name="s"/> and size 1x1</returns>
+        public static implicit operator ILBaseArray(string s) {
+            return new ILRetArray<string>(new string[] { s }, ILSize.Scalar1_1); 
+        }
+        //public static implicit operator ILBaseArray(string[] arr) {
+        //    return new ILRetArray<string>(new string[] { String.Join(";", arr) }, ILSize.Scalar1_1); 
+        //}
+        /// <summary>
+        /// Implicit cast from scalar of typeof(A) to ILRetArray&lt;typeof(A)&gt;
+        /// </summary>
+        /// <param name="a">Input scalar</param>
+        /// <returns>A ILRetArray of same type as <paramref name="a"/> ans size 1x1</returns>
+        public static implicit operator ILBaseArray(double[] a) {
+            if (a == null || a.Length == 0) {
+                return new ILRetArray<double>(ILSize.Empty00); 
+            }
+            ILCell ret = new ILCell(1,a.Length);
+            for (int i = 0; i < a.Length; i++) {
+                ret.SetValue(new ILRetArray<double>(new double[] { a[i] }, ILSize.Scalar1_1),0,i);  
+            }
+            //ret.SetValue("int[]",1,0); 
+            return ret; 
+        }
+        //public static implicit operator ILBaseArray(int[] a) {
+        //    if (a == null || a.Length == 0) {
+        //        return new ILRetArray<int>(ILSize.Empty00); 
+        //    }
+        //    ILCell ret = new ILCell(1,a.Length);
+        //    for (int i = 0; i < a.Length; i++) {
+        //        ret.SetValue(new ILRetArray<int>(new int[] { a[i] }, ILSize.Scalar1_1),0,i);  
+        //    }
+        //    //ret.SetValue("int[]",1,0); 
+        //    return ret; 
+        //}
+        #endregion
+
+        #region virtual
+        /// <summary>
+        /// Compare elements and shape of this array with another array
+        /// </summary>
+        /// <param name="A">Other array</param>
+        /// <returns>true if shape and element values of both arrays match, false otherwise</returns>
+        /// <remarks><para>'Equals' accepts two vectors even if the orientations do not match. Therefore, a row vector 
+        /// with the same element values than another column vector would be considered equal to each other.</para></remarks>
+        public override bool Equals(object A) {
+            ILBaseArray baseArray = A as ILBaseArray; 
+            if (baseArray != null) {
+                return Storage.Equals(baseArray.Storage);
+            }
+            if (IsScalar && A is System.ValueType) {
+                return String.Equals(A.ToString(),Storage.GetValue(0).ToString()); 
+            }
+            return false; 
+        }
+        /// <summary>
+        /// Generate a hash code based on the current arrays values
+        /// </summary>
+        /// <returns>Hash code</returns>
+        /// <remarks>The hashcode is created by taking the values currently stored in the array into account.
+        /// Therefore, the function iterates over all elements in the array - which makes it somehow an expensive 
+        /// operation. Take this into account, if you consider using large arrays in collections like dictionaries 
+        /// or hashtables, which make great use of hash codes.</remarks>
+        public override int GetHashCode() {
+            return Storage.GetHashCode();
+        }
+
+        internal virtual bool EnterScope() {
+            if (m_scopeCounter < 2) {
+                m_scopeCounter++;
+                return true;
+            }
+            return false; 
+        }
+        internal virtual void LeaveScope() {
+            if (--m_scopeCounter <= 0) {
+                Dispose();
+            }
+        }
+
+        #endregion
+
+        #region abstract interface
+        /// <summary>
+        /// Clone this array (shallow) 
+        /// </summary>
+        /// <returns>ILBaseArray as new representation of this storages data.</returns>
+        /// <remarks>The object returned will be of the same size than this array.
+        /// This this is a 'shallow' copy only! I.e., if elements are copied only. If they are 
+        /// references to any objects, those objects are not replicated.</remarks>
+        internal abstract ILBaseArray Clone(); 
+
+        /// <summary>
+        /// Determine if this array is of complex inner type.
+        /// </summary>
+        public abstract bool IsComplex {
+            get; 
+        }
+        /// <summary>
+        /// Determine if this array is of numeric inner type.
+        /// </summary>
+        public abstract bool IsNumeric {
+            get; 
+        }
+        /// <summary>
+        /// Print values of this instance to a stream. 
+        /// </summary>
+        /// <param name="outStream">Stream to write the values into.</param>
+        /// <param name="format">Format string to be used for output. See <see cref="System.String.Format(string,object)"/> for a specification
+        /// of valid formating expressions. This flag is only used, when 'method' is set to 'Serial'.</param>
+        /// <param name="method">A constant out of <see cref="ILArrayStreamSerializationFlags"/>. Specifies the way 
+        /// the values will be serialized.</param>
+        /// <remarks><para>If method 'Formatted' is used, any occurences of NewLine character(s) 
+        /// will be replaced from the format string before applying to the elements. This is done to 
+        /// prevent the format from breaking the 'page' style for the output.</para>
+        /// <para>If 'method' is set to 'Matlab', the array will be written as Matfile version 5.0. No compression will be used. The internal 'Name' property will be used as 
+        /// the array name for writing. This array instance will be the only array in the mat file. If you want to write several arrays bundled into one mat file, use the MatFile class to
+        /// create a collection of arrays and write the MatFile to stream.</para></remarks>
+        public abstract void ToStream(Stream outStream, string format, ILArrayStreamSerializationFlags method);
+
+        /// <summary>
+        /// Convert to string
+        /// </summary>
+        /// <returns>String representation of content</returns>
+        public override string ToString() {
+            return ToString(0);
+        }
+        /// <summary>
+        /// Convert to string with limited length
+        /// </summary>
+        /// <param name="maxLength">Maximal length of returned string; set to 0 to not limit result</param>
+        /// <returns>String representation of content</returns>
+        public virtual string ToString(int maxLength) {
+            string ret = ShortInfo(); 
+            if (m_storage.Size.NumberOfElements > 1) 
+                ret += Environment.NewLine + Storage.ValuesToString(maxLength); 
+            return ret; 
+        }
+        /// <summary>
+        /// Short textual summary of this instance, used for debug output
+        /// </summary>
+        /// <returns>String representation of type and size</returns>
+        /// <remarks>The type of elements and the size of the array are displayed. If the array
+        /// is scalar, its value is displayed next to the type.</remarks>
+        public virtual String ShortInfo() {
+            return Storage.ShortInfo(); 
+        }
+        /// <summary>
+        /// Dispose this array and all its content
+        /// </summary>
+        public void Dispose() {
+            if (IsDisposed) return;     
+            if (Storage != null) {
+                Storage.Dispose(); 
+            }
+        }
+        #endregion
+
+    }
+
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILBaseArrayGen.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILBaseArrayGen.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILBaseArrayGen.cs	(revision 9102)
@@ -0,0 +1,271 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using ILNumerics;
+using ILNumerics.Misc;
+using ILNumerics.Storage;
+using ILNumerics.Exceptions; 
+using System.Runtime.Serialization;
+using System.Runtime.Serialization.Formatters.Binary;
+using System.IO;
+using System.Text;
+using System.Collections.Generic;
+using System.Collections; 
+
+namespace ILNumerics {
+
+    /// <summary>
+    /// Typed base class for all ILNumerics data storage classes for any storage type. 
+    /// </summary>
+    /// <remarks><para>You should not use this type directly. It serves as a base class 
+    /// for all typed storages only and will be used by derived classes like ILArray<![CDATA[<>]]>.</para>
+    /// <para>If you are looking for an (untyped) base class to be used as generic class for any ILArray types, you should use ILBaseArray instead!</para>
+    /// </remarks>
+    [Serializable]
+    public abstract partial class ILBaseArray<ElementType> 
+        : ILBaseArray, IEnumerable<ElementType> {
+        
+        internal ILBaseArray(ILStorage storage, bool isTempArray) : base(storage, isTempArray) { }
+
+        #region attributes
+        #endregion
+
+        #region properties 
+        /// <summary>
+        /// Determine if this array has complex elements.
+        /// </summary>
+        public override bool IsComplex {
+            get {
+                return (this is ILBaseArray<complex> 
+                 || this is ILBaseArray<fcomplex>);
+            }
+        }
+        /// <summary>
+        /// Determine if this array holds numeric values.
+        /// </summary>
+        /// <remarks>An ILArray is numeric as long as its elements are one of the 
+        /// following types: 
+        /// <list type="table">
+        /// <listheader>
+        ///     <term>inner type</term>
+        /// </listheader>
+        /// <item>
+        ///     <term>System.double</term>
+        ///     <description>floating point, real, 8 bytes </description>
+        /// </item>
+        /// <item>
+        ///     <term>System.float</term>
+        ///     <description>floating point real, 4 bytes</description>
+        /// </item>
+        /// <item>
+        ///     <term>ILNumerics.complex</term>
+        ///     <description>floating point complex, 16 bytes</description>
+        /// </item>
+        /// <item>
+        ///     <term>ILNumerics.fcomplex</term>
+        ///     <description>floating point complex, 8 bytes</description>
+        /// </item>
+        /// <item>
+        ///     <term>System.char</term>
+        ///     <description>integer, real, 1 byte</description>
+        /// </item>
+        /// <item>
+        ///     <term>System.byte</term>
+        ///     <description>integer, real, 1 byte</description>
+        /// </item>
+        /// <item>
+        ///     <term>System.Int16</term>
+        ///     <description>integer, real, 2 byte</description>
+        /// </item>
+        /// <item>
+        ///     <term>System.Int32</term>
+        ///     <description>integer, real, 4 byte</description>
+        /// </item>
+        /// <item>
+        ///     <term>System.Int64</term>
+        ///     <description>integer, real, 8 byte</description>
+        /// </item>
+        /// <item>
+        ///     <term>System.UInt16</term>
+        ///     <description>unsigned integer, real, 2 byte</description>
+        /// </item>
+        /// <item>
+        ///     <term>System.UInt32</term>
+        ///     <description>unsigned integer, real, 4 byte</description>
+        /// </item>
+        /// <item>
+        ///     <term>System.UInt64</term>
+        ///     <description>unsigned integer, real, 8 byte</description>
+        /// </item>
+        /// </list>
+        /// </remarks>
+        public override bool IsNumeric {
+            get {
+                if (this is ILBaseArray<double> ||
+                    this is ILBaseArray<float> ||
+                    this is ILBaseArray<complex> ||
+                    this is ILBaseArray<fcomplex> ||
+                    this is ILBaseArray<byte> ||
+                    this is ILBaseArray<char> ||
+                    this is ILBaseArray<Int16> ||
+                    this is ILBaseArray<Int32> ||
+                    this is ILBaseArray<Int64> ||
+                    this is ILBaseArray<UInt16> ||
+                    this is ILBaseArray<UInt32> ||
+                    this is ILBaseArray<UInt64>)
+                    return true;
+                return false;
+            }
+        }
+
+        /// <summary>
+        /// Access to internal typed storage 
+        /// </summary>
+        internal new ILStorage<ElementType> Storage {
+            get { return (m_storage as ILStorage<ElementType>); }
+        }
+
+        #endregion
+
+        #region public interface
+        /// <summary>
+        ///  Serialize this array into a binary stream.
+        /// </summary>
+        /// <param name="outStream">System.IO.Stream to receive the byte stream 
+        /// for this ILBaseArray</param>
+        /// <returns>True on success, false on error.</returns>
+        public virtual bool Serialize(Stream outStream) {
+            try {
+                BinaryFormatter bf = new BinaryFormatter();
+                bf.Serialize(outStream, this);
+                return true;
+            } catch (Exception) {
+                return false;
+            }
+        }
+        /// <summary>
+        /// Deserialize / restore array from binary stream 'inStream'
+        /// </summary>
+        /// <param name="inStream">System.IO.Stream to reconstruct the 
+        /// array from</param>
+        /// <returns>Array reconstructed from stream.</returns>
+        /// <exception cref="System.Runtime.Serialization.SerializationException">If the array could not get restored</exception>
+        public static ILBaseArray<ElementType> Deserialize(Stream inStream) {
+            try {
+                BinaryFormatter bf = new BinaryFormatter();
+                ILBaseArray<ElementType> ret = (ILBaseArray<ElementType>)bf.Deserialize(inStream);
+                return ret;
+            } catch (Exception e) {
+                throw e;
+            }
+        }
+
+        /// <summary>
+        /// Get single element from this array
+        /// </summary>
+        /// <param name="idx">Indices, location of element</param>
+        /// <returns>The selected value</returns>
+        public virtual ElementType GetValue(params int[] idx) {
+            return Storage.GetValueTyped(idx); 
+        }
+        /// <summary>
+        /// Get minimum and maximum value of all elements - if any
+        /// </summary>
+        /// <param name="min">[Output] Minimum value</param>
+        /// <param name="max">[Output] Maximum value</param>
+        /// <returns>true if the limits exists and could be computed, false otherwise</returns>
+        /// <remarks>Empty arrays will return false. In this case the output parameter will be: default(ElementType).
+        /// </remarks>
+        public virtual bool GetLimits(out ElementType min, out ElementType max) {
+            return Storage.GetLimits(out min, out max); 
+        }
+        /// <summary>
+        /// Get minimum and maximum value of all elements - if any
+        /// </summary>
+        /// <param name="min">[Output] Minimum value</param>
+        /// <param name="max">[Output] Maximum value</param>
+        /// <param name="includeInfNaNs">true: recognize Inf, NaN values; false: ignore those values</param>
+        /// <returns>true if the limits exists and could be computed, false otherwise</returns>
+        /// <remarks>Empty arrays will return false. In this case the output parameter will be: default(ElementType).</remarks>
+        internal bool GetLimits(out ElementType min, out ElementType max, bool includeInfNaNs) {
+            return Storage.GetLimits(out min, out max, includeInfNaNs); 
+        }
+        #endregion
+
+        #region IEnumerable<ILBaseArray<ElementType>> Member
+
+        /// <summary>
+        /// Enumerator returning elements as ElementType
+        /// </summary>
+        /// <returns>Enumerator</returns>
+        /// <remarks>This method enables the us of ILNumerics arrays in foreach loops.
+        /// <para>This iterator implements IEnumerable&lt;ElementType> explicitely and is used in situations, 
+        /// where instances of ILNumerics arrays are casted to instances of the IEnumerable interface. This iterator 
+        /// is not integrated into the ILNumerics memory management.</para></remarks>
+        /// <example><code>ILDenseStorage&lt;T&gt; A = ILMath.rand(5,4,6);
+        /// foreach (double element in A) {
+        /// // all elements are scalar double values
+        /// String.Format("Element: {0} ",element);
+        /// // Note: 'element' cannot be used to alter the collection! 
+        /// } 
+        /// </code></example> 
+        IEnumerator<ElementType> System.Collections.Generic.IEnumerable<ElementType>.GetEnumerator() {
+            return Storage.GetEnumerator();
+        }
+        /// <summary>
+        /// Enumerator returning elements as ElementType
+        /// </summary>
+        /// <returns>Enumerator</returns>
+        /// <remarks>This method enables the use of ILNumerics arrays in foreach loops directly.</remarks>
+        IEnumerator System.Collections.IEnumerable.GetEnumerator() {
+            return GetEnumerator(); 
+        }
+        /// <summary>
+        /// Enumerator returning elements as ElementType
+        /// </summary>
+        /// <returns>Enumerator</returns>
+        /// <remarks>This method enables the use of ILNumerics arrays in foreach loops directly.</remarks>
+        public abstract IEnumerator<ElementType> GetEnumerator(); 
+        #endregion
+
+        #region public interface 
+        #endregion
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILBaseCell.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILBaseCell.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILBaseCell.cs	(revision 9102)
@@ -0,0 +1,360 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using ILNumerics.Storage; 
+
+namespace ILNumerics {
+    /// <summary>
+    /// The class implements additional functionality needed for cells
+    /// </summary>
+    public class ILBaseCell : ILDenseArray<ILStorage>  {
+
+        #region constructors
+        internal ILBaseCell(ILCellStorage cellStorage, bool tempArr) 
+            : base(cellStorage, tempArr) { }
+        #endregion constructors
+
+        #region properties
+        /// <summary>
+        /// Transposed version of this ILCell
+        /// </summary>
+        /// <remarks>This property is an alias for 'Shifted(1). </remarks>
+        /// <seealso cref="ILNumerics.ILBaseCell.Shifted(int)"/>
+        public new ILRetCell T {
+            get {
+                return new ILRetCell((ILCellStorage)Storage.ShiftDimensions(1));
+            }
+        }
+        /// <summary>
+        /// Access to the more specialized version (ILCellStorage) of this storage
+        /// </summary>
+        internal new ILCellStorage Storage {
+            get { return (m_storage as ILCellStorage); }
+            set {
+                // e.g. Storage.Detach() may return itself (if no detaching is 
+                // required). So we must check for that equalty here! 
+                if (!object.Equals(value, m_storage)) {
+                    m_storage.Dispose();
+                    m_storage = value;
+                }
+            }
+        }
+        /// <summary>
+        /// Clone of this cell
+        /// </summary>
+        /// <remarks><para>
+        /// Clones of all arrays in ILNumerics.Server are done in a very fast, lazy way. This means, 
+        /// at the time the clone is made, no relevant memory is copied. Elements of both arrays rather point to the same 
+        /// underlying System.Array. A reference counting mechanism ensures the detaching of thoses arrays on write access.</para>
+        /// <para>Cells profit from the same efficient clone creation process. However, since a cell may store an arbitrarily deep 
+        /// hirarchy of other cells and arrays, in order to clone a cell, the cells elements have to be cloned as well - in an 
+        /// recursive manner. Clones play an important role for ILNumerics cells. They are used to implement value semantics for cell
+        /// elements. I.e.: the cloned cell returned cannot not be used to alter elements of the original cell in any way.</para></remarks>
+        public new ILRetCell C {
+            get {
+                return new ILRetCell((ILCellStorage)Storage.Clone());
+            }
+        }
+        #endregion
+
+        #region public interface
+        /// <summary>
+        /// Concatenate this cell 
+        /// </summary>
+        /// <param name="A">Cell to concatenate this cell with</param>
+        /// <param name="dim">Dimension index along which to concatenate the cells.</param>
+        /// <returns>New cell with concatenation of all elements of both cells</returns>
+        /// <remarks>The array returned will be a copy of both cells involved. 
+        /// If <paramref name="dim"/> is larger than 
+        /// the number of dimensions of one of the arrays its value will be used in modulus. 
+        /// <para>The resulting cell has the size of both input cells, laid beside one 
+        /// another along the <paramref name="dim"/> dimension.</para></remarks>
+        public ILRetCell Concat(ILInCell A, int dim) {
+            using (ILScope.Enter(A))
+                return new ILRetCell((ILCellStorage)Storage.Concat(A.Storage, dim));
+        }
+        /// <summary>
+        /// Retrieve a single array of a known type from a cell position
+        /// </summary>
+        /// <typeparam name="T">Element type of the array</typeparam>
+        /// <param name="indices">Position of the array within this cell</param>
+        /// <returns>Lazy, shallow clone of the array found at the given position</returns>
+        public ILRetArray<T> GetArray<T>(params ILBaseArray[] indices) {
+            using (ILScope.Enter(indices))
+                return new ILRetArray<T>(Storage.GetDenseStorage<T>(indices));
+        }
+        /// <summary>
+        /// Retrieve a single element from the given position
+        /// </summary>
+        /// <param name="indices">Position of the element to retrieve, must evaluate to a scalar position</param>
+        /// <returns>A clone of the scalar element found</returns>
+        /// <remarks>
+        /// <para>The method returns a lazy, shallow clone of the content of the cell element specified by <paramref name="indices"/>. 
+        /// However, the return type (<code>ILBaseArray</code>) is not strongly typed and may contain <b>any</b> element. According to the 
+        /// true element stored in the cell, this might be an array of arbitrary type, null or even another cell. Moreover, handling 
+        /// <code>ILBaseArray</code> directly is not recommended for ILNumerics, since this would hinder the memory management from proper 
+        /// functioning. Therefore: <b>The use of this method is not recommended and left to ILNumerics experts - for very 
+        /// specific and rare situations.</b></para>
+        /// </remarks>
+        internal ILBaseArray GetBaseArray(params ILBaseArray[] indices) {
+            using (ILScope.Enter(indices))
+                return Storage.GetScalar(indices);
+        }
+        /// <summary>
+        /// Retrieve a subcell of this cell
+        /// </summary>
+        /// <param name="indices">Subcell definition, arbitrary size</param>
+        /// <returns>A cell with a lazy, shallow clone of the elements of this cell, addressed by <paramref name="indices"/></returns>
+        /// <remarks>The cell returned will have the size and shape specified by <paramref name="indices"/>.</remarks>
+        public ILRetCell GetCell(params ILBaseArray[] indices) {
+            using (ILScope.Enter(indices)) {
+                ILCellStorage retStorage = (ILCellStorage)Storage.Subarray(indices);
+                if (retStorage.Size.NumberOfElements == 1) {
+                    ILCellStorage retInner = retStorage.GetValueTyped(0) as ILCellStorage;
+                    if (retInner == null) 
+                        throw new Exceptions.ILArgumentException("no cell found at the specified position");
+                    return new ILRetCell(retInner); 
+                } else {
+                    throw new Exceptions.ILArgumentException("index specification must resolve to a scalar element location");
+                }
+            }
+        }
+        /// <summary>
+        /// Enumerator returning elements as scalar cells
+        /// </summary>
+        /// <returns>Enumerator</returns>
+        /// <remarks>This method enables the use of cells in foreach loops.
+        /// <para>The iterator is returned, if arrays are directly used in foreach statements. The iterator 
+        /// is compatible with ILNumerics memory management.</para></remarks>
+        /// <example><code>ILDenseStorage&lt;T&gt; A = ILMath.rand(5,4,6);
+        /// foreach (double element in A) {
+        /// // all elements are scalar double values
+        /// String.Format("Element: {0} ",element);
+        /// // Note: 'element' cannot be used to alter the collection! 
+        /// } 
+        /// </code></example> 
+        public new IEnumerator<ILRetCell> GetEnumerator() {
+            int len = Size.NumberOfElements;
+            for (int i = 0; i < len; i++) {
+                //yield return GetBaseArray(i);
+                yield return new ILRetCell((ILCellStorage)Storage.Subarray(i));
+            }
+        }
+        /// <summary>
+        /// Retrieve single element from this cell
+        /// </summary>
+        /// <param name="idx">Position of the element</param>
+        /// <returns>Lazy, shallow clone of the element to retrieve or null, if there is no element at this place</returns>
+        public new object GetValue(params int[] idx) {
+            return Storage.GetValue(idx); 
+        }
+        /// <summary>
+        /// Retrieve a typed single element from within the cell, supports deep indexing
+        /// </summary>
+        /// <typeparam name="T">Expected type of the value to be returned</typeparam>
+        /// <param name="indices">Location of the single element addressed</param>
+        /// <returns>A clone of the single element addressed by <paramref name="indices"/></returns>
+        /// <remarks>The element returned will have the type given by <typeparamref name="T"/>. It is an error to specify 
+        /// a different type as the true type of the element specified. An exception is thrown if both types differ.</remarks>
+        public T GetValue<T>(params int[] indices) {
+            return Storage.GetValue<T>(indices);
+        }
+        /// <summary>
+        /// Test if an element of the cell is an array of the given element type
+        /// </summary>
+        /// <typeparam name="T">The array element type to check the cell element against</typeparam>
+        /// <param name="position">Position of the cell element to be tested</param>
+        /// <returns>true if the element found at the given position is an array of the element type <typeparamref name="T"/>, false otherwise</returns>
+        /// <remarks>The method is helpful in order to investigate the contents of a cell array. If you are not sure about the 
+        /// types of elements in the cell, this function can be used to make sure, elements are of the expected type before retrieving them as such.
+        /// <para>In most situations, elements of a cell are stored arrays of a distinct element type. That element type is given to IsTypeOf as 
+        /// typeparameter <typeparamref name="T"/>. That means, in order to find out, if the first cell element stores an array of int (<code>ILArray&lt;int></code>), 
+        /// one may use <code>cell.IsTypeOf&lt;int>(0)</code></para>
+        /// <para>In order to test, if a cell element is of type <code>ILCell</code>, one can provide the type <code>ILCell</code> as type parameter: 
+        /// <code>cell.IsTypeOf&lt;ILCell>(0)</code>. Note the different semantic when checking for cell elements of type cell. Here we do not test for the 
+        /// element type but for the array type itself, ie. <code>ILCell</code>. The reason of this is: the type of elements of <code>ILCell</code> is 
+        /// an implementation detail and therefore hidden to the user.</para>
+        /// </remarks>
+        /// <example>
+        /// <para>In the following example a ILCell of size 3x2 is created. It stores several array types, among which other cells are stored as elements of the outer cell.</para>
+        /// <code>ILCell cell = ILMath.cell(new ILSize(3, 2) 
+        ///                      , "first element"
+        ///                      , 2.0
+        ///                      , ILMath.cell(Math.PI, 100f)
+        ///                      , ILMath.create&lt;short>(1, 2, 3, 4, 5, 6)
+        ///                      , new double[] {-1.4, -1.5, -1.6});
+        /// </code>
+        /// The cell is now: 
+        /// <code>ILCell [3,2]
+        ///          &lt;String>      first element  &lt;Int16> [2,3,4,5,6] 
+        ///          &lt;Double>          2          ILCell [1,3]           
+        ///          ILCell [2,1]                                    (null)	
+        /// </code>
+        /// We test the element type of every element in the cell: 
+        /// <code>
+        /// Console.Out.WriteLine("cell[0,0] is of type 'string': {0}", cell.IsTypeOf&lt;string>(0));
+        /// Console.Out.WriteLine("cell[0,0] is of type 'double': {0}", cell.IsTypeOf&lt;double>(0));
+        ///                                      
+        /// Console.Out.WriteLine("cell[1,0] is of type 'double': {0}", cell.IsTypeOf&lt;double>(1));
+        /// Console.Out.WriteLine("cell[2,0] is of type 'ILCell': {0}", cell.IsTypeOf&lt;ILCell>(2));
+        ///                                                                         
+        /// Console.Out.WriteLine("cell[0,1] is of type 'short': {0}", cell.IsTypeOf&lt;short>(0, 1));
+        /// Console.Out.WriteLine("cell[1,1] is of type 'ILCell': {0}", cell.IsTypeOf&lt;ILCell>(1, 1));
+        /// Console.Out.WriteLine("cell[2,1] is of type 'double': {0}", cell.IsTypeOf&lt;double>(2, 1));
+        /// </code>
+        /// This gives the following output: 
+        /// <code>
+        /// cell[0,0] is element type 'string': True
+        /// cell[0,0] is element type 'double': False
+        /// cell[1,0] is element type 'double': True
+        /// cell[2,0] is element type 'ILCell': True
+        /// cell[0,1] is element type 'short': True
+        /// cell[1,1] is element type 'ILCell': True
+        /// cell[2,1] is element type 'double': False  // element is null, IsTypeOf&lt;> never gives true
+        /// </code></example>
+        public bool IsTypeOf<T>(params ILBaseArray[] position) {
+            using (ILScope.Enter(position))
+                return Storage.IsTypeOf<T>(position);
+        }
+        /// <summary>
+        /// Create reshaped copy of this cell
+        /// </summary>
+        /// <param name="size">New size of the cell</param>
+        /// <returns>Reshaped copy of the cell</returns>
+        /// <remarks><para>The current instance will not be changed! A new cell is created, having 
+        /// the elements of this cell and a shape as determined by <paramref name="size"/>.</para>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the number of elements in 
+        /// <paramref name="size"/> do not match the number of elements in this cell.</exception>
+        public new ILRetCell Reshape(ILSize size) {
+            ILCell ret = C;
+            ret.Storage.Reshape(size);
+            return ret;
+        }
+        /// <summary>
+        /// Create reshaped copy of this cell
+        /// </summary>
+        /// <param name="size">New size of the cell</param>
+        /// <returns>Reshaped copy of the cell</returns>
+        /// <remarks><para>The current instance will not be changed! A new cell is created, having 
+        /// the elements of this cell and a shape as determined by <paramref name="size"/>.</para>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the number of elements in 
+        /// <paramref name="size"/> do not match the number of elements in this cell.</exception>
+        public new ILRetCell Reshape(params int[] size) {
+            return Reshape(new ILSize(size));
+        }
+        /// <summary>
+        /// Create replication of this cell
+        /// </summary>
+        /// <param name="dims">Size descriptor
+        /// <remarks>If the number of elements in <paramref name="dims"/> is 
+        /// less than the number of dimensions in this cell, the trailing dimensions will 
+        /// be set to 1 (singleton dimensions). On the other hand, if the number specified 
+        /// is larger then the number of dimension stored inside the storge the resulting 
+        /// storage will get its number of dimensions extended accordingly. </param></remarks>
+        /// <returns>Array created by multiple replications of this array along 
+        /// arbitrary dimensions according to <paramref name="dims"/></returns>
+        public new ILRetCell Repmat(params int[] dims) {
+            return new ILRetCell((ILCellStorage)Storage.Repmat(dims));
+        }        
+        /// <summary>
+        /// Dimension shifted cell from this cell
+        /// </summary>
+        /// <param name="shift">Number of dimensions to shift</param>
+        /// <returns>Shifted version of this cell</returns>
+        /// <remarks><para>The shift is done 'to the left':</para>
+        /// <example><code>ILCell A = cell(2,4); <br/>
+        /// ILCell B = A.Shifted(1); <br/>
+        /// // B is now: ILCell [4,2] <br/>
+        /// // <br/>
+        /// ILCell C = cell(2,4,3);<br/>
+        /// ILCell D = C.Shifted(1); <br/>
+        /// // D is now: ILCell [4,3,2] <br/>
+        /// </code></example>
+        /// <para>The dimensions are shifted circulary to the left. This 
+        /// can be imagined as removing the first dimensions from the beginning of the list of 
+        /// dimensions and "append" them to the end in a ringbuffer style. </para>
+        /// <para>For dimension shifts of '1', you may consider using the 
+        /// <see cref="ILNumerics.ILDenseArray{ElementType}.T"/> property for readability.</para>
+        /// <para><paramref name="shift"/> must be positive. It is taken modulus the number of dimensions.</para>
+        /// <seealso cref="ILNumerics.ILDenseArray{ElementType}.T"/></remarks>
+        public new ILRetCell Shifted(int shift) {
+            return new ILRetCell((ILCellStorage)Storage.ShiftDimensions(shift));
+        }
+        /// <summary>
+        /// Subarray access. Get/set regular subarray. 
+        /// </summary>
+        /// <param name="indices">Address range</param>
+        /// <returns>Reference cell array with subarray addressed by <c>indices</c>. </returns>
+        /// <remarks>Query access: for N-dimensional cell arrays missing trailing dimensions indices will be choosen to be 0. Therefore you 
+        /// may ommit those trailing dimensions in <c>indices</c>.
+        /// <para>The indexer may be used for querying or altering single/any elements 
+        /// in this cell. <c>indices</c> may contains index specifications for one to any 
+        /// dimension. The cell array returned will have the size specified by <c>indices</c>.</para>
+        /// <para>Values returned will be reference cells. All elements contained will be 'deep references' created by 
+        /// recursively walking downwards the elements and replacing them by references to itself. Therefore altering the 
+        /// values returned will not alter the original elements.</para>
+        /// <para>The indexer may also be used for removing parts of the cell. Therefore null must be assigned to the range specified by <c>indices</c> (using the set-access). <c>indices</c> 
+        /// must contain exactly one dimension specification other than 'full' in this case. This may be any vector-sized numeric ILArray of any 
+        /// numeric type. If <c>indices</c> apply to fewer dimensions than the number of dimensions existing, the upper dimensions will be 
+        /// merged and the array will be reshaped before applying the removal to it.
+        /// <example>
+        /// <code>
+        /// ILCell C = new ILCell(4,10); 
+        /// C[":",2] = null;  // &gt;- will remove the third column (index: 2) from the cell.
+        /// C[full,vec(2,5)] = null;  &gt;- will remove columns 3...6
+        /// C[1,1] = null; &gt;- will produce an error. Only one dimension can be specified not full! 
+        /// </code></example></para>
+        /// <para>The general behavior of this access methods is full compatible with the corresponding Matlab/Octave/Scilab access: a(:) = []. </para>
+        /// </remarks>
+        public new ILRetCell Subarray(params ILBaseArray[] indices) {
+            using (ILScope.Enter(indices)) {
+                ILCellStorage elements = (ILCellStorage)Storage.Subarray(indices);
+                return new ILRetCell(elements);
+            }
+        }
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILBaseLogical.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILBaseLogical.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILBaseLogical.cs	(revision 9102)
@@ -0,0 +1,257 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using ILNumerics;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions; 
+using ILNumerics.Storage;
+using ILNumerics.Native;
+using System.Text; 
+
+namespace ILNumerics {
+	/// <summary>
+	/// Boolean array for high performance relational operations on arbitrary arrays 
+	/// </summary>
+	/// <remarks>
+	/// Logical arrays are derived from <![CDATA[ILArray<byte>]]>. It consumes
+	/// 1 byte per element and is the output parameter of all relational comparisons
+	/// as well as the input parameter for all functions consuming <![CDATA[ILArray<byte>]]>.
+    /// The difference between <![CDATA[<byte>]]> and an ILLogical is, the ILLogical 
+    /// storing a integer value with the number of nonzero elements as additional information. 
+    /// Therefore functions like 'find' are able to determine the lenght of output array to 
+    /// be created omitting the need of multiple walks through the array. Therefore ILLogicalArrays 
+    /// consume (a little) more time while construction but are much more performand on functions like 
+    /// 'find'.
+	/// </remarks>
+    [Serializable]
+    public class ILBaseLogical : ILDenseArray<byte> {
+
+        #region properties 
+        /// <summary>
+        /// Number of 'true' elements in this array
+        /// </summary>
+        /// <remarks>This value caches the number of 'true' elements in this logical array. 
+        /// It may be used for information purposes but is actually needed internally for performance 
+        /// reasons.</remarks>
+        public virtual long NumberNonZero {
+            get {
+                return Storage.NumberNonZero;
+            }
+            internal set {
+                Storage.NumberNonZero = value; 
+            }
+        }
+        /// <summary>
+        /// Shift the dimensions of this array by one (transpose for matrix)
+        /// </summary>
+        public new ILRetLogical T {
+            get {
+                return new ILRetLogical((ILLogicalStorage)Storage.ShiftDimensions(1), NumberNonZero);
+            }
+        }
+        internal new ILLogicalStorage Storage {
+            get {
+                return (m_storage as ILLogicalStorage);
+            }
+        }
+        /// <summary>
+        /// Create clone of this array 
+        /// </summary>
+        public new ILRetLogical C {
+            get {
+                return new ILRetLogical((ILLogicalStorage)base.Clone().Storage, NumberNonZero);
+            }
+        }
+        #endregion
+
+        #region constructors
+        /// <summary>
+        /// Constructor creating ILLogical from dense storage
+        /// </summary>
+        /// <param name="A">Input array, the storage of this ILArray will directly be used for 
+        /// storage of the new ILLogical</param>
+        /// <param name="isTempArray">Indicate whether the result is supposed to be a temporary array (true) or persistent (false)</param>
+		internal ILBaseLogical(ILDenseStorage<byte> A, bool isTempArray)
+			: base(A,isTempArray) {
+			NumberNonZero = sumElements();
+		}
+        #endregion
+
+        #region helper functions
+        /// <summary>
+        /// Sum all elements of this storage. 
+        /// </summary>
+        /// <returns>Number of non zero elements</returns>
+        protected int sumElements() {
+            int ret = 0; 
+            int nrElements = Storage.Size.NumberOfElements; 
+            // physical storage 
+            unsafe {
+                fixed (byte* pInArray = GetArrayForRead()) {
+                    byte* pCurData = pInArray;
+                    byte* pLastElement = pInArray + nrElements;
+                    while (pCurData < pLastElement)
+                        ret += *pCurData++;
+                }
+            }
+            return ret; 
+        }
+        #endregion
+ 
+        #region public functions
+        /// <summary>
+        /// Concatenate this array
+        /// </summary>
+        /// <param name="A">N-dimensional array. Except for dimensions <paramref name="dim"/>
+        /// the dimensions of A must match the dimensions of this storage</param>
+        /// <param name="dim">Index of dimension to concatenate arrays along.
+        /// If dim is larger than the number of dimensions of any of the arrays,
+        /// its value will be used in modulus the number of dimensions.</param>
+        /// <returns>New array having the size 
+        /// of both input arrays layed behind each other along the dim's-dimension</returns>
+        public ILRetLogical Concat(ILInLogical A, int dim) {
+            using (ILScope.Enter(A))
+            return new ILRetLogical ((ILLogicalStorage)Storage.Concat(A.Storage, dim));
+        }
+        /// <summary>
+        /// Create reshaped copy of this logical array
+        /// </summary>
+        /// <param name="size">New dimensions of the array</param>
+        /// <returns>Reshaped copy of this array</returns>
+        /// <remarks><para>The current instance will not be changed! A new array is created, having 
+        /// the elements of this array and a shape as determined by <paramref name="size"/>.</para>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the number of elements in 
+        /// <paramref name="size"/> do not match the number of elements in this array.</exception>
+        public new ILRetLogical Reshape(ILSize size) {
+            using (ILScope.Enter()) {
+                ILLogical ret = C;
+                ret.Storage.Reshape(size);
+                return ret;
+            }
+        }
+        /// <summary>
+        /// Create reshaped copy of this logical array
+        /// </summary>
+        /// <param name="size">New dimensions of the array</param>
+        /// <returns>Reshaped copy of the array</returns>
+        /// <remarks><para>The current instance will not be changed! A new array is created, having 
+        /// the elements of this array and a shape as determined by <paramref name="size"/>.</para>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the number of elements in 
+        /// <paramref name="size"/> do not match the number of elements in this array.</exception>
+        public new ILRetLogical Reshape(params int[] size) {
+            return Reshape(new ILSize(size));
+        }
+        /// <summary>
+        /// Create replication of this array
+        /// </summary>
+        /// <param name="dims">Dimensions specifier. If the number of elements in <paramref name="dims"/> is 
+        /// less than the number of dimensions in this array, the trailing dimensions will 
+        /// be set to 1 (singleton dimensions). On the other hand, if the number specified 
+        /// is larger then the number of dimension stored inside the storge the resulting 
+        /// storage will get its number of dimensions extended accordingly. </param>
+        /// <returns>array being created out of multiple replications of this array along 
+        /// arbitrary dimensions according to <paramref name="dims"/></returns>
+        public new ILRetLogical Repmat(params int[] dims) {
+            return new ILRetLogical((ILLogicalStorage)Storage.Repmat(dims));
+        }
+        /// <summary>
+        /// Create logical array from this logical and shift dimensions
+        /// </summary>
+        /// <param name="shift">Number of dimensions to shift</param>
+        /// <returns>Shifted version of this array</returns>
+        /// <remarks><para>The shift is done 'to the left':</para>
+        /// <example><code>ILArray&lt;double> A = zeros(2,4); 
+        /// ILArray&lt;double> B = A.Shifted(1); 
+        /// // B is now: &lt;double> [4,2] 
+        /// 
+        /// ILArray&lt;double> C = zeros(2,4,3);
+        /// ILArray&lt;double> D = C.Shifted(1); 
+        /// // D is now: &lt;double> [4,3,2] 
+        /// </code></example>
+        /// <para>The dimensions are shifted circulary to the left. This 
+        /// can be imagined as removing the first dimensions from the beginning of the list of 
+        /// dimensions and "append" them to the end in a ringbuffer style.</para>
+        /// <para>For dimension shifts of '1', you may consider using the 
+        /// <see cref="ILNumerics.ILDenseArray{ElementType}.T"/> property for readability.</para>
+        /// <para><paramref name="shift"/> must be positive. It is taken modulus the number of dimensions.</para>
+        /// <seealso cref="ILNumerics.ILDenseArray{ElementType}.T"/></remarks>
+        public new ILRetLogical Shifted(int shift) {
+            return new ILRetLogical((ILLogicalStorage)Storage.ShiftDimensions(shift));
+        }
+        /// <summary>
+        ///	Subarray from this array
+        /// </summary>
+        /// <param name="range">Arrays specifying the ranges to create subarray from</param>
+        /// <returns>Subarray as specified</returns>
+        public new ILRetLogical Subarray(params ILBaseArray[] range) {
+            using (ILScope.Enter(range))
+            return new ILRetLogical((ILLogicalStorage)Storage.Subarray(range));
+        }
+        /// <summary>
+        /// Short summary of this logical array
+        /// </summary>
+        /// <returns>Type and size information</returns>
+        public override string ShortInfo() {
+            string ret = "Logical ";
+            if (object.Equals(m_storage,null)) 
+                return ret + " (disposed)"; 
+            if (Storage.Size.NumberOfElements == 1)
+                ret += Storage.GetValue(0);
+            else
+                ret += Storage.Size.ToString();
+            return ret.ToString();
+        }
+        #endregion
+
+        #region depricated 
+        /// <summary>
+        /// [deprecated] create empty ILLogical 
+        /// </summary>
+        /// <returns>empty ILLogical.</returns>
+        [Obsolete()]
+        public static ILRetLogical empty(ILSize dim) {
+            return new ILRetLogical(new byte[0],dim);
+        }
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILCell.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILCell.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILCell.cs	(revision 9102)
@@ -0,0 +1,399 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Text; 
+using ILNumerics.Storage; 
+using ILNumerics.Exceptions;
+using System.Collections.Generic; 
+
+namespace ILNumerics {
+    /// <summary>
+    /// ILCell: container class holding and managing arbitrary array objects 
+    /// </summary>
+    /// <remarks>
+    /// ILCell acts as general purpose container. It stores arbitrary arrays of arbitrary element type. 
+    /// Read and write access to cells provide value semantics - changes on arrays stored inside/ and 
+    /// retrieved from a cell cannot change the corresponding original array. 
+    /// </remarks>
+    [Serializable]
+    public sealed class ILCell : ILBaseCell {
+
+        private static readonly bool s_isTempArray = false; 
+
+        #region constructors
+        /// <summary>
+        /// Create cell object with pre-created data in specified dimensions 
+        /// </summary>
+        /// <param name="data">predefined element data array, will be used for new cell (no copy will be made)</param>
+        /// <param name="size">size of the new cell</param>
+        /// <remarks>object array data will directly be used for storage. No 
+        /// copy will be made. However, any arrays referenced by data are dereferenced for storage inside the cell. The size must match prod(size)</remarks>
+        [Obsolete("use <see cref='ILNumerics.ILMath.cell'/> instead!")]
+        internal ILCell(ILStorage[] data, params int[] size)
+            : base(new ILCellStorage(data, new ILSize(size)), s_isTempArray) {
+        }
+        /// <summary>
+        /// Create cell object with pre-created data in specified dimensions 
+        /// </summary>
+        /// <param name="data">predefined element data array, will be used for new cell (no copy will be made)</param>
+        /// <param name="size">size of the new cell</param>
+        /// <remarks>object array data will directly be used for storage. No 
+        /// copy will be made. However, any arrays referenced by data are dereferenced for storage inside the cell. The size must match prod(size)</remarks>
+        [Obsolete("use <see cref='ILNumerics.ILMath.cell'/> instead!")]
+        internal ILCell(ILStorage[] data, ILSize size)
+            : base(new ILCellStorage(data, size), s_isTempArray) {
+        }
+        /// <summary>
+        /// [deprecated] create new cell object, elements will be 'null' 
+        /// </summary>
+        /// <param name="size">dimension sizes of the new cell</param>
+        /// <remarks><para>After creation, the cell elements can be set by use 
+        /// of the indexer methods or by using corresponding methods of ILCell like SetValue()</para>
+        /// <para>Consider using <see cref="M:ILNumerics.ILMath.cell()"/> in order to create 
+        /// cell arrays.</para></remarks>
+        /// <seealso cref="P:ILNumerics.ILCell.Item(System.Int32[])"/>
+        /// <seealso cref="P:ILNumerics.ILCell.Item(ILNumerics.ILBaseArray[])"/>
+        /// <seealso cref="ILNumerics.ILBaseCell.GetArray{_T}(ILNumerics.ILBaseArray[])"/>
+        [Obsolete("use <see cref='ILNumerics.ILMath.cell(ILSize)'/> instead!")]
+        public ILCell(params int[] size)
+            : base(new ILCellStorage(new ILStorage[prod(size)], new ILSize(size)), s_isTempArray) {  }
+
+        internal ILCell(ILCellStorage cellStorage)
+            : base(cellStorage, s_isTempArray) { }
+
+        [Obsolete("use <see cref='ILNumerics.ILMath.cell'/> instead!")]
+        internal ILCell(ILSize size, params ILStorage[] values)
+            : base(new ILCellStorage(values, size), s_isTempArray) { }
+
+        #endregion constructors
+
+        #region properties
+        /// <summary>
+        /// Replace the elements of this array with another array's elements, preventing memory leaks
+        /// </summary>
+        /// <param name="value">New array</param>
+        public ILRetCell a {
+            set { Assign(value); }
+            get { return this.C; }
+        }
+        #endregion
+
+        #region implicit casts
+        
+        #region constructional operators
+        //public static implicit operator ILCell(double value) {
+        //    return createScalar(value); 
+        //}
+        //public static implicit operator ILCell(float value) {
+        //    return createScalar(value); 
+        //}
+        //public static implicit operator ILCell(byte value) {
+        //    return createScalar(value); 
+        //}
+        //public static implicit operator ILCell(int[] value) {
+        //    return createArray(value); 
+        //}
+        #endregion
+
+        #region conversional operators
+        /// <summary>
+        /// Convert temporary cell to persistent cell
+        /// </summary>
+        /// <param name="A">Temporary cell</param>
+        /// <returns>Persistent cell</returns>
+        public static implicit operator ILCell(ILRetCell A) {
+            if (object.Equals(A, null))
+                return null;
+            ILCell ret = new ILCell((ILCellStorage)A.GiveStorageAwayOrClone());
+            ILScope.Context.RegisterArray(ret);
+            return ret;
+        }
+        /// <summary>
+        /// Convert input parameter cell to persistent cell
+        /// </summary>
+        /// <param name="A">Input parameter cell</param>
+        /// <returns>Persistent cell</returns>
+        public static implicit operator ILCell(ILInCell A) {
+            if (object.Equals(A, null))
+                return null;
+            ILCell ret = new ILCell(new ILCellStorage(
+                A.Storage.GetDataArray(), A.Size));
+            ILScope.Context.RegisterArray(ret);
+            return ret;
+        }
+        /// <summary>
+        /// Convert output parameter cell to persistent cell
+        /// </summary>
+        /// <param name="A">Output parameter cell</param>
+        /// <returns>Persistent cell</returns>
+        public static implicit operator ILCell(ILOutCell A) {
+            if (object.Equals(A, null))
+                return null;
+            ILCell ret = new ILCell(new ILCellStorage(
+                A.Storage.GetDataArray(), A.Size));
+            ILScope.Context.RegisterArray(ret);
+            return ret;
+        }
+        #endregion
+
+        #endregion
+
+        #region helper functions
+        internal static long prod(int[] sizes) {
+            int ret = 1;
+            for (int i = 0; i < sizes.Length; i++)
+                ret *= sizes[i];
+            return ret;
+        }
+        #endregion helper functions
+
+        #region public interface 
+        /// <summary>
+        /// Replaces storage of this array with new array elements, registers this array for out-of-scope disposal
+        /// </summary>
+        /// <param name="value">New array</param>
+        public void Assign(ILRetCell value) {
+            if (!IsDisposed)
+                Storage.Dispose();
+            m_storage = value.GiveStorageAwayOrClone();
+            //ILScope.Context.RegisterArray(this);  
+        }
+        /// <summary>
+        /// Set single element of the cell
+        /// </summary>
+        /// <param name="value">The new value</param>
+        /// <param name="idx">Indices specifying the location to set the element to</param>
+        /// <remarks>The function supports the following features: 
+        /// <list type="bullet">
+        /// <item>Automatic expansion of the cell, when addressing an element outside of the cells size limits.</item>
+        /// <item>Before storing the new element into the cell, an old element may existing on the same location gets disposed.</item>
+        /// <item>A clone of the new value is stored, therefore, none of the source and the stored element are altered, whenever the other cell is altered (value semantics).</item>
+        /// <item>The function supports deep index addressing. This is the only way of altering array elements inside the cell - without recreation.</item>
+        /// </list>
+        /// <para>Removal of parts of the cell is <b>not</b> supported. If null or an empty array is provided as <paramref name="value"/>, the corresponding 
+        /// element is overwritten or removed.</para>
+        /// </remarks>
+        public void SetValue(ILBaseArray value, params int[] idx) {
+            using (ILScope.Enter(value)) {
+                Storage.SetValueTyped(value.Storage, idx);
+            }
+        }
+        /// <summary>
+        /// Set single element of the cell
+        /// </summary>
+        /// <param name="value">The new value</param>
+        /// <param name="idx">Indices specifying the location to set the element to</param>
+        /// <remarks>The function supports the following features: 
+        /// <list type="bullet">
+        /// <item>Automatic expansion of the cell, when addressing an element outside of the cells size limits.</item>
+        /// <item>Before storing the new element into the cell, an old element may existing on the same location gets disposed.</item>
+        /// <item>A clone of the new value is stored, therefore, none of the source and the stored element are altered, whenever the other cell is altered (value semantics).</item>
+        /// <item>The function supports deep index addressing. This is the only way of altering array elements inside the cell - without recreation.</item>
+        /// </list>
+        /// <para>Removal of parts of the cell is <b>not</b> supported. If null or an empty array is provided as <paramref name="value"/>, the corresponding 
+        /// element is overwritten or removed.</para>
+        /// </remarks>
+        internal void SetValue(ILStorage value, params int[] idx) {
+            Storage.SetValueTyped(value, idx);
+        }
+        /// <summary>
+        /// Alter range of this array
+        /// </summary>
+        /// <param name="value">Array with new values</param>
+        /// <param name="range">Range specification</param>
+        /// <remarks>All common array modification/ reshaping/ removing/ expansion rules apply.
+        /// <para>Like for almost all operations on cell, the values stored in the cell are 
+        /// not connected to the original cell elements outside the cell (value semantics).</para></remarks>
+        public void SetRange(ILInCell value, params ILBaseArray[] range) {
+            using (ILScope.Enter(range))
+            using (ILScope.Enter(value)) {
+                if (Object.ReferenceEquals(value, null)) {
+                    Storage.IndexSubrange(null, range);
+                } else {
+                    Storage.IndexSubrange((ILCellStorage)value.Storage.Clone(), range);
+                }
+            }
+        }
+        #endregion
+
+        #region Index access
+        /// <summary>
+        /// Get/set/remove single element 
+        /// </summary> 
+        /// <paramref name="indices" value="Index to element"/>
+        /// <value>Inner element, new inner element or null</value>
+        /// <remarks>The type of access depends on the length of indices. If indices contains only one element, 
+        /// the array will be accessed via sequential index access. This is sometimes called referred to as 'linear' 
+        /// index addressing. 
+        /// Sequential index access reflects the index of internal storage the way the data are actually organized 
+        /// in memory. This access method is mainly convinient for vectors where you are not interested of orientation.
+        /// The following example demonstrates sequential index access for ILArray's (which also holds for ILCells): 
+        /// <example>For <c>
+        /// ILArray&lt;double&gt; A = ILMath.counter(1,12);</c>, <c>A[2]</c> gives: 3.0.
+        /// But the transpose 
+        /// <c>A.T[2]</c> gives also: 3.0.
+        /// For matrices and N-dimensional arrays this holds as well: 
+        /// <code>
+        /// ILArray&lt;double&gt; A = ILMath.counter(1.0,1.0,3,2,2);
+        /// A = 
+        /// [1.0 4.0
+        ///  2.0 5.0 
+        ///  3.0 6.0 
+        /// 
+        ///  7.0 10.0
+        ///  8.0 11.0
+        ///  9.0 12.0]
+        /// 
+        /// A = ILMath.Reshape(A,3,2,2); 
+        /// A[10] gives 11.0
+        /// A[10,1] gives ILArgumentException -> out of range
+        /// A[2,1,1] gives 12.0
+        /// A[2,1] gives 6.0 (set trailing dimension to '0')</code></example>
+        /// <para>If the element addressed is a ILCell itself, a deep reference to this element will be returned instead. 
+        /// I.e. all elements of the ILCell will be recursively replaced with references to itself. Therefore, altering the 
+        /// elements returned will not alter the elements contained in the cell.</para>
+        /// <para>
+        /// <list type="bullet">
+        /// <listheader>The type of the element returned depends on the type of the element addressed:</listheader>
+        /// <item>For ILArray&lt;ElementType&gt; the array returned will be a clone of the original array.</item> 
+        /// <item>For ILCell the ILBaseArray returned is a deep reference of the original elements stored.</item>
+        /// <item>For other types the behavior is undefined. (since other types are not implemented yet ;)</item>
+        /// </list> </para>
+        /// <para>This indexer may also be used for direct access to inner elements of (elements of elements of ...) this cell:
+        /// <example>
+        /// <code>
+        /// ILCell innerCell = new ILCell(2,1); 
+        /// innerCell[0] = ILMath.vec(10,200); 
+        /// innerCell[1] = new int[] {-10,-20,-30};
+        /// ILCell cell = new ILCell(2,1); 
+        /// cell[0] = innerCell; 
+        /// cell[1] = new string[] {"foobla"}; 
+        /// // cell is now: 
+        /// // [ILCell,(1x2)] 
+        /// //      [innerCell[0], ILArray&lt;double&gt;(1x181)]
+        /// //      [innerCell[0], ILArray&lt;double&gt;(1x3)]
+        /// // [ILArray&lt;string&gt;,(1x1)]
+        /// 
+        /// cell[0,0] -&gt; will give innerCell eq. ILCell (1x2)
+        /// cell[0,1] -&gt; will give ILArray&lt;string&gt;
+        /// cell[0,0,0,1] -&gt; will give innerCell[1] eq. ILArray&lt;int&gt;(1x3)
+        /// </code>
+        /// </example> 
+        /// In the last example above the trailing indices specified make the indexer walk down into the ILCell element and retrieve 
+        /// the content of this element. This kind of index access may be done as deep as you want. Just 
+        /// append the inner indices into inner elements to the right side of index specification. Addressing inner elements 
+        /// this way is the only way to alter elements <b>directly</b> inside the ILCell. </para></remarks>
+        public ILRetCell this[params int[] indices] {
+            get {
+                ILStorage val = Storage.GetValueTyped(indices);
+                if (val is ILCellStorage)
+                    return new ILRetCell((ILCellStorage)val);
+                else
+                    return new ILRetCell(new ILStorage[] { val }, ILSize.Scalar1_1);
+            }
+            set {
+                using (ILScope.Enter(value)) {
+                    if (!object.Equals(value,null) && value.Storage.FromImplicitCast && value.IsScalar) {
+                        SetValue((value as ILDenseArray<ILStorage>).GetValue(0), indices);
+                    } else {
+                        SetValue((object.Equals(value,null)) ? null : value.Storage, indices);
+                    }
+                }
+            }
+        }
+
+        /// <summary>
+        /// Subarray access. Get/set regular subarray. 
+        /// </summary>
+        /// <param name="indices">Address range</param>
+        /// <returns>Reference cell array with subarray addressed by <c>indices</c>. </returns>
+        /// <remarks>Query access: for N-dimensional cell arrays missing trailing dimensions indices will be choosen to be 0. Therefore you 
+        /// may ommit those trailing dimensions in <c>indices</c>.
+        /// <para>The indexer may be used for querying or altering single/any elements 
+        /// in this cell. <c>indices</c> may contains index specifications for one to any 
+        /// dimension. The cell array returned will have the size specified by <c>indices</c>.</para>
+        /// <para>Values returned will be reference cells. All elements contained will be 'deep references' created by 
+        /// recursively walking downwards the elements and replacing them by references to itself. Therefore altering the 
+        /// values returned will not alter the original elements.</para>
+        /// <para>The indexer may also be used for removing parts of the cell. Therefore null must be assigned to the range specified by <c>indices</c> (using the set-access). <c>indices</c> 
+        /// must contain exactly one dimension specification other than 'full' in this case. This may be any vector-sized numeric ILArray of any 
+        /// numeric type. If <c>indices</c> apply to fewer dimensions than the number of dimensions existing, the upper dimensions will be 
+        /// merged and the array will be reshaped before applying the removal to it.
+        /// <example>
+        /// <code>
+        /// ILCell C = new ILCell(4,10); 
+        /// C[":",2] = null;  // &gt;- will remove the third column (index: 2) from the cell.
+        /// C[full,vec(2,5)] = null;  &gt;- will remove columns 3...6
+        /// C[1,1] = null; &gt;- will produce an error. Only one dimension can be specified not full! 
+        /// </code></example></para>
+        /// <para>The general behavior of this access methods is full compatible with the corresponding Matlab/Octave/Scilab access: a(:) = []. </para>
+        /// </remarks>
+        public ILRetCell this[params ILBaseArray[] indices] {
+            get {
+                using (ILScope.Enter(indices)) {
+                    ILCellStorage elements = (ILCellStorage)Storage.Subarray(indices);
+                    return new ILRetCell(elements);
+                }
+            }
+            set {
+                using (ILScope.Enter(indices))
+                using (ILScope.Enter(value)) {
+                    if (Object.ReferenceEquals(value, null)) {
+                        Storage.IndexSubrange(null, indices);
+                    } else {
+                        //if (value.Storage.FromImplicitCast && value.IsScalar) {
+                        //    Storage.IndexSubrange((ILDenseStorage<ILStorage>)value.GetValue(0), indices);
+                        //} else {
+                        Storage.IndexSubrange((ILCellStorage)value.Storage.Clone(), indices);
+                        //}
+                    }
+                }
+            }
+        }
+
+        #endregion index access
+
+        #region memory management
+        internal override bool EnterScope() {
+            return false;
+        }
+        #endregion
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILDenseArray.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILDenseArray.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILDenseArray.cs	(revision 9102)
@@ -0,0 +1,398 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using ILNumerics.Storage;
+using System.IO; 
+using ILNumerics.Exceptions;
+
+namespace ILNumerics {
+    [System.Diagnostics.DebuggerTypeProxy(typeof(ILNumerics.Misc.ILArrayDebuggerProxy<>))]
+    [System.Diagnostics.DebuggerDisplay("{ShortInfo(),nq}")]
+    [Serializable]
+    // ToDo: DOKU for ILDenseArray<ElementType> missing
+    public partial class ILDenseArray<ElementType> : ILBaseArray<ElementType> {
+
+        #region constructors
+        internal ILDenseArray(ILStorage storage, bool isTempArray)
+            : base(storage, isTempArray) {
+
+        }
+        #endregion
+
+        #region properties
+        /// <summary>
+        /// internal access to the underlying storage
+        /// </summary>
+        internal new ILDenseStorage<ElementType> Storage {
+            get { return (m_storage as ILDenseStorage<ElementType>); }
+            set {
+                // e.g. Storage.Detach() may return itself (if no detaching is 
+                // required). So we must check for that equalty here! 
+                if (!object.Equals(value, m_storage)) {
+                    m_storage.Dispose();
+                    m_storage = value;
+                }
+            }
+        }
+        /// <summary>
+        /// Clone of this array (fast, lazy and shallow)
+        /// </summary>
+        public virtual ILRetArray<ElementType> C {
+            get {
+                return new ILRetArray<ElementType>((ILDenseStorage<ElementType>)Storage.Clone());
+            }
+        }
+        /// <summary>
+        /// Return transposed version of this array
+        /// </summary>
+        /// <remarks>For matrices, this swaps columns with rows. For arrays, the dimensions are shifted by one.
+        /// <para>Note, for complex elements, <b>no</b> conjugate is created! Use conj(A.T) if this is intended.</para></remarks>
+        public ILRetArray<ElementType> T {
+            get {
+                // if this is updated to create a conjugate for complex data types 
+                // -> do not forget to update quick reference ILNumerics4Matlab also!
+                return new ILRetArray<ElementType>(Storage.ShiftDimensions(1));
+            }
+        }
+        /// <summary>
+        ///  [deprecated] Get maximum value of array - if any
+        /// </summary>
+        /// <remarks>This property is marked as deprecated and will be removed in a future version. Use one of the 
+        /// following alternatives instead: 
+        /// </remarks>
+        /// <seealso cref="ILNumerics.ILBaseArray&lt;ElementType>.GetLimits(out ElementType, out ElementType)"/>
+        [Obsolete()]
+        public ElementType MaxValue {
+            get {
+                ElementType ret, dummy;
+                GetLimits(out dummy, out ret);
+                return ret;
+            }
+        }
+        /// <summary>
+        ///  [deprecated] Get minimum value of array - if any
+        /// </summary>
+        /// <remarks>This property is marked as deprecated and will be removed in a future version. Use one of the 
+        /// following alternatives instead: 
+        /// <list type="bullets">
+        /// <item><seealso cref="ILNumerics.ILBaseArray{T}.GetLimits"/></item>
+        /// <item><seealso cref="ILNumerics.ILMath.minall"/></item>
+        /// </list></remarks>
+        [Obsolete()]
+        public ElementType MinValue {
+            get {
+                ElementType ret, dummy;
+                GetLimits(out ret, out dummy);
+                return ret;
+            }
+        }
+        #endregion
+
+        #region memory management
+        /// <summary>
+        /// Get number of arrays, referencing the same underlying data storage 
+        /// </summary>
+        /// <return>This number is always greater than or equal to 1.</return>
+        /// <remarks>For temporary arrays, calling this property does not - as usual - 
+        /// disposes the array</remarks>
+        public int ReferenceCount {
+            get {
+                return Storage.ReferenceCount;
+            }
+        }
+
+        #endregion
+
+        #region public function
+        /// <summary>
+        /// Clone of this array
+        /// </summary>
+        /// <remarks><para>
+        /// Clones of all arrays in ILNumerics are done in a very fast, lazy way. This means, 
+        /// at the time the clone is made, no relevant memory is copied. Elements of both arrays rather point to the same 
+        /// underlying System.Array. A reference counting mechanism ensures the detaching of thoses arrays 
+        /// on write access.</para>
+        /// <para>The clone returned will be of the same type as this instance.</para></remarks>
+        internal override ILBaseArray Clone() {
+            ILRetArray<ElementType> ret = new ILRetArray<ElementType>((ILDenseStorage<ElementType>)Storage.Clone());
+            return ret;
+        }
+        /// <summary>
+        /// Concatenate this array
+        /// </summary>
+        /// <param name="A">N-dimensional array. Except for dimensions <paramref name="dim"/>
+        /// the dimensions of A must match the dimensions of this storage</param>
+        /// <param name="dim">Index of dimension to concatenate arrays along.
+        /// If dim is larger than the number of dimensions of any of the arrays,
+        /// its value will be used in modulus the number of dimensions.</param>
+        /// <returns>New array having the size 
+        /// of both input arrays layed behind each other along the dim's-dimension</returns>
+        public ILRetArray<ElementType> Concat(ILInArray<ElementType> A, int dim) {
+            using (ILScope.Enter(A))
+                return new ILRetArray<ElementType>(Storage.Concat(A.Storage, dim));
+        }
+        /// <summary>
+        /// Copy values of all elements into System.Array.
+        /// </summary>
+        /// <param name="outArray">[Output] System.Array, holding all element values of this ILDenseStorage.</param>
+        /// <remarks>The System.Array may be predefined. If its length is sufficient, it will be used and 
+        /// its leading elements will be overwritten when function returns. If 'outArray' is null or has too few elements, 
+        /// it will be recreated from the ILNumerics memory pool.</remarks>
+        public void ExportValues(ref ElementType[] outArray) {
+            Storage.ExportValues(ref outArray);
+        }
+        /// <summary>
+        /// Get direct reference to inner System.Array storage for <b>read access</b> - use with care! 
+        /// </summary>
+        /// <returns>Reference to inner System.Array for reading</returns>
+        /// <remarks>This method is provided for experts only! Altering elements of this 
+        /// array may cause the data to be invalidated or corrupted! Use this array only for reading! Note 
+        /// the ILNumerics array storage format (column major). Keep in mind, the length 
+        /// of the array may exceeds the number of elements! 
+        /// <para>Accessing the inner system array directly should be left to ILNumerics experts only! 
+        /// Unless you really know, what you are doing, you should rather use the higher order access 
+        /// methods provided by ILArray&lt;T>!</para>
+        /// <para>Unlike (almost) all other member function of an array, this function
+        /// does not keep track of internal memory management. It means, the storage which this array is based 
+        /// upon, will not be set free after the function returns. You (as the user of the array) will have to pay 
+        /// attention yourself, when to call dispose on the array - if necessary. Also, for elements of reference
+        /// types (e.g. ILCell), retrieving and storing elements from/into the System.Array directly does 
+        /// not simulate a value semantic as all other functions do! This means, references are copied. Attention
+        /// must be paid to dereference / clone elements accordingly. </para></remarks>
+        public ElementType[] GetArrayForRead() {
+            return Storage.GetArrayForRead();
+        }
+        /// <summary>
+        /// Direct reference to inner System.Array storage for write access - use with care!
+        /// </summary>
+        /// <returns>Reference to inner System.Array</returns>
+        /// <remarks>Altering this array can be done directly. If necessary, the array is detached before 
+        /// returned. Watch the column order format of storages in ILNumerics. Keep in mind, the length 
+        /// of the System.Array may exceed the number of elements of the ILNumerics array.
+        /// <para>Accessing the inner system array directly should be left to ILNumerics experts only. 
+        /// Unless you really know, what you are doing, you should rather use the higher order access 
+        /// methods provided by ILArray&lt;T>!</para>
+        /// <para>Unlike (almost) all other member function of an array, this function
+        /// does not keep track of internal memory management. It means, the storage which this array is based 
+        /// upon, will not be set free after the function returns. You (as the user of the array) will have to pay 
+        /// attention yourself, when to call dispose on the array - if necessary. Also, for elements of reference
+        /// types (e.g. ILCell), retrieving and storing elements from/into the System.Array directly does 
+        /// not simulate a value semantic as all other functions do! This means, references are copied. Attention
+        /// must be paid to dereference / clone elements accordingly. </para></remarks>
+        public ElementType[] GetArrayForWrite() {
+            return Storage.GetArrayForWrite();
+        }
+        /// <summary>
+        /// Enumerator returning elements as ElementType
+        /// </summary>
+        /// <returns>Enumerator</returns>
+        /// <remarks>This method enables the use of ILNumerics arrays in foreach loops.
+        /// <para>The iterator is returned, if arrays are directly used in foreach statements. The iterator 
+        /// is compatible with ILNumerics memory management.</para></remarks>
+        /// <example><code>ILArray&lt;double&gt; A = rand(5,4,6);
+        /// foreach (double element in A) {
+        ///     // all elements are scalar double values
+        ///     String.Format("Element: {0} ", element);
+        ///     // Note: 'element' cannot be used to alter the collection! 
+        /// } </code>
+        /// </example> 
+        public override IEnumerator<ElementType> GetEnumerator() {
+            ElementType[] values = GetArrayForRead();
+            int len = Size.NumberOfElements;
+            for (int i = 0; i < len; i++)
+                yield return values[i];
+        }
+        /// <summary>
+        /// Gives away internal storage for further use (e.g. in ILArray), disposes this array
+        /// </summary>
+        /// <returns>Internal storage</returns>
+        internal ILDenseStorage<ElementType> GiveStorageAwayOrClone() {
+            if (m_scopeCounter <= 0) {
+                ILDenseStorage<ElementType> ret = Storage;
+                m_storage = null;
+                return ret;
+            } else {
+                return (ILDenseStorage<ElementType>)Storage.Clone(); 
+            }
+        }
+        /// <summary>
+        /// Create replication of this array
+        /// </summary>
+        /// <param name="dims">Dimensions specifier. If the number of elements in <paramref name="dims"/> is 
+        /// less than the number of dimensions in this array, the trailing dimensions will 
+        /// be set to 1 (singleton dimensions). On the other hand, if the number specified 
+        /// is larger then the number of dimension stored inside the storge the resulting 
+        /// storage will get its number of dimensions extended accordingly. </param>
+        /// <returns>Array being created by multiple replications of this array along 
+        /// arbitrary dimensions according to <paramref name="dims"/></returns>
+        internal ILRetArray<ElementType> Repmat(params int[] dims) {
+            return new ILRetArray<ElementType>(Storage.Repmat(dims));
+        }
+        /// <summary>
+        /// Reshaped copy of this array
+        /// </summary>
+        /// <param name="dimensions">New dimensions of the array</param>
+        /// <returns>Reshaped copy of the array</returns>
+        /// <remarks><para>The current instance will not be changed. A new storage is created, having 
+        /// the elements of this array and a shape as determined by <paramref name="dimensions"/>.</para>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the number of elements in <paramref name="dimensions"/>
+        /// do not match the number of elements in this array.</exception>
+        public ILRetArray<ElementType> Reshape(ILSize dimensions) {
+            using (ILScope.Enter()) {
+                ILArray<ElementType> ret = C;
+                ret.Storage.Reshape(dimensions);
+                return ret;
+            }
+        }
+        /// <summary>
+        /// Reshaped copy of this array
+        /// </summary>
+        /// <param name="dimensions">New dimensions of the array</param>
+        /// <returns>Reshaped copy of the array</returns>
+        /// <remarks><para>The current instance will not be changed. A new array is created, having 
+        /// the elements of this array and a shape as determined by <paramref name="dimensions"/>.</para>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the number of elements in 'newDimension'
+        /// do not match the number of elements in this array.</exception>
+        public ILRetArray<ElementType> Reshape(params int[] dimensions) {
+            return Reshape(new ILSize(dimensions));
+        }
+        /// <summary>
+        /// Subarray creation
+        /// </summary>
+        /// <param name="size">Range specification, defining the size of the subarray</param>
+        /// <returns>Subarray as copy of a part of this array</returns>
+        /// <remarks>Consult the ILNumerics subarray documentation for all subarray indexing rules.</remarks>
+        public ILRetArray<ElementType> Subarray(params ILBaseArray[] size) {
+            using (ILScope.Enter(size))
+                return new ILRetArray<ElementType>(Storage.Subarray(size));
+        }
+        /// <summary>
+        /// Create array from this array and shift dimensions
+        /// </summary>
+        /// <param name="shift">Number of dimensions to shift</param>
+        /// <returns>Shifted version of this array</returns>
+        /// <remarks><para>The shift is done 'to the left':</para>
+        /// <example><code>ILArray&lt;double> A = zeros(2,4); 
+        /// ILArray&lt;double> B = A.Shifted(1); 
+        /// // B is now: &lt;double> [4,2]
+        /// 
+        /// ILArray&lt;double> C = zeros(2,4,3);
+        /// ILArray&lt;double> D = C.Shifted(1);
+        /// // D is now: &lt;double> [4,3,2]
+        /// </code></example>
+        /// <para>The dimensions are shifted circulary to the left. This 
+        /// can be imagined as removing the first dimensions from the beginning of the list of 
+        /// dimensions and "append" them to the end in a ringbuffer style.</para>
+        /// <para>For dimension shifts of '1', you may consider using the 
+        /// <see cref="ILNumerics.ILDenseArray{ElementType}.T"/> property for readability.</para>
+        /// <para><paramref name="shift"/> must be positive. It is taken modulus the number of dimensions.</para>
+        /// <seealso cref="ILNumerics.ILDenseArray{ElementType}.T"/></remarks>
+        public ILRetArray<ElementType> Shifted(int shift) {
+            return new ILRetArray<ElementType>(Storage.ShiftDimensions(shift));
+        }
+        /// <summary>
+        /// Send values of this instance to stream. 
+        /// </summary>
+        /// <param name="stream">Stream to write the values into.</param>
+        /// <param name="format">Format string to be used for output. See <see cref="System.String.Format(string,object)"/> for a specification
+        /// of valid formating expressions. This flag is only used, when 'method' is set to 'Serial'.</param>
+        /// <param name="method">A constant out of <see cref="ILArrayStreamSerializationFlags"/>. Specifies the way in which
+        /// the values will be serialized.</param>
+        /// <remarks><para>If the 'Formatted' method is used, any occurences of the NewLine character(s) 
+        /// will be replaced from the format string before applying to the elements. This is done to 
+        /// prevent the format from breaking the 'page' style of the output.</para>
+        /// <para>If 'method' is set to 'Matlab', the array will be written as Matfile version 5.0. No compression will be used. The internal 'Name' property will be used as the
+        /// array name for writing. This array instance will be the only array in the .mat file. If you want to write several arrays bundled into one mat file, use the MatFile class to
+        /// create a collection of arrays and write the MatFile to stream.</para></remarks>
+        public override void ToStream(Stream stream, string format, ILArrayStreamSerializationFlags method) {
+            try {
+                int len;
+                switch (method) {
+                    case ILArrayStreamSerializationFlags.Serial:
+                        len = Size.NumberOfElements;
+                        using (TextWriter tw = new StreamWriter(stream)) {
+                            for (int i = 0; i < len; i++) {
+                                tw.Write(format, GetValue(i));
+                            }
+                        }
+                        break;
+                    case ILArrayStreamSerializationFlags.Formatted:
+                        format = format.Replace(Environment.NewLine, "");
+                        ILDenseStorage<ElementType> temp = this.Storage.ShiftDimensions(1);
+                        //len = Dimensions.NumberOfElements / Dimensions[1]; 
+                        using (TextWriter tw = new StreamWriter(stream)) {
+                            tw.Write(temp.ValuesToString(0));
+                        }
+                        break;
+                    case ILArrayStreamSerializationFlags.Matlab:
+                        ILMatFile mf = new ILMatFile(new ILBaseArray[1] { this });
+                        mf.Write(stream);
+                        break;
+                }
+            } catch (Exception e) {
+                throw new ILException("ToStream: Could not serialize to stream.", e);
+            }
+        }
+        /// <summary>
+        /// Give that storage away for in-place operations, if possible (depends on scope and temp type of array)
+        /// </summary>
+        /// <returns>true if the storage of the array is about to get disposed anyway</returns>
+        /// <remarks>The function investigates the state of the array. If this is a temporary array in 
+        /// the outer most scope, it would get disposed after the </remarks>
+        internal bool TryGetStorage4InplaceOp(out ElementType[] array) {
+            // check if this array is yet to be available 
+            if (!Settings.AllowInArrayAssignments && m_isTempArray && m_scopeCounter <= 1) {
+                // it's efficient only if we dont have to make a copy of the underlying array
+                if (Storage.ReferenceCount == 1) {
+                    ILDenseStorage<ElementType> storage = Storage;
+                    m_storage = null;
+                    array = storage.GetArrayForWrite();
+                    return true;
+                }
+            }
+            array = null;
+            return false;
+        }
+        #endregion
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILFullRange.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILFullRange.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILFullRange.cs	(revision 9102)
@@ -0,0 +1,56 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using ILNumerics.Storage; 
+
+namespace ILNumerics.Misc {
+
+    internal sealed class ILFullRange  {
+
+        internal ILFullRange() { }
+
+        public override string ToString() {
+            return String.Empty; 
+        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILInArray.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILInArray.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILInArray.cs	(revision 9102)
@@ -0,0 +1,317 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.IO; 
+using System.Runtime.Serialization; 
+using System.Runtime.CompilerServices;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions;
+
+namespace ILNumerics {
+    /// <summary>
+    /// Rectangular array, used as input parameter only 
+    /// </summary>
+    /// <typeparam name="ElementType">Inner type. This will mostly be a system numeric type or a 
+    /// complex floating point type.</typeparam>
+    /// <remarks><para>This class extends the primary <c>ILArray</c> by optimizing its behavior for the case when used as an
+    /// input parameter to functions.</para><para>When writing your own function all <i>input</i> parameters should be of type <c>ILInArray</c>. 
+    /// Similary, all return types should be of type <see cref="ILNumerics.ILRetArray{T}"/> and all "out" parameters of type <see cref="ILNumerics.ILOutArray{T}"/>.</para>
+    /// <para>Other than being used to transfer arguments into functions, <c>ILInArray</c> should not be used.</para>
+    /// </remarks>
+    /// <seealso cref="ILNumerics.ILArray{T}"/>
+    /// <seealso cref="ILNumerics.ILRetArray{T}"/>
+    /// <seealso cref="ILNumerics.ILOutArray{T}"/>
+    [Serializable]
+    public sealed partial class ILInArray<ElementType> : ILDenseArray<ElementType> {
+
+        private static readonly bool s_isTempArray = true; 
+
+        #region constructors
+        /// <summary>
+        /// create new ILInArray, specify (dense) storage
+        /// </summary>
+        /// <param name="storage"></param>
+        internal ILInArray(ILDenseStorage<ElementType> storage)
+            : base(storage, s_isTempArray) {
+        }
+        /// <summary>
+        /// create new ILInArray, specify dimensions
+        /// </summary>
+        /// <param name="dimensions"></param>
+        internal ILInArray(ILSize dimensions) 
+            : base(new ILDenseStorage<ElementType>(dimensions), s_isTempArray) {
+        }
+        /// <summary>
+        /// create new ILInArray from System.Array
+        /// </summary>
+        /// <param name="elements">System.Array</param>
+        /// <param name="dimensions">dimension specifier</param>
+        internal ILInArray(ElementType[] elements, ILSize dimensions) :
+            base(new ILDenseStorage<ElementType>(elements, dimensions), s_isTempArray) {
+        }
+        /// <summary>
+        /// create new ILInArray from System.Array
+        /// </summary>
+        /// <param name="elements">System.Array</param>
+        /// <param name="dimensions">dimension specifier</param>
+        internal ILInArray(ElementType[] elements, params int[] dimensions) :
+            base(new ILDenseStorage<ElementType>(elements, new ILSize(dimensions)), s_isTempArray) {
+        }
+        /// <summary>
+        /// create new ILInArray from System.Array
+        /// </summary>
+        /// <param name="elements">variable length System.Array</param>
+        internal ILInArray(params ElementType[] elements) :
+            base(new ILDenseStorage<ElementType>(elements, new ILSize(1, elements.Length)), s_isTempArray) {
+        }
+
+        #endregion
+
+        #region implicit cast operators
+        #region constructional operators
+        /// <summary>
+        /// Implicitly convert scalar to array of size 1x1 (scalar).
+        /// </summary>
+        /// <param name="val">System type of size scalar</param>
+        /// <returns>New ILInArray of type ILInArray <![CDATA[<typeof(val)>]]> of size 1x1 
+        /// holding the only element with value of val.
+        /// </returns>
+        public static implicit operator ILInArray<ElementType> (ElementType val) {
+            ILInArray<ElementType> ret = new ILInArray<ElementType>(
+                        new ILDenseStorage<ElementType>(
+                            new ElementType[1] {val}, 
+                            new ILSize(1,1)));
+            return ret; 
+        }
+        /// <summary>
+        /// Implicitly cast one dimensional System.Array to ILNumerics array (vector)
+        /// </summary>
+        /// <param name="A">1-dimensional system array, arbitrary type</param>
+        /// <returns>ILNumerics array of same element type as elements of A. 
+        /// Row vector. If A is null: empty array.</returns>
+        /// <remarks>The System.Array A will directly be used for the new ILNumerics array! 
+        /// No copy will be done! Make sure, not to reference A after this conversion!</remarks>
+        public static implicit operator ILInArray<ElementType> (ElementType[] A) {
+            if (A == null) {
+                return null; 
+                //ILDenseStorage<ElementType> dS = new ILDenseStorage<ElementType>(new ElementType[0], ILSize.Empty00); 
+                //return new ILInArray<ElementType>(dS);                          
+            }
+            ILArray<ElementType> ret; 
+            if (Settings.CreateRowVectorsByDefault)
+                ret = new ILInArray<ElementType>(A, 1, A.Length);
+            else 
+                ret = new ILInArray<ElementType>(A, A.Length, 1); 
+            if (Settings.AllowInArrayAssignments)
+                ILScope.Context.RegisterArray(ret);
+            return ret; 
+        }
+        /// <summary>
+        /// Implicitly convert n-dimensional System.Array to ILNumerics array
+        /// </summary>
+        /// <param name="A">Arbitrarily sized System.Array</param>
+        /// <returns>If A is null: empty array. Else: new ILNumerics array of the same size as A</returns>
+        /// <remarks>The inner type of input array <paramref name="A"/> must match the requested type
+        /// <typeparamref name="ElementType"/>. The resulting ILInArray will reflect all dimensions of 
+        /// A. Elements of A will get copied to elements of output array (shallow copy).</remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILCastException"> if type of input does not match 
+        /// ElementType</exception>
+        public static implicit operator ILInArray<ElementType> (Array A) {
+            if (A == null) {
+                return null;
+            }
+            if (A.Length == 0) {
+                return new ILInArray<ElementType>(ILSize.Empty00);
+            }
+            if (A.GetType().GetElementType() != typeof(ElementType)) 
+                throw new ILCastException("inner type of System.Array must match");
+            int[] dims = new int[A.Rank];
+            ElementType[] retArr = ILMemoryPool.Pool.New<ElementType>(A.Length);
+            int posArr = 0; 
+            for (int i = 0; i < dims.Length; i++) {
+                dims[i] = A.GetLength(dims.Length - i - 1);
+            }
+            if (dims.Length == 1 && Settings.CreateRowVectorsByDefault) {
+                dims = new int[2] { 1, dims[0] };
+            }
+            foreach (ElementType item in A) 
+                retArr[posArr++] = item; 
+            ILInArray<ElementType> ret = new ILInArray<ElementType>(retArr,dims);
+            if (Settings.AllowInArrayAssignments)
+                ILScope.Context.RegisterArray(ret);
+            return ret; 
+        }
+        /// <summary>
+        /// Implicitly cast two dimensional System.Array to ILNumerics array
+        /// </summary>
+        /// <param name="A">2-dimensional System.Array</param>
+        /// <returns>If A is null: empty array. ILNumerics array of same size and type as A otherwise.</returns>
+        public static implicit operator ILInArray<ElementType>(ElementType[,] A) {
+            if (A == null) {
+                return null;
+            }
+            if (A.Length == 0) {
+                return new ILInArray<ElementType>(ILSize.Empty00);
+            }
+            int[] dims = new int[2];
+            ElementType[] retArr = ILMemoryPool.Pool.New<ElementType>(A.Length);
+            int posArr = 0;
+            for (int i = 0; i < 2; i++) {
+                dims[i] = A.GetLength(dims.Length - i - 1);
+            }
+            foreach (ElementType item in A)
+                retArr[posArr++] = item;
+            ILInArray<ElementType> ret = new ILInArray<ElementType>(retArr, dims);
+            if (Settings.AllowInArrayAssignments)
+                ILScope.Context.RegisterArray(ret);
+            return ret; 
+        }
+        /// <summary>
+        /// Implicitly casts three dimensional System.Array to ILNumerics array
+        /// </summary>
+        /// <param name="A">3-dimensional System.Array</param>
+        /// <returns>If A is null: empty array. ILNumerics array of same size and type as A otherwise.</returns>
+        public static implicit operator ILInArray<ElementType>(ElementType[,,] A) {
+            if (A == null) {
+                return null;
+            }
+            if (A.Length == 0) {
+                return new ILInArray<ElementType>(ILSize.Empty00);
+            }
+            int[] dims = new int[3];
+            ElementType[] retArr = ILMemoryPool.Pool.New<ElementType>(A.Length);
+            int posArr = 0;
+            for (int i = 0; i < 3; i++) {
+                dims[i] = A.GetLength(dims.Length - i - 1);
+            }
+            foreach (ElementType item in A)
+                retArr[posArr++] = item;
+            ILInArray<ElementType> ret = new ILInArray<ElementType>(retArr, dims);
+            if (Settings.AllowInArrayAssignments)
+                ILScope.Context.RegisterArray(ret);
+            return ret; 
+        }
+        /// <summary>
+        /// Implicitly cast ILInArray to ILRetCell
+        /// </summary>
+        /// <param name="array">Input array</param>
+        /// <returns>1x1 cell holding the array</returns>
+        public static implicit operator ILRetCell(ILInArray<ElementType> array) {
+            using (ILScope.Enter(array)) {
+                ILRetCell ret = new ILRetCell(ILSize.Scalar1_1, array.Storage);
+                ret.Storage.FromImplicitCast = true;
+                return ret;
+            }
+        }
+        #endregion
+
+        #region conversional operators 
+        /// <summary>
+        /// Convert temporary to input parameter array
+        /// </summary>
+        /// <param name="array">Temp array</param>
+        /// <returns>Input parameter array, will survive the current scope only</returns>
+        public static implicit operator ILInArray<ElementType>(ILRetArray<ElementType> array) {
+            if (object.Equals(array, null)) 
+                return null;
+            ILInArray<ElementType> ret = new ILInArray<ElementType>(array.GiveStorageAwayOrClone());
+            if (Settings.AllowInArrayAssignments)
+                ILScope.Context.RegisterArray(ret);
+            return ret; 
+        }
+        /// <summary>
+        /// Convert persistent to input parameter array
+        /// </summary>
+        /// <param name="array">Persistent array</param>
+        /// <returns>Input parameter array, will survive the current scope only</returns>
+        public static implicit operator ILInArray<ElementType>(ILArray<ElementType> array) {
+            if (object.Equals(array, null))
+                return null;
+            ILInArray<ElementType> ret = new ILInArray<ElementType>(new ILDenseStorage<ElementType>(
+                array.Storage.GetDataArray(), array.Size));
+            if (Settings.AllowInArrayAssignments)
+                ILScope.Context.RegisterArray(ret);
+            return ret; 
+
+        }
+        /// <summary>
+        /// Convert output paramter array to input parameter array
+        /// </summary>
+        /// <param name="array">Output parameter array</param>
+        /// <returns>Input parameter array, will survive the current scope only</returns>
+        public static implicit operator ILInArray<ElementType>(ILOutArray<ElementType> array) {
+            if (object.Equals(array, null))
+                return null;
+            ILInArray<ElementType> ret = new ILInArray<ElementType>(new ILDenseStorage<ElementType>(
+                array.Storage.GetDataArray(), array.Size));
+            if (Settings.AllowInArrayAssignments)
+                ILScope.Context.RegisterArray(ret);
+            return ret;
+        }
+        #endregion
+        #endregion
+
+        #region indexer + memory management
+        /// <summary>
+        /// Subarray creation/ manipulation/ deletion
+        /// </summary>
+        /// <param name="range">Range specification, defining the size of the subarray</param>
+        /// <returns>Subarray as copy of this array</returns>
+        public ILRetArray<ElementType> this[params ILBaseArray[] range] {
+            get {
+                using (ILScope.Enter(this))
+                using (ILScope.Enter(range))
+                    return new ILRetArray<ElementType>(Storage.Subarray(range));
+            }
+        }
+
+        internal override void LeaveScope() {
+            m_scopeCounter--;
+            if (m_scopeCounter <= 0) {
+                Dispose();
+            }
+        }
+
+        #endregion
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILInCell.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILInCell.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILInCell.cs	(revision 9102)
@@ -0,0 +1,221 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Text; 
+using ILNumerics.Storage; 
+using ILNumerics.Exceptions;
+using System.Collections.Generic; 
+
+namespace ILNumerics {
+    /// <summary>
+    /// ILCell : container class holding arbitrary array objects 
+    /// </summary>
+    /// <remarks>
+    /// ILCell acts as general purpose container. It stores arbitrary arrays of arbitrary element type. 
+    /// </remarks>
+    public sealed class ILInCell : ILBaseCell {
+
+        private static readonly bool s_isTempArray = true; 
+
+        #region constructors
+        /// <summary>
+        /// Create cell object with pre-created data in specified dimensions 
+        /// </summary>
+        /// <param name="data">Predefined element data array, will be used for new cell (no copy will be made)</param>
+        /// <param name="size">Size of the new cell</param>
+        /// <remarks>Object array data will directly be used for storage. No 
+        /// copy will be made. However, any arrays referenced by data are dereferenced for storage inside the cell. The size must match prod(size)</remarks>
+        [Obsolete("use <see cref='ILNumerics.ILMath.cell'/> instead!")]
+        internal ILInCell(ILStorage[] data, params int[] size)
+            : base(new ILCellStorage(data, new ILSize(size)), s_isTempArray) {
+        }
+        /// <summary>
+        /// Create cell object with pre-created data in specified dimensions 
+        /// </summary>
+        /// <param name="data">predefined element data array, will be used for new cell (no copy will be made)</param>
+        /// <param name="size">size of the new cell</param>
+        /// <remarks>object array data will directly be used for storage. No 
+        /// copy will be made. However, any arrays referenced by data are dereferenced for storage inside the cell. The size must match prod(size)</remarks>
+        [Obsolete("use <see cref='ILNumerics.ILMath.cell'/> instead!")]
+        internal ILInCell(ILStorage[] data, ILSize size)
+            : base(new ILCellStorage(data, size), s_isTempArray) {
+        }
+        /// <summary>
+        /// create new cell object, elements will be 'null' 
+        /// </summary>
+        /// <param name="size">dimension sizes of the new cell</param>
+        [Obsolete("use <see cref='ILNumerics.ILMath.cell'/> instead!")]
+        internal ILInCell(params int[] size)
+            : base(new ILCellStorage(new ILStorage[prod(size)], new ILSize(size)), s_isTempArray) { }
+
+        internal ILInCell(ILCellStorage cellStorage)
+            : base(cellStorage, s_isTempArray) { }
+
+        [Obsolete("use <see cref='ILNumerics.ILMath.cell'/> instead!")]
+        internal ILInCell(ILSize size, params ILStorage[] values)
+            : base(new ILCellStorage(values, size), s_isTempArray) { }
+
+        #endregion constructors
+
+        #region implicit casts (for subarray definitions)
+        #region constructional operators
+        //public static implicit operator ILCell(double value) {
+        //    return createScalar(value); 
+        //}
+        //public static implicit operator ILCell(float value) {
+        //    return createScalar(value); 
+        //}
+        //public static implicit operator ILCell(byte value) {
+        //    return createScalar(value); 
+        //}
+        //public static implicit operator ILCell(int[] value) {
+        //    return createArray(value); 
+        //}
+        #endregion
+
+        #region conversional operators
+        /// <summary>
+        /// Convert temporary cell to input parameter type cell
+        /// </summary>
+        /// <param name="cell">Temporary cell</param>
+        /// <returns>Input parameter type cell</returns>
+        public static implicit operator ILInCell(ILRetCell cell) {
+            if (object.Equals(cell, null))
+                return null;
+            ILInCell ret = new ILInCell((ILCellStorage)cell.GiveStorageAwayOrClone());
+            if (Settings.AllowInArrayAssignments)
+                ILScope.Context.RegisterArray(ret);
+            return ret;
+        }
+        /// <summary>
+        /// Convert temporary cell to input parameter type cell
+        /// </summary>
+        /// <param name="cell">ILCell</param>
+        /// <returns>Input parameter type cell</returns>
+        public static implicit operator ILInCell(ILCell cell) {
+            if (object.Equals(cell, null))
+                return null;
+            ILInCell ret = new ILInCell(new ILCellStorage(
+                cell.Storage.GetDataArray(), cell.Size));
+            if (Settings.AllowInArrayAssignments)
+                ILScope.Context.RegisterArray(ret);
+            return ret;
+        }
+        /// <summary>
+        /// Convert output parameter type cell to input parameter type cell
+        /// </summary>
+        /// <param name="cell">Output parameter type cell</param>
+        /// <returns>Input parameter type cell</returns>
+        public static implicit operator ILInCell(ILOutCell cell) {
+            if (object.Equals(cell, null))
+                return null;
+            ILInCell ret = new ILInCell(new ILCellStorage(
+                cell.Storage.GetDataArray(), cell.Size));
+            if (Settings.AllowInArrayAssignments)
+                ILScope.Context.RegisterArray(ret);
+            return ret;
+        }
+        #endregion
+        #endregion
+
+        #region helper functions
+        internal static long prod(int[] sizes) {
+            int ret = 1;
+            for (int i = 0; i < sizes.Length; i++)
+                ret *= sizes[i];
+            return ret;
+        }
+        #endregion helper functions
+
+        #region Index access
+        /// <summary>
+        /// Return single element in a scalar cell 
+        /// </summary> 
+        /// <paramref name="indices" value="Index to element"/>
+        /// <remarks>
+        /// <para>The indexer retrieves a single element from within the cell. It returns the single element 
+        /// in a new (scalar) cell. Use dereferencing functions like GetArray&lt;T>() in order to retrieve 
+        /// the element value (ie. the array addressed) without a cell container.</para>
+        /// <para>Input parameter type cells are immutable! They are not intended to be altered! Therefore, 
+        /// write access on such cells is disabled. In order to alter content of a cell, assign the cell to a regular
+        /// persistent cell of type <see cref="T:ILNumerics.ILCell"/>.</para></remarks>
+        public ILRetCell this[params int[] indices] {
+            get {
+                ILStorage val = Storage.GetValueTyped(indices);
+                if (val is ILCellStorage)
+                    return new ILRetCell((ILCellStorage)val);
+                else
+                    return new ILRetCell(new ILStorage[] { val }, ILSize.Scalar1_1);
+            }
+        }
+
+        /// <summary>
+        /// Subarray access. Get regular subarray. 
+        /// </summary>
+        /// <param name="indices">Address range</param>
+        /// <returns>Cell array with subcell range from this instance, addressed by <c>indices</c> </returns>
+        /// <remarks>
+        /// <para>The indexer is used to query subcell ranges. All general indexing/ subarray addressing rules apply.
+        /// The elements addressed are returned within a new temporary cell instance.</para>
+        /// <para>Input parameter type cells are immutable! They are not intended to be altered! Therefore, 
+        /// write access on such cells is disabled. In order to alter content of a cell, assign the cell to a regular
+        /// persistent cell of type <see cref="T:ILNumerics.ILCell"/>.</para></remarks>
+        public ILRetCell this[params ILBaseArray[] indices] {
+            get {
+                using (ILScope.Enter(indices)) {
+                    ILCellStorage elements = (ILCellStorage)Storage.Subarray(indices);
+                    return new ILRetCell(elements);
+                }
+            }
+        }
+
+        #endregion index access
+
+        #region memory management
+        internal override void LeaveScope() {
+            m_scopeCounter--;
+            if (m_scopeCounter <= 0) {
+                Dispose();
+            }
+        }
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILInLogical.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILInLogical.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILInLogical.cs	(revision 9102)
@@ -0,0 +1,405 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using ILNumerics;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions; 
+using ILNumerics.Storage;
+using ILNumerics.Native;
+using System.Text; 
+
+namespace ILNumerics {
+    /// <summary>
+    /// Boolean array for high performance relational operations on arbitrary arrays 
+    /// </summary>
+    /// <remarks>
+    /// Logical arrays are derived from <![CDATA[ILArray<byte>]]>. It consumes
+    /// 1 byte per element and is the output parameter of all relational comparisons
+    /// as well as the input parameter for all functions consuming <![CDATA[ILArray<byte>]]>.
+    /// The difference between <![CDATA[ILArray<byte>]]> and logical arrays is, the logical array 
+    /// storing a integer value with the number of nonzero elements as additional information. 
+    /// Therefore functions like 'find' are able to determine the lenght of output array to 
+    /// be created omitting the need of multiple walks through the array. Therefore ILLogicalArrays 
+    /// consume (a little) more time while construction but are much more performand on functions like 
+    /// 'find'.
+    /// </remarks>
+    [Serializable]
+    public sealed class ILInLogical : ILBaseLogical {
+
+        private static readonly bool s_isTempArray = true;
+
+        #region constructors
+        /// <summary>
+        ///	constructor - create logical array of specified size
+        /// </summary>
+        /// <param name="size">
+        /// Variable length int array specifying the number and size of dimensions to 
+        /// be created.
+        /// </param>
+        /// <remarks>
+        /// The size parameter may not be null or an empty array! An exception will be 
+        /// thrown in this case. The dimensions will be trimmed before processing 
+        /// (removing trailing non singleton dimensions). 
+        /// </remarks>
+        internal ILInLogical(params int[] size)
+            : base(new ILLogicalStorage(new ILSize(size)), s_isTempArray) {
+            NumberNonZero = sumElements();
+        }
+        /// <summary>
+        ///	constructor - create logical array of specified size
+        /// </summary>
+        /// <param name="size">
+        /// dimension object
+        /// </param>
+        /// <remarks>
+        /// The size parameter may not be null. An exception will be 
+        /// thrown in this case. The dimensions will be trimmed before processing 
+        /// (removing trailing singleton dimensions). 
+        /// </remarks>
+        internal ILInLogical(ILSize size)
+            : base(new ILLogicalStorage(size), s_isTempArray) {
+            NumberNonZero = sumElements();
+        }
+        /// <summary>
+        /// Constructor creating logical array from dense storage
+        /// </summary>
+        /// <param name="A">input array, the storage of this ILArray will directly be used for 
+        /// storage of the new logical array</param>
+        internal ILInLogical(ILLogicalStorage A)
+            : base(A, s_isTempArray) {
+            NumberNonZero = sumElements();
+        }
+        /// <summary>
+        /// Constructor creating logical array from (dense) storage
+        /// </summary>
+        /// <param name="A">input array storage, the storage will directly be used for 
+        /// storage of the new logical array</param>
+        /// <param name="numberNonZero">number of nonzero elements in A. Must be positive or 0.</param>
+        /// <remarks> Providing this parameter prevents the constructor from having to count the 
+        /// 'true' elements in A.</remarks>
+        internal ILInLogical(ILLogicalStorage A, long numberNonZero)
+            : base(A, s_isTempArray) {
+            if (numberNonZero < 0)
+                throw new ILNumerics.Exceptions.ILArgumentException("invalid number of non-zero-elements given!");
+            NumberNonZero = numberNonZero;
+        }
+        /// <summary>
+        ///	constructor - create logical array of specified size 
+        /// from data array
+        /// </summary>
+        /// <param name="size">
+        /// Variable length int array specifying the number and size of dimensions to 
+        /// be created.
+        /// </param>
+        /// <param name="data"> byte array matching the size of the dimensions 
+        /// specified. The data will directly be used as storage! No copy will be made!</param>
+        /// <remarks>
+        /// The size parameter may not be null or an empty array! An Exception will be 
+        /// thrown in this case. The dimensions will be trimmed before processing 
+        /// (removing trailing non singleton dimensions). 
+        /// </remarks>
+        internal ILInLogical(byte[] data, params int[] size)
+            : base(new ILLogicalStorage(data, new ILSize(size)), s_isTempArray) {
+            NumberNonZero = sumElements();
+        }
+        /// <summary>
+        /// Constructor creating logical array, provide predefined storage
+        /// </summary>
+        /// <param name="data">predefined storage elements. The array will directly be used 
+        /// as underlying storage. No copy will be made! </param>
+        /// <param name="dimension">Dimensions specification.</param>
+        internal ILInLogical(byte[] data, ILSize dimension)
+            : base(new ILLogicalStorage(data, dimension), s_isTempArray) {
+           NumberNonZero = sumElements();
+        }
+        /// <summary>
+        /// Constructor creating logical array, predefined storage (fast version)
+        /// </summary>
+        /// <param name="data">predefined storage elements. The array will directly be used 
+        /// as underlying storage. No copy will be made! </param>
+        /// <param name="dimension">Dimensions specification.</param>
+        /// <param name="nonZeroCount">number of nonzero elements in <paramref name="data"/>. 
+        /// Providing this parameter prevents from counting the 'true' elements (again). </param>
+        internal ILInLogical(byte[] data, ILSize dimension, long nonZeroCount)
+            : base(new ILLogicalStorage(data, dimension), s_isTempArray) {
+            if (nonZeroCount < 0)
+                throw new ILNumerics.Exceptions.ILArgumentException("invalid number of non-zero-elements given!");
+            NumberNonZero = nonZeroCount;
+        }
+        #endregion
+
+        #region operator overloading
+
+        #region operational operators
+        /// <summary>
+        /// Invert values of array elements 
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns>New logical array, having the element values of A inverted</returns>
+        public static ILRetLogical operator !(ILInLogical A) {
+            if (object.Equals(A, null))
+                throw new ILArgumentException("operator !: array must not be null");
+            return (A != (byte)1);
+        }
+        #endregion
+
+        #region conversional operators 
+        public static implicit operator ILInLogical(ILArray<byte> a) {
+            if (object.Equals(a, null))
+                return null;
+            ILInLogical ret = new ILInLogical(new ILLogicalStorage(
+                a.Storage.GetDataArray(), a.Size));
+            if (Settings.AllowInArrayAssignments)
+                ILScope.Context.RegisterArray(ret);
+            return ret; 
+        }
+        public static implicit operator ILInLogical(ILInArray<byte> a) {
+            if (object.Equals(a, null))
+                return null;
+            ILInLogical ret = new ILInLogical(new ILLogicalStorage(
+                a.Storage.GetDataArray(), a.Size));
+            if (Settings.AllowInArrayAssignments)
+                ILScope.Context.RegisterArray(ret);
+            return ret; 
+        }
+        public static implicit operator ILArray<byte>(ILInLogical a) {
+            if (object.Equals(a, null))
+                return null;
+            ILArray<byte> ret = new ILArray<byte>(
+                new ILDenseStorage<byte>(a.Storage.GetDataArray(), a.Size));
+            ILScope.Context.RegisterArray(ret);
+            return ret;
+        }
+        public static implicit operator ILInArray<byte>(ILInLogical a) {
+            if (object.Equals(a, null))
+                return null;
+            ILInArray<byte> ret = new ILInArray<byte>(
+                new ILDenseStorage<byte>(a.Storage.GetDataArray(), a.Size));
+            if (Settings.AllowInArrayAssignments)
+                ILScope.Context.RegisterArray(ret);
+            return ret;
+        }
+        public static implicit operator ILInLogical(ILRetLogical a) {
+            if (object.Equals(a,null))
+                return null;
+            ILLogicalStorage storage = (ILLogicalStorage)a.GiveStorageAwayOrClone();
+            ILInLogical ret = new ILInLogical(storage, storage.NumberNonZero);
+            if (Settings.AllowInArrayAssignments)
+                ILScope.Context.RegisterArray(ret);
+            return ret;
+        }
+        public static implicit operator ILInLogical(ILLogical a) {
+            if (object.Equals(a, null))
+                return null;
+            ILInLogical ret = new ILInLogical(new ILLogicalStorage(a.Storage.GetDataArray(), a.Size));
+            if (Settings.AllowInArrayAssignments)
+                ILScope.Context.RegisterArray(ret);
+            return ret;
+        }
+        #endregion
+
+        #region constructional operators 
+        /// <summary>
+        /// Implicitly convert logical array to bool
+        /// </summary>
+        /// <param name="A">logical array</param>
+        /// <returns>true if <b>all</b> elements of A are non-zero, false otherwise 
+        /// </returns>
+        /// <remarks>If A is null or empty, the function returns false. Otherwise allall returns true, 
+        /// if all elements of A are non-zero and returns false, if A contains any zero elements.</remarks>
+        public static implicit operator bool(ILInLogical A) {
+            // this operator is implicit for convenience reasons: 
+            // if(tmp[0]!=-10.0) { ... is only possible this way
+            if (object.Equals(A, null) || A.IsEmpty)
+                return false;
+            if (A.IsScalar)
+                return A.GetValue(0, 0) == 1;
+            if (Settings.LogicalArrayToBoolConversion == LogicalConversionMode.ImplicitAllAll) {
+                if (A.Size.NumberOfElements > 0) {
+                    return ILMath.allall(A).GetValue(0) == 1;
+                } else {
+                    return false; 
+                }
+            } else { // if (Settings.LogicalArrayToBoolConversion == LogicalConversionMode.NonScalarThrowsException) {
+                if (!A.IsScalar) {
+                    throw new ILArgumentException("error while attempting to convert logical of size " + A.Size.ToString() + " to boolean");
+                } else {
+                    return A.GetValue(0) == 1; 
+                }
+            }
+        }
+
+        /// <summary>
+        /// Implicitly convert scalar byte to logical array of size 1x1 (scalar).
+        /// </summary>
+        /// <param name="val">Byte scalar</param>
+        /// <returns>New logical array of size 1x1 holding the only element of type <c>byte</c>
+        /// with value of val.</returns>
+        public static implicit operator ILInLogical(bool val) {
+            ILInLogical ret = new ILInLogical(new byte[1] { val ? (byte)1 : (byte)0 }, 1, 1);
+            return ret;
+        }
+
+        /// <summary>
+        /// Implicitly convert integer scalar to logical array of size 1x1 (scalar).
+        /// </summary>
+        /// <param name="val">Scalar value</param>
+        /// <returns>New logical array of size 1x1 holding the only element of type Byte 
+        /// with value of val.</returns>
+        public static implicit operator ILInLogical(int val) {
+            ILInLogical ret = new ILInLogical(new Byte[1] { 
+                                 val != 0 ? (byte)1:(byte)0 }, 1, 1);
+            return ret;
+        }
+        /// <summary>
+        /// implicitly cast one dimensional System.Array to ILNumerics array (vector)
+        /// </summary>
+        /// <param name="A">1 dimensional system array, arbitrary type</param>
+        /// <returns>ILNumerics array of same element type as elements of A. 
+        /// Row vector. If A is null: empty array.</returns>
+        /// <remarks>The System.Array A will directly be used for the new ILNumerics array! 
+        /// No copy will be done! Make sure, not to reference A after this conversion!</remarks>
+        public static implicit operator ILInLogical(byte[] A) {
+            if (A == null) {
+                ILLogicalStorage dS = new ILLogicalStorage(new byte[0], ILSize.Empty00);
+                return new ILInLogical(dS);
+            }
+            ILInLogical ret = new ILInLogical(A, 1, A.Length);
+            if (Settings.AllowInArrayAssignments)
+                ILScope.Context.RegisterArray(ret);
+            return ret;
+        }
+        /// <summary>
+        /// Implicitly convert n-dim. System.Array to ILNumerics array
+        /// </summary>
+        /// <param name="A">Arbitrarily sized System.Array</param>
+        /// <returns>If A is null: empty array. Else: new ILNumerics array of the same size as A</returns>
+        /// <remarks>The inner type of input array <paramref name="A"/> must match the requested type
+        /// <typeparamref name="ElementType"/>. The resulting ILArray will reflect all dimensions of 
+        /// A. Elements of A will get copied to elements of output array (shallow copy).</remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILCastException">If type of input does not match 
+        /// ElementType</exception>
+        public static implicit operator ILInLogical(Array elements) {
+            if (elements == null || elements.Length == 0) {
+                return new ILInLogical(ILSize.Empty00);
+            }
+            if (elements.GetType().GetElementType() != typeof(byte))
+                throw new ILCastException("inner type of System.Array must match");
+            int[] dims = new int[elements.Rank];
+            byte[] retArr = ILMemoryPool.Pool.New<byte>(elements.Length);
+            int posArr = 0;
+            for (int i = 0; i < dims.Length; i++) {
+                dims[i] = elements.GetLength(dims.Length - i - 1);
+            }
+            foreach (byte item in elements)
+                retArr[posArr++] = item;
+            ILInLogical ret = new ILInLogical(retArr, dims);
+            if (Settings.AllowInArrayAssignments)
+                ILScope.Context.RegisterArray(ret);
+            return ret; 
+        }
+        /// <summary>
+        /// Implicitly cast two dimensional System.Array to ILNumerics array
+        /// </summary>
+        /// <param name="A">2-dimensional System.Array</param>
+        /// <returns>If A is null: empty array. ILNumerics array of same size and type as A otherwise.</returns>
+        public static implicit operator ILInLogical(byte[,] A) {
+            if (A == null || A.Length == 0) {
+                return new ILInLogical(ILSize.Empty00);
+            }
+            int[] dims = new int[2];
+            byte[] retArr = ILMemoryPool.Pool.New<byte>(A.Length);
+            int posArr = 0;
+            for (int i = 0; i < 2; i++) {
+                dims[i] = A.GetLength(dims.Length - i - 1);
+            }
+            foreach (byte item in A)
+                retArr[posArr++] = item;
+            ILInLogical ret = new ILInLogical(retArr, dims);
+            if (Settings.AllowInArrayAssignments)
+                ILScope.Context.RegisterArray(ret);
+            return ret;
+        }
+        /// <summary>
+        /// Implicitly cast three dimensional System.Array to ILNumerics array
+        /// </summary>
+        /// <param name="A">3-dimensional System.Array</param>
+        /// <returns>If A is null: empty array. ILNumerics array of same size and type as A otherwise.</returns>
+        public static implicit operator ILInLogical(byte[, ,] A) {
+            if (A == null || A.Length == 0) {
+                return new ILInLogical(ILSize.Empty00);
+            }
+            int[] dims = new int[3];
+            byte[] retArr = ILMemoryPool.Pool.New<byte>(A.Length);
+            int posArr = 0;
+            for (int i = 0; i < 3; i++) {
+                dims[i] = A.GetLength(dims.Length - i - 1);
+            }
+            foreach (byte item in A)
+                retArr[posArr++] = item;
+            ILInLogical ret = new ILInLogical(retArr, dims);
+            if (Settings.AllowInArrayAssignments)
+                ILScope.Context.RegisterArray(ret);
+            return ret;
+        }
+        #endregion
+        #endregion
+
+        #region index access + mutability
+        /// <summary>
+        /// Subarray access (readonly)
+        /// </summary>
+        /// <param name="range">Range specification</param>
+        /// <returns>Logical array with the elements specified by range</returns>
+        /// <remarks>Query access: for N-dimensional arrays trailing dimensions will be choosen to be 0. Therefore you 
+        /// may ommit those trailing dimensions in range.
+        /// <para>The indexer may be used for querying any elements 
+        /// in this array. <c>range</c> may contains index specifications for one ... to any 
+        /// dimension. The array returned will have the size specified by range.</para>
+        /// </remarks>
+        public ILRetLogical this[params ILBaseArray[] dims] {
+            get {
+                return new ILRetLogical((ILLogicalStorage)Storage.Subarray(dims));
+            }
+        }
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILLogical.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILLogical.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILLogical.cs	(revision 9102)
@@ -0,0 +1,440 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using ILNumerics;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions; 
+using ILNumerics.Storage;
+using ILNumerics.Native;
+using System.Text; 
+
+namespace ILNumerics {
+    /// <summary>
+    /// Boolean array for high performance relational operations on arbitrary arrays 
+    /// </summary>
+    /// <remarks>
+    /// Logical arrays are derived from <c><![CDATA[ILArray<byte>]]></c>. It consumes
+    /// 1 byte per element and is the output parameter of all relational comparisons
+    /// as well as the input parameter for all functions consuming <c><![CDATA[ILArray<byte>]]></c>.
+    /// The difference between arrays and logical arrays is: the logical array 
+    /// stores a integer value with the number of nonzero elements as additional information. 
+    /// Therefore functions like 'find' are able to determine the lenght of output array to 
+    /// be created omitting the need of multiple walks through the array. Therefore ILLogicalArrays 
+    /// consume (a little) more time while construction but are much more performand on functions like 
+    /// 'find'.
+    /// </remarks>
+    [Serializable]
+    public sealed class ILLogical : ILBaseLogical {
+        
+        private static readonly bool s_isTempArray = false;
+
+        #region constructors
+        /// <summary>
+        ///	constructor - create logical array of type <c>Byte</c> of specified size
+        /// </summary>
+        /// <param name="size">
+        /// Variable length int array specifying the number and size of dimensions to 
+        /// be created.
+        /// </param>
+        /// <remarks>
+        /// The size parameter may not be null or an empty array! An Exception will be 
+        /// thrown in this case. The dimensions will be trimmed before processing 
+        /// (removing trailing non singleton dimensions). 
+        /// Depending on the requested size an ILArray &lt; byte &gt; of the specified dimensions 
+        /// will be created. The type of storage will be <c>bool</c>.
+        /// </remarks>
+        internal ILLogical(params int[] size)
+            : base(new ILLogicalStorage(new ILSize(size)), s_isTempArray) {
+            NumberNonZero = sumElements();
+        }
+        /// <summary>
+        ///	constructor - create logical array of type <c>Byte</c> of specified size
+        /// </summary>
+        /// <param name="size">
+        /// dimension object
+        /// </param>
+        /// <remarks>
+        /// The size parameter may not be null. An Exception will be 
+        /// thrown in this case. The dimensions will be trimmed before processing 
+        /// (removing trailing singleton dimensions). 
+        /// Depending on the requested size an logical array of the specified dimensions 
+        /// will be created. The element type is be <c>bool</c>.
+        /// </remarks>
+        internal ILLogical(ILSize size)
+            : base(new ILLogicalStorage(size), s_isTempArray) {
+            NumberNonZero = sumElements();
+        }
+        /// <summary>
+        /// Constructor creating logical array from dense storage
+        /// </summary>
+        /// <param name="A">input array, the storage of this ILArray will directly be used for 
+        /// storage of the new logical array</param>
+        internal ILLogical(ILLogicalStorage A)
+            : base(A, s_isTempArray) {
+            NumberNonZero = sumElements();
+        }
+        /// <summary>
+        /// Constructor creating logical array from (dense) storage
+        /// </summary>
+        /// <param name="A">input array, the storage of this ILArray will directly be used for 
+        /// storage of the new logical array</param>
+        /// <param name="numberNonZero">number of nonzero elements in A. Must be positive or 0.</param>
+        /// <remarks> Providing this parameter prevents the constructor from having to count the 
+        /// 'true' elements in A.</remarks>
+        internal ILLogical(ILLogicalStorage A, long numberNonZero)
+            : base(A, s_isTempArray) {
+            if (numberNonZero < 0)
+                throw new ILNumerics.Exceptions.ILArgumentException("invalid number of non-zero-elements given!");
+            NumberNonZero = numberNonZero;
+        }
+        /// <summary>
+        ///	constructor - create logical array of specified size 
+        /// from data array
+        /// </summary>
+        /// <param name="size">
+        /// Variable length int array specifying the number and size of dimensions to 
+        /// be created.
+        /// </param>
+        /// <param name="data"> byte array matching the size of the dimensions 
+        /// specified. The data will directly be used as storage! No copy will be made!</param>
+        /// <remarks>
+        /// The size parameter may not be null or an empty array! An Exception will be 
+        /// thrown in this case. The dimensions will be trimmed before processing 
+        /// (removing trailing non singleton dimensions). 
+        /// Depending on the requested size an logical array of the specified size 
+        /// will be created. The type of storage will be <c>byte</c>.
+        /// </remarks>
+        internal ILLogical(byte[] data, params int[] size)
+            : base(new ILLogicalStorage(data, new ILSize(size)), s_isTempArray) {
+            NumberNonZero = sumElements();
+        }
+        /// <summary>
+        /// Constructor creating logical array, provide predefined storage
+        /// </summary>
+        /// <param name="data">predefined storage elements. The array will directly be used 
+        /// as underlying storage. No copy will be made! </param>
+        /// <param name="dimension">Dimensions specification.</param>
+        internal ILLogical(byte[] data, ILSize dimension)
+            : base(new ILLogicalStorage(data, dimension), s_isTempArray) {
+           NumberNonZero = sumElements();
+        }
+        /// <summary>
+        /// Constructor creating logical array, predefined storage (fast version)
+        /// </summary>
+        /// <param name="data">predefined storage elements. The array will directly be used 
+        /// as underlying storage. No copy will be made! </param>
+        /// <param name="dimension">Dimensions specification.</param>
+        /// <param name="nonZeroCount">number of nonzero elements in <paramref name="data"/>. 
+        /// Providing this parameter prevents from counting the 'true' elements (again). </param>
+        internal ILLogical(byte[] data, ILSize dimension, long nonZeroCount)
+            : base(new ILLogicalStorage(data, dimension), s_isTempArray) {
+            if (nonZeroCount < 0)
+                throw new ILNumerics.Exceptions.ILArgumentException("invalid number of non-zero-elements given!");
+            NumberNonZero = nonZeroCount;
+        }
+        #endregion
+
+        #region operator overloading
+        #region constructional operators
+        /// <summary>
+        /// Implicitly convert boolean scalar to logical array of size 1x1 (scalar).
+        /// </summary>
+        /// <param name="val">Boolean scalar</param>
+        /// <returns>New logical array of size 1x1 holding the only element of type Byte 
+        /// with value of val.</returns>
+        public static implicit operator ILLogical(bool val) {
+            ILLogical ret = new ILLogical(new byte[1] { val ? (byte)1 : (byte)0 }, 1, 1);
+            return ret;
+        }
+        /// <summary>
+        /// Implicitly convert logical array to bool
+        /// </summary>
+        /// <param name="A">logical array</param>
+        /// <returns>true if <b>all</b> elements of A are non-zero, false otherwise 
+        /// </returns>
+        /// <remarks> If A is null or empty, the function returns false. Otherwise allall returns true, 
+        /// if all elements of A are non-zero and returns false, if A contains any zero elements.</remarks>
+        public static implicit operator bool(ILLogical A) {
+            // this operator is implicit for convenience reasons: 
+            // if(tmp[0]!=-10.0) { ... is only possible this way
+            if (object.Equals(A, null) || A.IsEmpty)
+                return false;
+            if (A.IsScalar)
+                return A.GetValue(0, 0) == 1;
+            return ILMath.allall(A).GetValue(0) == 1;
+        }
+        /// <summary>
+        /// Implicitly convert integer scalar to logical array of size 1x1 (scalar).
+        /// </summary>
+        /// <param name="val">Scalar value</param>
+        /// <returns>New logical array of size 1x1 holding the only element of type Byte 
+        /// with value of val.</returns>
+        public static implicit operator ILLogical(int val) {
+            ILLogical ret = new ILLogical(new Byte[1] { 
+                                 val != 0 ? (byte)1:(byte)0 }, 1, 1);
+            return ret;
+        }
+        /// <summary>
+        /// Implicitly cast one dimensional System.Array to ILNumerics array (vector)
+        /// </summary>
+        /// <param name="A">1-dimensional system array, arbitrary type</param>
+        /// <returns>ILNumerics array of same element type as elements of A. 
+        /// Row vector. If A is null: empty array.</returns>
+        /// <remarks>The System.Array A will directly be used for the new ILNumerics array! 
+        /// No copy will be done! Make sure, not to reference A after this conversion!</remarks>
+        public static implicit operator ILLogical(byte[] A) {
+            if (A == null) {
+                ILLogicalStorage dS = new ILLogicalStorage(new byte[0], ILSize.Empty00);
+                return new ILLogical(dS);
+            }
+            return new ILLogical(A, 1, A.Length);
+        }
+        /// <summary>
+        /// Implicitly convert n-dim. System.Array to ILNumerics array
+        /// </summary>
+        /// <param name="A">Arbitrarily sized System.Array</param>
+        /// <returns>If A is null: empty array. Else: new ILNumerics array of the same size as A</returns>
+        /// <remarks>The inner type of input array <paramref name="A"/> must match the requested type
+        /// <typeparamref name="ElementType"/>. The resulting ILArray will reflect all dimensions of 
+        /// A. Elements of A will get copied to elements of output array (shallow copy).</remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILCastException"> if type of input does not match 
+        /// ElementType</exception>
+        public static implicit operator ILLogical(Array elements) {
+            if (elements == null || elements.Length == 0) {
+                return new ILLogical(ILSize.Empty00);
+            }
+            if (elements.GetType().GetElementType() != typeof(byte))
+                throw new ILCastException("inner type of System.Array must match");
+            int[] dims = new int[elements.Rank];
+            byte[] retArr = ILMemoryPool.Pool.New<byte>(elements.Length);
+            int posArr = 0;
+            for (int i = 0; i < dims.Length; i++) {
+                dims[i] = elements.GetLength(dims.Length - i - 1);
+            }
+            foreach (byte item in elements)
+                retArr[posArr++] = item;
+            return new ILLogical(retArr, dims);
+        }
+        /// <summary>
+        /// Implicitly cast two dimensional System.Array to ILNumerics array
+        /// </summary>
+        /// <param name="A">2D System.Array</param>
+        /// <returns>If A is null: empty array. ILNumerics array of same size and type as A otherwise.</returns>
+        public static implicit operator ILLogical(byte[,] A) {
+            if (A == null || A.Length == 0) {
+                return new ILLogical(ILSize.Empty00);
+            }
+            int[] dims = new int[2];
+            byte[] retArr = ILMemoryPool.Pool.New<byte>(A.Length);
+            int posArr = 0;
+            for (int i = 0; i < 2; i++) {
+                dims[i] = A.GetLength(dims.Length - i - 1);
+            }
+            foreach (byte item in A)
+                retArr[posArr++] = item;
+            return new ILLogical(retArr, dims);
+        }
+        /// <summary>
+        /// Implicitly cast three dimensional System.Array to ILNumerics array
+        /// </summary>
+        /// <param name="A">3-dimensional System.Array</param>
+        /// <returns>If A is null: empty array. ILNumerics array of same size and type as A otherwise.</returns>
+        public static implicit operator ILLogical(byte[, ,] A) {
+            if (A == null || A.Length == 0) {
+                return new ILLogical(ILSize.Empty00);
+            }
+            int[] dims = new int[3];
+            byte[] retArr = ILMemoryPool.Pool.New<byte>(A.Length);
+            int posArr = 0;
+            for (int i = 0; i < 3; i++) {
+                dims[i] = A.GetLength(dims.Length - i - 1);
+            }
+            foreach (byte item in A)
+                retArr[posArr++] = item;
+            return new ILLogical(retArr, dims);
+        }
+        #endregion
+
+        #region operational operators
+        /// <summary>
+        /// Invert values of array elements 
+        /// </summary>
+        /// <param name="in1">Input array</param>
+        /// <returns>New solid logical array, inverted element values</returns>
+        public static ILRetLogical operator !(ILLogical in1) {
+            if (object.Equals(in1, null))
+                throw new ILArgumentException("operator -(): parameter must not be null!");
+            return (in1 != (byte)1);
+        }
+        #endregion
+
+        #region conversional operators
+        public static implicit operator ILLogical(ILRetLogical A) {
+            if (object.Equals(A, null))
+                return null;
+            ILLogicalStorage aStorage = (ILLogicalStorage)A.GiveStorageAwayOrClone(); 
+            ILLogical ret = new ILLogical(aStorage, aStorage.NumberNonZero);
+            ILScope.Context.RegisterArray(ret);
+            return ret;
+        }
+        public static implicit operator ILLogical(ILInLogical A) {
+            if (object.Equals(A, null))
+                return null;
+            ILLogicalStorage storage = A.Storage; 
+            ILLogical ret = new ILLogical(
+                    new ILLogicalStorage(storage.GetDataArray(), storage.Size));
+            ILScope.Context.RegisterArray(ret);
+            return ret;
+        }
+        public static implicit operator ILLogical(ILArray<byte> A) {
+            if (object.Equals(A, null))
+                return null;
+            ILLogical ret = new ILLogical(
+                new ILLogicalStorage(A.Storage.GetDataArray(), A.Size));
+            ILScope.Context.RegisterArray(ret);
+            return ret;
+        }
+        public static implicit operator ILLogical(ILInArray<byte> A) {
+            if (object.Equals(A, null))
+                return null;
+            ILLogical ret = new ILLogical(
+                new ILLogicalStorage(A.Storage.GetDataArray(), A.Size));
+            ILScope.Context.RegisterArray(ret);
+            return ret;
+        }
+
+        public static implicit operator ILArray<byte>(ILLogical A) {
+            if (object.Equals(A, null))
+                return null;
+            ILArray<byte> ret = new ILArray<byte>(
+                new ILDenseStorage<byte>(A.Storage.GetDataArray(), A.Size)); 
+            ILScope.Context.RegisterArray(ret);
+            return ret; 
+        }
+        public static implicit operator ILInArray<byte>(ILLogical A) {
+            if (object.Equals(A,null)) 
+                return null; 
+            ILInArray<byte> ret = new ILInArray<byte>(
+                new ILDenseStorage<byte>(A.Storage.GetDataArray(), A.Size)); 
+            return ret;
+        }
+        #endregion
+
+        #endregion operator overloads 
+
+        #region index access + mutability
+        /// <summary>
+        /// Subarray access
+        /// </summary>
+        /// <param name="range">Range specification</param>
+        /// <returns>Reference pointing to the elements of this array specified by range. If used for removal: 
+        /// the array will be changed to a referencing array having the parts requested removed and reshaped accordingly.</returns>
+        /// <remarks>Query access: for N-dimensional arrays trailing dimensions will be choosen to be 0. Therefore you 
+        /// may ommit those trailing dimensions in range.
+        /// <para>The indexer may be used for querying or altering single/any elements 
+        /// in this array. <c>range</c> may contains index specifications for one ... any 
+        /// dimension. The array returned will have the size specified by range.</para>
+        /// <para>The indexer may also be used for removing parts of the array. Therefore an empty array 
+        /// (of the same type) or 'null' must be assigned to the range specified by <c>range</c> using the set-access. <c>range</c> 
+        /// must contain exactly one dimension specification other than null. This may be any vector-sized numeric ILArray of any 
+        /// type. If <c>range</c> applies 
+        /// to less dimensions than dimensions existing in the array, the upper dimensions will be 
+        /// merged and the array will be reshaped before applying the removal to it.</para>
+        /// <para>In case of removal the ILArray returned will be a reference array.</para></remarks>
+        public ILRetLogical this[params ILBaseArray[] dims] {
+            get {
+                return new ILRetLogical((ILLogicalStorage)Storage.Subarray(dims));
+            }
+            set {
+                SetRange(value,dims); 
+                NumberNonZero = sumElements();
+            }
+        }
+        /// <summary>
+        /// Set single value to element at index specified
+        /// </summary>
+        /// <param name="value">New value</param>
+        /// <param name="idx">Index of element to be altered</param>
+        public void SetValue(byte value, params int[] idx) {
+            Storage.SetValueTyped(value, idx);
+        }
+        /// <summary>
+        /// Alter a range of this array
+        /// </summary>
+        /// <param name="value">Array with new values</param>
+        /// <param name="range">Range specification</param>
+        public void SetRange(ILInLogical value, params ILBaseArray[] range) {
+            using (ILScope.Enter(value))
+            using (ILScope.Enter(range)) {
+                if (object.Equals(value, null)) {
+                    Storage.IndexSubrange(null, range); 
+                } else {
+                    Storage.IndexSubrange(value.Storage, range);
+                }
+            }
+        }
+        /// <summary>
+        /// Replace the elements of this array with another array's elements, preventing memory leaks
+        /// </summary>
+        /// <param name="value">New array</param>
+        public ILRetLogical a {
+            set { Assign(value); }
+            get { return this.C; }
+        }
+        /// <summary>
+        /// Replaces storage of this array with new array elements, registers this array for out-of-scope disposal
+        /// </summary>
+        /// <param name="value">New array</param>
+        public void Assign(ILRetLogical value) { 
+            if (!IsDisposed)
+                Storage.Dispose();
+            m_storage = value.GiveStorageAwayOrClone();
+            //ILScope.Context.RegisterArray(this);  
+        }
+        #endregion
+
+        #region memory management
+        internal override bool EnterScope() {
+            return false;
+        }
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILOutArray.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILOutArray.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILOutArray.cs	(revision 9102)
@@ -0,0 +1,271 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using ILNumerics.Storage; 
+using ILNumerics.Exceptions; 
+
+namespace ILNumerics {
+
+    /// <summary>
+    /// Rectangular array, used as output parameter only 
+    /// </summary>
+    /// <typeparam name="ElementType">Inner type. This will mostly be a system numeric type or a 
+    /// complex floating point type.</typeparam>
+    /// <remarks><para>This class extends the primary <c>ILArray</c> by optimizing its behavior for the case when used as an
+    /// output parameter of functions.</para><para>When writing your own function all <i>output</i> parameters should be of type <c>ILOutArray</c>. Do not
+    /// use <c>out ILArray</c>! Similary, all return types should be of type <see cref="ILNumerics.ILRetArray{T}"/> and all input parameters of type <see cref="ILNumerics.ILInArray{T}"/>.</para>
+    /// <para>Other than being used to retrieve results from functions, <c>ILOutArray</c> should not be used.</para>
+    /// </remarks>
+    /// <seealso cref="ILNumerics.ILArray{T}"/>
+    /// <seealso cref="ILNumerics.ILRetArray{T}"/>
+    /// <seealso cref="ILNumerics.ILInArray{T}"/>
+    [Serializable]
+    public sealed class ILOutArray<ElementType> : ILDenseArray<ElementType> {
+
+        #region attributes
+        private ILArray<ElementType> m_originalArray; 
+        private static bool s_isTempArray = false; 
+        #endregion
+
+        #region constructors
+        /// <summary>
+        /// Create new output parameter array
+        /// </summary>
+        /// <param name="storage">Dense storage for the new array</param>
+        internal ILOutArray(ILDenseStorage<ElementType> storage)
+            : base(storage, s_isTempArray) {
+            //ILScope.Context.RegisterArray(this);
+        }
+        #endregion
+
+        #region implicit cast operators
+        #region constructional operators
+        ///// <summary>
+        ///// Implicitly convert scalar to array of size 1x1 (scalar).
+        ///// </summary>
+        ///// <param name="val">System type of size scalar</param>
+        ///// <returns>New ILOutArray of type ILOutArray <![CDATA[<typeof(val)>]]> of size 1x1 
+        ///// holding the only element with value of val.
+        ///// </returns>
+        //public static implicit operator ILOutArray<ElementType> (ElementType val) {
+        //    ILOutArray<ElementType> ret = new ILOutArray<ElementType>(
+        //                new ILDenseStorage<ElementType>(
+        //                    new ElementType[1] {val}, 
+        //                    new ILSize(1,1)));
+        //    return ret; 
+        //}
+        ///// <summary>
+        ///// implicitly cast one dimensional System.Array to ILNumerics array (vector)
+        ///// </summary>
+        ///// <param name="A">1 dimensional system array, arbitrary type</param>
+        ///// <returns>ILNumerics array of same element type as elements of A. 
+        ///// Row vector. If A is null: empty array.</returns>
+        ///// <remarks>The System.Array A will directly be used for the new ILNumerics array! 
+        ///// No copy will be done! Make sure, not to reference A after this conversion!</remarks>
+        //public static implicit operator ILOutArray<ElementType> (ElementType[] A) {
+        //    if (A == null) {
+        //        ILDenseStorage<ElementType> dS = new ILDenseStorage<ElementType>(new ElementType[0], ILSize.Empty00); 
+        //        return new ILOutArray<ElementType>(dS);                          
+        //    }
+        //    return new ILOutArray<ElementType>(A,1,A.Length);  // constructor will register the array in scope context! 
+        //}
+        ///// <summary>
+        ///// implicitly convert n-dimensional System.Array to ILNumerics array
+        ///// </summary>
+        ///// <param name="A">arbitrarily sized System.Array</param>
+        ///// <returns>If A is null: empty array. Else: new ILNumerics array of the same size as A</returns>
+        ///// <remarks>The inner type of input array <paramref name="A"/> must match the requested type
+        ///// <typeparamref name="ElementType"/>. The resulting ILOutArray will reflect all dimensions of 
+        ///// A. Elements of A will get copied to elements of output array (shallow copy).</remarks>
+        ///// <exception cref="ILNumerics.Exceptions.ILCastException"> if type of input does not match 
+        ///// ElementType</exception>
+        //public static implicit operator ILOutArray<ElementType> (Array elements) {
+        //    if (elements == null || elements.Length == 0) {
+        //        return new ILOutArray<ElementType>(ILSize.Empty00);
+        //    }
+        //    if (elements.GetType().GetElementType() != typeof(ElementType)) 
+        //        throw new ILCastException("inner type of System.Array must match"); 
+        //    int [] dims = new int[elements.Rank]; 
+        //    ElementType [] retArr = ILMemoryPool.Pool.New<ElementType>(elements.Length);
+        //    int posArr = 0; 
+        //    for (int i = 0; i < dims.Length; i++) {
+        //        dims[i] = elements.GetLength(dims.Length-i-1);
+        //    }
+        //    foreach (ElementType item in elements) 
+        //        retArr[posArr++] = item; 
+        //    ILOutArray<ElementType> ret = new ILOutArray<ElementType>(retArr,dims);
+        //    return ret; 
+        //}
+        ///// <summary>
+        ///// implicitly cast two dimensional System.Array to ILNumerics array
+        ///// </summary>
+        ///// <param name="A">2D System.Array</param>
+        ///// <returns>If A is null: empty array. ILNumerics array of same size and type as A otherwise.</returns>
+        //public static implicit operator ILOutArray<ElementType>(ElementType[,] A) {
+        //    if (A == null || A.Length == 0) {
+        //        return new ILOutArray<ElementType>(ILSize.Empty00);
+        //    }
+        //    int[] dims = new int[2];
+        //    ElementType[] retArr = ILMemoryPool.Pool.New<ElementType>(A.Length);
+        //    int posArr = 0;
+        //    for (int i = 0; i < 2; i++) {
+        //        dims[i] = A.GetLength(dims.Length - i - 1);
+        //    }
+        //    foreach (ElementType item in A)
+        //        retArr[posArr++] = item;
+        //    ILOutArray<ElementType> ret = new ILOutArray<ElementType>(retArr, dims);
+        //    return ret; 
+        //}
+        ///// <summary>
+        ///// implicitly cast three dimensional System.Array to ILNumerics array
+        ///// </summary>
+        ///// <param name="A">3D System.Array</param>
+        ///// <returns>If A is null: empty array. ILNumerics array of same size and type as A otherwise.</returns>
+        //public static implicit operator ILOutArray<ElementType>(ElementType[,,] A) {
+        //    if (A == null || A.Length == 0) {
+        //        return new ILOutArray<ElementType>(ILSize.Empty00);
+        //    }
+        //    int[] dims = new int[3];
+        //    ElementType[] retArr = ILMemoryPool.Pool.New<ElementType>(A.Length);
+        //    int posArr = 0;
+        //    for (int i = 0; i < 3; i++) {
+        //        dims[i] = A.GetLength(dims.Length - i - 1);
+        //    }
+        //    foreach (ElementType item in A)
+        //        retArr[posArr++] = item;
+        //    ILOutArray<ElementType> ret = new ILOutArray<ElementType>(retArr, dims);
+        //    return ret; 
+        //}
+        #endregion
+        #region conversional operators
+        /// <summary>
+        /// Creates an output parameter type array from regular array
+        /// </summary>
+        /// <param name="A">Original array</param>
+        /// <returns>Output parameter type array, references the original array</returns>
+        public static implicit operator ILOutArray<ElementType>(ILArray<ElementType> A) {
+            if (object.Equals(A, null))
+                return null;
+            // we over take the storage (identical reference) to the new OutArray
+            // and store the reference to the original as well.
+            // It will be needed to synchronize changes to the denseStorage later (on Remove and Expand).
+            ILOutArray<ElementType> ret = new ILOutArray<ElementType>(A.Storage);
+            ret.m_originalArray = A; 
+            return ret; 
+        }
+        #endregion
+        #endregion
+
+        #region memory management
+        /// <summary>
+        /// Replace the elements of this array with another array's elements, preventing memory leaks
+        /// </summary>
+        /// <param name="value">New array</param>
+        public ILRetArray<ElementType> a {
+            set { Assign(value); }
+            get { return this.C; }
+        }
+        /// <summary>
+        /// Replaces storage of this array with new array elements, registers this array for out-of-scope disposal
+        /// </summary>
+        /// <param name="value">New array</param>
+        public void Assign(ILRetArray<ElementType> value) {
+            if (!IsDisposed)
+                Storage.Dispose();
+            ILDenseStorage<ElementType> storage = value.GiveStorageAwayOrClone();
+            m_storage = storage; 
+            if (!object.ReferenceEquals(m_originalArray, null)) {
+                // update original array as well
+                (m_originalArray as ILDenseArray<ElementType>).Storage = storage; 
+            }
+            //ILScope.Context.RegisterArray(this);  
+        }
+        internal override bool EnterScope() {
+            return false;
+        }
+        #endregion
+
+        #region mutability + indexer
+        /// <summary>
+        /// Set single value to element at index specified
+        /// </summary>
+        /// <param name="value">New value</param>
+        /// <param name="idx">Index of element to be altered</param>
+        public void SetValue(ElementType value, params int[] idx) {
+            Storage.SetValueTyped(value, idx);
+        }
+
+        /// <summary>
+        /// Alter range of this array
+        /// </summary>
+        /// <param name="value">Array with new values</param>
+        /// <param name="range">Range specification</param>
+        public void SetRange(ILInArray<ElementType> value, params ILBaseArray[] range) {
+            using (ILScope.Enter(value))
+            using (ILScope.Enter(range)) {
+                if (object.Equals(value, null)) {
+                    Storage.IndexSubrange(null, range);
+                } else {
+                    using (ILScope.Enter(value))
+                        Storage.IndexSubrange(value.Storage, range);
+                }
+            }
+        }
+        /// <summary>
+        /// Subarray creation/manipulation/deletion
+        /// </summary>
+        /// <param name="range">Range specification, defining the size of the subarray</param>
+        /// <returns>Subarray as copy of this array</returns>
+        public ILRetArray<ElementType> this[params ILBaseArray[] range] {
+            get {
+                using (ILScope.Enter(range))
+                    return new ILRetArray<ElementType>(Storage.Subarray(range));
+            }
+            set {
+                SetRange(value, range);
+            }
+        }
+
+        #endregion
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILOutCell.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILOutCell.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILOutCell.cs	(revision 9102)
@@ -0,0 +1,298 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Text; 
+using ILNumerics.Storage; 
+using ILNumerics.Exceptions;
+using System.Collections.Generic; 
+
+namespace ILNumerics {
+    /// <summary>
+    /// ILCell : container class holding arbitrary array objects 
+    /// </summary>
+    /// <remarks>
+    /// ILCell acts as general purpose container. It stores arbitrary arrays of arbitrary element type. 
+    /// 
+    /// </remarks>
+    public sealed class ILOutCell : ILBaseCell {
+
+        #region attributes
+        ILCell m_originalCell;
+        private static readonly bool s_isTempArray = false;
+        #endregion
+
+        #region properties
+        /// <summary>
+        /// Replace the elements of this array with another array's elements, preventing memory leaks
+        /// </summary>
+        /// <param name="value">New array</param>
+        public ILRetCell a {
+            set { Assign(value); }
+            get { return this.C; }
+        }
+        #endregion
+
+        #region constructors
+
+        /// <summary>
+        /// do not use this constructor! Out arrays are to be created implicitely only!
+        /// </summary>
+        /// <param name="cellStorage">storage of source cell</param>
+        internal ILOutCell(ILCellStorage cellStorage)
+            : base(cellStorage, s_isTempArray) { }
+
+        #endregion constructors
+
+        #region implicit casts 
+        /// <summary>
+        /// Implicitely convert persistent cell to output parameter type cell 
+        /// </summary>
+        /// <param name="A">Original cell</param>
+        /// <returns>Output parameter cell</returns>
+        public static implicit operator ILOutCell(ILCell A) {
+            if (object.Equals(A, null))
+                return null;
+            ILOutCell ret = new ILOutCell(A.Storage);
+            ret.m_originalCell = A; 
+            return ret;
+        }
+        #endregion
+
+        #region public interface
+        /// <summary>
+        /// Replaces storage of this array with new array elements, registers this array for out-of-scope disposal
+        /// </summary>
+        /// <param name="value">New array</param>
+        public void Assign(ILRetCell value) {
+            if (!IsDisposed)
+                Storage.Dispose();
+            ILCellStorage storage = (ILCellStorage)value.GiveStorageAwayOrClone();
+            m_storage = storage;
+            if (!ILMath.isnull(m_originalCell)) {
+                (m_originalCell as ILDenseArray<ILStorage>).Storage = storage;
+            }
+            //ILScope.Context.RegisterArray(this);  
+        }
+        /// <summary>
+        /// Set single element of the cell
+        /// </summary>
+        /// <param name="value">The new value</param>
+        /// <param name="idx">Indices specifying the location to set the element to</param>
+        /// <remarks>The function supports the following features: 
+        /// <list type="bullet">
+        /// <item>Automatic expansion of the cell, when addressing an element outside of the cells size limits.</item>
+        /// <item>Before storing the new element into the cell, an old element may existing on the same location gets disposed.</item>
+        /// <item>A clone of the new value is stored, therefore, none of the source and the stored element are altered, whenever the other cell is altered (value semantics).</item>
+        /// <item>The function supports deep index addressing. This is the only way of altering array elements inside the cell - without recreation.</item>
+        /// </list>
+        /// <para>Removal of parts of the cell is <b>not</b> supported. If null or an empty array is provided as <paramref name="value"/>, the corresponding 
+        /// element is overwritten or removed.</para>
+        /// </remarks>
+        public void SetValue(ILBaseArray value, params int[] idx) {
+            using (ILScope.Enter(value)) {
+                Storage.SetValueTyped(value.Storage, idx);
+            }
+        }
+        /// <summary>
+        /// Set single element of the cell
+        /// </summary>
+        /// <param name="value">The new value</param>
+        /// <param name="idx">Indices specifying the location to set the element to</param>
+        /// <remarks>The function supports the following features: 
+        /// <list type="bullet">
+        /// <item>Automatic expansion of the cell, when addressing an element outside of the cells size limits.</item>
+        /// <item>Before storing the new element into the cell, an old element may existing on the same location gets disposed.</item>
+        /// <item>A clone of the new value is stored, therefore, none of the source and the stored element are altered, whenever the other cell is altered (value semantics).</item>
+        /// <item>The function supports deep index addressing. This is the only way of altering array elements inside the cell - without recreation.</item>
+        /// </list>
+        /// <para>Removal of parts of the cell is <b>not</b> supported. If null or an empty array is provided as <paramref name="value"/>, the corresponding 
+        /// element is overwritten or removed.</para>
+        /// </remarks>
+        internal void SetValue(ILStorage value, params int[] idx) {
+            Storage.SetValueTyped(value, idx);
+        }
+        #endregion
+
+        #region Index access
+        /// <summary>
+        /// Get/set/remove single element 
+        /// </summary> 
+        /// <paramref name="indices" value="index to element"/>
+        /// <value>Inner element, new inner element or null</value>
+        /// <remarks>The type of access depends on the length of indices. If indices contains only one element, 
+        /// the array will be accessed via sequential index access. This is sometimes called referred to as 'linear' 
+        /// index addressing. 
+        /// Sequential index access reflects the index of internal storage the way the data are actually organized 
+        /// in memory. This access method is mainly convinient for vectors where you are not interested of orientation.
+        /// The following example demonstrates sequential index access for ILArray's (which also holds for ILCells): 
+        /// <example>For <c>ILArray&lt;double&gt; A = ILMath.counter(1,12);</c>, <c>A[2]</c> gives: 3.0.
+        /// But the transpose 
+        /// <c>A.T[2]</c> gives also: 3.0.
+        /// For matrices and N-dimensional arrays this holds as well: 
+        /// <code>
+        /// ILArray&lt;double&gt; A = ILMath.counter(1.0,1.0,3,2,2);
+        /// A = 
+        /// [1.0 4.0
+        ///  2.0 5.0 
+        ///  3.0 6.0 
+        /// 
+        ///  7.0 10.0
+        ///  8.0 11.0
+        ///  9.0 12.0]
+        /// 
+        /// A = ILMath.Reshape(A,3,2,2); 
+        /// A[10] gives 11.0
+        /// A[10,1] gives ILArgumentException -> out of range
+        /// A[2,1,1] gives 12.0
+        /// A[2,1] gives 6.0 (set trailing dimension to '0')</code></example>
+        /// <para>If the element addressed is a ILCell itself, a deep reference to this element will be returned instead. 
+        /// I.e. all elements of the ILCell will be recursively replaced with references to itself. Therefore, altering the 
+        /// elements returned will not alter the elements contained in the cell.</para>
+        /// <para>
+        /// <list type="bullet">
+        /// <listheader>The type of the element returned depends on the type of the element addressed:</listheader>
+        /// <item>For ILArray&lt;ElementType&gt; the array returned will be a clone of the original array.</item> 
+        /// <item>For ILCell the ILBaseArray returned is a deep reference of the original elements stored.</item>
+        /// <item>For other types the behavior is undefined. (since other types are not implemented yet ;)</item>
+        /// </list> </para>
+        /// <para>This indexer may also be used for direct access to inner elements of (elements of elements of ...) this cell:
+        /// <example>
+        /// <code>
+        /// ILCell innerCell = new ILCell(2,1); 
+        /// innerCell[0] = ILMath.vec(10,200); 
+        /// innerCell[1] = new int[] {-10,-20,-30};
+        /// ILCell cell = new ILCell(2,1); 
+        /// cell[0] = innerCell; 
+        /// cell[1] = new string[] {"foobla"}; 
+        /// // cell is now: 
+        /// // [ILCell,(1x2)] 
+        /// //      [innerCell[0], ILArray&lt;double&gt;(1x181)]
+        /// //      [innerCell[0], ILArray&lt;double&gt;(1x3)]
+        /// // [ILArray&lt;string&gt;,(1x1)]
+        /// 
+        /// cell[0,0] -&gt; will give innerCell eq. ILCell (1x2)
+        /// cell[0,1] -&gt; will give ILArray&lt;string&gt;
+        /// cell[0,0,0,1] -&gt; will give innerCell[1] eq. ILArray&lt;int&gt;(1x3)
+        /// </code>
+        /// </example> 
+        /// In the last example above the trailing indices specified make the indexer walk down into the ILCell element and retrieve 
+        /// the content of this element. This kind of index access may be done as deep as you want. Just 
+        /// append the inner indices into inner elements to the right side of index specification. Addressing inner elements 
+        /// this way is the only way to alter elements <b>directly</b> inside the ILCell. </para>
+        /// <para>Output parameter type cell carry a reference to the original array they were created from. 
+        /// Modifications of outpur parameter type cells are immediately applied to the original array also.</para></remarks>
+        public ILRetCell this[params int[] indices] {
+            get {
+                ILStorage val = Storage.GetValueTyped(indices);
+                if (val is ILCellStorage)
+                    return new ILRetCell((ILCellStorage)val);
+                else
+                    return new ILRetCell(new ILStorage[] { val }, ILSize.Scalar1_1);
+            }
+            set {
+                using (ILScope.Enter(value)) {
+                    if (!object.Equals(value, null) && value.Storage.FromImplicitCast && value.IsScalar) {
+                        SetValue((value as ILDenseArray<ILStorage>).GetValue(0), indices);
+                    } else {
+                        SetValue((object.Equals(value, null)) ? null : value.Storage, indices);
+                    }
+                }
+            }
+        }
+
+        /// <summary>
+        /// Subarray access. Get/set regular subarray. 
+        /// </summary>
+        /// <param name="indices">Address range</param>
+        /// <returns>Reference cell array with subarray addressed by <c>indices</c>. </returns>
+        /// <remarks>Query access: for N-dimensional cell arrays missing trailing dimensions indices will be choosen to be 0. Therefore you 
+        /// may ommit those trailing dimensions in <c>indices</c>.
+        /// <para>The indexer may be used for querying or altering single/any elements 
+        /// in this cell. <c>indices</c> may contains index specifications for one to any 
+        /// dimension. The cell array returned will have the size specified by <c>indices</c>.</para>
+        /// <para>Values returned will be reference cells. All elements contained will be 'deep references' created by 
+        /// recursively walking downwards the elements and replacing them by references to itself. Therefore altering the 
+        /// values returned will not alter the original elements.</para>
+        /// <para>The indexer may also be used for removing parts of the cell. Therefore null must be assigned to the range specified by <c>indices</c> (using the set-access). <c>indices</c> 
+        /// must contain exactly one dimension specification other than 'full' in this case. This may be any vector-sized numeric ILArray of any 
+        /// numeric type. If <c>indices</c> apply to fewer dimensions than the number of dimensions existing, the upper dimensions will be 
+        /// merged and the array will be reshaped before applying the removal to it.
+        /// <example>
+        /// <code>
+        /// ILCell C = new ILCell(4,10); 
+        /// C[":",2] = null;  // &gt;- will remove the third column (index: 2) from the cell.
+        /// C[full,vec(2,5)] = null;  &gt;- will remove columns 3...6
+        /// C[1,1] = null; &gt;- will produce an error. Only one dimension can be specified not full! 
+        /// </code></example></para>
+        /// <para>The general behavior of this access methods is full compatible with the corresponding Matlab/Octave/Scilab access: a(:) = []. </para>
+        /// <para>Output parameter type cell carry a reference to the original array they were created from. 
+        /// Modifications of outpur parameter type cells are immediately applied to the original array also.</para></remarks>
+        public new ILRetCell this[params ILBaseArray[] indices] {
+            get {
+                using (ILScope.Enter(indices)) {
+                    ILCellStorage elements = (ILCellStorage)Storage.Subarray(indices);
+                    return new ILRetCell(elements);
+                }
+            }
+            set {
+                using (ILScope.Enter(indices))
+                using (ILScope.Enter(value)) {
+                    if (Object.ReferenceEquals(value, null)) {
+                        Storage.IndexSubrange(null, indices);
+                    } else {
+                        //if (value.Storage.FromImplicitCast && value.IsScalar) {
+                        //    Storage.IndexSubrange((ILDenseStorage<ILStorage>)value.GetValue(0), indices);
+                        //} else {
+                        Storage.IndexSubrange((ILCellStorage)value.Storage.Clone(), indices);
+                        //}
+                    }
+                }
+            }
+        }
+
+        #endregion index access
+
+        #region memory management
+        internal override bool EnterScope() {
+            return false;
+        }
+        #endregion
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILOutLogical.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILOutLogical.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILOutLogical.cs	(revision 9102)
@@ -0,0 +1,268 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using ILNumerics.Storage; 
+using ILNumerics.Exceptions; 
+
+namespace ILNumerics {
+    
+    /// <summary>
+    /// Boolean array for high performance relational operations on arbitrary arrays 
+    /// </summary>
+    /// <remarks>
+    /// Logical arrays store true/false conditions as elements. Each element consumes
+    /// one byte. Logical arrays are the output parameter of all relational comparisons.</remarks>
+    [Serializable]
+    public sealed class ILOutLogical : ILBaseLogical {
+
+        #region attributes
+        private ILLogical m_originalArray; 
+        #endregion
+
+        #region constructors
+        /// <summary>
+        /// Constructor - create logical array of type <c>Byte</c> of specified size
+        /// </summary>
+        /// <param name="size">
+        /// Variable length int array specifying the number and size of dimensions to 
+        /// be created.
+        /// </param>
+        /// <remarks>
+        /// The size parameter may not be null or an empty array! An Exception will be 
+        /// thrown in this case. The dimensions will be trimmed before processing 
+        /// (removing trailing non singleton dimensions). 
+        /// Depending on the requested size an ILArray &lt; byte &gt; of the specified dimensions 
+        /// will be created. The type of storage will be <c>bool</c>.
+        /// </remarks>
+        internal ILOutLogical(params int[] size)
+            : base(new ILLogicalStorage(new ILSize(size)),false) {
+            NumberNonZero = sumElements();
+        }
+        /// <summary>
+        /// Constructor - create logical array of type <c>byte</c> of specified size
+        /// </summary>
+        /// <param name="size">
+        /// Size descriptor
+        /// </param>
+        /// <remarks>
+        /// The size parameter may not be null. An Exception will be 
+        /// thrown in this case. The dimensions will be trimmed before processing 
+        /// (removing trailing singleton dimensions). 
+        /// Depending on the requested size an logical array of the specified dimensions 
+        /// will be created. The element type is be <c>bool</c>.
+        /// </remarks>
+        internal ILOutLogical(ILSize size)
+            : base(new ILLogicalStorage(size),false) {
+            NumberNonZero = sumElements();
+        }
+        /// <summary>
+        /// Constructor creating logical array from dense storage
+        /// </summary>
+        /// <param name="A">Input array, the storage of this ILArray will directly be used for 
+        /// storage of the new logical array</param>
+        internal ILOutLogical(ILLogicalStorage A)
+            : base(A,false) {
+            NumberNonZero = sumElements();
+        }
+        /// <summary>
+        /// Constructor creating logical array from (dense) storage
+        /// </summary>
+        /// <param name="A">Input array, the storage of this ILArray will directly be used for 
+        /// storage of the new logical array</param>
+        /// <param name="numberNonZero">Number of nonzero elements in A. Must be positive or 0.</param>
+        /// <remarks>Providing this parameter prevents the constructor from having to count the 
+        /// 'true' elements in A.</remarks>
+        internal ILOutLogical(ILLogicalStorage A, long numberNonZero)
+            : base(A, false) {
+            if (numberNonZero < 0)
+                throw new ILNumerics.Exceptions.ILArgumentException("invalid number of non-zero-elements given!");
+            NumberNonZero = numberNonZero;
+        }
+        /// <summary>
+        /// Constructor - create logical array of specified size from data array
+        /// </summary>
+        /// <param name="size">
+        /// Variable length int array specifying the number and size of dimensions to 
+        /// be created.
+        /// </param>
+        /// <param name="data">byte array matching the size of the dimensions 
+        /// specified. The data will directly be used as storage! No copy will be made!</param>
+        /// <remarks>
+        /// The size parameter may not be null or an empty array! An Exception will be 
+        /// thrown in this case. The dimensions will be trimmed before processing 
+        /// (removing trailing non singleton dimensions). 
+        /// Depending on the requested size an logical array of the specified size 
+        /// will be created. The type of storage will be <c>byte</c>.
+        /// </remarks>
+        internal ILOutLogical(byte[] data, params int[] size)
+            : base(new ILLogicalStorage( data, new ILSize(size)),false) {
+            NumberNonZero = sumElements();
+        }
+        /// <summary>
+        /// Constructor creating logical array, provide predefined storage
+        /// </summary>
+        /// <param name="data">Predefined storage elements. The array will directly be used 
+        /// as underlying storage. No copy will be made! </param>
+        /// <param name="size">Dimensions specification.</param>
+        internal ILOutLogical(byte[] data, ILSize size)
+            : base(new ILLogicalStorage(data, size), false) {
+           NumberNonZero = sumElements();
+        }
+        /// <summary>
+        /// Constructor creating logical array, predefined storage (fast version)
+        /// </summary>
+        /// <param name="data">predefined storage elements. The array will directly be used 
+        /// as underlying storage. No copy will be made! </param>
+        /// <param name="size">Dimensions specification.</param>
+        /// <param name="nonZeroCount">number of nonzero elements in <paramref name="data"/>. 
+        /// Providing this parameter prevents from counting the 'true' elements (again). </param>
+        internal ILOutLogical(byte[] data, ILSize size, long nonZeroCount)
+            : base(new ILLogicalStorage(data, size), false) {
+            if (nonZeroCount < 0)
+                throw new ILNumerics.Exceptions.ILArgumentException("invalid number of non-zero-elements given!");
+            NumberNonZero = nonZeroCount;
+        }
+        #endregion
+
+        #region implicit cast operators
+        #region conversional operators
+        /// <summary>
+        /// Convert logical array to output parameter type array
+        /// </summary>
+        /// <param name="A">Source logical array</param>
+        /// <returns>Output parameter type array</returns>
+        public static implicit operator ILOutLogical(ILLogical A) {
+            if (object.Equals(A,null))
+                return null;
+            ILOutLogical ret = new ILOutLogical(A.Storage);
+            ret.m_originalArray = A;
+            return ret;
+        }
+        #endregion
+        #endregion
+
+        #region index access + mutability
+        /// <summary>
+        /// Subarray access
+        /// </summary>
+        /// <param name="range">Range specification</param>
+        /// <returns>Reference pointing to the elements of this array specified by range. If used for removal: 
+        /// the array will be changed to a referencing array having the parts requested removed and reshaped accordingly.</returns>
+        /// <remarks>Query access: for N-dimensional arrays trailing dimensions will be choosen to be 0. Therefore you 
+        /// may ommit those trailing dimensions in range.
+        /// <para>The indexer may be used for querying or altering single/any elements 
+        /// in this array. <c>range</c> may contains index specifications for one ... any 
+        /// dimension. The array returned will have the size specified by range.</para>
+        /// <para>The indexer may also be used for removing parts of the array. Therefore an empty array 
+        /// (of the same type) or 'null' must be assigned to the range specified by <c>range</c> using the set-access. <c>range</c> 
+        /// must contain exactly one dimension specification other than null. This may be any vector-sized numeric ILArray of any 
+        /// type. If <c>range</c> applies 
+        /// to less dimensions than dimensions existing in the array, the upper dimensions will be 
+        /// merged and the array will be reshaped before applying the removal to it.</para>
+        /// <para>In case of removal the ILArray returned will be a reference array.</para></remarks>
+        public ILRetLogical this[params ILBaseArray[] dims] {
+            get {
+                return new ILRetLogical((ILLogicalStorage)Storage.Subarray(dims));
+            }
+            set {
+                SetRange(value,dims); 
+                NumberNonZero = sumElements();
+            }
+        }
+        /// <summary>
+        /// Set single value to element at index specified
+        /// </summary>
+        /// <param name="value">New value</param>
+        /// <param name="idx">Index of element to be altered</param>
+        public void SetValue(byte value, params int[] idx) {
+            Storage.SetValueTyped(value, idx);
+        }
+        /// <summary>
+        /// Alter a range of this array
+        /// </summary>
+        /// <param name="value">Array with new values</param>
+        /// <param name="range">Range specification</param>
+        public void SetRange(ILInLogical value, params ILBaseArray[] range) {
+            using (ILScope.Enter(value))
+            using (ILScope.Enter(range)) {
+                if (object.Equals(value, null)) {
+                    Storage.IndexSubrange(null, range); 
+                } else {
+                    using (ILScope.Enter(value))
+                        Storage.IndexSubrange(value.Storage, range);
+                }
+            }
+        }
+        /// <summary>
+        /// Replace the elements of this array with another array's elements, preventing memory leaks
+        /// </summary>
+        /// <param name="value">New array</param>
+        public ILRetLogical a {
+            set { Assign(value); }
+            get { return this.C; }
+        }
+        /// <summary>
+        /// Replaces storage of this array with new array elements, registers this array for out-of-scope disposal
+        /// </summary>
+        /// <param name="value">new array</param>
+        public void Assign(ILRetLogical value) {
+            if (!IsDisposed)
+                Storage.Dispose();
+            ILLogicalStorage storage = (ILLogicalStorage)value.GiveStorageAwayOrClone(); 
+            m_storage = storage;
+            if (!ILMath.isnull(m_originalArray)) {
+                (m_originalArray as ILDenseArray<byte>).Storage = storage; 
+            }
+            //ILScope.Context.RegisterArray(this);  
+        }
+
+        #endregion
+
+        #region memory management
+        internal override bool EnterScope() {
+            return false;
+        }
+        #endregion
+    
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILRegularRange.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILRegularRange.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILRegularRange.cs	(revision 9102)
@@ -0,0 +1,158 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using ILNumerics.Storage;
+using System.Linq.Expressions;
+using ILNumerics.Data; 
+
+namespace ILNumerics.Misc {
+    internal sealed class ILRegularRange {
+
+        ILBaseArray m_startA; 
+        ILBaseArray m_stepA; 
+        ILBaseArray m_endA;
+        int m_start; 
+        int m_step; 
+        int m_end;
+        bool m_isEvaluated = false; 
+        bool m_basedOnEndPlaceholder = false; 
+
+        internal ILRegularRange(ILBaseArray start, ILBaseArray step, ILBaseArray end) { 
+            m_startA = start; 
+            m_stepA = step; 
+            m_endA = end; 
+            //// make sure, Length will always be positive! 
+            //if ((m_start > m_end && m_step > 0) || 
+            //    (m_start < m_end && m_step < 0)) {
+            //    throw new Exceptions.ILArgumentException(String.Format("invalid range: check start:step:end! was: [{0}:{1}:{2}]",m_start,m_step,m_end));
+            //}
+            //if (m_step == 0)  throw new Exceptions.ILArgumentException("invalid range: step must not equal 0");
+        }
+        internal ILRegularRange(int start, int end) {
+            m_startA = start; 
+            m_stepA = 1; 
+            m_endA = end; 
+            // make sure, Length will always be positive! 
+            //if (m_start > m_end) throw new Exceptions.ILArgumentException("invalid range: start must be lower as or equal to end"); 
+        }
+        internal void Evaluate(int dimLength) {
+            if (m_isEvaluated) return; 
+            m_step = ILMath.toint32(m_stepA).GetValue(0);
+            evaluateSingle(ref m_start, m_startA, dimLength); 
+            evaluateSingle(ref m_end, m_endA, dimLength); 
+            if (m_step == 0 || Math.Sign((m_end-m_start)/m_step) < 0) {
+                Length = 0;
+            } else if (m_basedOnEndPlaceholder && dimLength < 0) {
+                Length = 0; 
+            } else {
+                Length =  (m_end-m_start) / m_step + 1; // ?? was: (int)Math.Ceiling((m_end - m_start) / (float)m_step) + 1;
+            }
+            m_isEvaluated = true; 
+        }
+        private void evaluateSingle(ref int parameter, ILBaseArray input, int dimLength) {
+            if (input is ILBaseArray<Expression>) {
+                parameter = ILExpression.Evaluate((input as ILBaseArray<Expression>).GetValue(0),dimLength); 
+                m_basedOnEndPlaceholder = true; 
+            } else {
+                parameter = ILMath.toint32(input).GetValue(0); 
+            }
+        }
+        internal void Expand(ILIntList target, ref int outLen, ref int min, ref int max, int dimLen) {
+            if (!m_isEvaluated) 
+                Evaluate(dimLen); 
+            if (Length <= 0 || Math.Sign((m_end-m_start)/m_step) < 0) 
+                return; 
+
+            int i = m_start;
+            if (m_start == m_end) {
+                target.Add(i); 
+            } else if (m_start < m_end) {
+                do {
+                    target.Add(i);     
+                    i += m_step;
+                } while (i <= m_end); 
+            } else {
+                do {
+                    target.Add(i);     
+                    i += m_step;
+                } while (i >= m_end); 
+            }
+
+            int _min = Math.Min(m_start,m_end); 
+            if (_min < min) min = _min; 
+            int _max = Math.Max(m_start,m_end); 
+            if (_max > max) max = _max; 
+            outLen += Length; 
+        }
+        public int Length { get; private set; }
+
+        public override string ToString() {
+            return String.Format("[{0}:{1}:{2}]",m_start,m_step,m_end);
+        }
+
+        internal void Extract<T>(T[] source, T[] dest, int dimLen) {
+            if (!m_isEvaluated) 
+                Evaluate(dimLen); 
+            if (Math.Sign((m_end-m_start)/m_step) < 0) 
+                return; 
+
+            int i = m_start;
+            int pos = 0;
+            if (m_start < m_end) {
+                do {
+                    dest[pos++] = source[i];
+                    i += m_step;
+                } while (i <= m_end);
+            } else if (m_start > m_end) {
+                do {
+                    dest[pos++] = source[i];
+                    i += m_step;
+                } while (i >= m_end);
+            } else {
+                // start == end
+                dest[0] = source[m_start];
+            }
+        }
+    }
+
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILRetArray.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILRetArray.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILRetArray.cs	(revision 9102)
@@ -0,0 +1,690 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.IO; 
+using System.Text;
+using ILNumerics.Storage;
+using ILNumerics; 
+using ILNumerics.Exceptions; 
+using ILNumerics.Misc;
+
+namespace ILNumerics {
+    /// <summary>
+    /// N-dimensional, generic array class, temporary variant, is disposed after first use
+    /// </summary>
+    /// <typeparam name="ElementType">Inner element type</typeparam>
+    public sealed class ILRetArray<ElementType> : ILDenseArray<ElementType> {
+
+        #region properties
+        /// <summary>
+        /// Clone of this array (fast, cheap and shallow)
+        /// </summary>
+        /// <remarks><para>Calling this member will dispose this instance afterwards (for temporary arrays).</para>
+        /// </remarks>
+        public override ILRetArray<ElementType> C {
+            get {
+                return this;
+            }
+        }
+
+        /// <summary>
+        /// Size descriptor shortcut
+        /// </summary>
+        public override ILSize S {
+            get {
+                using (ILScope.Enter(this))
+                    return Storage.Size;
+            }
+        }
+        /// <summary>
+        /// Size descriptor 
+        /// </summary>
+        public override ILSize Size {
+            get {
+                using (ILScope.Enter(this))
+                    return Storage.Size;
+            }
+        }
+        /// <summary>
+        /// Test if this array instance is a column vector
+        /// </summary>
+        public override bool IsColumnVector {
+            get {
+                using (ILScope.Enter(this))
+                    return Size[1] == 1 && Size.NumberOfDimensions == 2; ;
+            }
+        }
+        /// <summary>
+        /// Test if this array instance is a row vector
+        /// </summary>
+        public override bool IsRowVector {
+            get {
+                using (ILScope.Enter(this))
+                    return Size[0] == 1 && Size.NumberOfDimensions == 2;
+            }
+        }
+        /// <summary>
+        /// Determine if this array has complex elements.
+        /// </summary>
+        /// <remarks><para>Calling this member will dispose this instance afterwards (for temporary arrays).</para></remarks>
+        public override bool IsComplex {
+            get {
+                using (ILScope.Enter(this))
+                    return base.IsComplex;
+            }
+        }
+        /// <summary>
+        /// Test if this instance is an empty array (number of elements stored = 0)
+        /// </summary>
+        public override bool IsEmpty {
+            get {
+                using (ILScope.Enter(this))
+                    return Size.NumberOfElements == 0;
+            }
+        }
+        /// <summary>
+        /// Test if this instance is a matrix
+        /// </summary>
+        /// <remarks>In order for an array to be a matrix the number of <b>non singleton</b> 
+        /// dimensions must equal 2. This attribute is readonly.</remarks>
+        public override bool IsMatrix {
+            get {
+                using (ILScope.Enter(this))
+                    return Size.NumberOfDimensions == 2;
+            }
+        }
+        /// <summary>
+        /// Determine if this array holds numeric values.
+        /// </summary>
+        /// <remarks>An ILArray is numeric as long as its elements are one of the 
+        /// following types: 
+        /// <list type="table">
+        /// <listheader>
+        ///     <term>inner type</term>
+        /// </listheader>
+        /// <item>
+        ///     <term>System.double</term>
+        ///     <description>floating point, real, 8 bytes </description>
+        /// </item>
+        /// <item>
+        ///     <term>System.float</term>
+        ///     <description>floating point real, 4 bytes</description>
+        /// </item>
+        /// <item>
+        ///     <term>ILNumerics.complex</term>
+        ///     <description>floating point complex, 16 bytes</description>
+        /// </item>
+        /// <item>
+        ///     <term>ILNumerics.fcomplex</term>
+        ///     <description>floating point complex, 8 bytes</description>
+        /// </item>
+        /// <item>
+        ///     <term>System.char</term>
+        ///     <description>integer, real, 1 byte</description>
+        /// </item>
+        /// <item>
+        ///     <term>System.byte</term>
+        ///     <description>integer, real, 1 byte</description>
+        /// </item>
+        /// <item>
+        ///     <term>System.Int16</term>
+        ///     <description>integer, real, 2 byte</description>
+        /// </item>
+        /// <item>
+        ///     <term>System.Int32</term>
+        ///     <description>integer, real, 4 byte</description>
+        /// </item>
+        /// <item>
+        ///     <term>System.Int64</term>
+        ///     <description>integer, real, 8 byte</description>
+        /// </item>
+        /// <item>
+        ///     <term>System.UInt16</term>
+        ///     <description>unsigned integer, real, 2 byte</description>
+        /// </item>
+        /// <item>
+        ///     <term>System.UInt32</term>
+        ///     <description>unsigned integer, real, 4 byte</description>
+        /// </item>
+        /// <item>
+        ///     <term>System.UInt64</term>
+        ///     <description>unsigned integer, real, 8 byte</description>
+        /// </item>
+        /// </list>
+        /// <para>Calling this member will dispose this instance afterwards (for temporary arrays).</para>
+        /// </remarks>
+        public override bool IsNumeric {
+            get {
+                using (ILScope.Enter(this))
+                    return base.IsNumeric;
+            }
+        }
+        /// <summary>
+        /// Test if this instance is a scalar
+        /// </summary>
+        /// <remarks>This attribute is readonly. It returns: Size.NumberOfElements == 1.</remarks>
+        public override bool IsScalar {
+            get {
+                using (ILScope.Enter(this))
+                    return Size.NumberOfElements == 1;
+            }
+        }
+        /// <summary>
+        /// Test if this array is a vector
+        /// </summary>
+        /// <remarks>In order for an array to be a vector the number of <b>non singleton</b> 
+        /// dimensions must equal 1. Keep in mind that all ILArrays have at least 2 dimensions. Therefore 
+        /// it is not sufficient to test for the number of dimensions, but to take the number of 
+        /// <b>non singleton</b> dimensions into account. This attribute is readonly.</remarks>
+        public override bool IsVector {
+            get {
+                using (ILScope.Enter(this))
+                    return (Size[0] == 1 || Size[1] == 1) && Size.NumberOfDimensions == 2;
+            }
+        }
+        /// <summary>
+        /// Length of the longest dimension of this instance
+        /// </summary>
+        /// <remarks>This property is readonly.
+        /// <para>Calling this member will dispose this instance afterwards (for temporary arrays).</para></remarks>
+        public override int Length {
+            get {
+                using (ILScope.Enter(this))
+                    return base.Length;
+            }
+        }
+        /// <summary>
+        /// Return transposed version of this array
+        /// </summary>
+        public new ILRetArray<ElementType> T {
+            get {
+                using (ILScope.Enter(this))
+                    return new ILRetArray<ElementType>(Storage.ShiftDimensions(1));
+            }
+        }
+        /// <summary>
+        /// Gets the name of this array (readonly)
+        /// </summary>
+        public new String Name {
+            get {
+                using (ILScope.Enter(this))
+                    return m_name;
+            }
+        }
+        #endregion
+
+        #region constructors
+        internal ILRetArray(ILDenseStorage<ElementType> denseStorage) :
+            base(denseStorage, true) { }
+
+        internal ILRetArray(ElementType[] elements, params int[] dimensions) :
+            this(elements, new ILSize(dimensions)) { }
+
+        internal ILRetArray(ElementType[] elements, ILSize dimensions) :
+            base(new ILDenseStorage<ElementType>(elements, dimensions), true) { }
+
+        internal ILRetArray(ILSize dimensions) :
+            base(new ILDenseStorage<ElementType>(dimensions), true) { }
+
+        internal static ILRetArray<ElementType> empty(ILSize dimension) {
+            return new ILRetArray<ElementType>(new ElementType[0], dimension);
+        }
+
+        #endregion
+
+        #region operator overloads
+        #region constructive operators
+        /// <summary>
+        /// Implicitly convert scalar to array of size 1x1 (scalar).
+        /// </summary>
+        /// <param name="val">Single element of ElementType type</param>
+        /// <returns>New array of of size 1x1 holding the only element with value of val.
+        /// </returns>
+        public static implicit operator ILRetArray<ElementType>(ElementType val) {
+            ILRetArray<ElementType> ret = new ILRetArray<ElementType>(
+                        new ILDenseStorage<ElementType>(new ElementType[] { val }, new ILSize(1, 1)));
+            return ret;
+        }
+        /// <summary>
+        /// Implicitly cast one dimensional System.Array to ILNumerics array (vector)
+        /// </summary>
+        /// <param name="A">1-dimensional system array, arbitrary type</param>
+        /// <returns>ILNumerics array of same element type as elements of A. 
+        /// Row vector. If A is null: empty array.</returns>
+        /// <remarks>The System.Array A will directly be used for the new ILNumerics array! 
+        /// No copy will be done! Make sure, not to reference A after this conversion!</remarks>
+        public static implicit operator ILRetArray<ElementType>(ElementType[] A) {
+            if (A == null) { 
+                // TODO: check: return null better? 
+                ILDenseStorage<ElementType> dS = new ILDenseStorage<ElementType>(new ElementType[0], ILSize.Empty00);
+                return new ILRetArray<ElementType>(dS);
+            }
+            return new ILRetArray<ElementType>(A, 1, A.Length);
+        }
+        /// <summary>
+        /// Implicitly convert n-dim. System.Array to ILNumerics array
+        /// </summary>
+        /// <param name="A">Arbitrarily sized System.Array</param>
+        /// <returns>If A is null: empty array. Else: new ILNumerics array of the same size as A</returns>
+        /// <remarks>The inner type of input array <paramref name="A"/> must match the requested type
+        /// <typeparamref name="ElementType"/>. The resulting ILArray will reflect all dimensions of 
+        /// A. Elements of A will get copied to elements of output array (shallow copy).</remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILCastException">If type of input does not match 
+        /// ElementType</exception>
+        public static implicit operator ILRetArray<ElementType>(Array A) {
+            if (A == null || A.Length == 0) {
+                // TODO: check: return null better? 
+                return new ILRetArray<ElementType>(ILSize.Empty00);
+            }
+            if (A.GetType().GetElementType() != typeof(ElementType))
+                throw new ILCastException("inner type of System.Array must match");
+            int[] dims = new int[A.Rank];
+            ElementType[] retArr = ILMemoryPool.Pool.New<ElementType>(A.Length);
+            int posArr = 0;
+            for (int i = 0; i < dims.Length; i++) {
+                dims[i] = A.GetLength(dims.Length - i - 1);
+            }
+            foreach (ElementType item in A)
+                retArr[posArr++] = item;
+            return new ILRetArray<ElementType>(retArr, dims);
+        }
+        /// <summary>
+        /// Implicitly cast two dimensional System.Array to ILNumerics array
+        /// </summary>
+        /// <param name="A">2-dimensional System.Array</param>
+        /// <returns>If A is null: empty array. ILNumerics array of same size and type as A otherwise.</returns>
+        public static implicit operator ILRetArray<ElementType>(ElementType[,] A) {
+            if (A == null || A.Length == 0) {
+                // TODO: check: return null better? 
+                return new ILRetArray<ElementType>(ILSize.Empty00);
+            }
+            int[] dims = new int[2];
+            ElementType[] retArr = ILMemoryPool.Pool.New<ElementType>(A.Length);
+            int posArr = 0;
+            for (int i = 0; i < 2; i++) {
+                dims[i] = A.GetLength(dims.Length - i - 1);
+            }
+            foreach (ElementType item in A)
+                retArr[posArr++] = item;
+            return new ILRetArray<ElementType>(retArr, dims);
+        }
+        /// <summary>
+        /// Implicitly cast three dimensional System.Array to ILNumerics array
+        /// </summary>
+        /// <param name="A">3-dimensional System.Array</param>
+        /// <returns>If A is null: empty array. ILNumerics array of same size and type as A otherwise.</returns>
+        public static implicit operator ILRetArray<ElementType>(ElementType[, ,] A) {
+            if (A == null || A.Length == 0) {
+                // TODO: check: return null better? 
+                return new ILRetArray<ElementType>(ILSize.Empty00);
+            }
+            int[] dims = new int[3];
+            ElementType[] retArr = ILMemoryPool.Pool.New<ElementType>(A.Length);
+            int posArr = 0;
+            for (int i = 0; i < 3; i++) {
+                dims[i] = A.GetLength(dims.Length - i - 1);
+            }
+            foreach (ElementType item in A)
+                retArr[posArr++] = item;
+            return new ILRetArray<ElementType>(retArr, dims);
+        }
+        /// <summary>
+        /// Convert array to temporary cell 
+        /// </summary>
+        /// <param name="A">Source array</param>
+        /// <returns>Temporary scalar cell, having the only element with a clone of A</returns>
+        public static implicit operator ILRetCell(ILRetArray<ElementType> A) {
+            using (ILScope.Enter(A)) {
+                ILRetCell ret = new ILRetCell(ILSize.Scalar1_1, A.Storage);
+                ret.Storage.FromImplicitCast = true;
+                return ret;
+            }
+        }
+        #endregion
+
+        #region implicit conversions
+        /// <summary>
+        /// 'Clone' conversion
+        /// </summary>
+        /// <param name="A">Source array</param>
+        /// <returns>Temporary ILArray, will be disposed after next operation</returns>
+        /// <remarks>This conversion is for convenient reasons only. It enables the direct 
+        /// use of (persistent) ILArray objects in situations where (temporary) ILRetArray 
+        /// is required. A (fast) clone will be made. This is an alias for A.C.</remarks>
+        public static implicit operator ILRetArray<ElementType>(ILArray<ElementType> A) {
+            if (object.Equals(A,null)) return null; 
+            return A.C;
+        }
+        /// <summary>
+        /// 'Clone' conversion
+        /// </summary>
+        /// <param name="A">Source array</param>
+        /// <returns>Temporary ILArray, will be disposed after next operation</returns>
+        /// <remarks>This conversion is for convenient reasons only. It enables the direct 
+        /// use of (persistent) ILArray objects in situations where (temporary) ILRetArray 
+        /// is required. One example is the conversion of ILArray as return type. 
+        /// A (fast) clone will be made. This is an alias for A.C.</remarks>
+        public static implicit operator ILRetArray<ElementType>(ILInArray<ElementType> A) {
+            if (object.Equals(A, null)) return null;
+            return A.C;
+        }
+        /// <summary>
+        /// 'Clone' conversion
+        /// </summary>
+        /// <param name="A">Source array</param>
+        /// <returns>temporary ILArray, will be disposed after next operation</returns>
+        /// <remarks>This conversion is for convenient reasons only. It enables the direct 
+        /// use of (persistent) ILArray objects in situations where (temporary) ILRetArray 
+        /// is required. One example is the conversion of ILArray as return type. 
+        /// A (fast) clone will be made. This is an alias for A.C.</remarks>
+        public static implicit operator ILRetArray<ElementType>(ILOutArray<ElementType> A) {
+            if (object.Equals(A, null)) return null;
+            return A.C;
+        }
+        #endregion
+        #endregion operator overloads
+
+        #region public function
+        /// <summary>
+        /// Clone of this array
+        /// </summary>
+        /// <remarks><para>
+        /// Clones of all arrays in ILNumerics are done in a very fast, lazy way. This means, 
+        /// at the time the clone is made, no relevant memory is copied. Elements of both arrays rather point to the same 
+        /// underlying System.Array. A reference counting mechanism ensures the detaching of thoses arrays 
+        /// on write access.</para>
+        /// <para>The clone returned will be of the same type as this instance.</para></remarks>
+        internal override ILBaseArray Clone() {
+            return this;
+        }
+        /// <summary>
+        /// Concatenate this array 
+        /// </summary>
+        /// <param name="A">n-dimensional storage</param>
+        /// <param name="dim">Dimension index along which to concatenate the arrays.</param>
+        /// <returns>New array with copy elements of this array and A</returns>
+        /// <remarks>The array returned will be a copy of both arrays involved. None 
+        /// of the input arrays will be altered. If <paramref name="dim"/> is larger than 
+        /// the number of dimensions of one of the arrays its value will be used in modulus. 
+        /// <para>The resulting array has the size of both input arrays, laid beside one 
+        /// another along the <paramref name="dim"/> dimension.</para></remarks>
+        public new ILRetArray<ElementType> Concat(ILInArray<ElementType> A, int dim) {
+            using (ILScope.Enter(this,A))
+                return new ILRetArray<ElementType>(Storage.Concat(A.Storage, dim));
+        }
+        /// <summary>
+        /// Compare elements and shape of this array with another array
+        /// </summary>
+        /// <param name="A">Other array</param>
+        /// <returns>true if shape and element values of both arrays match, false otherwise</returns>
+        /// <remarks><para>Calling this member will dispose this instance afterwards (for temporary arrays.</para></remarks>
+        public override bool Equals(object A) {
+            using (ILScope.Enter(this))
+                return base.Equals(A);
+        }
+        /// <summary>
+        /// Copy values of all elements into System.Array.
+        /// </summary>
+        /// <param name="outArray">[Output] System.Array, holding all element values of this ILDenseStorage.</param>
+        /// <remarks>The System.Array may be predefined. If its length is sufficient, it will be used and 
+        /// its leading elements will be overwritten when function returns. If 'outArray' is null or has too few elements, 
+        /// it will be recreated from the ILNumerics memory pool.</remarks>
+        public new void ExportValues(ref ElementType[] outArray) {
+            using (ILScope.Enter(this))
+                Storage.ExportValues(ref outArray); 
+        }
+        /// <summary>
+        /// Enumerator returning elements as ElementType
+        /// </summary>
+        /// <returns>Enumerator</returns>
+        /// <remarks>This method enables the use of ILNumerics arrays in foreach loops.
+        /// <para>The iterator is returned, if arrays are directly used in foreach statements. The iterator 
+        /// is compatible with ILNumerics memory management.</para></remarks>
+        /// <example><code>ILArray&lt;double&gt; A = rand(5,4,6);
+        /// foreach (double element in A) {
+        ///     // all elements are scalar double values
+        ///     String.Format("Element: {0} ", element);
+        ///     // Note: 'element' cannot be used to alter the collection! 
+        /// } </code>
+        /// </example> 
+        public override IEnumerator<ElementType> GetEnumerator() {
+            using (ILScope.Enter(this)) {
+                ElementType[] values = GetArrayForRead();
+                int len = Size.NumberOfElements;
+                for (int i = 0; i < len; i++)
+                    yield return values[i];
+            }
+        }
+        /// <summary>
+        /// Generate a hash code based on the current arrays values
+        /// </summary>
+        /// <returns>Hash code</returns>
+        /// <remarks>The hashcode is generated by taking the values currently stored in the array into account.
+        /// Therefore, the function must iterate over all elements in the array - which makes it somehow a costly 
+        /// operation. Take this into account, if you consider using large arrays in collections like dictionaries 
+        /// or hashtables, which make great use of hash codes.
+        /// <para>Calling this member will dispose this instance afterwards (for temporary arrays).</para></remarks>
+        public override int GetHashCode() {
+            using (ILScope.Enter(this))
+                return base.GetHashCode();
+        }
+        /// <summary>
+        /// Get minimum and maximum value of all elements - if any
+        /// </summary>
+        /// <param name="min">[Output] Minimum value</param>
+        /// <param name="max">[Output] Maximum value</param>
+        /// <returns>true if the limits exists and could be computed, false otherwise</returns>
+        /// <remarks>Empty arrays will return false. In this case the output parameter will be: default(ElementType).
+        /// <para>Calling this member will dispose this instance afterwards (for temporary arrays).</para></remarks>
+        public override bool GetLimits(out ElementType min, out ElementType max) {
+            using (ILScope.Enter(this))
+                return base.GetLimits(out min, out max);
+        }
+        /// <summary>
+        /// Get single element from this array
+        /// </summary>
+        /// <param name="idx">Indices, location of element</param>
+        /// <returns>The requested element</returns>
+        public override ElementType GetValue(params int[] idx) {
+            using (ILScope.Enter(this))
+                return base.GetValue(idx);
+        }
+        /// <summary>
+        /// Create replication of this array
+        /// </summary>
+        /// <param name="dims">Dimensions specifier. If the number of elements in <paramref name="dims"/> is 
+        /// less than the number of dimensions in this array, the trailing dimensions will 
+        /// be set to 1 (singleton dimensions). On the other hand, if the number specified 
+        /// is larger then the number of dimension stored inside the storge the resulting 
+        /// storage will get its number of dimensions extended accordingly. </param>
+        /// <returns>Array being created by multiple replications of this array along 
+        /// arbitrary dimensions according to <paramref name="dims"/></returns>
+        public new ILRetArray<ElementType> Repmat(params int[] dims) {
+            using (ILScope.Enter(this))
+                return new ILRetArray<ElementType>(Storage.Repmat(dims));
+        }
+        /// <summary>
+        /// Reshaped copy of this array
+        /// </summary>
+        /// <param name="dimensions">New dimensions of the array</param>
+        /// <returns>Reshaped copy of the array</returns>
+        /// <remarks><para>The current instance will not be changed. A new storage is created, having 
+        /// the elements of this array and a shape as determined by <paramref name="dimensions"/>.</para>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the number of elements in <paramref name="dimensions"/>
+        /// do not match the number of elements in this array.</exception>
+        public  new ILRetArray<ElementType> Reshape(ILSize dimensions) {
+            using (ILScope.Enter(this)) {
+                ILArray<ElementType> ret = C;
+                ret.Storage.Reshape(dimensions);
+                return ret;
+            }
+        }
+        /// <summary>
+        ///  Serialize this ILArray into a binary stream.
+        /// </summary>
+        /// <param name="outStream">System.IO.Stream to receive the byte stream 
+        /// for this ILBaseArray</param>
+        /// <returns>True on success, false on error.</returns>
+        /// <remarks><para>Calling this member will dispose this instance afterwards (for temporary arrays).</para>
+        /// </remarks>
+        public override bool Serialize(Stream outStream) {
+            using (ILScope.Enter(this))
+                return base.Serialize(outStream);
+        }
+        /// <summary>
+        /// Create array from this array and shift dimensions
+        /// </summary>
+        /// <param name="shift">Number of dimensions to shift</param>
+        /// <returns>Shifted version of this array</returns>
+        /// <remarks><para>The shift is done 'to the left':</para>
+        /// <example><code>ILArray&lt;double> A = zeros(2,4);
+        /// ILArray&lt;double> B = A.Shifted(1);
+        /// // B is now: &lt;double> [4,2]
+        /// 
+        /// ILArray&lt;double> C = zeros(2,4,3);
+        /// ILArray&lt;double> D = C.Shifted(1); 
+        /// // D is now: &lt;double> [4,3,2] 
+        /// </code></example>
+        /// <para>The dimensions are shifted circulary to the left. This 
+        /// can be imagined as removing the first dimensions from the beginning of the list of 
+        /// dimensions and "append" them to the end in a ringbuffer style.</para>
+        /// <para>For dimension shifts of '1', you may consider using the 
+        /// <see cref="ILNumerics.ILDenseArray{ElementType}.T"/> property for readability.</para>
+        /// <para><paramref name="shift"/> must be positive. It is taken modulus the number of dimensions.</para>
+        /// <seealso cref="ILNumerics.ILDenseArray{ElementType}.T"/></remarks>
+        public new ILRetArray<ElementType> Shifted(int shift) {
+            using (ILScope.Enter(this))
+                return new ILRetArray<ElementType>(Storage.ShiftDimensions(shift));
+        }
+        /// <summary>
+        /// Subarray creation
+        /// </summary>
+        /// <param name="size">Range specification, defining the size of the subarray</param>
+        /// <returns>Subarray as copy of a part of this array</returns>
+        /// <remarks>Consult the ILNumerics subarray documentation for all subarray indexing rules.</remarks>
+        public new ILRetArray<ElementType> Subarray(params ILBaseArray[] size) {
+            using (ILScope.Enter(this))
+            using (ILScope.Enter(size))
+                return new ILRetArray<ElementType>(Storage.Subarray(size));
+        }
+        
+        ///// <summary>
+        ///// Short textual summary of this instance; used for debug output
+        ///// </summary>
+        ///// <returns>String representation of type and size</returns>
+        ///// <remarks>The type of elements and the size of the array are displayed. If the array
+        ///// is scalar, its value is displayed next to the type.
+        ///// <para>Calling this member will dispose this instance afterwards (for temporary arrays).</para></remarks>
+        //public override string ShortInfo() {
+        //    using (ILScope.Enter(this))
+        //        return base.ShortInfo();
+        //}
+       
+        /// <summary>
+        /// Send values of this instance to stream. 
+        /// </summary>
+        /// <param name="stream">Stream to write the values into.</param>
+        /// <param name="format">Format string to be used for output. See <see cref="System.String.Format(string,object)"/> for a specification
+        /// of valid formating expressions. This flag is only used, when 'method' is set to 'Serial'.</param>
+        /// <param name="method">A constant out of <see cref="ILArrayStreamSerializationFlags"/>. Specifies the way in which
+        /// the values will be serialized.</param>
+        /// <remarks><para>If the 'Formatted' method is used, any occurences of the NewLine character(s) 
+        /// will be replaced from the format string before applying to the elements. This is done to 
+        /// prevent the format from breaking the 'page' style of the output.</para>
+        /// <para>If 'method' is set to 'Matlab', the array will be written as Matfile version 5.0. No compression will be used. The internal 'Name' property will be used as the
+        /// array name for writing. This array instance will be the only array in the .mat file. If you want to write several arrays bundled into one mat file, use the MatFile class to
+        /// create a collection of arrays and write the MatFile to stream.</para></remarks>
+        public override void ToStream(Stream stream, string format, ILArrayStreamSerializationFlags method) {
+            using (ILScope.Enter(this))
+                try {
+                    int len;
+                    switch (method) {
+                        case ILArrayStreamSerializationFlags.Serial:
+                            len = Size.NumberOfElements;
+                            using (TextWriter tw = new StreamWriter(stream)) {
+                                for (int i = 0; i < len; i++) {
+                                    tw.Write(format, GetValue(i));
+                                }
+                            }
+                            break;
+                        case ILArrayStreamSerializationFlags.Formatted:
+                            format = format.Replace(Environment.NewLine, "");
+                            ILDenseStorage<ElementType> temp = this.Storage.ShiftDimensions(1);
+                            //len = Dimensions.NumberOfElements / Dimensions[1]; 
+                            using (TextWriter tw = new StreamWriter(stream)) {
+                                tw.Write(temp.ValuesToString(0));
+                            }
+                            break;
+                        case ILArrayStreamSerializationFlags.Matlab:
+                            ILMatFile mf = new ILMatFile(new ILBaseArray[1] { this });
+                            mf.Write(stream);
+                            break;
+                    }
+                } catch (Exception e) {
+                    throw new ILException("ToStream: Could not serialize to stream.", e);
+                }
+        }
+        #endregion
+
+        #region indexer
+        /// <summary>
+        /// Subarray creation
+        /// </summary>
+        /// <param name="range">Range specification, defining the size of the subarray</param>
+        /// <returns>Subarray as copy of a part of this array</returns>
+        /// <remarks>Consult the ILNumerics subarray documentation for all subarray indexing rules.</remarks>
+        public ILRetArray<ElementType> this[params ILBaseArray[] range] {
+            get {
+                using (ILScope.Enter(this))
+                using (ILScope.Enter(range))
+                    return new ILRetArray<ElementType>(Storage.Subarray(range));
+            }
+        }
+        #endregion
+
+        #region memory management   
+        internal override bool EnterScope() {
+            return false; 
+        }
+        #endregion
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILRetCell.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILRetCell.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILRetCell.cs	(revision 9102)
@@ -0,0 +1,915 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using ILNumerics.Exceptions;
+using ILNumerics.Storage;
+
+namespace ILNumerics {
+    /// <summary>
+    /// ILCell: container class holding arbitrary array objects 
+    /// </summary>
+    /// <remarks>
+    /// ILCell acts as general purpose container. It stores arbitrary arrays of arbitrary element type. 
+    /// </remarks>
+    public sealed class ILRetCell : ILBaseCell {
+
+        private static readonly bool s_isTempArray = true;
+
+        #region constructors
+        /// <summary>
+        /// Create cell object with pre-created data in specified dimensions 
+        /// </summary>
+        /// <param name="data">Predefined element data array, will be used for new cell (no copy will be made)</param>
+        /// <param name="size">Size of the new cell</param>
+        /// <remarks>Object array data will directly be used for storage. No 
+        /// copy will be made. However, any arrays referenced by data are dereferenced for storage inside the cell. The size must match prod(size)</remarks>
+        [Obsolete("use <see cref='ILNumerics.ILMath.cell'/> instead!")]
+        internal ILRetCell(ILStorage[] data, params int[] size)
+            : base(new ILCellStorage(data, new ILSize(size)), s_isTempArray) {
+        }
+        /// <summary>
+        /// Create cell object with pre-created data in specified dimensions 
+        /// </summary>
+        /// <param name="data">Predefined element data array, will be used for new cell (no copy will be made)</param>
+        /// <param name="size">Size of the new cell</param>
+        /// <remarks>Object array data will directly be used for storage. No 
+        /// copy will be made. However, any arrays referenced by data are dereferenced for storage inside the cell. The size must match prod(size)</remarks>
+        [Obsolete("use <see cref='ILNumerics.ILMath.cell'/> instead!")]
+        internal ILRetCell(ILStorage[] data, ILSize size)
+            : base(new ILCellStorage(data, size), s_isTempArray) {
+        }
+        /// <summary>
+        /// Create new cell object, elements will be 'null' 
+        /// </summary>
+        /// <param name="size">Size descriptor of the new cell</param>
+        [Obsolete("use <see cref='ILNumerics.ILMath.cell'/> instead!")]
+        internal ILRetCell(params int[] size)
+            : base(new ILCellStorage(new ILStorage[ILCell.prod(size)], new ILSize(size)), s_isTempArray) { }
+
+        internal ILRetCell(ILCellStorage cellStorage)
+            : base(cellStorage, s_isTempArray) { }
+
+        [Obsolete("use <see cref='ILNumerics.ILMath.cell'/> instead!")]
+        internal ILRetCell(ILSize size, params ILStorage[] values)
+            : base(new ILCellStorage(values, size), s_isTempArray) { }
+
+        #endregion constructors
+
+        #region properties
+        /// <summary>
+        /// Clone of this cell
+        /// </summary>
+        /// <remarks><para>
+        /// Clones of all arrays in ILNumerics are done in a very fast, lazy way. This means, 
+        /// at the time the clone is made, no relevant memory is copied. Elements of both arrays rather point to the same 
+        /// underlying System.Array. A reference counting mechanism ensures the detaching of thoses arrays on write access.</para>
+        /// <para>Cells profit from the same efficient clone creation process. However, since a cell may store an arbitrarily deep 
+        /// hierarchy of other cells and arrays, in order to clone a cell, the cell elements have to be cloned as well - in an 
+        /// recursive manner. Clones play an important role for ILNumerics cells. They are used to implement value semantics for cell
+        /// elements. I.e.: the cloned cell returned cannot not be used to alter elements of the original cell in any way.</para></remarks>
+        public new ILRetCell C {
+            get {
+                return this;
+            }
+        }
+        /// <summary>
+        /// Size descriptor shortcut
+        /// </summary>
+        public override ILSize S {
+            get {
+                using (ILScope.Enter(this))
+                    return Storage.Size;
+            }
+        }
+        /// <summary>
+        /// Size descriptor
+        /// </summary>
+        public override ILSize Size {
+            get {
+                using (ILScope.Enter(this))
+                    return Storage.Size;
+            }
+        }
+        /// <summary>
+        /// Test if this array instance is a column vector
+        /// </summary>
+        public override bool IsColumnVector {
+            get {
+                using (ILScope.Enter(this))
+                    return Size[1] == 1 && Size.NumberOfDimensions == 2; ;
+            }
+        }
+        /// <summary>
+        /// Test if this array instance is a row vector
+        /// </summary>
+        public override bool IsRowVector {
+            get {
+                using (ILScope.Enter(this))
+                    return Size[0] == 1 && Size.NumberOfDimensions == 2;
+            }
+        }
+        /// <summary>
+        /// Determine if this array has complex elements.
+        /// </summary>
+        /// <remarks><para>Calling this member will dispose this instance afterwards (for temporary arrays).</para></remarks>
+        public override bool IsComplex {
+            get {
+                using (ILScope.Enter(this))
+                    return base.IsComplex;
+            }
+        }
+        /// <summary>
+        /// Test if this instance is an empty array (number of elements stored = 0)
+        /// </summary>
+        public override bool IsEmpty {
+            get {
+                using (ILScope.Enter(this))
+                    return Size.NumberOfElements == 0;
+            }
+        }
+        /// <summary>
+        /// Test if this instance is a matrix
+        /// </summary>
+        /// <remarks>In order for an array to be a matrix the number of <b>non singleton</b> 
+        /// dimensions must equal 2. This attribute is readonly.</remarks>
+        public override bool IsMatrix {
+            get {
+                using (ILScope.Enter(this))
+                    return Size.NumberOfDimensions == 2;
+            }
+        }
+        /// <summary>
+        /// Determine if this array holds numeric values.
+        /// </summary>
+        /// <remarks>An ILArray is numeric as long as its elements are one of the 
+        /// following types: 
+        /// <list type="table">
+        /// <listheader>
+        ///     <term>inner type</term>
+        /// </listheader>
+        /// <item>
+        ///     <term>System.double</term>
+        ///     <description>floating point, real, 8 bytes </description>
+        /// </item>
+        /// <item>
+        ///     <term>System.float</term>
+        ///     <description>floating point real, 4 bytes</description>
+        /// </item>
+        /// <item>
+        ///     <term>ILNumerics.complex</term>
+        ///     <description>floating point complex, 16 bytes</description>
+        /// </item>
+        /// <item>
+        ///     <term>ILNumerics.fcomplex</term>
+        ///     <description>floating point complex, 8 bytes</description>
+        /// </item>
+        /// <item>
+        ///     <term>System.char</term>
+        ///     <description>integer, real, 1 byte</description>
+        /// </item>
+        /// <item>
+        ///     <term>System.byte</term>
+        ///     <description>integer, real, 1 byte</description>
+        /// </item>
+        /// <item>
+        ///     <term>System.Int16</term>
+        ///     <description>integer, real, 2 byte</description>
+        /// </item>
+        /// <item>
+        ///     <term>System.Int32</term>
+        ///     <description>integer, real, 4 byte</description>
+        /// </item>
+        /// <item>
+        ///     <term>System.Int64</term>
+        ///     <description>integer, real, 8 byte</description>
+        /// </item>
+        /// <item>
+        ///     <term>System.UInt16</term>
+        ///     <description>unsigned integer, real, 2 byte</description>
+        /// </item>
+        /// <item>
+        ///     <term>System.UInt32</term>
+        ///     <description>unsigned integer, real, 4 byte</description>
+        /// </item>
+        /// <item>
+        ///     <term>System.UInt64</term>
+        ///     <description>unsigned integer, real, 8 byte</description>
+        /// </item>
+        /// </list>
+        /// <para>Calling this member will dispose this instance afterwards (for temporary arrays).</para>
+        /// </remarks>
+        public override bool IsNumeric {
+            get {
+                using (ILScope.Enter(this))
+                    return base.IsNumeric;
+            }
+        }
+        /// <summary>
+        /// Test if this instance is a scalar
+        /// </summary>
+        /// <remarks>This attribute is readonly. It returns: Dimension.NumberOfElements == 1.</remarks>
+        public override bool IsScalar {
+            get {
+                using (ILScope.Enter(this))
+                    return Size.NumberOfElements == 1;
+            }
+        }
+        /// <summary>
+        /// Test if this array is a vector
+        /// </summary>
+        /// <remarks>In order for an array to be a vector the number of <b>non singleton</b> 
+        /// dimensions must equal 1. Keep in mind that all ILArrays have at least 2 dimensions. Therefore 
+        /// it is not sufficient to test for the number of dimensions, but to take the number of 
+        /// <b>non singleton</b> dimensions into account. This attribute is readonly.</remarks>
+        public override bool IsVector {
+            get {
+                using (ILScope.Enter(this))
+                    return (Size[0] == 1 || Size[1] == 1) && Size.NumberOfDimensions == 2;
+            }
+        }
+        /// <summary>
+        /// Length of the longest dimension of this instance
+        /// </summary>
+        /// <remarks>This property is readonly.
+        /// <para>Calling this member will dispose this instance afterwards (for temporary arrays).</para></remarks>
+        public override int Length {
+            get {
+                using (ILScope.Enter(this))
+                    return base.Length;
+            }
+        }
+        /// <summary>
+        /// Transposed version of this ILCell
+        /// </summary>
+        public new ILRetCell T {
+            get {
+                using (ILScope.Enter(this))
+                    return new ILRetCell((ILCellStorage)Storage.ShiftDimensions(1));
+            }
+        }
+        /// <summary>
+        /// Gets the name of this array (readonly)
+        /// </summary>
+        public new String Name {
+            get {
+                using (ILScope.Enter(this))
+                    return m_name;
+            }
+        }
+        /// <summary>
+        /// Access to the more specialized version (ILCellStorage) of this storage
+        /// </summary>
+        internal new ILCellStorage Storage {
+            get { return (m_storage as ILCellStorage); }
+            set {
+                // e.g. Storage.Detach() may return itself (if no detaching is 
+                // required). So we must check for that equalty here! 
+                if (!object.Equals(value, m_storage)) {
+                    m_storage.Dispose();
+                    m_storage = value;
+                }
+            }
+        }
+        #endregion
+
+        #region implicit casts
+        #region constructional operators
+        /// <summary>
+        /// Convert primitive integer to a scalar temporary cell
+        /// </summary>
+        /// <param name="value">Primitive scalar int value</param>
+        /// <returns>New scalar temporary cell</returns>
+        public static implicit operator ILRetCell(int value) {
+            ILRetCell ret = createScalar(value);
+            ret.Storage.FromImplicitCast = true;
+            return ret;
+        }
+        /// <summary>
+        /// Convert primitive double to a scalar temporary cell
+        /// </summary>
+        /// <param name="value">Primitive scalar double value</param>
+        /// <returns>New scalar temporary cell</returns>
+        public static implicit operator ILRetCell(double value) {
+            ILRetCell ret = createScalar(value);
+            ret.Storage.FromImplicitCast = true;
+            return ret;
+        }
+        /// <summary>
+        /// Convert primitive float to a scalar temporary cell
+        /// </summary>
+        /// <param name="value">Primitive scalar float value</param>
+        /// <returns>New scalar temporary cell</returns>
+        public static implicit operator ILRetCell(float value) {
+            ILRetCell ret = createScalar(value);
+            ret.Storage.FromImplicitCast = true;
+            return ret;
+        }
+        /// <summary>
+        /// Convert primitive byte to a scalar temporary cell
+        /// </summary>
+        /// <param name="value">Primitive byte int value</param>
+        /// <returns>New scalar temporary cell</returns>
+        public static implicit operator ILRetCell(byte value) {
+            ILRetCell ret = createScalar(value);
+            ret.Storage.FromImplicitCast = true;
+            return ret;
+        }
+        /// <summary>
+        /// Encapsulate integer System.Array into a scalar temporary cell
+        /// </summary>
+        /// <param name="value">Primitive System.Int32 value - no copy will be made!</param>
+        /// <returns>New scalar temporary cell</returns>
+        public static implicit operator ILRetCell(int[] value) {
+            ILRetCell ret = createArray(value);
+            ret.Storage.FromImplicitCast = true;
+            return ret;
+        }
+        /// <summary>
+        /// Convert string to a scalar temporary cell
+        /// </summary>
+        /// <param name="value">String value</param>
+        /// <returns>New scalar temporary cell</returns>
+        public static implicit operator ILRetCell(string value) {
+            ILRetCell ret = createScalar(value);
+            ret.Storage.FromImplicitCast = true;
+            return ret;
+        }
+        /// <summary>
+        /// Encapsulate array of strings into a scalar temporary cell
+        /// </summary>
+        /// <param name="value">String array - no copy will be made!</param>
+        /// <returns>New scalar temporary cell</returns>
+        public static implicit operator ILRetCell(string[] value) {
+            ILRetCell ret = createArray(value);
+            ret.Storage.FromImplicitCast = true;
+            return ret;
+        }
+        #endregion
+
+        #region conversional operators
+        /// <summary>
+        /// Convert cell to temporary cell
+        /// </summary>
+        /// <param name="A">Cell</param>
+        /// <returns>Temporary cell</returns>
+        public static implicit operator ILRetCell(ILCell A) {
+            if (object.Equals(A, null)) return null;
+            return A.C;
+        }
+        /// <summary>
+        /// Convert input parameter cell to temporary cell
+        /// </summary>
+        /// <param name="A">Input parameter cell</param>
+        /// <returns>Temporary cell</returns>
+        public static implicit operator ILRetCell(ILInCell A) {
+            if (object.Equals(A, null)) return null;
+            return A.C;
+        }
+        /// <summary>
+        /// Convert output parameter cell to temporary cell
+        /// </summary>
+        /// <param name="A">Output parameter cell</param>
+        /// <returns>Temporary cell</returns>
+        public static implicit operator ILRetCell(ILOutCell A) {
+            if (object.Equals(A, null)) return null;
+            return A.C;
+        }
+        /// <summary>
+        /// Wrap single logical array into a new scalar temporary cell
+        /// </summary>
+        /// <param name="A">Logical array</param>
+        /// <returns>Scalar cell</returns>
+        public static implicit operator ILRetCell(ILBaseLogical A) {
+            if (object.Equals(A, null)) return null;
+            ILRetCell ret = ILMath.cell(A);
+            ret.Storage.FromImplicitCast = true;
+            return ret;
+        }
+        #endregion
+        #endregion
+
+        #region helper functions
+        private static ILRetCell createScalar<T>(T value) {
+            using (ILScope.Enter()) {
+                ILCell ret = new ILCell(1, 1);
+                ret.SetValue(new ILDenseStorage<T>(new T[] { value }, ILSize.Scalar1_1), 0, 0);
+                return ret;
+            }
+        }
+        private static ILRetCell createArray<T>(T[] value) {
+            using (ILScope.Enter()) {
+                ILCell ret = new ILCell(1, 1);
+                ret.SetValue(new ILDenseStorage<T>(value, new ILSize(1, value.Length)), 0, 0);
+                return ret;
+            }
+        }
+        #endregion helper functions
+
+        #region public interface
+        /// <summary>
+        /// Clone of this array
+        /// </summary>
+        /// <remarks><para>
+        /// Clones of all arrays in ILNumerics are done in a very fast, lazy way. This means, 
+        /// at the time the clone is made, no relevant memory is copied. Elements of both arrays rather point to the same 
+        /// underlying System.Array. A reference counting mechanism ensures the detaching of thoses arrays 
+        /// on write access.</para>
+        /// <para>The clone returned will be of the same type as this instance.</para></remarks>
+        internal override ILBaseArray Clone() {
+            return this;
+        }
+        /// <summary>
+        /// Concatenate this cell 
+        /// </summary>
+        /// <param name="A">Cell to concatenate this cell with</param>
+        /// <param name="dim">Dimension index along which to concatenate the cells.</param>
+        /// <returns>new cell with concatenation of all elements of both cells</returns>
+        /// <remarks>The array returned will be a copy of both cells involved. 
+        /// If <paramref name="dim"/> is larger than 
+        /// the number of dimensions of one of the arrays its value will be used in modulus. 
+        /// <para>The resulting cell has the size of both input cells, laid beside one 
+        /// another along the <paramref name="dim"/> dimension.</para></remarks>
+        public new ILRetCell Concat(ILInCell A, int dim) {
+            using (ILScope.Enter(this))
+            using (ILScope.Enter(A))
+                return base.Concat(A, dim);
+        }
+        /// <summary>
+        /// Compare elements and shape of this array with another array
+        /// </summary>
+        /// <param name="A">Other array</param>
+        /// <returns>true if shape and element values of both arrays match, false otherwise</returns>
+        /// <remarks><para>Calling this member will dispose this instance afterwards (for temporary arrays.</para></remarks>
+        public override bool Equals(object A) {
+            using (ILScope.Enter(this))
+                return base.Equals(A);
+        }
+        /// <summary>
+        /// Copy values of all elements into System.Array.
+        /// </summary>
+        /// <param name="outArray">[Output] System.Array, holding all element values of this ILDenseStorage.</param>
+        /// <remarks>The System.Array may be predefined. If its length is sufficient, it will be used and 
+        /// its leading elements will be overwritten when function returns. If 'outArray' is null or has too few elements, 
+        /// it will be recreated from the ILNumerics memory pool.</remarks>
+        internal new void ExportValues(ref ILStorage[] outArray) {
+            using (ILScope.Enter(this))
+                Storage.ExportValues(ref outArray);
+        }
+        /// <summary>
+        /// Retrieve a single array of a known type from a cell position
+        /// </summary>
+        /// <typeparam name="T">Element type of the array</typeparam>
+        /// <param name="indices">Position of the array within this cell</param>
+        /// <returns>Lazy, shallow clone of the array found at the given position</returns>
+        public new ILRetArray<T> GetArray<T>(params ILBaseArray[] indices) {
+            using (ILScope.Enter(this))
+            using (ILScope.Enter(indices))
+                return base.GetArray<T>(indices);
+        }
+        /// <summary>
+        /// Retrieve a single element from the given position
+        /// </summary>
+        /// <param name="indices">Position of the element to retrieve, must evaluate to a scalar position</param>
+        /// <returns>A clone of the scalar element found</returns>
+        /// <remarks>
+        /// <para>The method returns a lazy, shallow clone of the content of the cell element specified by <paramref name="indices"/>. 
+        /// However, the return type (<code>ILBaseArray</code>) is not strongly typed and may contain <b>any</b> element. According to the 
+        /// true element stored in the cell, this might be an array of arbitrary type, null or even another cell. Moreover, handling 
+        /// <code>ILBaseArray</code> directly is not recommended for ILNumerics, since this would hinder the memory management from proper 
+        /// functioning. Therefore: <b>The use of this method is not recommended and left to ILNumerics experts - for very 
+        /// specific and rare situations.</b></para>
+        /// </remarks>
+        public new ILBaseArray GetBaseArray(params ILBaseArray[] indices) {
+            using (ILScope.Enter(this))
+            using (ILScope.Enter(indices))
+                return base.GetBaseArray(indices);
+        }
+        /// <summary>
+        /// Retrieve a subcell of this cell
+        /// </summary>
+        /// <param name="indices">Subcell definition, arbitrary size</param>
+        /// <returns>A cell with a lazy, shallow clone of the elements of this cell, addressed by <paramref name="indices"/></returns>
+        /// <remarks>The cell returned will have the size and shape specified by <paramref name="indices"/>.</remarks>
+        public new ILRetCell GetCell(params ILBaseArray[] indices) {
+            using (ILScope.Enter(this))
+            using (ILScope.Enter(indices)) {
+                return new ILRetCell((ILCellStorage)Storage.Subarray(indices));
+            }
+        }
+        /// <summary>
+        /// Enumerator returning elements as scalar cells
+        /// </summary>
+        /// <returns>Enumerator</returns>
+        /// <remarks>This method enables the use of cells in foreach loops.
+        /// <para>The iterator is returned, if arrays are directly used in foreach statements. The iterator 
+        /// is compatible with ILNumerics memory management.</para></remarks>
+        /// <example><code>ILDenseStorage&lt;T&gt; A = ILMath.rand(5,4,6);
+        /// foreach (double element in A) {
+        /// // all elements are scalar double values
+        /// String.Format("Element: {0} ",element);
+        /// // Note: 'element' cannot be used to alter the collection! 
+        /// } 
+        /// </code></example> 
+        public new IEnumerator<ILRetCell> GetEnumerator() {
+            using (ILScope.Enter(this)) {
+                return base.GetEnumerator();
+            }
+        }
+        /// <summary>
+        /// Generate a hash code based on the current arrays values
+        /// </summary>
+        /// <returns>Hash code</returns>
+        /// <remarks>The hashcode is generated by taking the values currently stored in the array into account.
+        /// Therefore, the function must iterate over all elements in the array - which makes it somehow a costly 
+        /// operation. Take this into account, if you consider using large arrays in collections like dictionaries 
+        /// or hashtables, which make great use of hash codes.
+        /// <para>Calling this member will dispose this instance afterwards (for temporary arrays).</para></remarks>
+        public override int GetHashCode() {
+            using (ILScope.Enter(this))
+                return base.GetHashCode();
+        }
+        /// <summary>
+        /// Get minimum and maximum value of all elements - if any
+        /// </summary>
+        /// <param name="min">[Output] Minimum value</param>
+        /// <param name="max">[Output] Maximum value</param>
+        /// <returns>true if the limits exists and could be computed, false otherwise</returns>
+        /// <remarks>Empty arrays will return false. In this case the output parameter will be: default(ElementType).
+        /// <para>Calling this member will dispose this instance afterwards (for temporary arrays).</para></remarks>
+        internal new bool GetLimits(out ILStorage min, out ILStorage max) {
+            using (ILScope.Enter(this))
+                return base.GetLimits(out min, out max);
+        }
+        /// <summary>
+        /// Retrieve single element from this cell
+        /// </summary>
+        /// <param name="idx">Position of the element</param>
+        /// <returns>Lazy, shallow clone of the element to retrieve or null, if there is no element at this place</returns>
+        public new object GetValue(params int[] idx) {
+            using (ILScope.Enter(this)) {
+                return base.GetValue(idx);
+            }
+        }
+        /// <summary>
+        /// Retrieve a typed single element from within the cell, supports deep indexing
+        /// </summary>
+        /// <typeparam name="T">Expected type of the value to be returned</typeparam>
+        /// <param name="indices">Location of the single element addressed</param>
+        /// <returns>A clone of the single element addressed by <paramref name="indices"/></returns>
+        /// <remarks>The element returned will have the type given by <typeparamref name="T"/>. It is an error to specify 
+        /// a different type as the true type of the element specified. An exception is thrown if both types differ.</remarks>
+        public new T GetValue<T>(params int[] indices) {
+            using (ILScope.Enter(this)) {
+                return Storage.GetValue<T>(indices);
+            }
+        }
+        /// <summary>
+        /// Test if an element of the cell is an array of the given element type
+        /// </summary>
+        /// <typeparam name="T">The array element type to check the cell element against</typeparam>
+        /// <param name="position">Position of the cell element to be tested</param>
+        /// <returns>true if the element found at the given position is an array of the element type <typeparamref name="T"/>, false otherwise</returns>
+        /// <remarks>The method is helpful in order to investigate the contents of a cell array. If you are not sure about the 
+        /// types of elements in the cell, this function can be used to make sure, elements are of the expected type before retrieving them as such.
+        /// <para>In most situations, elements of a cell are stored arrays of a distinct element type. That element type is given to IsTypeOf as 
+        /// typeparameter <typeparamref name="T"/>. That means, in order to find out, if the first cell element stores an array of int (<code>ILArray&lt;int></code>), 
+        /// one may use <code>cell.IsTypeOf&lt;int>(0)</code></para>
+        /// <para>In order to test, if a cell element is of type <code>ILCell</code>, one can provide the type <code>ILCell</code> as type parameter: 
+        /// <code>cell.IsTypeOf&lt;ILCell>(0)</code>. Note the different semantic when checking for cell elements of type cell. Here we do not test for the 
+        /// element type but for the array type itself, ie. <code>ILCell</code>. The reason of this is: the type of elements of <code>ILCell</code> is 
+        /// an implementation detail and therefore hidden to the user.</para>
+        /// </remarks>
+        /// <example>
+        /// <para>In the following example a ILCell of size 3x2 is created. It stores several array types, among which other cells are stored as elements of the outer cell.</para>
+        /// <code>ILCell cell = ILMath.cell(new ILSize(3, 2) 
+        ///                      , "first element"
+        ///                      , 2.0
+        ///                      , ILMath.cell(Math.PI, 100f)
+        ///                      , ILMath.create&lt;short>(1, 2, 3, 4, 5, 6)
+        ///                      , new double[] {-1.4, -1.5, -1.6});
+        /// </code>
+        /// The cell is now: 
+        /// <code>ILCell [3,2]
+        ///          &lt;String>      first element  &lt;Int16> [2,3,4,5,6] 
+        ///          &lt;Double>          2          ILCell [1,3]           
+        ///          ILCell [2,1]                                    (null)	
+        /// </code>
+        /// We test the element type of every element in the cell: 
+        /// <code>
+        /// Console.Out.WriteLine("cell[0,0] is of type 'string': {0}", cell.IsTypeOf&lt;string>(0));
+        /// Console.Out.WriteLine("cell[0,0] is of type 'double': {0}", cell.IsTypeOf&lt;double>(0));
+        ///                                      
+        /// Console.Out.WriteLine("cell[1,0] is of type 'double': {0}", cell.IsTypeOf&lt;double>(1));
+        /// Console.Out.WriteLine("cell[2,0] is of type 'ILCell': {0}", cell.IsTypeOf&lt;ILCell>(2));
+        ///                                                                         
+        /// Console.Out.WriteLine("cell[0,1] is of type 'short': {0}", cell.IsTypeOf&lt;short>(0, 1));
+        /// Console.Out.WriteLine("cell[1,1] is of type 'ILCell': {0}", cell.IsTypeOf&lt;ILCell>(1, 1));
+        /// Console.Out.WriteLine("cell[2,1] is of type 'double': {0}", cell.IsTypeOf&lt;double>(2, 1));
+        /// </code>
+        /// This gives the following output: 
+        /// <code>
+        /// cell[0,0] is element type 'string': True
+        /// cell[0,0] is element type 'double': False
+        /// cell[1,0] is element type 'double': True
+        /// cell[2,0] is element type 'ILCell': True
+        /// cell[0,1] is element type 'short': True
+        /// cell[1,1] is element type 'ILCell': True
+        /// cell[2,1] is element type 'double': False  // element is null, IsTypeOf&lt;> never gives true
+        /// </code></example>
+        public new bool IsTypeOf<T>(params ILBaseArray[] position) {
+            using (ILScope.Enter(this))
+            using (ILScope.Enter(position)) {
+                return Storage.IsTypeOf<T>(position);
+            }
+        }
+        /// <summary>
+        /// Create replication of this cell
+        /// </summary>
+        /// <param name="dims">Dimensions specifier. If the number of elements in <paramref name="dims"/> is 
+        /// less than the number of dimensions in this cell, the trailing dimensions will 
+        /// be set to 1 (singleton dimensions). On the other hand, if the number specified 
+        /// is larger then the number of dimension stored inside the storge the resulting 
+        /// storage will get its number of dimensions extended accordingly. </param>
+        /// <returns>Array being created by multiple replications of this array along 
+        /// arbitrary dimensions according to <paramref name="dims"/></returns>
+        public new ILRetCell Repmat(params int[] dims) {
+            using (ILScope.Enter(this))
+                return new ILRetCell((ILCellStorage)Storage.Repmat(dims));
+        }
+        /// <summary>
+        /// Create reshaped copy of this cell
+        /// </summary>
+        /// <param name="dimensions">New dimensions of the cell</param>
+        /// <returns>Reshaped copy of the cell</returns>
+        /// <remarks><para>The current instance will not be changed! A new cell is created, having 
+        /// the elements of this cell and a shape as determined by <paramref name="dimensions"/>.</para>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the number of elements in 
+        /// <paramref name="dimensions"/> do not match the number of elements in this cell.</exception>
+        public new ILRetCell Reshape(ILSize dimensions) {
+            using (ILScope.Enter(this)) {
+                return base.Reshape(dimensions);
+            }
+        }
+        /// <summary>
+        ///  Serialize this ILArray into a binary stream.
+        /// </summary>
+        /// <param name="outStream">System.IO.Stream to receive the byte stream 
+        /// for this ILBaseArray</param>
+        /// <returns>True on success, false on error.</returns>
+        /// <remarks><para>Calling this member will dispose this instance afterwards (for temporary arrays).</para>
+        /// </remarks>
+        public override bool Serialize(Stream outStream) {
+            using (ILScope.Enter(this))
+                return base.Serialize(outStream);
+        }
+        /// <summary>
+        /// Dimension shifted cell from this cell
+        /// </summary>
+        /// <param name="shift">Number of dimensions to shift</param>
+        /// <returns>Shifted version of this cell</returns>
+        /// <remarks><para>The shift is done 'to the left':</para>
+        /// <example><code>ILCell A = cell(2,4); 
+        /// ILCell B = A.Shifted(1);
+        /// // B is now: ILCell [4,2] 
+        /// 
+        /// ILCell C = cell(2,4,3);
+        /// ILCell D = C.Shifted(1);
+        /// // D is now: ILCell [4,3,2]
+        /// </code></example>
+        /// <para>The dimensions are shifted circulary to the left. This 
+        /// can be imagined as removing the first dimensions from the beginning of the list of 
+        /// dimensions and "append" them to the end in a ringbuffer style. </para>
+        /// <para>For dimension shifts of '1', you may consider using the 
+        /// <see cref="ILNumerics.ILDenseArray{ElementType}.T"/> property for readability.</para>
+        /// <para><paramref name="shift"/> must be positive. It is taken modulus the number of dimensions.</para>
+        /// <seealso cref="ILNumerics.ILDenseArray{ElementType}.T"/></remarks>
+        public new ILRetCell Shifted(int shift) {
+            using (ILScope.Enter(this))
+                return new ILRetCell((ILCellStorage)Storage.ShiftDimensions(shift));
+        }
+        /// <summary>
+        /// Subarray access (readonly) 
+        /// </summary>
+        /// <param name="indices">Address range</param>
+        /// <returns>Reference cell array with subarray addressed by <c>indices</c>. </returns>
+        /// <remarks>Query access: for N-dimensional cell arrays missing trailing dimensions indices will be choosen to be 0. Therefore you 
+        /// may ommit those trailing dimensions in <c>indices</c>.
+        /// <para>The indexer may be used for querying or altering single/any elements 
+        /// in this cell. <c>indices</c> may contains index specifications for one to any 
+        /// dimension. The cell array returned will have the size specified by <c>indices</c>.</para>
+        /// <para>Values returned will be reference cells. All elements contained will be 'deep references' created by 
+        /// recursively walking downwards the elements and replacing them by references to itself. Therefore altering the 
+        /// values returned will not alter the original elements stored in the cell.</para>
+        /// </remarks>
+        public new ILRetCell Subarray(params ILBaseArray[] indices) {
+            using (ILScope.Enter(this))
+            using (ILScope.Enter(indices)) {
+                ILCellStorage elements = (ILCellStorage)Storage.Subarray(indices);
+                return new ILRetCell(elements);
+            }
+        }
+        /// <summary>
+        /// Send values of this instance to stream
+        /// </summary>
+        /// <param name="stream">Stream to write the values into.</param>
+        /// <param name="format">Format string to be used for output. See <see cref="System.String.Format(string,object)"/> for a specification
+        /// of valid formating expressions. This flag is only used, when 'method' is set to 'Serial'.</param>
+        /// <param name="method">A constant out of <see cref="ILArrayStreamSerializationFlags"/>. Specifies the way in which
+        /// the values will be serialized.</param>
+        /// <remarks><para>If the 'Formatted' method is used, any occurences of the NewLine character(s) 
+        /// will be replaced from the format string before applying to the elements. This is done to 
+        /// prevent the format from breaking the 'page' style of the output.</para>
+        /// <para>Writing cells to *.mat files is NOT SUPPORTED yet! </para></remarks>
+        public override void ToStream(Stream stream, string format, ILArrayStreamSerializationFlags method) {
+            using (ILScope.Enter(this))
+                try {
+                    int len;
+                    switch (method) {
+                        case ILArrayStreamSerializationFlags.Serial:
+                            len = Size.NumberOfElements;
+                            using (TextWriter tw = new StreamWriter(stream)) {
+                                for (int i = 0; i < len; i++) {
+                                    tw.Write(format, GetValue(i));
+                                }
+                            }
+                            break;
+                        case ILArrayStreamSerializationFlags.Formatted:
+                            format = format.Replace(Environment.NewLine, "");
+                            ILDenseStorage<ILStorage> temp = this.Storage.ShiftDimensions(1);
+                            //len = Dimensions.NumberOfElements / Dimensions[1]; 
+                            using (TextWriter tw = new StreamWriter(stream)) {
+                                tw.Write(temp.ValuesToString(0));
+                            }
+                            break;
+                        case ILArrayStreamSerializationFlags.Matlab:
+                            ILMatFile mf = new ILMatFile(new ILBaseArray[1] { this });
+                            mf.Write(stream);
+                            break;
+                    }
+                } catch (Exception e) {
+                    throw new ILException("ToStream: Could not serialize to stream.", e);
+                }
+        }
+        #endregion
+
+        #region Index access
+        /// <summary>
+        /// Get/set/remove single element 
+        /// </summary> 
+        /// <paramref name="indices" value="Index to element"/>
+        /// <value>Inner element, new inner element or null</value>
+        /// <remarks>The type of access depends on the length of indices. If indices contains only one element, 
+        /// the array will be accessed via sequential index access. This is sometimes called referred to as 'linear' 
+        /// index addressing. 
+        /// Sequential index access reflects the index of internal storage the way the data are actually organized 
+        /// in memory. This access method is mainly convinient for vectors where you are not interested of orientation.
+        /// The following example demonstrates sequential index access for ILArray's (which also holds for ILCells): 
+        /// <example><code>
+        /// ILArray&lt;double&gt; A = ILMath.counter(1,12);
+        /// A[2] gives: 3.0
+        /// </code>But the transpose 
+        /// <code>
+        /// A.T[2] gives also: 3.0
+        /// </code> 
+        /// For matrices and N-dimensional arrays this holds as well: 
+        /// <code>
+        /// ILArray&lt;double&gt; A = ILMath.counter(1.0,1.0,3,2,2);
+        /// A = 
+        /// [1.0 4.0
+        ///  2.0 5.0 
+        ///  3.0 6.0 
+        /// 
+        ///  7.0 10.0
+        ///  8.0 11.0
+        ///  9.0 12.0]
+        /// 
+        /// A = ILMath.Reshape(A,3,2,2); 
+        /// A[10] gives 11.0
+        /// A[10,1] gives ILArgumentException -> out of range
+        /// A[2,1,1] gives 12.0
+        /// A[2,1] gives 6.0 (set trailing dimension to '0')</code></example>
+        /// <para>If the element addressed is a ILCell itself, a deep reference to this element will be returned instead. 
+        /// I.e. all elements of the ILCell will be recursively replaced with references to itself. Therefore, altering the 
+        /// elements returned will not alter the elements contained in the cell.</para>
+        /// <para>
+        /// <list type="bullet">
+        /// <listheader>The type of the element returned depends on the type of the element addressed:</listheader>
+        /// <item>For ILArray&lt;ElementType&gt; the array returned will be a clone of the original array.</item> 
+        /// <item>For ILCell the ILBaseArray returned is a deep reference of the original elements stored.</item>
+        /// <item>For other types the behavior is undefined. (since other types are not implemented yet ;)</item>
+        /// </list> </para>
+        /// <para>This indexer may also be used for direct access to inner elements of (elements of elements of ...) this cell:
+        /// <example>
+        /// <code>
+        /// ILCell innerCell = new ILCell(2,1); 
+        /// innerCell[0] = ILMath.vec(10,200); 
+        /// innerCell[1] = new int[] {-10,-20,-30};
+        /// ILCell cell = new ILCell(2,1); 
+        /// cell[0] = innerCell; 
+        /// cell[1] = new string[] {"foobla"}; 
+        /// // cell is now: 
+        /// // [ILCell,(1x2)] 
+        /// //      [innerCell[0], ILArray&lt;double&gt;(1x181)]
+        /// //      [innerCell[0], ILArray&lt;double&gt;(1x3)]
+        /// // [ILArray&lt;string&gt;,(1x1)]
+        /// 
+        /// cell[0,0] -&gt; will give innerCell eq. ILCell (1x2)
+        /// cell[0,1] -&gt; will give ILArray&lt;string&gt;
+        /// cell[0,0,0,1] -&gt; will give innerCell[1] eq. ILArray&lt;int&gt;(1x3)
+        /// </code>
+        /// </example> 
+        /// In the last example above the trailing indices specified make the indexer walk down into the ILCell element and retrieve 
+        /// the content of this element. This kind of index access may be done as deep as you want. Just 
+        /// append the inner indices into inner elements to the right side of index specification. Addressing inner elements 
+        /// this way is the only way to alter elements <b>directly</b> inside the ILCell. </para></remarks>
+        public ILRetCell this[params int[] indices] {
+            get {
+                using (ILScope.Enter(this)) {
+                    ILStorage val = Storage.GetValueTyped(indices);
+                    if (val is ILCellStorage)
+                        return new ILRetCell((ILCellStorage)val);
+                    else
+                        return new ILRetCell(new ILStorage[] { val }, ILSize.Scalar1_1);
+                }
+            }
+        }
+
+        /// <summary>
+        /// Subarray access. Get/set regular subarray. 
+        /// </summary>
+        /// <param name="indices">Address range</param>
+        /// <returns>Reference cell array with subarray addressed by <c>indices</c>. </returns>
+        /// <remarks>Query access: for N-dimensional cell arrays missing trailing dimensions indices will be choosen to be 0. Therefore you 
+        /// may ommit those trailing dimensions in <c>indices</c>.
+        /// <para>The indexer may be used for querying or altering single/any elements 
+        /// in this cell. <c>indices</c> may contains index specifications for one to any 
+        /// dimension. The cell array returned will have the size specified by <c>indices</c>.</para>
+        /// <para>Values returned will be reference cells. All elements contained will be 'deep references' created by 
+        /// recursively walking downwards the elements and replacing them by references to itself. Therefore altering the 
+        /// values returned will not alter the original elements.</para>
+        /// <para>The indexer may also be used for removing parts of the cell. Therefore null must be assigned to the range specified by <c>indices</c> (using the set-access). <c>indices</c> 
+        /// must contain exactly one dimension specification other than 'full' in this case. This may be any vector-sized numeric ILArray of any 
+        /// numeric type. If <c>indices</c> apply to fewer dimensions than the number of dimensions existing, the upper dimensions will be 
+        /// merged and the array will be reshaped before applying the removal to it.
+        /// <example>
+        /// <code>
+        /// ILCell C = new ILCell(4,10); 
+        /// C[":",2] = null;  // &gt;- will remove the third column (index: 2) from the cell.
+        /// C[full,vec(2,5)] = null;  &gt;- will remove columns 3...6
+        /// C[1,1] = null; &gt;- will produce an error. Only one dimension can be specified not full! 
+        /// </code></example></para>
+        /// <para>The general behavior of this access methods is full compatible with the corresponding Matlab/Octave/Scilab access: a(:) = []. </para>
+        /// </remarks>
+        public ILRetCell this[params ILBaseArray[] indices] {
+            get {
+                using (ILScope.Enter(this))
+                using (ILScope.Enter(indices)) {
+                    return Subarray(indices);
+                }
+            }
+        }
+
+        #endregion index access
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILRetLogical.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILRetLogical.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/ILRetLogical.cs	(revision 9102)
@@ -0,0 +1,832 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic; 
+using System.IO;
+using ILNumerics;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions; 
+using ILNumerics.Storage;
+using ILNumerics.Native;
+using System.Text; 
+
+namespace ILNumerics {
+    /// <summary>
+    /// Boolean array for high performance relational operations on arbitrary arrays 
+    /// </summary>
+    /// <remarks>
+    /// Logical arrays store true/false conditions as elements. Each element consumes
+    /// one byte. Logical arrays are the output parameter of all relational comparisons.</remarks>
+    [Serializable]
+    public sealed class ILRetLogical : ILBaseLogical {
+
+        private static readonly bool s_isTempArray = true;
+
+        #region properties
+        /// <summary>
+        /// Number of 'true' elements in this array
+        /// </summary>
+        /// <remarks>This value caches the number of 'true' elements in this logical array. 
+        /// It may be used for information purposes but is actually needed internally for performance 
+        /// reasons.</remarks>
+        public override long NumberNonZero {
+            get {
+                using (ILScope.Enter(this))
+                    return Storage.NumberNonZero;
+            }
+            internal set {
+                Storage.NumberNonZero = value;
+            }
+        }
+        /// <summary>
+        /// Shift the dimensions of this array by one (transpose for matrix)
+        /// </summary>
+        public new ILRetLogical T {
+            get {
+                using (ILScope.Enter(this))
+                    return new ILRetLogical((ILLogicalStorage)Storage.ShiftDimensions(1), NumberNonZero);
+            }
+        }
+        /// <summary>
+        /// Create clone of this array 
+        /// </summary>
+        public new ILRetLogical C {
+            get {
+                return this; 
+            }
+        }
+        /// <summary>
+        /// Size descriptor shortcut
+        /// </summary>
+        public override ILSize S {
+            get {
+                using (ILScope.Enter(this))
+                    return Storage.Size;
+            }
+        }
+        /// <summary>
+        /// Size descriptor
+        /// </summary>
+        public override ILSize Size {
+            get {
+                using (ILScope.Enter(this))
+                    return Storage.Size;
+            }
+        }
+        /// <summary>
+        /// Test if this array instance is a column vector (e.g. n x 1)
+        /// </summary>
+        public override bool IsColumnVector {
+            get {
+                using (ILScope.Enter(this))
+                    return Size[1] == 1 && Size.NumberOfDimensions == 2; ;
+            }
+        }
+        /// <summary>
+        /// Test if this array instance is a row vector (e.g. 1 x n)
+        /// </summary>
+        public override bool IsRowVector {
+            get {
+                using (ILScope.Enter(this))
+                    return Size[0] == 1 && Size.NumberOfDimensions == 2;
+            }
+        }
+        /// <summary>
+        /// Determine if this array has complex elements.
+        /// </summary>
+        /// <remarks><para>Calling this member will dispose this instance afterwards (for temporary arrays).</para></remarks>
+        public override bool IsComplex {
+            get {
+                using (ILScope.Enter(this))
+                    return false;
+            }
+        }
+        /// <summary>
+        /// Test if this instance is an empty array (number of elements stored = 0)
+        /// </summary>
+        public override bool IsEmpty {
+            get {
+                using (ILScope.Enter(this))
+                    return Size.NumberOfElements == 0;
+            }
+        }
+        /// <summary>
+        /// Test if this instance is a matrix
+        /// </summary>
+        /// <remarks>In order for an array to be a matrix the number of <b>non singleton</b> 
+        /// dimensions must equal 2. This attribute is readonly.</remarks>
+        public override bool IsMatrix {
+            get {
+                using (ILScope.Enter(this))
+                    return Size.NumberOfDimensions == 2;
+            }
+        }
+        /// <summary>
+        /// Determine if this array holds numeric values.
+        /// </summary>
+        /// <remarks>An ILArray is numeric as long as its elements are one of the 
+        /// following types: 
+        /// <list type="table">
+        /// <listheader>
+        ///     <term>inner type</term>
+        /// </listheader>
+        /// <item>
+        ///     <term>System.double</term>
+        ///     <description>floating point, real, 8 bytes </description>
+        /// </item>
+        /// <item>
+        ///     <term>System.float</term>
+        ///     <description>floating point real, 4 bytes</description>
+        /// </item>
+        /// <item>
+        ///     <term>ILNumerics.complex</term>
+        ///     <description>floating point complex, 16 bytes</description>
+        /// </item>
+        /// <item>
+        ///     <term>ILNumerics.fcomplex</term>
+        ///     <description>floating point complex, 8 bytes</description>
+        /// </item>
+        /// <item>
+        ///     <term>System.char</term>
+        ///     <description>integer, real, 1 byte</description>
+        /// </item>
+        /// <item>
+        ///     <term>System.byte</term>
+        ///     <description>integer, real, 1 byte</description>
+        /// </item>
+        /// <item>
+        ///     <term>System.Int16</term>
+        ///     <description>integer, real, 2 byte</description>
+        /// </item>
+        /// <item>
+        ///     <term>System.Int32</term>
+        ///     <description>integer, real, 4 byte</description>
+        /// </item>
+        /// <item>
+        ///     <term>System.Int64</term>
+        ///     <description>integer, real, 8 byte</description>
+        /// </item>
+        /// <item>
+        ///     <term>System.UInt16</term>
+        ///     <description>unsigned integer, real, 2 byte</description>
+        /// </item>
+        /// <item>
+        ///     <term>System.UInt32</term>
+        ///     <description>unsigned integer, real, 4 byte</description>
+        /// </item>
+        /// <item>
+        ///     <term>System.UInt64</term>
+        ///     <description>unsigned integer, real, 8 byte</description>
+        /// </item>
+        /// </list>
+        /// <para>Calling this member will dispose this instance afterwards (for temporary arrays).</para>
+        /// </remarks>
+        public override bool IsNumeric {
+            get {
+                using (ILScope.Enter(this))
+                    return true;
+            }
+        }
+        /// <summary>
+        /// Test if this instance is a scalar
+        /// </summary>
+        /// <remarks>This attribute is readonly. It returns: Size.NumberOfElements == 1.</remarks>
+        public override bool IsScalar {
+            get {
+                using (ILScope.Enter(this))
+                    return Size.NumberOfElements == 1;
+            }
+        }
+        /// <summary>
+        /// Test if this array is a vector
+        /// </summary>
+        /// <remarks>In order for an array to be a vector the number of <b>non singleton</b> 
+        /// dimensions must equal 1. Keep in mind that all ILArrays have at least 2 dimensions. Therefore 
+        /// it is not sufficient to test for the number of dimensions, but to take the number of 
+        /// <b>non singleton</b> dimensions into account. This attribute is readonly.</remarks>
+        public override bool IsVector {
+            get {
+                using (ILScope.Enter(this))
+                    return (Size[0] == 1 || Size[1] == 1) && Size.NumberOfDimensions == 2;
+            }
+        }
+        /// <summary>
+        /// Length of the longest dimension of this instance
+        /// </summary>
+        /// <remarks>This property is readonly.
+        /// <para>Calling this member will dispose this instance afterwards (for temporary arrays).</para></remarks>
+        public override int Length {
+            get {
+                using (ILScope.Enter(this))
+                    return base.Length;
+            }
+        }
+        /// <summary>
+        /// Gets the name of this array (readonly)
+        /// </summary>
+        public new String Name {
+            get {
+                using (ILScope.Enter(this))
+                    return m_name;
+            }
+        }
+        #endregion
+
+        #region constructors
+        internal ILRetLogical(ILDenseStorage<byte> A)
+            : base(new ILLogicalStorage(A.GetDataArray(), A.Size), s_isTempArray) {
+        }
+        /// <summary>
+        /// Constructor creating ILRetLogical from dense storage
+        /// </summary>
+        /// <param name="A">input array, the storage given will directly be used for 
+        /// storage of the new logical array</param>
+        internal ILRetLogical(ILLogicalStorage A)
+            : base(A, s_isTempArray) {
+        }
+        /// <summary>
+        /// create temporary logical from predefined storage
+        /// </summary>
+        /// <param name="A">the storage will directly be used as storage of the new logical array</param>
+        /// <param name="numberNonZero">number of nonzero elements in A. Must be positive or 0.</param>
+        /// <remarks> Providing this parameter prevents the constructor from having to count the 
+        /// 'true' elements in A.</remarks>
+        internal ILRetLogical(ILLogicalStorage A, long numberNonZero)
+            : base(A, s_isTempArray) {
+            if (numberNonZero < 0) 
+                throw new ILNumerics.Exceptions.ILArgumentException("invalid number of non-zero-elements given!");
+            NumberNonZero = numberNonZero;
+        }
+        /// <summary>
+        ///	create temporary logical array of specified size
+        /// </summary>
+        /// <param name="size">
+        /// variable length int array specifying the number and size of dimensions to 
+        /// be created.
+        /// </param>
+        /// <remarks>
+        /// The size parameter may not be null or an empty array. An exception will be 
+        /// thrown in this case. The dimensions will be trimmed before processing 
+        /// (removing trailing non singleton dimensions). 
+        /// Depending on the requested size a logical temporary array of the specified size 
+        /// will be created. </remarks>
+        internal ILRetLogical(ILSize size)
+            : base(new ILLogicalStorage(size), s_isTempArray) {
+        }
+        /// <summary>
+        ///	Constructor - create ILRetLogical of specified size 
+        /// from data array
+        /// </summary>
+        /// <param name="size">
+        /// Variable length int array specifying the number and size of dimensions to 
+        /// be created.
+        /// </param>
+        /// <param name="data">byte array matching the size of the dimensions 
+        /// specified. The data will directly be used as storage! No copy will be made!</param>
+        /// <remarks>
+        /// The size parameter may not be null or an empty array! An Exception will be 
+        /// thrown in this case. The dimensions will be trimmed before processing 
+        /// (removing trailing non singleton dimensions). 
+        /// Depending on the requested size an ILRetLogical of the specified size 
+        /// will be created. The type of storage will be <code>byte</code>.
+        /// </remarks>
+        public ILRetLogical(byte[] data, params int[] size)
+            : base(new ILLogicalStorage(data, new ILSize(size)), s_isTempArray) {
+        }
+        /// <summary>
+        /// Constructor creating ILRetLogical, provide predefined storage
+        /// </summary>
+        /// <param name="data">Predefined storage elements. The array will directly be used 
+        /// as underlying storage. No copy will be made! </param>
+        /// <param name="size">Size descriptor</param>
+        public ILRetLogical(byte[] data, ILSize size)
+            : base(new ILLogicalStorage(data, size), s_isTempArray) {
+        }
+        /// <summary>
+        /// Constructor creating ILRetLogical, predefined storage (fast version)
+        /// </summary>
+        /// <param name="data">Predefined storage elements. The array will directly be used 
+        /// as underlying storage. No copy will be made! </param>
+        /// <param name="size">Size descriptor</param>
+        /// <param name="nonZeroCount">Number of nonzero elements in <paramref name="data"/>. 
+        /// Providing this parameter prevents from counting the 'true' elements (again). </param>
+        public ILRetLogical(byte[] data, ILSize size, long nonZeroCount)
+            : base(new ILLogicalStorage(data, size), s_isTempArray) {
+            if (nonZeroCount < 0)
+                throw new ILNumerics.Exceptions.ILArgumentException("invalid number of non-zero-elements given!");
+            NumberNonZero = nonZeroCount;
+        }
+        #endregion
+
+        #region public functions
+        /// <summary>
+        /// Clone of this array
+        /// </summary>
+        /// <remarks><para>
+        /// Clones of all arrays in ILNumerics are done in a very fast, lazy way. This means, 
+        /// at the time the clone is made, no relevant memory is copied. Elements of both arrays rather point to the same 
+        /// underlying System.Array. A reference counting mechanism ensures the detaching of thoses arrays 
+        /// on write access.</para>
+        /// <para>The clone returned will be of the same type as this instance.</para></remarks>
+        internal override ILBaseArray Clone() {
+            return this;
+        }
+        /// <summary>
+        /// Concatenate this array
+        /// </summary>
+        /// <param name="A">N-dimensional array. Except for dimensions <paramref name="dim"/>
+        /// the dimensions of A must match the dimensions of this storage</param>
+        /// <param name="dim">Index of dimension to concatenate arrays along.
+        /// If dim is larger than the number of dimensions of any of the arrays,
+        /// its value will be used in modulus the number of dimensions.</param>
+        /// <returns>New array having the size 
+        /// of both input arrays layed behind each other along the dim's-dimension</returns>
+        public new ILRetLogical Concat(ILInLogical A, int dim) {
+            using (ILScope.Enter(this,A))
+                return new ILRetLogical((ILLogicalStorage)Storage.Concat(A.Storage, dim));
+        }
+        /// <summary>
+        /// Compare elements and shape of this array with another array
+        /// </summary>
+        /// <param name="A">Other array</param>
+        /// <returns>true if shape and element values of both arrays match, false otherwise</returns>
+        /// <remarks><para>Calling this member will dispose this instance afterwards (for temporary arrays.</para></remarks>
+        public override bool Equals(object A) {
+            using (ILScope.Enter(this))
+                return base.Equals(A);
+        }
+        /// <summary>
+        /// Copy values of all elements into System.Array.
+        /// </summary>
+        /// <param name="outArray">[Output] System.Array, holding all element values of this ILDenseStorage.</param>
+        /// <remarks>The System.Array may be predefined. If its length is sufficient, it will be used and 
+        /// its leading elements will be overwritten when function returns. If 'outArray' is null or has too few elements, 
+        /// it will be recreated from the ILNumerics memory pool.</remarks>
+        public new void ExportValues(ref byte[] outArray) {
+            using (ILScope.Enter(this))
+                Storage.ExportValues(ref outArray);
+        }
+        /// <summary>
+        /// Enumerator returning elements as ElementType
+        /// </summary>
+        /// <returns>Enumerator</returns>
+        /// <remarks>This method enables the use of ILNumerics arrays in foreach loops.
+        /// <para>The iterator is returned, if arrays are directly used in foreach statements. The iterator 
+        /// is compatible with ILNumerics memory management.</para></remarks>
+        /// <example><code>ILDenseStorage&lt;T&gt; A = ILMath.rand(5,4,6);
+        /// foreach (double element in A) {
+        /// // all elements are scalar double values
+        /// String.Format("Element: {0} ",element);
+        /// // Note: 'element' cannot be used to alter the collection! 
+        /// } 
+        /// </code></example> 
+        public override IEnumerator<byte> GetEnumerator() {
+            using (ILScope.Enter(this)) {
+                byte[] values = GetArrayForRead();
+                int len = Size.NumberOfElements;
+                for (int i = 0; i < len; i++)
+                    yield return values[i];
+            }
+        }
+        /// <summary>
+        /// Generate a hash code based on the current arrays values
+        /// </summary>
+        /// <returns>Hash code</returns>
+        /// <remarks>The hashcode is generated by taking the values currently stored in the array into account.
+        /// Therefore, the function must iterate over all elements in the array - which makes it somehow a costly 
+        /// operation. Take this into account, if you consider using large arrays in collections like dictionaries 
+        /// or hashtables, which make great use of hash codes.
+        /// <para>Calling this member will dispose this instance afterwards (for temporary arrays).</para></remarks>
+        public override int GetHashCode() {
+            using (ILScope.Enter(this))
+                return base.GetHashCode();
+        }
+        /// <summary>
+        /// Get minimum and maximum value of all elements - if any
+        /// </summary>
+        /// <param name="min">[Output] Minimum value</param>
+        /// <param name="max">[Output] Maximum value</param>
+        /// <returns>true if the limits exists and could be computed, false otherwise</returns>
+        /// <remarks>Empty arrays will return false. In this case the output parameter will be: default(ElementType).
+        /// <para>Calling this member will dispose this instance afterwards (for temporary arrays).</para></remarks>
+        public override bool GetLimits(out byte min, out byte max) {
+            using (ILScope.Enter(this))
+                return base.GetLimits(out min, out max);
+        }
+        /// <summary>
+        /// Get single element from this array
+        /// </summary>
+        /// <param name="idx">Indices, location of element</param>
+        /// <returns>The requested element</returns>
+        public override byte GetValue(params int[] idx) {
+            using (ILScope.Enter(this))
+                return base.GetValue(idx);
+        }
+        /// <summary>
+        /// Create reshaped copy of this logical array
+        /// </summary>
+        /// <param name="size">New dimensions of the array</param>
+        /// <returns>Reshaped copy of this array</returns>
+        /// <remarks><para>The current instance will not be changed! A new array is created, having 
+        /// the elements of this array and a shape as determined by <paramref name="size"/>.</para>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the number of elements in 
+        /// <paramref name="size"/> do not match the number of elements in this array.</exception>
+        public new ILRetLogical Reshape(ILSize size) {
+            using (ILScope.Enter(this)) {
+                ILLogical ret = C;
+                ret.Storage.Reshape(size);
+                return ret;
+            }
+        }
+        /// <summary>
+        /// Create replication of this array
+        /// </summary>
+        /// <param name="dims">Dimensions specifier. If the number of elements in <paramref name="dims"/> is 
+        /// less than the number of dimensions in this array, the trailing dimensions will 
+        /// be set to 1 (singleton dimensions). On the other hand, if the number specified 
+        /// is larger then the number of dimension stored inside the storge the resulting 
+        /// storage will get its number of dimensions extended accordingly. </param>
+        /// <returns>Array being created out of multiple replications of this array along 
+        /// arbitrary dimensions according to <paramref name="dims"/></returns>
+        public new ILRetLogical Repmat(params int[] dims) {
+            using (ILScope.Enter(this)) 
+            return new ILRetLogical((ILLogicalStorage)Storage.Repmat(dims));
+        }
+        /// <summary>
+        ///  Serialize this ILArray into a binary stream.
+        /// </summary>
+        /// <param name="outStream">System.IO.Stream to receive the byte stream 
+        /// for this ILBaseArray</param>
+        /// <returns>True on success, false on error.</returns>
+        /// <remarks><para>Calling this member will dispose this instance afterwards (for temporary arrays).</para>
+        /// </remarks>
+        public override bool Serialize(Stream outStream) {
+            using (ILScope.Enter(this))
+                return base.Serialize(outStream);
+        }
+        /// <summary>
+        /// Create logical array from this logical and shift dimensions
+        /// </summary>
+        /// <param name="shift">Number of dimensions to shift</param>
+        /// <returns>Shifted version of this array</returns>
+        /// <remarks><para>The shift is done 'to the left':</para>
+        /// <example><code>ILArray&lt;double> A = zeros(2,4);
+        /// ILArray&lt;double> B = A.Shifted(1); 
+        /// // B is now: &lt;double> [4,2] 
+        /// 
+        /// ILArray&lt;double> C = zeros(2,4,3);
+        /// ILArray&lt;double> D = C.Shifted(1); 
+        /// // D is now: &lt;double> [4,3,2] 
+        /// </code></example>
+        /// <para>The dimensions are shifted circulary to the left. This 
+        /// can be imagined as removing the first dimensions from the beginning of the list of 
+        /// dimensions and "append" them to the end in a ringbuffer style.</para>
+        /// <para>For dimension shifts of '1', you may consider using the 
+        /// <see cref="ILNumerics.ILDenseArray{ElementType}.T"/> property for readability.</para>
+        /// <para><paramref name="shift"/> must be positive. It is taken modulus the number of dimensions.</para>
+        /// <seealso cref="ILNumerics.ILDenseArray{ElementType}.T"/></remarks>
+        public new ILRetLogical Shifted(int shift) {
+            using (ILScope.Enter(this))
+                return new ILRetLogical((ILLogicalStorage)Storage.ShiftDimensions(shift));
+        }
+        /// <summary>
+        ///	Subarray from this array
+        /// </summary>
+        /// <param name="range">Arrays specifying the ranges to create subarray from</param>
+        /// <returns>Subarray as specified</returns>
+        public new ILRetLogical Subarray(params ILBaseArray[] range) {
+            using (ILScope.Enter(this))
+            using (ILScope.Enter(range))
+                return new ILRetLogical((ILLogicalStorage)Storage.Subarray(range));
+        }
+        /// <summary>
+        /// Send values of this instance to stream. 
+        /// </summary>
+        /// <param name="stream">Stream to write the values into.</param>
+        /// <param name="format">Format string to be used for output. See <see cref="System.String.Format(string,object)"/> for a specification
+        /// of valid formating expressions. This flag is only used, when 'method' is set to 'Serial'.</param>
+        /// <param name="method">A constant out of <see cref="ILArrayStreamSerializationFlags"/>. Specifies the way in which
+        /// the values will be serialized.</param>
+        /// <remarks><para>If the 'Formatted' method is used, any occurences of the NewLine character(s) 
+        /// will be replaced from the format string before applying to the elements. This is done to 
+        /// prevent the format from breaking the 'page' style of the output.</para>
+        /// <para>If 'method' is set to 'Matlab', the array will be written as Matfile version 5.0. No compression will be used. The internal 'Name' property will be used as the
+        /// array name for writing. This array instance will be the only array in the .mat file. If you want to write several arrays bundled into one mat file, use the MatFile class to
+        /// create a collection of arrays and write the MatFile to stream.</para></remarks>
+        public override void ToStream(Stream stream, string format, ILArrayStreamSerializationFlags method) {
+            using (ILScope.Enter(this))
+                try {
+                    int len;
+                    switch (method) {
+                        case ILArrayStreamSerializationFlags.Serial:
+                            len = Size.NumberOfElements;
+                            using (TextWriter tw = new StreamWriter(stream)) {
+                                for (int i = 0; i < len; i++) {
+                                    tw.Write(format, GetValue(i));
+                                }
+                            }
+                            break;
+                        case ILArrayStreamSerializationFlags.Formatted:
+                            format = format.Replace(Environment.NewLine, "");
+                            ILDenseStorage<byte> temp = this.Storage.ShiftDimensions(1);
+                            //len = Dimensions.NumberOfElements / Dimensions[1]; 
+                            using (TextWriter tw = new StreamWriter(stream)) {
+                                tw.Write(temp.ValuesToString(0));
+                            }
+                            break;
+                        case ILArrayStreamSerializationFlags.Matlab:
+                            ILMatFile mf = new ILMatFile(new ILBaseArray[1] { this });
+                            mf.Write(stream);
+                            break;
+                    }
+                } catch (Exception e) {
+                    throw new ILException("ToStream: Could not serialize to stream.", e);
+                }
+        }
+        #endregion
+
+        #region index access + mutability
+        /// <summary>
+        /// Subarray access (readonly)
+        /// </summary>
+        /// <param name="range">Range specification</param>
+        /// <returns>Logical array with the elements specified by range</returns>
+        /// <remarks>Query access: for N-dimensional arrays trailing dimensions will be choosen to be 0. Therefore you 
+        /// may ommit those trailing dimensions in range.
+        /// <para>The indexer may be used for querying any elements 
+        /// in this array. <c>range</c> may contains index specifications for one ... to any 
+        /// dimension. The array returned will have the size specified by range.</para>
+        /// </remarks>
+        public ILRetLogical this[params ILBaseArray[] range] {
+            get {
+                using (ILScope.Enter(this))
+                using (ILScope.Enter(range))
+                    return new ILRetLogical((ILLogicalStorage)Storage.Subarray(range));
+            }
+        } 
+        #endregion
+
+        #region operator overloading
+        #region constructional operators 
+        /// <summary>
+        /// Implicitly cast one dimensional System.Array to ILNumerics array (vector)
+        /// </summary>
+        /// <param name="A">1-dimensional system array, arbitrary type</param>
+        /// <returns>ILNumerics array of same element type as elements of A. 
+        /// Row vector. If A is null: empty array.</returns>
+        /// <remarks>The System.Array A will directly be used for the new ILNumerics array! 
+        /// No copy will be done! Make sure, not to reference A after this conversion!</remarks>
+        public static implicit operator ILRetLogical(byte[] A) {
+            if (A == null) {
+                return new ILRetLogical(ILSize.Empty00);
+            }
+            return new ILRetLogical(A, 1, A.Length);
+        }
+        /// <summary>
+        /// Implicitly convert n-dim. System.Array to ILNumerics array
+        /// </summary>
+        /// <param name="A">Arbitrarily sized System.Array</param>
+        /// <returns>If A is null: empty array. Else: new ILNumerics array of the same size as A</returns>
+        /// <remarks>The resulting ILArray will reflect all dimensions of 
+        /// A. Elements of A will get copied to elements of output array (shallow copy).</remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILCastException">If type of input does not match 
+        /// ElementType</exception>
+        public static implicit operator ILRetLogical(Array A) {
+            if (A == null || A.Length == 0) {
+                return new ILLogical(ILSize.Empty00);
+            }
+            if (A.GetType().GetElementType() != typeof(byte))
+                throw new ILCastException("inner type of System.Array must match");
+            int[] dims = new int[A.Rank];
+            byte[] retArr = ILMemoryPool.Pool.New<byte>(A.Length);
+            int posArr = 0;
+            for (int i = 0; i < dims.Length; i++) {
+                dims[i] = A.GetLength(dims.Length - i - 1);
+            }
+            foreach (byte item in A)
+                retArr[posArr++] = item;
+            return new ILRetLogical(retArr, dims);
+        }
+        /// <summary>
+        /// Implicitly cast two dimensional System.Array to ILNumerics array
+        /// </summary>
+        /// <param name="A">2D System.Array</param>
+        /// <returns>If A is null: empty array. ILNumerics array of same size and type as A otherwise.</returns>
+        public static implicit operator ILRetLogical(byte[,] A) {
+            if (A == null || A.Length == 0) {
+                return new ILRetLogical(ILSize.Empty00);
+            }
+            int[] dims = new int[2];
+            byte[] retArr = ILMemoryPool.Pool.New<byte>(A.Length);
+            int posArr = 0;
+            for (int i = 0; i < 2; i++) {
+                dims[i] = A.GetLength(dims.Length - i - 1);
+            }
+            foreach (byte item in A)
+                retArr[posArr++] = item;
+            return new ILRetLogical(retArr, dims);
+        }
+        /// <summary>
+        /// Implicitly cast three dimensional System.Array to ILNumerics array
+        /// </summary>
+        /// <param name="A">3D System.Array</param>
+        /// <returns>If A is null: empty array. ILNumerics array of same size and type as A otherwise.</returns>
+        public static implicit operator ILRetLogical(byte[, ,] A) {
+            if (A == null || A.Length == 0) {
+                return new ILRetLogical(ILSize.Empty00);
+            }
+            int[] dims = new int[3];
+            byte[] retArr = ILMemoryPool.Pool.New<byte>(A.Length);
+            int posArr = 0;
+            for (int i = 0; i < 3; i++) {
+                dims[i] = A.GetLength(dims.Length - i - 1);
+            }
+            foreach (byte item in A)
+                retArr[posArr++] = item;
+            return new ILRetLogical(retArr, dims);
+        }
+
+        /// <summary>
+        /// Implicitly convert boolean System.Byte to scalar logical array
+        /// </summary>
+        /// <param name="val">System.Byte</param>
+        /// <returns>Scalar logical array with value of val.</returns>
+        public static implicit operator ILRetLogical(bool val) {
+            ILRetLogical ret = new ILRetLogical(new byte[1] { val ? (byte)1 : (byte)0 }, 1, 1);
+            return ret;
+        }
+        /// <summary>
+        /// Implicitly convert logical array to System.Boolean
+        /// </summary>
+        /// <param name="A">Logical array</param>
+        /// <returns>true if elements of A are non-zero, false otherwise 
+        /// </returns>
+        /// <remarks>If A is null or empty, the function returns false. Otherwise returns true, 
+        /// if all elements of A are non-zero and returns false, if A contains zero elements.
+        /// <para>The behavior depends on the setting of the ILSettings.LogicalArrayToBoolConversion switch.
+        /// Per default, only scalar arrays are allowed to be converted implicitely. This can be changed 
+        /// to implicitely convert non-scalar arrays by using ILMath.any on the array.</para>
+        /// <seealso cref="ILNumerics.Settings.LogicalArrayToBoolConversion"/>
+        /// <seealso cref="ILNumerics.ILMath.any(ILInArray{double}, int)"/>
+        /// </remarks>
+        public static implicit operator bool(ILRetLogical A) {
+            using (ILScope.Enter(A)) {
+                // this operator is implicit for convenience reasons: 
+                // if(tmp[0]!=-10.0) { ... is only possible this way
+                if (object.Equals(A, null) || A.IsEmpty)
+                    return false;
+                if (A.IsScalar)
+                    return A.GetValue(0, 0) == 1;
+                if (Settings.LogicalArrayToBoolConversion == LogicalConversionMode.ImplicitAllAll)
+                    return ILMath.allall(A).GetValue(0) == 1;
+                //else if (Settings.ILSettings.LogicalArrayToBoolConversion == LogicalConversionMode.NonScalarThrowsException) 
+                throw new ILArgumentException("Nonscalar logical to bool conversion. See ILSettings.LogicalArrayToBoolConversion");
+            }
+        }
+        /// <summary>
+        /// Implicitly convert integer scalar to logical array of size 1x1 (scalar).
+        /// </summary>
+        /// <param name="val">Scalar value</param>
+        /// <returns>New logical array of size 1x1 holding the only element of type Byte 
+        /// with value of val.</returns>
+        public static implicit operator ILRetLogical(int val) {
+            ILRetLogical ret = new ILRetLogical(new Byte[1] { 
+                                 val != 0 ? (byte)1:(byte)0 }, 1, 1);
+            return ret;
+        }
+        #endregion
+
+        #region conversional operators 
+        /// <summary>
+        /// Convert logical to temporary logical array
+        /// </summary>
+        /// <param name="a">Original logical array</param>
+        /// <returns>Temporary logical array</returns>
+        public static implicit operator ILRetLogical(ILLogical a) {
+            if (object.Equals(a,null))
+                return null; 
+            return a.C;
+        }
+        /// <summary>
+        /// Convert logical input parameter type array to temporary logical array
+        /// </summary>
+        /// <param name="a">Logical input parameter type</param>
+        /// <returns>Temporary logical array</returns>
+        public static implicit operator ILRetLogical(ILInLogical a) {
+            if (object.Equals(a, null))
+                return null;
+            return a.C;
+        }
+        /// <summary>
+        /// Convert logical output parameter type array to temporary logical array
+        /// </summary>
+        /// <param name="a">Logical output parameter type</param>
+        /// <returns>Temporary logical array</returns>
+        public static implicit operator ILRetLogical(ILOutLogical a) {
+            if (object.Equals(a, null))
+                return null;
+            return a.C;
+        }
+        /// <summary>
+        /// Implicitly cast to ILArray&lt;byte&gt;
+        /// </summary>
+        /// <param name="a">A ILRetLogical</param>
+        /// <returns>ILArray&lt;byte&gt;</returns>
+        public static implicit operator ILArray<byte>(ILRetLogical a) {
+            if (object.Equals(a, null))
+                return null;
+            ILArray<byte> ret = new ILArray<byte>(a.GiveStorageAwayOrClone()); 
+            ILScope.Context.RegisterArray(ret); 
+            return ret; 
+        }
+        /// <summary>
+        /// Implicitly cast from ILArray&lt;byte&gt;
+        /// </summary>
+        /// <param name="a">An ILArray&lt;byte&gt;</param>
+        /// <returns>logical return array</returns>
+        public static implicit operator ILRetLogical(ILArray<byte> a) {
+            if (object.Equals(a,null))
+                return null; 
+            return new ILRetLogical(new ILLogicalStorage(
+                a.Storage.GetDataArray(),a.Size)); 
+        }
+        /// <summary>
+        /// Implicitly cast from ILInArray&lt;byte&gt;
+        /// </summary>
+        /// <param name="a">An ILInArray&lt;byte&gt;</param>
+        /// <returns>logical return array</returns>
+        public static implicit operator ILInArray<byte>(ILRetLogical a) {
+            if (object.Equals(a,null))
+                return null; 
+            ILArray<byte> ret = new ILArray<byte>(a.GiveStorageAwayOrClone());
+            if (Settings.AllowInArrayAssignments)
+                ILScope.Context.RegisterArray(ret);
+            return ret;
+        }
+        /// <summary>
+        /// Implicitly cast from ILInArray&lt;byte&gt;
+        /// </summary>
+        /// <param name="a">An ILInArray&lt;byte&gt;</param>
+        /// <returns>logical return array</returns>
+        public static implicit operator ILRetLogical(ILInArray<byte> a) {
+            if (object.Equals(a, null))
+                return null;
+            return new ILRetLogical(new ILLogicalStorage(
+                a.Storage.GetDataArray(), a.Size));
+        }
+        #endregion
+
+        #region operational operators
+        /// <summary>
+        /// Invert values of array elements 
+        /// </summary>
+        /// <param name="in1">Input array</param>
+        /// <returns>New logical array, inverted element values</returns>
+        public static ILRetLogical operator !(ILRetLogical in1) {
+            if (object.Equals(in1,null))
+                throw new ILArgumentException("operator -(): parameter must not be null!");
+            return (in1 != (byte)1);
+        }
+        #endregion
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/Operator_Overloads.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/Operator_Overloads.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Array/Operator_Overloads.cs	(revision 9102)
@@ -0,0 +1,527 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using ILNumerics;
+using ILNumerics.Misc;
+using ILNumerics.Storage;
+using ILNumerics.Native;
+using ILNumerics.Exceptions;
+
+namespace ILNumerics {
+
+    public abstract partial class ILDenseArray<ElementType> {
+
+        /// <summary>
+        /// Elementwise subtraction operator
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>Result of subtraction</returns>
+        /// <remarks>The operator is defined for both arrays of the same numeric 'ElementType' (double, float, complex,
+        /// fcomplex, int, long, byte).</remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the array elements are of an unsupported type</exception>
+        public static ILRetArray<ElementType> operator -(ILDenseArray<ElementType> A, ILDenseArray<ElementType> B) {
+            using (ILScope.Enter(A,B)) 
+            // TODO: check if (A.GetType() == typeof(ILDenseArray<double>)) is faster due to JIT optimizations
+            if (A is ILDenseArray< double>) {
+                return (ILRetArray<ElementType>)(object)ILMath.subtract((A as ILDenseArray<double>).C, (B as ILDenseArray<double>).C);
+            } else if (A is  ILDenseArray<float>) {
+                return (ILRetArray<ElementType>)(object)ILMath.subtract((A as ILDenseArray<float>).C, (B as ILDenseArray<float>).C);
+            } else if (A is  ILDenseArray<complex>) {
+                return (ILRetArray<ElementType>)(object)ILMath.subtract((A as ILDenseArray<complex>).C, (B as ILDenseArray<complex>).C);
+            } else if (A is  ILDenseArray<fcomplex>) {
+                return (ILRetArray<ElementType>)(object)ILMath.subtract((A as ILDenseArray<fcomplex>).C, (B as ILDenseArray<fcomplex>).C);
+            } else if (A is  ILDenseArray<int>) {
+                return (ILRetArray<ElementType>)(object)ILMath.subtract((A as ILDenseArray<int>).C, (B as ILDenseArray<int>).C);
+            } else if (A is  ILDenseArray<long>) {
+                return (ILRetArray<ElementType>)(object)ILMath.subtract((A as ILDenseArray<long>).C, (B as ILDenseArray<long>).C);
+            } else if (A is  ILDenseArray<byte>) {
+                return (ILRetArray<ElementType>)(object)ILMath.subtract((A as ILDenseArray<byte>).C, (B as ILDenseArray<byte>).C);
+            } else {
+                throw new ILArgumentException("Operator - not defined for arrays of element type '" + typeof(ElementType).Name + "'");
+            }
+        }
+
+        /// <summary>
+        /// Elementwise addition operator
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>Result of addition</returns>
+        /// <remarks>The operator is defined for both arrays of the same numeric 'ElementType' (double, float, complex,
+        /// fcomplex, int, long, byte).</remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the array elements are of an unsupported type</exception>
+        public static ILRetArray<ElementType> operator +(ILDenseArray<ElementType> A, ILDenseArray<ElementType> B) {
+            using (ILScope.Enter(A, B))
+                if (A is ILDenseArray< double>) {
+                return (ILRetArray<ElementType>)(object)ILMath.add((A as ILDenseArray<double>).C, (B as ILDenseArray<double>).C);
+            } else if (A is  ILDenseArray<float>) {
+                return (ILRetArray<ElementType>)(object)ILMath.add((A as ILDenseArray<float>).C, (B as ILDenseArray<float>).C);
+            } else if (A is  ILDenseArray<complex>) {
+                return (ILRetArray<ElementType>)(object)ILMath.add((A as ILDenseArray<complex>).C, (B as ILDenseArray<complex>).C);
+            } else if (A is  ILDenseArray<fcomplex>) {
+                return (ILRetArray<ElementType>)(object)ILMath.add((A as ILDenseArray<fcomplex>).C, (B as ILDenseArray<fcomplex>).C);
+            } else if (A is  ILDenseArray<int>) {
+                return (ILRetArray<ElementType>)(object)ILMath.add((A as ILDenseArray<int>).C, (B as ILDenseArray<int>).C);
+            } else if (A is  ILDenseArray<long>) {
+                return (ILRetArray<ElementType>)(object)ILMath.add((A as ILDenseArray<long>).C, (B as ILDenseArray<long>).C);
+            } else if (A is  ILDenseArray<byte>) {
+                return (ILRetArray<ElementType>)(object)ILMath.add((A as ILDenseArray<byte>).C, (B as ILDenseArray<byte>).C);
+            } else {
+                throw new ILArgumentException("Operator + not defined for arrays of element type '" + typeof(ElementType).Name + "'");
+            }
+        }
+
+        /// <summary>
+        /// Elementwise multiplication operator
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>Result of multiplication</returns>
+        /// <remarks>The operator is defined for both arrays of the same numeric 'ElementType' (double, float, complex,
+        /// fcomplex, int, long, byte).</remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the array elements are of an unsupported type</exception>
+        public static ILRetArray<ElementType> operator *(ILDenseArray<ElementType> A, ILDenseArray<ElementType> B) {
+            using (ILScope.Enter(A, B))
+                if (A is ILDenseArray< double>) {
+                return (ILRetArray<ElementType>)(object)ILMath.multiplyElem((A as ILDenseArray<double>).C, (B as ILDenseArray<double>).C);
+            } else if (A is  ILDenseArray<float>) {
+                return (ILRetArray<ElementType>)(object)ILMath.multiplyElem((A as ILDenseArray<float>).C, (B as ILDenseArray<float>).C);
+            } else if (A is  ILDenseArray<complex>) {
+                return (ILRetArray<ElementType>)(object)ILMath.multiplyElem((A as ILDenseArray<complex>).C, (B as ILDenseArray<complex>).C);
+            } else if (A is  ILDenseArray<fcomplex>) {
+                return (ILRetArray<ElementType>)(object)ILMath.multiplyElem((A as ILDenseArray<fcomplex>).C, (B as ILDenseArray<fcomplex>).C);
+            } else if (A is  ILDenseArray<int>) {
+                return (ILRetArray<ElementType>)(object)ILMath.multiplyElem((A as ILDenseArray<int>).C, (B as ILDenseArray<int>).C);
+            } else if (A is  ILDenseArray<long>) {
+                return (ILRetArray<ElementType>)(object)ILMath.multiplyElem((A as ILDenseArray<long>).C, (B as ILDenseArray<long>).C);
+            } else if (A is  ILDenseArray<byte>) {
+                return (ILRetArray<ElementType>)(object)ILMath.multiplyElem((A as ILDenseArray<byte>).C, (B as ILDenseArray<byte>).C);
+            } else {
+                throw new ILArgumentException("Operator * not defined for arrays of element type '" + typeof(ElementType).Name + "'");
+            }
+        }
+
+        ///// <summary>
+        ///// Elementwise exponentiation operator   ----------- CAUTION! THE ^ OPERATOR HAS LOWER PRECEEDENCE AS THE *,+,-... OPERATORS! 
+        ///// </summary>
+        ///// <param name="A">Bases</param>
+        ///// <param name="B">Exponents</param>
+        ///// <returns>Result of exponentiation of base elements A and exponents in B</returns>
+        ///// <remarks>The operator is defined for both arrays of the same numeric 'ElementType' (double, float, complex,
+        ///// fcomplex, int, long, byte).</remarks>
+        ///// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the array elements are of an unsupported type</exception>
+        //public static ILRetArray<ElementType> operator ^(ILDenseArray<ElementType> A, ILDenseArray<ElementType> B) {
+        //    if (A is ILDenseArray< double >) {
+        //        return (ILRetArray<ElementType>)(object)ILMath.pow((A as ILDenseArray<double>).C, (B as ILDenseArray<double>).C); 
+        //    } else if (A is  ILDenseArray<float>) {
+        //        return (ILRetArray<ElementType>)(object)ILMath.pow((A as ILDenseArray<float>).C, (B as ILDenseArray<float>).C); 
+        //    } else if (A is  ILDenseArray<complex>) {
+        //        return (ILRetArray<ElementType>)(object)ILMath.pow((A as ILDenseArray<complex>).C, (B as ILDenseArray<complex>).C); 
+        //    } else if (A is  ILDenseArray<fcomplex>) {
+        //        return (ILRetArray<ElementType>)(object)ILMath.pow((A as ILDenseArray<fcomplex>).C, (B as ILDenseArray<fcomplex>).C); 
+        //    } else if (A is  ILDenseArray<int>) {
+        //        return (ILRetArray<ElementType>)(object)ILMath.pow((A as ILDenseArray<int>).C, (B as ILDenseArray<int>).C); 
+        //    } else if (A is  ILDenseArray<long>) {
+        //        return (ILRetArray<ElementType>)(object)ILMath.pow((A as ILDenseArray<long>).C, (B as ILDenseArray<long>).C); 
+        //    } else if (A is  ILDenseArray<byte>) {
+        //        return (ILRetArray<ElementType>)(object)ILMath.pow((A as ILDenseArray<byte>).C, (B as ILDenseArray<byte>).C); 
+        //    } else  {
+        //        throw new ILArgumentException("Operator * not defined for "+ A.GetType().Name + " and " + B.GetType().Name);
+        //    }
+        //}
+
+        /// <summary>
+        /// Elementwise division operator
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>Result of division</returns>
+        /// <remarks>The operator is defined for both arrays of the same numeric 'ElementType' (double, float, complex,
+        /// fcomplex, int, long, byte).</remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the array elements are of an unsupported type</exception>
+        public static ILRetArray<ElementType> operator /(ILDenseArray<ElementType> A, ILDenseArray<ElementType> B) {
+            using (ILScope.Enter(A, B))
+                if (A is ILDenseArray< double>) {
+                    return (ILRetArray<ElementType>)(object)ILMath.divide((A as ILDenseArray<double>).C, (B as ILDenseArray<double>).C);
+                } else if (A is  ILDenseArray<float>) {
+                    return (ILRetArray<ElementType>)(object)ILMath.divide((A as ILDenseArray<float>).C, (B as ILDenseArray<float>).C);
+                } else if (A is  ILDenseArray<complex>) {
+                    return (ILRetArray<ElementType>)(object)ILMath.divide((A as ILDenseArray<complex>).C, (B as ILDenseArray<complex>).C);
+                } else if (A is  ILDenseArray<fcomplex>) {
+                    return (ILRetArray<ElementType>)(object)ILMath.divide((A as ILDenseArray<fcomplex>).C, (B as ILDenseArray<fcomplex>).C);
+                } else if (A is  ILDenseArray<int>) {
+                    return (ILRetArray<ElementType>)(object)ILMath.divide((A as ILDenseArray<int>).C, (B as ILDenseArray<int>).C);
+                } else if (A is  ILDenseArray<long>) {
+                    return (ILRetArray<ElementType>)(object)ILMath.divide((A as ILDenseArray<long>).C, (B as ILDenseArray<long>).C);
+                } else if (A is  ILDenseArray<byte>) {
+                    return (ILRetArray<ElementType>)(object)ILMath.divide((A as ILDenseArray<byte>).C, (B as ILDenseArray<byte>).C);
+                } else {
+                    throw new ILArgumentException("Operator / not defined for arrays of element type '" + typeof(ElementType).Name + "'");
+                }
+        }
+
+        /// <summary>
+        /// Elementwise modulus operator
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>Result of modulus operation</returns>
+        /// <remarks>The operator is defined for 2 arrays of the same numeric real element types: double, float, int, long, byte.</remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the array elements are of an unsupported type</exception>
+        public static ILRetArray<ElementType> operator %(ILDenseArray<ElementType> A, ILDenseArray<ElementType> B) {
+            using (ILScope.Enter(A, B))
+                if (A is ILDenseArray< double>) {
+                    return (ILRetArray<ElementType>)(object)ILMath.mod((A as ILDenseArray<double>).C, (B as ILDenseArray<double>).C);
+                } else if (A is  ILDenseArray<float>) {
+                    return (ILRetArray<ElementType>)(object)ILMath.mod((A as ILDenseArray<float>).C, (B as ILDenseArray<float>).C);
+                } else if (A is  ILDenseArray<int>) {
+                    return (ILRetArray<ElementType>)(object)ILMath.mod((A as ILDenseArray<int>).C, (B as ILDenseArray<int>).C);
+                } else if (A is  ILDenseArray<long>) {
+                    return (ILRetArray<ElementType>)(object)ILMath.mod((A as ILDenseArray<long>).C, (B as ILDenseArray<long>).C);
+                } else if (A is  ILDenseArray<byte>) {
+                    return (ILRetArray<ElementType>)(object)ILMath.mod((A as ILDenseArray<byte>).C, (B as ILDenseArray<byte>).C);
+                } else {
+                    throw new ILArgumentException("Operator % not defined for arrays of element type '" + typeof(ElementType).Name + "'");
+                }
+        }
+
+        /// <summary>
+        /// 'Equalty' operator of two arrays
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>Logical array of same size than A and B, result of operation along all elements</returns>
+        /// <remarks>Sizes and types of A and B must match.</remarks>
+        public static ILRetLogical operator ==(ILDenseArray<ElementType> A, ILDenseArray<ElementType> B) {
+            using (ILScope.Enter(A, B)) {
+                if (object.Equals(A, null)) {
+                    if (object.Equals(B, null)) {
+                        return true;
+                    } else {
+                        return false;
+                    }
+                } else {
+                    if (object.Equals(B, null)) {
+                        return false;
+                    }
+                }
+                if (false) {
+
+                } else if (A is ILDenseArray< double> && B is ILDenseArray< double>) {
+                    return ILMath.eq((A as ILDenseArray< double>).C, (B as ILDenseArray< double>).C);
+
+                    #region HYCALPER AUTO GENERATED CODE
+
+                } else if (A is ILDenseArray<Int64> && B is ILDenseArray<Int64>) {
+                    return ILMath.eq((A as ILDenseArray<Int64>).C, (B as ILDenseArray<Int64>).C);
+                } else if (A is ILDenseArray<Int32> && B is ILDenseArray<Int32>) {
+                    return ILMath.eq((A as ILDenseArray<Int32>).C, (B as ILDenseArray<Int32>).C);
+                } else if (A is ILDenseArray<float> && B is ILDenseArray<float>) {
+                    return ILMath.eq((A as ILDenseArray<float>).C, (B as ILDenseArray<float>).C);
+                } else if (A is ILDenseArray<fcomplex> && B is ILDenseArray<fcomplex>) {
+                    return ILMath.eq((A as ILDenseArray<fcomplex>).C, (B as ILDenseArray<fcomplex>).C);
+                } else if (A is ILDenseArray<complex> && B is ILDenseArray<complex>) {
+                    return ILMath.eq((A as ILDenseArray<complex>).C, (B as ILDenseArray<complex>).C);
+                } else if (A is ILDenseArray<byte> && B is ILDenseArray<byte>) {
+                    return ILMath.eq((A as ILDenseArray<byte>).C, (B as ILDenseArray<byte>).C);
+
+                    #endregion HYCALPER AUTO GENERATED CODE
+                } else if (A is ILDenseArray<String> && B is ILDenseArray<String>) {
+                    return ILMath.eq((A as ILDenseArray<String>).C, (B as ILDenseArray<String>).C);
+                } else {
+                    throw new ILArgumentTypeException("Operator '==' not defined for arrays of element type '" + typeof(ElementType).Name + "'");
+                }
+            }
+        }
+
+        /// <summary>
+        /// 'unequalty' operator of two arrays
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>Logical array of same size than A and B, result of operation along all elements</returns>
+        /// <remarks>Sizes and types of A and B must match.</remarks>
+        public static ILRetLogical operator !=(ILDenseArray<ElementType> A, ILDenseArray<ElementType> B) {
+            using (ILScope.Enter(A, B)) {
+                if (object.Equals(A, null)) {
+                    if (object.Equals(B, null)) {
+                        return false;
+                    } else {
+                        return true;
+                    }
+                } else {
+                    if (object.Equals(B, null)) {
+                        return true;
+                    }
+                }
+                if (false) {
+
+                } else if (A is ILDenseArray< double> && B is ILDenseArray< double>) {
+                    return ILMath.neq((A as ILDenseArray< double>).C, (B as ILDenseArray< double>).C);
+
+                    #region HYCALPER AUTO GENERATED CODE
+
+                } else if (A is ILDenseArray<Int64> && B is ILDenseArray<Int64>) {
+                    return ILMath.neq((A as ILDenseArray<Int64>).C, (B as ILDenseArray<Int64>).C);
+                } else if (A is ILDenseArray<Int32> && B is ILDenseArray<Int32>) {
+                    return ILMath.neq((A as ILDenseArray<Int32>).C, (B as ILDenseArray<Int32>).C);
+                } else if (A is ILDenseArray<float> && B is ILDenseArray<float>) {
+                    return ILMath.neq((A as ILDenseArray<float>).C, (B as ILDenseArray<float>).C);
+                } else if (A is ILDenseArray<fcomplex> && B is ILDenseArray<fcomplex>) {
+                    return ILMath.neq((A as ILDenseArray<fcomplex>).C, (B as ILDenseArray<fcomplex>).C);
+                } else if (A is ILDenseArray<complex> && B is ILDenseArray<complex>) {
+                    return ILMath.neq((A as ILDenseArray<complex>).C, (B as ILDenseArray<complex>).C);
+                } else if (A is ILDenseArray<byte> && B is ILDenseArray<byte>) {
+                    return ILMath.neq((A as ILDenseArray<byte>).C, (B as ILDenseArray<byte>).C);
+
+                    #endregion HYCALPER AUTO GENERATED CODE
+                } else if (A is ILDenseArray<String> && B is ILDenseArray<String>) {
+                    return ILMath.neq((A as ILDenseArray<String>).C, (B as ILDenseArray<String>).C);
+                } else {
+                    throw new ILArgumentTypeException("Operator '!=' not defined for arrays of element type '" + typeof(ElementType).Name + "'");
+                }
+            }
+        }
+
+        /// <summary>
+        /// 'greater or equal' operator of two arrays
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>Logical array of same size than A and B, result of operation along all elements</returns>
+        /// <remarks>Sizes and types of A and B must match.</remarks>
+        public static ILRetLogical operator >=(ILDenseArray<ElementType> A, ILDenseArray<ElementType> B) {
+            using (ILScope.Enter(A, B)) {
+                if (false) {
+
+                } else if (A is ILDenseArray< double> && B is ILDenseArray< double>) {
+                    return ILMath.ge((A as ILDenseArray< double>).C, (B as ILDenseArray< double>).C);
+
+                    #region HYCALPER AUTO GENERATED CODE
+
+                } else if (A is ILDenseArray<Int64> && B is ILDenseArray<Int64>) {
+                    return ILMath.ge((A as ILDenseArray<Int64>).C, (B as ILDenseArray<Int64>).C);
+                } else if (A is ILDenseArray<Int32> && B is ILDenseArray<Int32>) {
+                    return ILMath.ge((A as ILDenseArray<Int32>).C, (B as ILDenseArray<Int32>).C);
+                } else if (A is ILDenseArray<float> && B is ILDenseArray<float>) {
+                    return ILMath.ge((A as ILDenseArray<float>).C, (B as ILDenseArray<float>).C);
+                } else if (A is ILDenseArray<fcomplex> && B is ILDenseArray<fcomplex>) {
+                    return ILMath.ge((A as ILDenseArray<fcomplex>).C, (B as ILDenseArray<fcomplex>).C);
+                } else if (A is ILDenseArray<complex> && B is ILDenseArray<complex>) {
+                    return ILMath.ge((A as ILDenseArray<complex>).C, (B as ILDenseArray<complex>).C);
+                } else if (A is ILDenseArray<byte> && B is ILDenseArray<byte>) {
+                    return ILMath.ge((A as ILDenseArray<byte>).C, (B as ILDenseArray<byte>).C);
+
+                    #endregion HYCALPER AUTO GENERATED CODE
+                } else {
+                    throw new ILArgumentTypeException("Operator '>=' not defined for arrays of element type '" + typeof(ElementType).Name + "'");
+                }
+            }
+        }
+
+        /// <summary>
+        /// 'smaller or equal' operator of two arrays
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>Logical array of same size than A and B, result of operation along all elements</returns>
+        /// <remarks>Sizes and types of A and B must match.</remarks>
+        public static ILRetLogical operator <=(ILDenseArray<ElementType> A, ILDenseArray<ElementType> B) {
+            using (ILScope.Enter(A, B)) {
+                if (false) {
+
+                } else if (A is ILDenseArray< double> && B is ILDenseArray< double>) {
+                    return ILMath.le((A as ILDenseArray< double>).C, (B as ILDenseArray< double>).C);
+
+                    #region HYCALPER AUTO GENERATED CODE
+
+                } else if (A is ILDenseArray<Int64> && B is ILDenseArray<Int64>) {
+                    return ILMath.le((A as ILDenseArray<Int64>).C, (B as ILDenseArray<Int64>).C);
+                } else if (A is ILDenseArray<Int32> && B is ILDenseArray<Int32>) {
+                    return ILMath.le((A as ILDenseArray<Int32>).C, (B as ILDenseArray<Int32>).C);
+                } else if (A is ILDenseArray<float> && B is ILDenseArray<float>) {
+                    return ILMath.le((A as ILDenseArray<float>).C, (B as ILDenseArray<float>).C);
+                } else if (A is ILDenseArray<fcomplex> && B is ILDenseArray<fcomplex>) {
+                    return ILMath.le((A as ILDenseArray<fcomplex>).C, (B as ILDenseArray<fcomplex>).C);
+                } else if (A is ILDenseArray<complex> && B is ILDenseArray<complex>) {
+                    return ILMath.le((A as ILDenseArray<complex>).C, (B as ILDenseArray<complex>).C);
+                } else if (A is ILDenseArray<byte> && B is ILDenseArray<byte>) {
+                    return ILMath.le((A as ILDenseArray<byte>).C, (B as ILDenseArray<byte>).C);
+
+                    #endregion HYCALPER AUTO GENERATED CODE
+                } else {
+                    throw new ILArgumentTypeException("Operator '<=' not defined for arrays of element type '" + typeof(ElementType).Name + "'");
+                }
+            }
+        }
+
+        /// <summary>
+        /// 'greater' operator of two arrays
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>Logical array of same size than A and B, result of operation along all elements</returns>
+        /// <remarks>Dimension and types of A and B must match.</remarks>
+        public static ILRetLogical operator >(ILDenseArray<ElementType> A, ILDenseArray<ElementType> B) {
+            using (ILScope.Enter(A, B)) {
+                if (false) {
+
+                } else if (A is ILDenseArray< double> && B is ILDenseArray< double>) {
+                    return ILMath.gt((A as ILDenseArray< double>).C, (B as ILDenseArray< double>).C);
+
+                    #region HYCALPER AUTO GENERATED CODE
+
+                } else if (A is ILDenseArray<Int64> && B is ILDenseArray<Int64>) {
+                    return ILMath.gt((A as ILDenseArray<Int64>).C, (B as ILDenseArray<Int64>).C);
+                } else if (A is ILDenseArray<Int32> && B is ILDenseArray<Int32>) {
+                    return ILMath.gt((A as ILDenseArray<Int32>).C, (B as ILDenseArray<Int32>).C);
+                } else if (A is ILDenseArray<float> && B is ILDenseArray<float>) {
+                    return ILMath.gt((A as ILDenseArray<float>).C, (B as ILDenseArray<float>).C);
+                } else if (A is ILDenseArray<fcomplex> && B is ILDenseArray<fcomplex>) {
+                    return ILMath.gt((A as ILDenseArray<fcomplex>).C, (B as ILDenseArray<fcomplex>).C);
+                } else if (A is ILDenseArray<complex> && B is ILDenseArray<complex>) {
+                    return ILMath.gt((A as ILDenseArray<complex>).C, (B as ILDenseArray<complex>).C);
+                } else if (A is ILDenseArray<byte> && B is ILDenseArray<byte>) {
+                    return ILMath.gt((A as ILDenseArray<byte>).C, (B as ILDenseArray<byte>).C);
+
+                    #endregion HYCALPER AUTO GENERATED CODE
+                } else {
+                    throw new ILArgumentTypeException("Operator '>' not defined for arrays of element type '" + typeof(ElementType).Name + "'");
+                }
+            }
+        }
+        /// <summary>
+        /// 'smaller' operator of two arrays
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>Logical array of same size than A and B, result of operation along all elements</returns>
+        /// <remarks>Dimension and types of A and B must match.</remarks>
+        public static ILRetLogical operator <(ILDenseArray<ElementType> A, ILDenseArray<ElementType> B) {
+            using (ILScope.Enter(A, B)) {
+                if (false) {
+
+                } else if (A is ILDenseArray< double> && B is ILDenseArray< double>) {
+                    return ILMath.lt((A as ILDenseArray< double>).C, (B as ILDenseArray< double>).C);
+
+                    #region HYCALPER AUTO GENERATED CODE
+
+                } else if (A is ILDenseArray<Int64> && B is ILDenseArray<Int64>) {
+                    return ILMath.lt((A as ILDenseArray<Int64>).C, (B as ILDenseArray<Int64>).C);
+                } else if (A is ILDenseArray<Int32> && B is ILDenseArray<Int32>) {
+                    return ILMath.lt((A as ILDenseArray<Int32>).C, (B as ILDenseArray<Int32>).C);
+                } else if (A is ILDenseArray<float> && B is ILDenseArray<float>) {
+                    return ILMath.lt((A as ILDenseArray<float>).C, (B as ILDenseArray<float>).C);
+                } else if (A is ILDenseArray<fcomplex> && B is ILDenseArray<fcomplex>) {
+                    return ILMath.lt((A as ILDenseArray<fcomplex>).C, (B as ILDenseArray<fcomplex>).C);
+                } else if (A is ILDenseArray<complex> && B is ILDenseArray<complex>) {
+                    return ILMath.lt((A as ILDenseArray<complex>).C, (B as ILDenseArray<complex>).C);
+                } else if (A is ILDenseArray<byte> && B is ILDenseArray<byte>) {
+                    return ILMath.lt((A as ILDenseArray<byte>).C, (B as ILDenseArray<byte>).C);
+
+                    #endregion HYCALPER AUTO GENERATED CODE
+                } else {
+                    throw new ILArgumentTypeException("Operator '<' not defined for arrays of element type '" + typeof(ElementType).Name + "'");
+                }
+            }
+        }
+
+        /// <summary>
+        /// Explicitly convert scalar array to System.Value type (ElementType)
+        /// </summary>
+        /// <param name="val">Array of arbitrary type and size of 1x1</param>
+        /// <returns>Single value of type ElementType and of scalar size (1x1)</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILCastException">If input array is not scalar</exception>
+        /// <exception cref="System.NullReferenceException">If val is null</exception>
+        public static explicit operator ElementType(ILDenseArray<ElementType> val) {
+            using (ILScope.Enter(val)) {
+                if (!val.IsScalar)
+                    throw new ILCastException("unable to convert array to scalar");
+                return val.GetValue(0);
+            }
+        }
+
+        /// <summary>
+        /// Implicitly convert scalar to array of size 1x1 (scalar).
+        /// </summary>
+        /// <param name="val">Single element of ElementType type</param>
+        /// <returns>New array of type ILRetArray<![CDATA[<ElementType>]]> of size 1x1 
+        /// holding the only element with value of val.
+        /// </returns>
+        public static implicit operator ILDenseArray<ElementType>(ElementType val) {
+            ILArray<ElementType> ret = new ILArray<ElementType>(new ILDenseStorage<ElementType>(ILSize.Scalar1_1));
+            ret.SetValue(val, 0, 0);
+            return ret.C;
+        }
+
+        /// <summary>
+        /// Negate elements of array - if applicable
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns>New solid arrray having the elements of A negated</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If elements of the array are not of 
+        /// any supported numeric type</exception>
+        public static ILRetArray<ElementType> operator -(ILDenseArray<ElementType> A) {
+            using (ILScope.Enter(A)) {
+                ILArray<ElementType> ret = ILMath.empty<ElementType>();
+                if (A is ILDenseArray<double>) {
+                    ILMath.invert((A as ILDenseArray<double>).C, (ret as ILArray<double>));
+                } else if (A is ILDenseArray<float>) {
+                    ILMath.invert((A as ILDenseArray<float>).C, (ret as ILArray<float>));
+                } else if (A is ILDenseArray<complex>) {
+                    ILMath.invert((A as ILDenseArray<complex>).C, (ret as ILArray<complex>));
+                } else if (A is ILDenseArray<fcomplex>) {
+                    ILMath.invert((A as ILDenseArray<fcomplex>).C, (ret as ILArray<fcomplex>));
+                } else if (A is ILDenseArray<Int32>) {
+                    ILMath.invert((A as ILDenseArray<Int32>).C, (ret as ILArray<Int32>));
+                } else if (A is ILDenseArray<Int64>) {
+                    ILMath.invert((A as ILDenseArray<Int64>).C, (ret as ILArray<Int64>));
+                } else if (A is ILDenseArray<byte>) {
+                    ILMath.invert((A as ILDenseArray<byte>).C, (ret as ILArray<byte>));
+                } else {
+                    throw new ILArgumentException("unary - operator not defined for arrays of element type '" + typeof(ElementType).Name + "'");
+                }
+                return ret.C;
+            }
+        }
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Data/ILAVLTree.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Data/ILAVLTree.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Data/ILAVLTree.cs	(revision 9102)
@@ -0,0 +1,588 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using keytype = System.Int64; 
+
+namespace ILNumerics.Data {
+    /// <summary>
+    /// AVL balanced search tree
+    /// </summary>
+    /// <remarks>The tree stores unique keys (type:System.Int64, configurable via build) in a balanced search tree.
+    /// <para>The implementation is optimized for random seek access and consecutive write access - if no matching key found. 
+    /// Also, the next higher key for a given query can be returned in O(1).</para>
+    /// <para>The AVL tree class is not intended to be used directly. It supports the ILNumerics infrastructure (ILMemoryPool) 
+    /// internally.</para></remarks>
+    internal class ILAVLTree {
+
+        internal ILAVLTreeNode m_root = getNode();
+        private int m_nodeCount = 0;
+#if DEBUG
+        internal int m_itemCount = 0; 
+#endif
+
+        #region caching
+        private static readonly int MAX_STACKSIZE = 50; 
+        private static readonly ILAVLTreeNode[] s_stack = new ILAVLTreeNode[MAX_STACKSIZE]; 
+        private static readonly int[] s_dirs = new int[MAX_STACKSIZE];
+        #endregion
+
+        #region public interface 
+        /// <summary>
+        /// Return number of keys currently existing in the tree
+        /// </summary>
+        public int Count {
+            get { return m_nodeCount; }   
+        } 
+        /// <summary>
+        /// Check and add a key to the collection
+        /// </summary>
+        /// <param name="key">Key</param>
+        /// <remarks>The function makes sure, the key is stored in the tree.</remarks>
+        public void Add(keytype key) {
+            int depth, added2Side = 0;
+            if (FindNode(key, m_root, s_stack, s_dirs, out depth)) {
+                // nothing to do - key is already there
+                return; 
+            } else {
+                // parent is the node where the key should be inserted below
+                ILAVLTreeNode newNode = getNode(); 
+                newNode.key = key; 
+                m_nodeCount++; 
+                added2Side = s_dirs[depth--]; 
+                if (added2Side == -1) { // insert as left child 
+                    System.Diagnostics.Debug.Assert(s_stack[depth+1] == null);
+                    s_stack[depth].left = newNode; 
+                    s_stack[depth].balance--; 
+                } else { // insert as right child
+                    System.Diagnostics.Debug.Assert(s_stack[depth+1] == null); 
+                    s_stack[depth].right = newNode; 
+                    s_stack[depth].balance++; 
+                }
+            }
+            // check balances along 's_stack' path -> up to root
+            // depth is at parent level now
+            ILAVLTreeNode node = s_stack[depth];
+            while (depth > 0) {
+                if (node.balance == 0) {
+                    return; 
+                }
+                if (node.balance * node.balance == 1) {
+                    node = s_stack[--depth]; 
+                    node.balance += s_dirs[depth+1]; 
+                    continue;
+                }
+                if (node.balance == 2) {
+                    if (node.right.balance >= 0) {
+                        // rebalance RR -> simple left rotation
+                        ILAVLTreeNode node2 = node.right; 
+                        if (s_dirs[depth] == 1) {
+                            s_stack[depth-1].right = node2; 
+                        } else {
+                            s_stack[depth-1].left = node2; 
+                        }
+                        if (node2.balance == 0) { 
+                            node.balance = 1; 
+                            node2.balance = -1; 
+                        } else {
+                            System.Diagnostics.Debug.Assert (node2.balance == 1); 
+                            node.balance = 0; 
+                            node2.balance = 0;  
+                        } 
+                        node.right = node2.left; 
+                        node2.left = node;
+                    } else {
+                        // rebalance RL -> double left rotation
+                        ILAVLTreeNode node2 = node.right;
+                        ILAVLTreeNode node3 = node2.left;
+                        if (s_dirs[depth] == 1) {
+                            s_stack[depth-1].right = node3; 
+                        } else {
+                            s_stack[depth-1].left = node3;  
+                        }
+                        if (node3.balance == -1) {
+                            node2.balance = 1; 
+                            node.balance = 0;
+                        } else if (node3.balance == 1) {
+                            node2.balance = 0;
+                            node.balance = -1;
+                        } else {
+                            node2.balance = 0; 
+                            node.balance = 0; 
+                        }
+                        node3.balance = 0; 
+
+                        node.right = node3.left; 
+                        node2.left = node3.right; 
+                        node3.left = node; 
+                        node3.right = node2; 
+                    }
+                } else { 
+                    System.Diagnostics.Debug.Assert(node.balance == -2);
+                    if (node.left.balance <= 0) {
+                        ILAVLTreeNode node2 = node.left; 
+                        // rebalance LL -> simple rotate right
+                        if (s_dirs[depth] == 1) {
+                            s_stack[depth-1].right = node2; 
+                        } else {
+                            s_stack[depth-1].left = node2; 
+                        }
+                        if (node2.balance == 0) {
+                            node.balance = -1; 
+                            node2.balance = 1; 
+                        } else {
+                            System.Diagnostics.Debug.Assert (node2.balance == -1); 
+                            node.balance = 0; 
+                            node2.balance = 0;  
+                        }
+                        node.left = node2.right; 
+                        node2.right = node;
+                    } else {
+                        // rebalance LR - double right rotation 
+                        ILAVLTreeNode node2 = node.left;
+                        ILAVLTreeNode node3 = node2.right;
+                        if (s_dirs[depth] == 1) {
+                            s_stack[depth-1].right = node3; 
+                        } else {
+                            s_stack[depth-1].left = node3;  
+                        }
+                        if (node3.balance == 1) {
+                            node2.balance = -1; 
+                            node.balance = 0; 
+                        } else if (node3.balance == -1) {
+                            node2.balance = 0; 
+                            node.balance = 1;  
+                        } else {
+                            node2.balance = 0; 
+                            node.balance = 0; 
+                        }
+                        node3.balance = 0; 
+
+                        node.left = node3.right; 
+                        node2.right = node3.left; 
+                        node3.right = node; 
+                        node3.left = node2; 
+                    }
+                }
+#if DEBUG
+                //if (!CheckTree()) {
+                //    return;
+                //}
+#endif
+                return; 
+            }
+        }
+        /// <summary>
+        /// Remove key from tree
+        /// </summary>
+        /// <param name="key">Key to be removed</param>
+        /// <remarks>The function makes sure, the tree does not contain a node with the given key.</remarks>
+        public void Remove(keytype key) {
+            int depth;
+            if (!FindNode(key, m_root, s_stack, s_dirs, out depth)) {
+                return; 
+            }
+#if DEBUG
+            int remDepth = depth; 
+#endif
+            // last entry in stack is the matching node
+            ILAVLTreeNode cur = s_stack[depth];
+            if (cur.left != null) {
+                if (cur.right != null) {
+                    // find replacement node 
+                    ILAVLTreeNode orig = cur; 
+                    cur = cur.left;
+                    s_stack[++depth] = cur; 
+                    s_dirs[depth] = -1; 
+                    while (cur.right != null) {
+                        cur = cur.right;
+                        s_stack[++depth] = cur; 
+                        s_dirs[depth] = 1; 
+                    }
+                    // exchange keys with current node
+                    orig.key = cur.key; 
+                    cur = cur.left;     
+                } else {
+                    cur = cur.left; 
+                }
+            } else {
+                if (cur.right != null) {
+                    // replace with right child
+                    cur = cur.right; 
+                } else {
+                    // no childs simply delete cur
+                    cur = null; 
+                }
+            }
+            depth--;
+            ILAVLTreeNode par = s_stack[depth];
+            if (s_dirs[depth+1] == 1) {
+                par.right = cur;
+                par.balance--; 
+            } else {
+                par.left = cur;
+                par.balance++; 
+            }
+            m_nodeCount--; 
+#if DEBUG
+            if (par.left != null) 
+                System.Diagnostics.Debug.Assert(par.left != par); 
+            if (par.right != null) 
+                System.Diagnostics.Debug.Assert(par.right != par); 
+         
+#endif
+            #region rebalance
+            cur = par; 
+            while (depth > 0) {
+                if (cur.balance == 0) {
+                    cur = s_stack[--depth];
+                    cur.balance -= s_dirs[depth + 1];
+                    continue;
+                }
+                if (cur.balance * cur.balance == 1) {
+                    break;
+                } else if (cur.balance == 2) {
+                    #region needs left rotations
+                    if (cur.right.balance >= 0) {
+                        // rebalance RR -> simple left rotation
+                        ILAVLTreeNode node2 = cur.right;
+                        if (s_dirs[depth] == 1) {
+                            s_stack[depth - 1].right = node2;
+                        } else {
+                            s_stack[depth - 1].left = node2;
+                        }
+                        cur.right = node2.left;
+                        node2.left = cur;
+                        if (node2.balance == 0) {
+                            cur.balance = 1;
+                            node2.balance = -1;
+                            break; 
+                        } else {
+                            System.Diagnostics.Debug.Assert(node2.balance == 1);
+                            cur.balance = 0;
+                            node2.balance = 0;
+                        }
+                    } else {
+                        // rebalance RL -> double left rotation
+                        ILAVLTreeNode node2 = cur.right;
+                        ILAVLTreeNode node3 = node2.left;
+                        if (s_dirs[depth] == 1) {
+                            s_stack[depth - 1].right = node3;
+                        } else {
+                            s_stack[depth - 1].left = node3;
+                        }
+                        if (node3.balance == -1) {
+                            node2.balance = 1;
+                            cur.balance = 0;
+                        } else if (node3.balance == 1) {
+                            node2.balance = 0;
+                            cur.balance = -1;
+                        } else {
+                            node2.balance = 0;
+                            cur.balance = 0;
+                        }
+                        node3.balance = 0;
+
+                        cur.right = node3.left;
+                        node2.left = node3.right;
+                        node3.left = cur;
+                        node3.right = node2;
+                    }
+                    #endregion
+                } else {
+                    #region needs right rotation
+                    System.Diagnostics.Debug.Assert(cur.balance == -2);
+                    if (cur.left.balance <= 0) {
+                        ILAVLTreeNode node2 = cur.left;
+                        // rebalance LL -> simple rotate right
+                        if (s_dirs[depth] == 1) {
+                            s_stack[depth - 1].right = node2;
+                        } else {
+                            s_stack[depth - 1].left = node2;
+                        }
+                        cur.left = node2.right;
+                        node2.right = cur;
+                        if (node2.balance == 0) {
+                            cur.balance = -1;
+                            node2.balance = 1;
+                            break; 
+                        } else {
+                            System.Diagnostics.Debug.Assert(node2.balance == -1);
+                            cur.balance = 0;
+                            node2.balance = 0;
+                        }
+                    } else {
+                        // rebalance LR - double right rotation 
+                        ILAVLTreeNode node2 = cur.left;
+                        ILAVLTreeNode node3 = node2.right;
+                        if (s_dirs[depth] == 1) {
+                            s_stack[depth - 1].right = node3;
+                        } else {
+                            s_stack[depth - 1].left = node3;
+                        }
+                        if (node3.balance == 1) {
+                            node2.balance = -1;
+                            cur.balance = 0;
+                        } else if (node3.balance == -1) {
+                            node2.balance = 0;
+                            cur.balance = 1;
+                        } else {
+                            node2.balance = 0;
+                            cur.balance = 0;
+                        }
+                        node3.balance = 0;
+
+                        cur.left = node3.right;
+                        node2.right = node3.left;
+                        node3.right = cur;
+                        node3.left = node2;
+                    }
+                    #endregion
+                }
+                // populate to parent 
+                if (--depth <= 0)
+                    break; 
+                cur = s_stack[depth];
+                cur.balance -= s_dirs[depth + 1];
+            }
+            #endregion
+#if DEBUG
+                //if (!CheckTree()) {
+                //    return;
+                //}
+#endif
+        }
+        /// <summary>
+        /// Find next higher key
+        /// </summary>
+        /// <param name="key">Key to find</param>
+        /// <returns>The key with the next higher value compared with <paramref name="key"/>, or -1 if no such key exists</returns>
+        public keytype Next(keytype key) {
+            if (m_root.right == null) {
+                return -1; 
+            }
+            int level = 0;
+            if (!FindNode(key, m_root, s_stack, s_dirs, out level) && level > 0)
+                level--; 
+            ILAVLTreeNode node = s_stack[level]; 
+            if (node.key >= key) return node.key; 
+            node = NextAsc(s_stack[level], s_stack, s_dirs, level); 
+            if (node != null && node.key > key) 
+                return node.key; 
+            return -1; 
+        }
+        /// <summary>
+        /// Clear the tree from all keys
+        /// </summary>
+        internal void Clear() {
+            m_root.right = null; 
+#if DEBUG
+            m_nodeCount = 0;
+            m_itemCount = 0; 
+#endif
+        }
+        #endregion
+
+        #region private helper
+        private static bool FindNode(keytype key, ILAVLTreeNode cur, ILAVLTreeNode[] path, int[] dirs, out int level) {
+            int depth = 0; 
+            while (true) {
+                path[depth] = cur; 
+                //if (cur.isNil) {
+                //    //Console.Out.WriteLine("Key:{0} depth: {1} {2}",cur.key, depth, s_dirs[depth] ); 
+                //    level = depth;  
+                //    return false;  
+                //}
+                if (cur.key == key) {
+                    level = depth; 
+                    return true; 
+                } else { 
+                    if (key < cur.key) {
+                        dirs[++depth] = -1; 
+                        path[depth] = cur.left; 
+                        if (cur.left == null) {
+                            level = depth; 
+                            return false; 
+                        } 
+                        cur = cur.left; 
+                    } else { // key > cur.key 
+                        dirs[++depth] = 1; 
+                        path[depth] = cur.right; 
+                        if (cur.right == null) {
+                            level = depth; 
+                            return false; 
+                        }
+                        cur = cur.right; 
+                    }
+                }
+            }
+        }
+        private static ILAVLTreeNode NextAsc(ILAVLTreeNode node, ILAVLTreeNode[] path, int[] dirs, int level) {
+            ILAVLTreeNode ret = node; 
+            if (node.right != null) {
+                node = node.right; 
+                while (node.left != null) {
+                    node = node.left; 
+                }
+                ret = node; 
+            } else {
+                while (level > 0) {
+                    // dirs[0] is always 0 (dummy root node) 
+                    if (dirs[level] == -1) {
+                        ret = path[--level];
+                        break;
+                    }
+                    level--;
+                }
+            }
+            return ret; 
+        }
+        /// <summary>
+        /// check the consistency of the tree
+        /// </summary>
+        /// <returns></returns>
+        internal bool CheckTree() {
+            if (m_root.right == null)
+                return true;
+            ILAVLTreeNode cur = m_root.right;
+            while (cur.left != null)
+                cur = cur.left;
+            keytype key = cur.key; 
+            int depth;
+            ILAVLTreeNode node = cur;
+            do {
+                Console.Out.Write("checking node: " + node.key); 
+                if (FindNode(node.key, m_root, s_stack, s_dirs, out depth)) {
+                    if (s_stack[depth] != node) 
+                        return false; 
+                    if (!checkTree(node)) {
+                        return false;
+                    }
+                    node = NextAsc(node, s_stack, s_dirs, depth); 
+                } else {
+                    return false;
+                }
+                Console.Out.WriteLine("... ok"); 
+            } while (node != null);
+            return true; 
+        }
+        private static ILAVLTreeNode getNode() {
+            var ret = new ILAVLTreeNode();
+            ret.key = -1; 
+            ret.balance = 0; 
+            //ret.right = ret; 
+            return ret; 
+        }
+        private bool checkTree(int key) {
+            ILAVLTreeNode[] tmpNodes = new ILAVLTreeNode[50]; 
+            int[] tmpKeys = new int[50]; 
+            int level;
+            if (!FindNode(key, m_root, tmpNodes, tmpKeys, out level)) {
+                return false; 
+            } 
+            return checkTree(tmpNodes[level]); 
+        }
+        private static bool checkTree(ILAVLTreeNode root) {
+            // check balance condition
+            int ltree = 0, rtree = 0; 
+            if (root.left != null) {
+                ltree = levelTree(root.left); 
+            } 
+            if (root.right != null) {
+                rtree = levelTree(root.right); 
+            }
+            int bal = rtree - ltree;
+            if (root.balance != bal) 
+                return false; 
+            if (bal * bal > 1) {
+                return false;   
+            }  
+     
+            return true; 
+
+        }
+        private static int levelTree(ILAVLTreeNode root) {
+            if (root.left == null && root.right == null) {
+                return 1; 
+            } else {
+                int ltree = 0, rtree = 0; 
+                if (root.left != null) {
+                    ltree = levelTree(root.left);                 
+                }
+                if (root.right != null) {
+                    rtree = levelTree(root.right); 
+                }
+                return Math.Max(ltree,rtree) + 1; 
+            }
+        }
+        #endregion
+        /// <summary>
+        /// an AVL tree node 
+        /// </summary>
+        public class ILAVLTreeNode {
+            /// <summary>
+            /// Key
+            /// </summary>
+            public keytype key; 
+            /// <summary>
+            /// Right child
+            /// </summary>
+            public ILAVLTreeNode right;
+            /// <summary>
+            /// Left child
+            /// </summary>
+            public ILAVLTreeNode left;
+            /// <summary>
+            /// Balance factor for the node
+            /// </summary>
+            public int balance;
+            /// <summary>
+            /// Rext representation of the node 
+            /// </summary>
+            /// <returns>String representation for the node</returns>
+            public override string ToString() {
+                return String.Format("{0} [{1}-{2}]",key,(left == null) ? "*" : left.key.ToString(), (right == null) ? "*" : right.key.ToString());
+            }
+        }
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Data/ILBTree.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Data/ILBTree.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Data/ILBTree.cs	(revision 9102)
@@ -0,0 +1,431 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using keytype = System.Int32; 
+
+namespace ILNumerics.Data {
+    /// <summary>
+    /// incomplete BTree implementation (it lags of a remove method)
+    /// </summary>
+    /// <typeparam name="T">value element type</typeparam>
+    public class ILBTree<T> {
+
+        //private static readonly int ORDER = 4;   // max number of childs
+        //private static readonly int MAX_KEYS = 3;  // uneven ! (order - 1) 
+        //private static readonly int MIN_CHILDS = 2;  
+        //private static readonly int MIN_KEYS = 1;  // uneven ! (order / 2 - 1)        
+        private static int m_order = 24; 
+        public static int ORDER  {
+            get { return m_order; }
+            set { 
+                if (value / 2 * 2 != value) {
+                    value++; 
+                }
+                m_order = value; 
+                MAX_KEYS = value -1; 
+                MIN_KEYS = value / 2 - 1; 
+            }
+        }   // max number of childs
+
+        public static int MAX_KEYS = 15;  // uneven ! (order - 1) 
+        public static int MIN_KEYS = 7;  // uneven ! (order / 2 - 1)
+        public static int DEFAULT_LIST_CAPACITY = 8; 
+
+        private int m_nodeCount = 0; 
+        private int m_levelCount = 1;
+        
+        private nodetype m_root; 
+
+        //private class itemtype {
+        //    public keytype Key; 
+        //    public List<T> Values;  
+        //    //private itemtype () {
+        //    //    Key = -1;
+        //    //    Values = new LinkedList<T>(); 
+        //    //}
+        //    public itemtype (keytype key, T value) {
+        //        Key = key;
+        //        Values = new List<T>(8); 
+        //        Values.Add(value);  
+        //    }
+        //    public override string ToString() {
+        //        return String.Format("K:{0} Count:{1}",Key,Values.Count); 
+        //    }
+        //}
+        private class nodetype {
+            //public itemtype[] Items; 
+            public int[] Keys; 
+            public List<T>[] Values; 
+            public nodetype[] Childs; 
+            /// <summary>
+            /// number of keys in the node
+            /// </summary>
+            public int Count; 
+
+            public nodetype() {
+                Count = 0;
+                //Items = new itemtype[ MAX_KEYS ];
+                Keys = new int[MAX_KEYS]; 
+                Values = new List<T>[MAX_KEYS]; 
+                Childs = new nodetype[ MAX_KEYS + 1 ];
+            }
+            public override string ToString() {
+                string itemDesc = "---";
+                if (Count > 0) {
+                    itemDesc = String.Format("{0} - {1}",Keys[0],Keys[Count-1]); 
+                }
+                return String.Format("{0} Items:[{1}]",Count,itemDesc); 
+            }
+
+        }
+
+        #region constructor
+        public ILBTree() {
+            m_root = new nodetype(); 
+            m_nodeCount = 1; 
+        }
+        #endregion
+
+        #region public interface
+
+        public int NodeCount {
+            get { return m_nodeCount; }
+        }
+        public int LevelCount {
+            get { return m_levelCount; }
+        }
+
+
+        public void Add(keytype key, T value) {
+            if (m_root.Count >= MAX_KEYS) {
+                nodetype newright = new nodetype(); 
+                keytype upkey; 
+                List<T> upval;
+                SplitNode(m_root,newright, out upkey, out upval); 
+                nodetype newRoot = new nodetype(); 
+                newRoot.Childs[0] = m_root; 
+                newRoot.Childs[1] = newright; 
+                newRoot.Keys[0] = upkey; 
+                newRoot.Values[0] = upval; 
+                newRoot.Count = 1; 
+                m_root = newRoot;
+                m_nodeCount += 2; 
+                m_levelCount++; 
+            }
+            AddValue(key, value, m_root); 
+        }
+        #endregion
+        
+        #region private helpers 
+        /// <summary>
+        ///  is the key contained in curNode ?
+        /// </summary>
+        /// <param name="curNode"></param>
+        /// <param name="key"></param>
+        /// <param name="location"></param>
+        /// <returns></returns>
+        private unsafe static bool SearchNode(nodetype curNode, keytype key, ref int location) {
+            int loc = 0, max = curNode.Count; int[] curNodeKeys = curNode.Keys; 
+            for (; loc < max; loc++) {
+                int curKey = curNodeKeys[loc];
+                if (curKey == key) {
+                    location = loc; 
+                    return true; 
+                } else if (curKey > key) {
+                    location = loc; 
+                    return false; 
+                }
+            }
+            location = loc; 
+            return false; 
+
+            //int loc = 0, max = curNode.Count;
+            //foreach (keytype curKey in curNode.Keys) {
+            //    if (curKey == key) {
+            //        location = loc; 
+            //        return true; 
+            //    } else if (curKey > key) {
+            //        location = loc; 
+            //        return false; 
+            //    }
+            //    if (++loc >= max) break; 
+            //}
+            //location = loc; 
+            //return false; 
+
+            //int loc = curNode.Count - 1;
+            //fixed (int* keys = curNode.Keys) {
+            //    int* curKey = keys + loc;
+            //    do {
+            //        if (*curKey == key) {
+            //            location = loc; 
+            //            return true; 
+            //        } else if (*curKey < key) {
+            //            location = ++loc; 
+            //            return false; 
+            //        }
+            //        curKey--;
+            //    } while (loc --> 0); 
+            //}
+            //location = 0; 
+            //return false; 
+        }
+        private void AddValue(keytype key, T value, nodetype curNode) {
+            System.Diagnostics.Debug.Assert(curNode.Count < MAX_KEYS); 
+            while (true) {
+                // search node (inlined from func) 
+                short max = (short)curNode.Count; 
+                short location = 0;
+                int[] curNodeKeys = curNode.Keys; 
+                for (; location < max; location++) {
+                    int curKey = curNodeKeys[location];
+                    if (curKey == key) {
+                        curNode.Values[location].Add(value); 
+                        return; 
+                    }
+                    if (curKey > key) {
+                        break; 
+                    }
+                }
+                nodetype childNode = curNode.Childs[location]; 
+                if (childNode == null) {
+                    // insert right here
+                    var newVals = new List<T>(8);
+                    newVals.Add(value); 
+                    InsertItemIntoNode(curNode,key,newVals,location,null);  
+                    break; 
+                } else {
+                    // check if the child is filled up allready
+                    if (childNode.Count >= MAX_KEYS) {
+                        nodetype newRightChild = new nodetype(); 
+                        int upkey; 
+                        List<T> upval; 
+                        SplitNode(childNode, newRightChild, out upkey, out upval); 
+                        m_nodeCount++; 
+                        InsertItemIntoNode(curNode,upkey, upval, location, newRightChild);  // cur node should always have space left! 
+                        // in which subtree to go? 
+                        if (key == upkey) {
+                            curNode.Values[location].Add(value); 
+                            return; 
+                        }
+                        if (key > upkey) 
+                            location++; 
+                    }
+                    //AddValue(key, value, curNode.Childs[location]); 
+                    curNode = curNode.Childs[location]; 
+                }
+            }
+        }
+
+        //private void AddValue(keytype key, T value, nodetype curNode) {
+        //    System.Diagnostics.Debug.Assert(curNode.Count < MAX_KEYS); 
+        //    int location; 
+        //    if (SearchNode(curNode, key, out location)) {
+        //        curNode.Values[location].Add(value); 
+        //    } else {
+        //        nodetype childNode = curNode.Childs[location]; 
+        //        if (childNode == null) {
+        //            // insert right here
+        //            var newVals = new List<T>(8);
+        //            newVals.Add(value); 
+        //            InsertItemIntoNode(curNode,key,newVals,location,null);  
+        //        } else {
+        //            // check if the child is filled up allready
+        //            if (childNode.Count >= MAX_KEYS) {
+        //                nodetype newRightChild = new nodetype(); 
+        //                int upkey; 
+        //                List<T> upval; 
+        //                SplitNode(childNode, newRightChild, out upkey, out upval); 
+        //                m_nodeCount++; 
+        //                InsertItemIntoNode(curNode,upkey, upval, location, newRightChild);  // cur node should always have space left! 
+        //                // in which subtree to go? 
+        //                if (key == upkey) {
+        //                    curNode.Values[location].Add(value); 
+        //                    return; 
+        //                }
+        //                if (key > upkey) 
+        //                    location++; 
+        //            }
+        //            AddValue(key, value, curNode.Childs[location]); 
+        //        }
+        //    }
+        //}
+
+        #region break 
+        #endregion
+
+        //private void AddValue(keytype key, T value, nodetype curNode, ref itemtype upcomingItem, ref nodetype rightchild) {
+        //    if (curNode == null) {
+        //        // we came from a leaf! let the parent handle the insertion
+        //        upcomingItem = new itemtype(key,value); 
+        //        rightchild = null; 
+        //        return; 
+        //    }
+        //    System.Diagnostics.Debug.Assert(curNode.Count < MAX_KEYS); 
+        //    int location; 
+        //    if (SearchNode(curNode, key, out location)) {
+        //        curNode.Items[location].Values.AddFirst(value); 
+        //        upcomingItem = null; 
+        //    } else {
+        //        nodetype childNode = curNode.Childs[location]; 
+        //        if (childNode.Count >= MAX_KEYS) {
+        //            nodetype newRightChild = new nodetype(); 
+        //            itemtype newUpItem; 
+        //            SplitNode(childNode, newRightChild, out newUpItem); 
+        //            InsertItemIntoNode(curNode,newUpItem,location,newRightChild);  // cur node should always have space left! 
+        //            // in which subtree to go? 
+        //            if (key > newUpItem.Key) 
+        //                location++; 
+        //            if (key == newUpItem.Key) {
+        //                curNode.Items[location].Values.AddFirst(value); 
+        //                upcomingItem = null; 
+        //                return; 
+        //            }
+        //        }
+        //        // location = index of child/ insertion point
+        //        AddValue(key, value, curNode.Childs[location], ref upcomingItem, ref rightchild); 
+        //        // handle upcoming node
+        //        if (upcomingItem != null) {
+        //            if (curNode.Count < MAX_KEYS) {
+        //                // insert right here
+        //                InsertItemIntoNode(curNode, upcomingItem, location, rightchild); 
+        //                upcomingItem = null; 
+        //            } else {
+        //                // split the node and move median up
+        //                SplitNode(curNode, upcomingItem, location, ref upcomingItem, ref rightchild); 
+        //            }
+        //        }
+        //    }
+        //}
+
+        private void SplitNode(nodetype curNode, nodetype newRight, out keytype upKey, out List<T> upval) {
+            System.Diagnostics.Debug.Assert(Math.Round(curNode.Count / 2.0) != curNode.Count / 2.0);
+            System.Diagnostics.Debug.Assert(curNode.Count == (MIN_KEYS * 2 + 1));
+            System.Diagnostics.Debug.Assert(curNode.Count == MAX_KEYS);
+            System.Diagnostics.Debug.Assert(newRight != null && newRight.Childs != null && newRight.Keys != null);
+            System.Diagnostics.Debug.Assert(newRight.Childs.Length == ORDER && newRight.Keys.Length == MAX_KEYS && newRight.Values.Length == MAX_KEYS);
+            for (int i = MIN_KEYS + 1, ni = 0; ni < MIN_KEYS; ni++, i++) {
+                newRight.Keys[ni] = curNode.Keys[i]; 
+                newRight.Values[ni] = curNode.Values[i]; 
+                newRight.Childs[ni+1] = curNode.Childs[i+1]; 
+                // clear old data
+                curNode.Keys[i] = -1; 
+                curNode.Values[i] = null; 
+                curNode.Childs[i+1] = null; 
+            }
+            curNode.Count = MIN_KEYS;
+            newRight.Count = MIN_KEYS; 
+            newRight.Childs[0] = curNode.Childs[MIN_KEYS + 1]; 
+            upKey = curNode.Keys[MIN_KEYS]; 
+            upval = curNode.Values[MIN_KEYS]; 
+            // clear old data
+            curNode.Keys[MIN_KEYS] = -1; 
+            curNode.Values[MIN_KEYS] = null; 
+            curNode.Childs[MIN_KEYS + 1] = null; 
+        }
+
+        //private void SplitNode(nodetype curNode, itemtype newItem, int location, ref itemtype upcomingItem, ref nodetype upcomingrightnode) {
+        //    var newnode = new nodetype();
+        //    if (location <= MIN_KEYS) {
+        //        // copy right node  
+        //        for (int ci = MIN_KEYS, ni = 0; ci < MAX_KEYS; ci++, ni++ ) {
+        //            newnode.Items[ni] = curNode.Items[ci]; 
+        //            newnode.Childs[ni+1] = curNode.Childs[ci]; 
+        //        }
+        //        // copy curNode 
+        //        for (int ci = MIN_KEYS; ci --> location; ) {
+        //            curNode.Items[ci+1] = curNode.Items[ci]; 
+        //            curNode.Childs[ci+1] = curNode.Childs[ci]; 
+        //        }
+        //        curNode.Count = MIN_KEYS + 1; 
+        //        newnode.Count = MAX_KEYS - MIN_KEYS; 
+        //        // insert new item  
+        //        curNode.Items[location] = newItem; 
+        //        curNode.Childs[location] = upcomingrightnode; 
+        //        newnode.Childs[0] = curNode.Childs[MIN_KEYS]; 
+        //        // give the median back upwards
+        //        upcomingItem = curNode.Items[MIN_KEYS]; 
+        //        upcomingrightnode = newnode; 
+        //    } else {
+        //        // copy right node -> up to insert location
+        //        int i = MIN_KEYS, ni = 0; 
+        //        for (; i < location; i++, ni++) {
+        //            newnode.Items[ni] = curNode.Items[i]; 
+        //            newnode.Childs[ni+1] = curNode.Childs[i]; 
+        //        }
+        //        // insert new item
+        //        newnode.Items[ni] = newItem; 
+        //        newnode.Childs[ni++] = upcomingrightnode; 
+        //        // copy rest of node to right side
+        //        for (; i < curNode.Count; i++, ni++) {
+        //            newnode.Items[ni] = curNode.Items[i]; 
+        //            newnode.Childs[ni+1] = curNode.Childs[i]; 
+        //        }
+        //        // update curNode
+        //        curNode.Count = MIN_KEYS + 1; 
+        //        newnode.Count = ni; 
+        //        newnode.Childs[0] = curNode.Childs[MIN_KEYS + 1]; 
+        //        upcomingItem = curNode.Items[MIN_KEYS + 1]; 
+        //        upcomingrightnode = newnode; 
+        //    }
+        //    m_nodeCount++; 
+        //}
+
+        private void InsertItemIntoNode(nodetype curNode, keytype newKey,List<T> newvalue, int location, nodetype rigthchild) {
+            int a = curNode.Count; 
+            for (; a --> location; ) {
+                curNode.Keys[a+1] = curNode.Keys[a];
+                curNode.Values[a+1] = curNode.Values[a];
+                curNode.Childs[a+2] = curNode.Childs[a+1]; 
+            }
+            // insert a new linked list at freed position
+            curNode.Keys[location] = newKey;
+            curNode.Values[location] = newvalue; 
+            curNode.Childs[location+1] = rigthchild; 
+            curNode.Count++; 
+        }
+
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Data/ILBinTree.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Data/ILBinTree.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Data/ILBinTree.cs	(revision 9102)
@@ -0,0 +1,189 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+#region LGPL License
+/*    
+    This file is part of ILNumerics.Net Core Module.
+
+    ILNumerics.Net Core Module is free software: you can redistribute it 
+    and/or modify it under the terms of the GNU Lesser General Public 
+    License as published by the Free Software Foundation, either version 3
+    of the License, or (at your option) any later version.
+
+    ILNumerics.Net Core Module is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with ILNumerics.Net Core Module.  
+    If not, see <http://www.gnu.org/licenses/>.
+*/
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+        using System.Windows.Forms; 
+
+
+namespace ILNumerics.Data {
+    public class ILBinTree<T> {
+        
+        protected int m_count; 
+        protected ILBinTreeNode<T> m_root;
+        public virtual bool Contains (T data) {
+            return Contains(m_root,data); 
+        }
+        private bool Contains(ILBinTreeNode<T> _root, T data) {
+            if (object.Equals(_root.Data,data)) return true;  
+            if (_root.LeftSon != null && Contains(_root.LeftSon,data)) return true; 
+            if (_root.RightSon != null && Contains(_root.RightSon,data)) return true; 
+            return false;      
+        }
+        //public ILBinTreeNode<T> Find(T data) {
+                
+        //}
+        //public ILBinTreeNode<T> AddLeftSon (ILBinTreeNode<T> node, T) {
+        //    T ret = null; 
+        //    if (node.LeftSon == null) {
+
+        //    } else {
+
+        //        return 
+        //    }
+        //}
+
+    }
+    public class ILBinTreeNode<T> {
+        internal T m_data; 
+        internal ILBinTreeNode<T> m_father; 
+        internal ILBinTreeNode<T> m_leftSon; 
+        internal ILBinTreeNode<T> m_rightSon; 
+
+        public T Data {
+            get {
+                return m_data; 
+            }
+            set {
+                m_data = value; 
+            }
+        }
+        public ILBinTreeNode<T> Father {
+            get {
+                return m_father; 
+            }
+            set {
+                m_father = value; 
+            }
+        }
+        public ILBinTreeNode<T> LeftSon {
+            get {
+                return m_leftSon; 
+            }
+            set {
+                m_leftSon = value; 
+            }
+        }
+        public ILBinTreeNode<T> RightSon {
+            get {
+                return m_rightSon; 
+            }
+            set {
+                m_rightSon = value; 
+            }
+        }
+        public ILBinTreeNode() {}
+        public ILBinTreeNode(T data) {
+            m_data = data; 
+        }
+
+        public bool IsLeaf() {
+            return m_leftSon == null && m_rightSon == null; 
+        }
+        public int Height () {
+            if (IsLeaf()) return 0; 
+            int lh = (m_leftSon != null) ? m_leftSon.Height() : 0; 
+            int rh = (m_rightSon != null) ? m_rightSon.Height() : 0; 
+            if (lh > rh) return lh + 1; else return rh + 1; 
+        }
+        public override string  ToString() {
+ 	        return ToString(0, '-', BinTreeWalkingMode.PreOrder);
+        }
+        public string ToString(int indent, char indentChar, BinTreeWalkingMode walkingMode) {
+            StringBuilder sb = new StringBuilder(); 
+            switch (walkingMode) {
+                case BinTreeWalkingMode.PreOrder:
+                    #region PreOrder
+                    string s; 
+                    if (m_data != null) {
+                        s = m_data.ToString(); 
+                    } else {
+                        s = "(null)"; 
+                    }
+                    sb.Append(s); indent += s.Length; 
+                    sb.Append(indentChar); 
+                    if (m_leftSon != null) {
+                        sb.Append(m_leftSon.ToString(indent + 1, indentChar,walkingMode)); 
+                    } else {
+                        sb.Append(Environment.NewLine); 
+                    }
+                    sb.Append(new String(' ',indent) + indentChar); 
+                    if (m_rightSon != null) {
+                        sb.Append(m_rightSon.ToString(indent + 1, indentChar,walkingMode)); 
+                    } else {
+                        sb.Append(Environment.NewLine); 
+                    } 
+                    break;
+                    #endregion
+                default: 
+                    throw new InvalidOperationException(); 
+            }
+            return sb.ToString();
+        }
+        
+    
+    }
+    public enum BinTreeWalkingMode {
+        PreOrder,
+        PostOrder,
+        InOrder
+    }
+
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Data/ILIntList.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Data/ILIntList.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Data/ILIntList.cs	(revision 9102)
@@ -0,0 +1,151 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace ILNumerics.Data {
+    internal class ILIntList {
+
+        int[] m_data; 
+        int m_count;
+
+        public static ILIntList Create() { 
+            return new ILIntList(); 
+        }
+        public static ILIntList Create(int initialCapacity) {
+            return new ILIntList(initialCapacity);
+        }
+        public static ILIntList Create(int initialCapacity, int value) {
+            return new ILIntList(initialCapacity, value);
+        }
+        internal ILIntList(ILDenseArray<int> array) {
+            m_count = array.S.NumberOfElements; 
+            m_data = ILMemoryPool.Pool.New<int>(m_count); 
+            System.Array.Copy(array.GetArrayForRead(), m_data, m_count); 
+        }
+
+        private ILIntList() {
+            m_count = 0; 
+            m_data = ILMemoryPool.Pool.New<int>(4); 
+        }
+        private ILIntList(int initialCapacity) {
+            m_count = 0;
+            m_data = ILMemoryPool.Pool.New<int>(initialCapacity); 
+        }
+
+        public ILIntList(int initialCapacity, int value) {
+            m_count = initialCapacity; 
+            m_data = ILMemoryPool.Pool.New<int>(initialCapacity);
+            for (int i = 0; i < m_data.Length; i++) {
+                if (i == initialCapacity) break; 
+                m_data[i] = value; 
+            }
+        } 
+
+        public int this[int index] {
+            get { 
+                //if (index >= m_count) 
+                //    throw new IndexOutOfRangeException(); 
+                return m_data[index]; 
+            }
+            set { m_data[index] = value; }
+        }
+
+        public int Count {
+            get { return m_count; }
+        }
+
+        public IEnumerator<int> GetEnumerator() {
+            for (int i = 0; i < m_count; i++) {
+                yield return m_data[i]; 
+            }
+        }
+
+        internal bool Contains( int val ) {
+            for (int i = 0; i < m_count; i++) {
+                if (m_data[i] == val) return true; 
+            }
+            return false; 
+        }
+
+        internal void Add( int val ) {
+            if (m_count == m_data.Length) {
+                doubleCapacity(); 
+            }
+            m_data[m_count++] = val; 
+        }
+
+        private void doubleCapacity() {
+            // we always give our data array at least 4 elements
+            int[] newArr = ILMemoryPool.Pool.New<int>(m_data.Length * 2); 
+            System.Array.Copy(m_data,newArr,m_count);
+            ILMemoryPool.Pool.Free(m_data); 
+            m_data = newArr; 
+        }
+        /// <summary>
+        /// caution! This may bring the ILIntList in inconsistent state! 
+        /// </summary>
+        /// <returns></returns>
+        internal int[] GetArray() {
+            return m_data; 
+        }
+
+        internal ILRetArray<int> ToTempArray() {
+            ILSize newDims = new ILSize(m_count, 1); 
+            ILRetArray<int> ret = new ILRetArray<int>(new Storage.ILDenseStorage<int>(m_data,newDims));
+            m_data = null; 
+            return ret; 
+        }
+
+        internal void Clear() {
+            ILMemoryPool.Pool.Free(m_data); 
+            m_data = new int[4]; 
+            m_count = 0; 
+        }
+
+        internal void Dispose() {
+            ILMemoryPool.Pool.Free(m_data); 
+            m_count = -1; 
+            m_data = null; 
+        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Data/ILIntList_CACHED.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Data/ILIntList_CACHED.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Data/ILIntList_CACHED.cs	(revision 9102)
@@ -0,0 +1,188 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Collections.Concurrent; 
+using System.Linq;
+using System.Text;
+
+namespace ILNumerics.Data {
+    public sealed class ILIntList {
+
+        private static readonly int INITIAL_CAPACITY = 4; 
+        private static Queue<ILIntList> s_cache = new Queue<ILIntList>();
+        private static object s_lock = new object();
+        public static ILIntList Create() {
+            lock (s_lock) {
+                ILIntList ret;
+                if (s_cache.Count > 0) {
+                    ret = s_cache.Dequeue();
+                    System.Diagnostics.Debug.Assert(ret.m_data.Length >= INITIAL_CAPACITY && ret.Count == 0);
+                    return ret;
+                } else {
+                    return new ILIntList();
+                }
+            }
+        }
+
+        public static ILIntList Create(int initialCapacity) {
+            
+            lock (s_lock) {
+                ILIntList ret;
+                if (s_cache.Count > 0) {
+                    ret = s_cache.Dequeue();
+                    System.Diagnostics.Debug.Assert(ret.m_data.Length >= INITIAL_CAPACITY && ret.Count == 0);
+                    return ret;
+                } else {
+                    return new ILIntList();
+                }
+            }
+        }
+
+        private static void Cache(ILIntList list) {
+            lock (s_lock) {
+                list.Clear();
+                s_cache.Enqueue(list);
+                System.Diagnostics.Debug.Assert(list.m_data.Length >= INITIAL_CAPACITY && list.Count == 0);
+            }
+        }
+
+        int[] m_data; 
+        int m_count;
+        int[] m_initialData; 
+
+        internal ILIntList( ILDenseArray<int> array ) {
+            m_count = array.D.NumberOfElements; 
+            m_data = ILMemoryPool.Pool.New<int>(m_count);
+            m_initialData = new int[INITIAL_CAPACITY]; 
+            System.Array.Copy(array.GetArrayForRead(), m_data, m_count); 
+        }
+
+        private ILIntList() {
+            m_count = 0;
+            m_data = new int[INITIAL_CAPACITY];
+            m_initialData = m_data;
+        }
+        private ILIntList(int initialCapacity) {
+            m_count = 0;
+            m_data = new int[initialCapacity];
+            m_initialData = null; 
+        }
+
+
+        public int this[int index] {
+            get {
+                //if (index >= m_count) 
+                //    throw new IndexOutOfRangeException(); 
+                return m_data[index];
+            }
+            set { m_data[index] = value; }
+        }
+
+        public int Count {
+            get { return m_count; }
+        }
+
+        public IEnumerator<int> GetEnumerator() {
+            for (int i = 0; i < m_count; i++) {
+                yield return m_data[i]; 
+            }
+        }
+
+        internal bool Contains( int val ) {
+            for (int i = 0; i < m_count; i++) {
+                if (m_data[i] == val) return true; 
+            }
+            return false; 
+        }
+
+        internal void Add( int val ) {
+            if (m_count == m_data.Length) {
+                doubleCapacity(); 
+            }
+            m_data[m_count++] = val; 
+        }
+
+        private void doubleCapacity() {
+            // we always give our data array at least INITIAL_CAPACITY elements
+            int[] newArr = ILMemoryPool.Pool.New<int>(m_data.Length * 2); 
+            System.Array.Copy(m_data,newArr,m_count);
+            if (m_data != m_initialData)
+                ILMemoryPool.Pool.RegisterObject(m_data);
+            m_data = newArr; 
+        }
+        /// <summary>
+        /// caution! This may bring the current instance of ILIntList in an UNUSABLE and inconsistent state! 
+        /// </summary>
+        /// <returns>internal int[] data array</returns>
+        internal int[] GetArray() {
+            return m_data; 
+        }
+        /// <summary>
+        /// transfers internal data to new array and disposes this list 
+        /// </summary>
+        /// <returns></returns>
+        internal ILRetArray<int> ToTempArray() {
+            ILSize newDims = new ILSize(1, m_count); 
+            ILRetArray<int> ret = new ILRetArray<int>(new Storage.ILDenseStorage<int>(m_data,newDims));
+            if (m_data == m_initialData) {
+                m_data = new int[INITIAL_CAPACITY];
+                m_initialData = m_data;
+            } else {
+                m_data = m_initialData;
+            }
+            Cache(this); 
+            return ret; 
+        }
+
+        internal void Clear() {
+            if (m_data.Length > INITIAL_CAPACITY) {
+                ILMemoryPool.Pool.RegisterObject(m_data);
+                m_data = m_initialData;
+            } 
+            m_count = 0; 
+        }
+
+        internal void Dispose() {
+            Cache(this); 
+        }
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Data/ILProrityQueue.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Data/ILProrityQueue.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Data/ILProrityQueue.cs	(revision 9102)
@@ -0,0 +1,119 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+#region LGPL License
+/*    
+    This file is part of ILNumerics.Net Core Module.
+
+    ILNumerics.Net Core Module is free software: you can redistribute it 
+    and/or modify it under the terms of the GNU Lesser General Public 
+    License as published by the Free Software Foundation, either version 3
+    of the License, or (at your option) any later version.
+
+    ILNumerics.Net Core Module is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with ILNumerics.Net Core Module.  
+    If not, see <http://www.gnu.org/licenses/>.
+*/
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace ILNumerics.Data {
+    /// <summary>
+    /// experimental performant priority queue implementation (WORK IN PROGRESS!)
+    /// </summary>
+    /// <typeparam name="T">inner type for elements (arbitrary)</typeparam>
+    public class ILProrityQueue<T> : ILBinTree<T> where T:IComparable {
+        /// <summary>
+        /// add an element to the queue
+        /// </summary>
+        /// <param name="element"></param>
+        public void Add(T element) {
+            ILBinTreeNode<T> cur = null; // m_root; 
+            while (cur != null) {
+                
+            }
+            m_count++; 
+        }
+
+        private void createHeap() {
+            
+        }
+        private void heapify(ILBinTreeNode<T> top) {
+            System.Diagnostics.Debug.Assert(top != null && top.Data != null); 
+            int res; 
+            ILBinTreeNode<T> child; 
+            if (top.LeftSon != null) {
+                System.Diagnostics.Debug.Assert(top.LeftSon.Data != null);
+                T ls = top.LeftSon.Data; 
+                if (top.RightSon != null) {
+                    System.Diagnostics.Debug.Assert(top.RightSon.Data != null);
+                    T rs = top.RightSon.Data; 
+                    if (ls.CompareTo(rs) > 0) 
+                        child = top.LeftSon; 
+                    else 
+                        child = top.RightSon;
+                } else {
+                    child = top.LeftSon; 
+                }
+            } else {
+                if (top.RightSon != null) {
+                    System.Diagnostics.Debug.Assert(top.RightSon.Data != null);
+                    child = top.RightSon; 
+                } else {
+                    return; 
+                }
+            }
+            // may exchange this data with largest node's value 
+            if (child.m_data.CompareTo(top.m_data) > 0) {
+                T tmp = child.m_data; 
+                child.m_data = top.m_data; 
+                top.m_data = tmp; 
+                heapify(child); 
+            }   
+        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Collections/ILAxisCollection.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Collections/ILAxisCollection.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Collections/ILAxisCollection.cs	(revision 9102)
@@ -0,0 +1,254 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Exceptions; 
+using System.Drawing; 
+using ILNumerics.Drawing.Interfaces; 
+using System.Reflection;  
+
+
+namespace ILNumerics.Drawing.Collections {
+        
+    /// <summary>
+    /// Collection of all 3 axes contained in each subfigure
+    /// </summary>
+    public class ILAxisCollection {
+
+        #region event + trigger
+        public event AxisChangedEventHandler Changed; 
+        internal void OnChanged(ILAxis sender, AxisNames axis) {
+            if (Changed != null) 
+                Changed(sender ,new ILAxisChangedEventArgs(axis));
+        }
+        #endregion
+
+        #region  attributes / properties
+        private int m_optimizeCounter; 
+        private ILAxis[] m_axes; 
+        private Size m_maximumSize; 
+        /// <summary>
+        /// Get / set ILAxis by index
+        /// </summary>
+        /// <param name="index">index of axis: XAxis = 0, YAxis = 1, ZAxis = 2</param>
+        /// <returns>ILAxis specified by index</returns>
+        /// <value>new ILAxis to be stored into the collection</value>
+        public ILAxis this[int index] {
+            get {
+                if (index < 0 || index > 2) 
+                    throw new ILArgumentException("ILAxisCollection: axis index out of bounds!");
+                return m_axes[index]; 
+            } 
+            set {
+                if (index < 0 || index > 2) 
+                    throw new ILArgumentException("ILAxisCollection: axis index out of bounds!");
+                m_axes [index] = value; 
+                Invalidate(); 
+            }
+        }
+        /// <summary>
+        /// Get / set ILAxis by name enum
+        /// </summary>
+        /// <param name="name">one of the enum values: XAxis, YAxis, ZAxis</param>
+        /// <returns>ILAxis specified by name</returns>
+        /// <value>new ILAxis to be stored into the collection</value>
+        public ILAxis this[AxisNames name] {
+            get {
+                switch (name) {
+                    case AxisNames.XAxis:
+                        return m_axes[0];
+                    case AxisNames.YAxis:
+                        return m_axes[1];
+                    default:
+                        return m_axes[2];
+                }
+            } 
+            set {
+                m_axes [(int)name] = value; 
+                Invalidate(); 
+            }
+        }
+        /// <summary>
+        /// Get access to the X-axis
+        /// </summary>
+        public ILAxis XAxis {
+            get {
+                return m_axes[0]; 
+            }
+        }
+        /// <summary>
+        /// Get access to the Y-axis
+        /// </summary>
+        public ILAxis YAxis {
+            get {
+                return m_axes[1]; 
+            }
+        }
+        /// <summary>
+        /// Get access to the Z-axis
+        /// </summary>
+        public ILAxis ZAxis {
+            get {
+                return m_axes[2]; 
+            }
+        }
+        /// <summary>
+        /// Maximum size of all axes contained in the collection
+        /// </summary>
+        public Size MaxTicLabelSize {
+            get {
+                System.Diagnostics.Debug.Assert(m_maximumSize.Width >= 0); 
+                return m_maximumSize; 
+            }
+        }
+        /// <summary>
+        /// Set visibility for all axes simultaneously
+        /// </summary>
+        public bool Visible {
+            set {
+                m_axes[0].Visible = value; 
+                m_axes[1].Visible = value; 
+                m_axes[2].Visible = value; 
+            }
+        }
+        /// <summary>
+        /// set visibility of axis lines simultaneously
+        /// </summary>
+        public bool LinesVisible {
+            set {
+                m_axes[0].NearLines.Visible = value;
+                m_axes[1].NearLines.Visible = value;
+                m_axes[2].NearLines.Visible = value;
+                m_axes[0].FarLines.Visible = value;
+                m_axes[1].FarLines.Visible = value;
+                m_axes[2].FarLines.Visible = value;
+            }
+        }
+        /// <summary>
+        /// set visibility of all axis grid lines simultaneously
+        /// </summary>
+        public bool GridVisible {
+            set {
+                m_axes[0].Grid.Visible = value;
+                m_axes[1].Grid.Visible = value;
+                m_axes[2].Grid.Visible = value;
+             }
+        }
+
+        #endregion
+
+        #region contructor
+        /// <summary>
+        /// create new ILAxisCollection
+        /// </summary>
+        internal ILAxisCollection(ILClippingData clippingView, IILCreationFactory factory) {
+            m_axes = new ILAxis[3];
+            m_axes[0] = factory.CreateAxis(AxisNames.XAxis,clippingView); 
+            m_axes[1] = factory.CreateAxis(AxisNames.YAxis,clippingView); 
+            m_axes[2] = factory.CreateAxis(AxisNames.ZAxis,clippingView); 
+            EventHandler handler = new EventHandler(Axis_Changed); 
+            m_axes[0].Changed += handler;
+            m_axes[1].Changed += handler;
+            m_axes[2].Changed += handler;
+        }
+        #endregion
+
+        #region public methods  
+        public void Initialize()  {
+
+        }
+        public void Invalidate() {
+            //m_maximumSize = Size.Empty; 
+            m_axes[0].Invalidate(); 
+            m_axes[1].Invalidate(); 
+            m_axes[2].Invalidate();
+        }
+
+        public void Dispose() {
+            if (m_axes.Length > 0 && m_axes[0] != null)
+                m_axes[0].Dispose(); 
+            if (m_axes.Length > 1 && m_axes[1] != null)
+                m_axes[1].Dispose(); 
+            if (m_axes.Length > 2 && m_axes[2] != null)
+                m_axes[2].Dispose();
+        }
+        #endregion
+
+        #region helper functions
+        protected void Axis_Changed(object sender, EventArgs e) {
+            Invalidate();
+            if (sender is ILAxis && sender != null) {
+                ILAxis ax = (ILAxis)sender; 
+                OnChanged(ax,(AxisNames)ax.Index); 
+            }
+        }
+        internal Size MeasureMaxTickLabelSize(Graphics gr) {
+            Size max = new Size(); 
+            for (int i = 0; i < m_axes.Length; i++) {
+                if (m_axes[i].Visible) {
+                    int pad = 2 * m_axes[i].LabeledTicks.Padding; 
+                    int x = m_axes[i].LabeledTicks.Size.Width + pad;
+                    int y = m_axes[i].LabeledTicks.Size.Height + pad; 
+                    if (y > max.Height) {
+                        max.Height = y; 
+                    }
+                    if (x > max.Width) {
+                        max.Width = x; 
+                    }
+                }
+            }
+            //if (max.Width > m_maximumSize.Width || max.Height > m_maximumSize.Height) {
+            //    m_maximumSize = max; 
+            //    m_optimizeCounter = 0; 
+            //    return max; 
+            //} else if (max.Width < m_maximumSize.Width 
+            //    || max.Height < m_maximumSize.Height) {
+            //    if (++m_optimizeCounter > 10) {
+            //        m_maximumSize = max; 
+            //        m_optimizeCounter = 0; 
+            //        return max; 
+            //    } 
+            //}
+            return max;
+        }
+        #endregion
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Collections/ILGraphCollection.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Collections/ILGraphCollection.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Collections/ILGraphCollection.cs	(revision 9102)
@@ -0,0 +1,507 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+#pragma warning disable 1591
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Exceptions;
+using ILNumerics.Drawing.Misc;
+using ILNumerics.Drawing.Interfaces; 
+using ILNumerics.Drawing.Graphs;
+using ILNumerics.Drawing.Plots;
+
+namespace ILNumerics.Drawing.Collections {
+    /// <summary>
+    /// Collection of graph objects - all graphs currently contained in a subfigure
+    /// </summary>
+    public sealed class ILGraphCollection : List<ILGraph>, IDisposable {
+
+        public event ILGraphCollectionChangedEvent CollectionChanged;
+        public event ILGraphChangedEvent GraphChanged; 
+        /// <summary>
+        /// triggers the ILGraphCollectionChanged event
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="reason"></param>
+        void OnChange (ILGraph graph, GraphCollectionChangeReason reason, IILPanelConfigurator configurator) {
+            if (CollectionChanged != null)
+                CollectionChanged(this, new ILGraphCollectionChangedEventArgs((ILGraph)graph, reason, configurator));
+        }
+        /// <summary>
+        /// triggers GraphChanged event, bubbles from single graph
+        /// </summary>
+        /// <param name="graphArgs">event arguments from graph</param>
+        void OnGraphChanged(ILGraph sender, ILGraphChangedEventArgs graphArgs) {
+            if (GraphChanged != null) {
+                GraphChanged(sender,graphArgs); 
+            }
+        }
+
+        #region members / properties
+        private IILCreationFactory m_graphFact; 
+        private ILClippingData m_clippingData;
+        private List<ILGraph> m_unsortedCache;
+        private ILGraphComparer m_graphComparer;
+        /// <summary>
+        /// Clippping volume for data in all graphs of the collection
+        /// </summary>
+        /// <remarks>This gives back the real ILClippingData object (no copy)</remarks>
+        public ILClippingData Limits {
+            get {
+                return m_clippingData;
+            }
+        }
+        #endregion 
+
+        #region constructor / disposal
+        /// <summary>
+        /// Create new ILGraphCollection
+        /// </summary>
+        /// <param name="panel">Output panel </param>
+        /// <param name="clippingData"></param>
+        internal ILGraphCollection(IILCreationFactory vPainterFact) : base() {
+            m_graphFact = vPainterFact; 
+            m_clippingData = new ILClippingData();
+            m_unsortedCache = new List<ILGraph>();
+            m_graphComparer = new ILGraphComparer(); 
+        }
+        /// <summary>
+        /// dispose all graphs contained in this collection
+        /// </summary>
+        public void Dispose() {
+            foreach (ILGraph graph in this) {
+                if (graph != null) 
+                    graph.Dispose(); 
+            }
+        }
+        #endregion
+
+        #region event handling
+        ///// <summary>
+        ///// signaled when one/some of the ILGraphs have changed
+        ///// </summary>
+        ///// <param name="sender"></param>
+        ///// <param name="e"></param>
+        //void Graph_Changed(object sender, ILGraphChangedEventArgs e) {
+        //    OnGraphChanged(sender as ILGraph,e); 
+        //}
+        /// <summary>
+        /// called once the limits of a graph have changed
+        /// </summary>
+        /// <param name="sender">graph</param>
+        /// <param name="e">event args, holding a reference to the clipping data</param>
+        void Limits_Changed(object sender, ClippingChangedEventArgs e) {
+            ILPoint3Df max = ILPoint3Df.MinValue; 
+            ILPoint3Df min = ILPoint3Df.MaxValue; 
+            foreach (ILGraph graph in this) {
+                max = ILPoint3Df.Max(max,graph.Limits.Max); 
+                min = ILPoint3Df.Min(min,graph.Limits.Min); 
+            }
+            m_clippingData.Set(min,max); 
+        }
+        #endregion
+
+        #region Collection manager
+        /// <summary>
+        /// clear all graphs from the collection
+        /// </summary>
+        public new void Clear() {
+            lock (this) {
+                foreach (ILGraph g in this) {
+                    g.Dispose(); 
+                }
+                base.Clear(); 
+            }
+            m_clippingData.Reset();  
+            Invalidate(); 
+            OnChange(null,GraphCollectionChangeReason.Deleted,null); 
+        }
+        /// <summary>
+        /// Add a new surface graph, provide all coordinate data
+        /// </summary>
+        /// <param name="Z">matrix holding Z coordinates (heights)</param>
+        /// <returns>reference to newly created surface graph</returns>
+        public ILSurfaceGraph AddSurfGraph(ILInArray<float> X, ILInArray<float> Y, ILInArray<float> Z, ILInArray<float> C) {
+            using (ILScope.Enter(X, Y, Z, C)) {
+                ILSurfaceGraph ret;
+                ret = (ILSurfaceGraph)m_graphFact.CreateGraph(Z, GraphType.Surf, X, Y, C);
+                m_clippingData.Update(ret.Limits);
+                Add(ret);
+                ret.Changed += new ILGraphChangedEvent(GraphChanged);
+                // trigger change event
+                OnChange(ret, GraphCollectionChangeReason.Added, null);
+                return ret;
+            }
+        }
+        /// <summary>
+        /// Add a new surface graph to collection
+        /// </summary>
+        /// <param name="data">matrix holding data to be plotted</param>
+        /// <returns>reference to newly created surface graph</returns>
+        public ILSurfaceGraph AddSurfGraph(ILInArray<float> data) {
+            using (ILScope.Enter(data)) {
+                return (ILSurfaceGraph)Add(data, GraphType.Surf)[0];
+            }
+        }
+        /// <summary>
+        /// add a plot to a new scene graph
+        /// </summary> 
+        /// <param name="plot">plot to be added to the panel</param>
+        /// <returns>newly created scene graph</returns>
+        public ILSceneGraph AddPlot(ILPlot plot) {
+            ILSceneGraph scene = AddSceneGraph();
+            scene.AddNode(plot);
+            return scene; 
+        }
+        /// <summary>
+        /// Add a new scene graph to collection
+        /// </summary>
+        /// <returns>reference to newly created surface graph</returns>
+        public ILSceneGraph AddSceneGraph() {
+            ILSceneGraph newGraph = m_graphFact.CreateSceneGraph();  
+            Add(newGraph); 
+            newGraph.Changed += new ILGraphChangedEvent(GraphChanged);
+            newGraph.Limits.Changed += new ILClippingDataChangedEvent(Limits_Changed);
+            newGraph.NodeAdded += new SceneGraphNodeHandler(sceneGraph_NodeAdded);
+            OnChange(newGraph, GraphCollectionChangeReason.Added, null);
+            return newGraph;
+        }
+
+        void sceneGraph_NodeAdded(object sender, ILSceneGraphNodeEventArgs args) {
+            if (args.Node != null && args.Node is IILPanelConfigurator) {
+                OnChange(sender as ILGraph, GraphCollectionChangeReason.Added, args.Node as IILPanelConfigurator); 
+            }
+        }
+        /// <summary>
+        /// add an newly created scene graph instance to the collection of graphs 
+        /// </summary>
+        /// <param name="sceneGraph">exisisting instance of scene graph</param>
+        /// <remarks><para>This overload may be used to add user defined graphs to 
+        /// the collection of graphs in order to use them in ILPanels. The user 
+        /// defined graph needs to derive from scene graph. It may uses all shapes 
+        /// compatible with ILSceneGraph. (ILLine,ILPolygon,ILLitBox,ILQuads,ILTriangles, etc...)
+        /// </para></remarks>
+        public void AddSceneGraph(ILSceneGraph sceneGraph) { 
+            if (sceneGraph == null) throw new ILArgumentException("scene graph must not be null!"); 
+            Add(sceneGraph); 
+            sceneGraph.Changed += new ILGraphChangedEvent(GraphChanged);
+            sceneGraph.Limits.Changed += new ILClippingDataChangedEvent(Limits_Changed);
+            OnChange(sceneGraph, GraphCollectionChangeReason.Added, null);
+        }
+
+        /// <summary>
+        /// Add a new imagesc graph to collection
+        /// </summary>
+        /// <param name="data">matrix holding data to be drawn</param>
+        /// <returns>newly created graph</returns>
+        public ILImageSCGraph AddImageSCGraph(ILInArray<float> data) {
+            using (ILScope.Enter(data))
+            return (ILImageSCGraph)Add(data,GraphType.Imagesc)[0]; 
+        }
+
+        /// <summary>
+        /// Add line graph(s)
+        /// </summary>
+        /// <param name="data">vector or matrix with date to be plotted. For matrices, the columns will be used to create new graphs.</param>
+        /// <returns>Array of newly created graph(s)</returns>
+        public ILPlot2DGraph[] AddLineGraph(ILInArray<double> A) {
+            using (ILScope.Enter(A)) {
+                return AddLineGraph(ILMath.tosingle(A));
+            }
+        }
+        /// <summary>
+        /// Add line graph(s)
+        /// </summary>
+        /// <param name="data">vector or matrix with date to be plotted. For matrices, the columns will be used to create new graphs.</param>
+        /// <returns>Array of newly created graph(s)</returns>
+        public ILPlot2DGraph[] AddLineGraph(ILInArray<float> A) {
+            using (ILScope.Enter(A)) {
+                List<ILGraph> graphs = Add(A, GraphType.Plot2D);
+                List<ILPlot2DGraph> ret = new List<ILPlot2DGraph>();
+                ILColorEnumerator cenumerator = new ILColorEnumerator(Colormaps.Lines);
+                foreach (ILGraph g in graphs) {
+                    ILPlot2DGraph plot2DGraph = (ILPlot2DGraph)g;
+                    ret.Add(plot2DGraph);
+                    plot2DGraph.Line.Color = cenumerator.NextColor();
+                }
+                return ret.ToArray();
+            }
+
+        }
+        /// <summary>
+        /// Add X/Y line graph(s)
+        /// </summary>
+        /// <param name="X">X coordinates. If this is a matrix, every column provides data for an individual graph.</param>
+        /// <param name="Y">Y coordinates. Same size as 'X'.</param>
+        /// <returns>newly created graph(s)</returns>
+        public ILPlot2DGraph[] AddLineGraph(ILInArray<double> XData, ILInArray<double> YData) {
+            using (ILScope.Enter(XData,YData)) {
+                return AddLineGraph(ILMath.tosingle(XData), ILMath.tosingle(YData));
+            }
+        }
+        /// <summary>
+        /// Add X/Y line graph(s)
+        /// </summary>
+        /// <param name="X">X coordinates. If this is a matrix, every column provides data for an individual graph.</param>
+        /// <param name="Y">Y coordinates. Same size as 'X'.</param>
+        /// <returns>newly created graph(s)</returns>
+        public ILPlot2DGraph[] AddLineGraph(ILInArray<float> XData, ILInArray<float> YData) {
+            using (ILScope.Enter(XData, YData)) {
+                List<ILGraph> graphs = Add(XData, YData, GraphType.Plot2D);
+                List<ILPlot2DGraph> ret = new List<ILPlot2DGraph>();
+                ILColorEnumerator cenumerator = new ILColorEnumerator(Colormaps.Lines);
+                foreach (ILGraph g in graphs) {
+                    ILPlot2DGraph plot2DGraph = (ILPlot2DGraph)g;
+                    ret.Add(plot2DGraph);
+                    plot2DGraph.Line.Color = cenumerator.NextColor();
+                }
+                return ret.ToArray();
+            }
+        }
+        /// <summary>
+        /// [Depricated] Add new line graph(s) (2D) to collection
+        /// </summary>
+        /// <param name="data">vector/array with date to be plotted. For arrays, the columns will be used.</param>
+        /// <returns>Array of newly created graph(s)</returns>
+        public ILPlot2DGraph[] AddPlot2DGraph(ILInArray<float> data) {
+            return AddLineGraph(data); 
+        }
+        /// <summary>
+        /// [Depricated] Add new X/Y 2D line graph(s), provide X and Y coordinates
+        /// </summary>
+        /// <param name="X">X coordinates. If this is a matrix, every column will produce an individual graph.</param>
+        /// <param name="Y">Y coordinates. Same size than 'X'.</param>
+        /// <returns>Array of newly created graph(s)</returns>
+        public ILPlot2DGraph[] AddPlot2DGraph(ILInArray<float> XData, ILInArray<float> YData) {
+            return AddLineGraph(XData, YData); 
+        }
+        /// <summary>
+        /// Add new numeric graph(s) of arbitrary (math) type
+        /// </summary>
+        /// <param name="data">data to be plotted</param>
+        /// <param name="properties">determine GraphType</param>
+        /// <returns>List with newly created graph(s)</returns>
+        public List<ILGraph> Add(ILInArray<float> data, GraphType graphType) {
+            using (ILScope.Enter(data)) {
+                if (!data.IsNumeric)
+                    throw new ILArgumentException("Add graph: data array must be numeric!");
+                List<ILGraph> ret = new List<ILGraph>();
+                ILGraph newGraph;
+                ILArray<float> tmpData;
+                lock (this) {
+                    #region add each graph type seperately
+                    switch (graphType) {
+                        case GraphType.Plot2D:
+                            if (data.IsVector || data.IsScalar) {
+                                newGraph = m_graphFact.CreateGraph(data, graphType);
+                                Add(newGraph);
+                                newGraph.Changed += new ILGraphChangedEvent(GraphChanged);
+                                m_clippingData.Update(newGraph.Limits);
+                                newGraph.Limits.Changed += new ILClippingDataChangedEvent(Limits_Changed);
+                                ret.Add(newGraph);
+                            } else if (data.IsMatrix) {
+                                // plot columns
+                                m_clippingData.EventingSuspend();
+                                tmpData = ILMath.tosingle(data);
+                                for (int c = 0; c < tmpData.Size[1]; c++) {
+                                    newGraph = m_graphFact.CreateGraph(tmpData[":", c], graphType);
+                                    Add(newGraph);
+                                    newGraph.Changed += new ILGraphChangedEvent(GraphChanged);
+                                    ret.Add(newGraph);
+                                    m_clippingData.Update(newGraph.Limits);
+                                    newGraph.Limits.Changed += new ILClippingDataChangedEvent(Limits_Changed);
+                                }
+                                m_clippingData.EventingResume();
+                            }
+                            // trigger change event
+                            OnChange(ret[0], GraphCollectionChangeReason.Added, ret[0] as IILPanelConfigurator);
+                            break;
+                        case GraphType.Surf:
+                            if (!data.IsMatrix)
+                                throw new ILArgumentException("Surf: source data must be a matrix!");
+                            tmpData = ILMath.tosingle(data);
+                            m_clippingData.EventingSuspend();
+                            // margin for Z-Direction
+                            float min, max;
+                            tmpData.GetLimits(out min, out max);
+                            float zmarg = (max - min > 0) ? (float)(Math.Abs(max - min) / 10.0) : 0.0f;
+                            m_clippingData.Update(new ILPoint3Df(0, 0, min - zmarg), new ILPoint3Df(data.Size[1] - 1, data.Size[0] - 1, max + zmarg));
+                            m_clippingData.EventingResume();
+                            newGraph = m_graphFact.CreateGraph(tmpData, graphType);
+                            Add(newGraph);
+                            newGraph.Changed += new ILGraphChangedEvent(GraphChanged);
+                            // trigger change event
+                            ret.Add(newGraph);
+                            OnChange(newGraph, GraphCollectionChangeReason.Added, newGraph as IILPanelConfigurator);
+                            break;
+                        case GraphType.Imagesc:
+                            if (!data.IsMatrix)
+                                throw new ILArgumentException("Surf: source data must be a matrix!");
+                            tmpData = ILMath.tosingle(data);
+                            // note, ImageSC does not contribute to global clipping, except that the clipping 
+                            // will be updated to include z = 0! 
+                            m_clippingData.EventingSuspend();
+                            m_clippingData.Update(new ILPoint3Df(-0.5f, -.5f, 0), new ILPoint3Df(data.Size[1] - 0.5f, data.Size[0] - 0.5f, 0));
+                            m_clippingData.EventingResume();
+                            newGraph = m_graphFact.CreateGraph(tmpData, graphType);
+                            Add(newGraph);
+                            newGraph.Changed += new ILGraphChangedEvent(GraphChanged);
+                            // trigger change event
+                            OnChange(newGraph, GraphCollectionChangeReason.Added, newGraph as IILPanelConfigurator);
+                            ret.Add(newGraph);
+                            break;
+                        default:
+                            throw new ILDrawingException("the type of drawing is not supported!");
+                    }
+                    #endregion
+                }
+                return ret;
+            }
+        }
+        /// <summary>
+        /// Add new graph(s) of arbitrary type, provide both axis data
+        /// </summary>
+        /// <param name="xData">x coordinates </param>
+        /// <param name="graphType">type of graph to be added</param>
+        /// <param name="yData">y coordinates</param>
+        /// <returns>List with newly created graph(s)</returns>
+        /// <remarks>The return value will be a list of all graphs created (and added),
+        /// since more than one graph may have been specified. This depends on the 
+        /// shape of the data provided.
+        /// <para>Currently only Plot2D graphs are supported as GraphType! </para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if the data provided are nor 
+        /// numeric or the size for one of the arrays <typeparamref name="xData"/> or <typeparamref name="yData"/> 
+        /// do not match. </exception>
+        public List<ILGraph> Add(ILInArray<float> xData, ILInArray<float> yData, GraphType graphType) {
+            using (ILScope.Enter(xData, yData)) {
+                if (!yData.IsNumeric || !xData.IsNumeric)
+                    throw new ILArgumentException("Add graph: data arrays must be numeric!");
+                List<ILGraph> ret = new List<ILGraph>();
+                ILGraph newGraph;
+                ILArray<float> tmpDataY, tmpDataX;
+                lock (this) {
+                    #region add each graph type seperately
+                    switch (graphType) {
+                        case GraphType.Plot2D:
+                            if (!yData.Size.IsSameSize(xData.Size))
+                                throw new ILArgumentException("Add graph: for X/Y plots, the size of X and Y must be equal!");
+                            if (yData.IsVector || yData.IsScalar) {
+                                newGraph = m_graphFact.CreateGraph(yData, graphType, xData);
+                                Add(newGraph);
+                                newGraph.Changed += new ILGraphChangedEvent(GraphChanged);
+                                m_clippingData.Update(newGraph.Limits);
+                                ret.Add(newGraph);
+                            } else if (yData.IsMatrix) {
+                                // plot columns
+                                m_clippingData.EventingSuspend();
+                                tmpDataY = ILMath.tosingle(yData);
+                                tmpDataX = ILMath.tosingle(xData);
+                                for (int c = 0; c < tmpDataY.Size[1]; c++) {
+                                    newGraph = m_graphFact.CreateGraph(tmpDataY[":", c], graphType, tmpDataX[":", c]);
+                                    Add(newGraph);
+                                    newGraph.Changed += new ILGraphChangedEvent(GraphChanged);
+                                    ret.Add(newGraph);
+                                    m_clippingData.Update(newGraph.Limits);
+                                }
+                                m_clippingData.EventingResume();
+                            }
+                            // trigger change event
+                            OnChange(ret[0], GraphCollectionChangeReason.Added, ret[0] as IILPanelConfigurator);
+                            break;
+                        default:
+                            throw new ILDrawingException("graph type is not supported in that mode yet!");
+                    }
+                    #endregion
+                }
+                return ret;
+            }
+        }
+        /// <summary>
+        /// Remove a graph from the collection and rescale data limits
+        /// </summary>
+        /// <param name="key">key of graph to be removed</param>
+        /// <returns>the ILGraph removed or null, if the key does not exist</returns>
+        /// <remarks>If the graph has been removed, the clipping data will be updated and a change event will be fired. </remarks>
+        public new bool Remove(ILGraph graph) {
+            lock (this) {
+                if (!Contains(graph)) return false; 
+                base.Remove(graph); 
+                // recreate clipping regions 
+                m_clippingData.EventingSuspend(); 
+                m_clippingData.Reset();  
+                foreach (ILGraph gr in this) {
+                    m_clippingData.Update (gr.Limits); 
+                }
+                m_clippingData.EventingResume(); 
+                OnChange(graph,GraphCollectionChangeReason.Deleted,null); 
+                Invalidate();
+                return true;
+            }
+        }
+        
+        #endregion
+
+        #region public interface 
+        public void Invalidate() {
+            foreach (ILGraph g in this) {
+                g.Invalidate(); 
+            }
+        }
+        internal void GetSortedList4Render(ILCamera camera, List<ILGraph> sortList) {
+            m_unsortedCache.Clear();
+            foreach (ILGraph g in this) {
+                if (g.Is3DGraph()) {
+                    sortList.Add(g); 
+                } else {
+                    m_unsortedCache.Add(g);
+                }
+            }
+            m_graphComparer.Camera = camera;
+            sortList.Sort(m_graphComparer);
+            sortList.AddRange(m_unsortedCache);
+        }
+        #endregion
+
+        #region private helper
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Collections/ILLightCollection.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Collections/ILLightCollection.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Collections/ILLightCollection.cs	(revision 9102)
@@ -0,0 +1,125 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Drawing.Lighting;
+using System.Collections; 
+
+namespace ILNumerics.Drawing.Collections {
+    /// <summary>
+    /// collection of 8 lights, individual configurable
+    /// </summary>
+    public class ILLightCollection 
+        : IEnumerable {
+
+        #region eventing
+        public EventHandler Changed; 
+        protected void OnChanged() {
+            if (Changed != null) {
+                Changed(this, new EventArgs()); 
+            }
+        }
+        #endregion
+
+        #region attributes
+        List<ILLight> m_lights; 
+        #endregion
+
+        #region properties
+        /// <summary>
+        /// set: enable/disable all lights; get: return true, if at least one light is enabled, false else 
+        /// </summary>
+        public bool Enabled {
+            get { 
+                foreach (ILLight l in m_lights)
+                    if (l.Enabled) return true; 
+                return false; 
+            }
+            set { 
+                foreach (ILLight l in m_lights) 
+                    l.Enabled = value; 
+            }
+        }
+        #endregion
+
+        #region constructors
+        public ILLightCollection () {
+            m_lights = new List<ILLight>(8);
+            for (int i = 0; i < 8; i++) {
+                ILLight light = new ILLight(i); 
+                m_lights.Add(light); 
+                light.Changed += new EventHandler(lightChanged); 
+            }
+        }
+        #endregion
+
+        #region public interface
+        /// <summary>
+        /// get light at specific index
+        /// </summary>
+        /// <param name="i">index of light, valid: 0...7</param>
+        /// <returns>Light at index i</returns>
+        public ILLight this[int i] {
+            get {
+                return m_lights[i]; 
+            }
+        }
+        #endregion
+
+        #region private helpers
+        protected void lightChanged (object sender, EventArgs args) {
+            OnChanged(); 
+        }
+        #endregion
+
+
+
+        #region IEnumerable Member
+
+        public IEnumerator GetEnumerator() {
+            for (int i = 0; i < m_lights.Count; i++) {
+                yield return m_lights[i]; 
+            }
+        }
+
+        #endregion
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Collections/ILSubfigureCollection.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Collections/ILSubfigureCollection.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Collections/ILSubfigureCollection.cs	(revision 9102)
@@ -0,0 +1,153 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Exceptions; 
+using ILNumerics.Drawing; 
+
+namespace ILNumerics.Drawing.Collections {
+    
+    /// <summary>
+    /// Collection of all subfigures contained in an ILFigureControl
+    /// </summary>
+    [Serializable]
+    public class ILSubfigureCollection {
+
+        #region attributes 
+        private Dictionary<int,ILSubfigure> m_subfigures;
+        #endregion
+
+        #region constructor
+        /// <summary>
+        /// create new ILSubfigureCollection
+        /// </summary>
+        public ILSubfigureCollection() {
+            m_subfigures = new Dictionary<int,ILSubfigure>();
+        }
+        #endregion
+
+        #region indexer
+        /// <summary>
+        /// Get / set subfigure by key
+        /// </summary>
+        /// <param name="key">key of subfigure</param>
+        /// <returns>subfigure specified by key</returns>
+        /// <value>subfigure to be stored into the collection</value>
+        public ILSubfigure this[int key] {
+            get {
+                if (!m_subfigures.ContainsKey(key)) 
+                    throw new ILArgumentException("ILSubfigureCollection: subfigure key not found!");
+                return m_subfigures[key]; 
+            } 
+            set {
+                if (!m_subfigures.ContainsKey(key)) 
+                    m_subfigures.Add(key, value); 
+                else 
+                    m_subfigures[key] = value; 
+            }
+        }
+        #endregion
+
+        #region properties
+        /// <summary>
+        /// number of subfigures currently stored in the collection
+        /// </summary>
+        public int Count {
+            get {
+                return m_subfigures.Count; 
+            }
+        }
+        #endregion
+
+        #region public interface 
+        /// <summary>
+        /// Add subfigure to subfigure collection
+        /// </summary>
+        /// <param name="key">the key to identify the new subfigure</param>
+        /// <param name="subfigure">the new subfigure</param>
+        /// <remarks>If a subfigure with the key already exist in the collection, 
+        /// it will be replaced by the new subfigure</remarks>
+        public void Add(int key, ILSubfigure subfigure) {
+            if (!m_subfigures.ContainsKey(key))
+                m_subfigures.Add(key,subfigure); 
+            else 
+                m_subfigures[key] = subfigure; 
+        }
+        /// <summary>
+        /// get all keys for all subfigures as key collection
+        /// </summary>
+        public Dictionary<int,ILSubfigure>.KeyCollection Keys {
+            get {
+                return m_subfigures.Keys;
+            }
+        }
+        /// <summary>
+        /// Get all subfigures as value collection
+        /// </summary>
+        public Dictionary<int, ILSubfigure>.ValueCollection Figures {
+            get {
+                return m_subfigures.Values; 
+            }
+        }
+        /// <summary>
+        /// Determine if a subfigure with the key given exist
+        /// </summary>
+        /// <param name="key">key of subfigure</param>
+        /// <returns>true if a subfigure with the given key exists, false otherwise</returns>
+        public bool Contains (int key) {
+            return m_subfigures.ContainsKey(key); 
+        }
+        /// <summary>
+        /// Reduce the number of subfigures to the given number
+        /// </summary>
+        /// <param name="number">number of subfigures to remain</param>
+        /// <remarks>If more than number subfigures exist, they will be removed. Highest keys will be removed first.</remarks>
+        public void Purge (int number) {
+            int[] keys = new int[m_subfigures.Count];
+            m_subfigures.Keys.CopyTo(keys,0);  
+            System.Array.Sort(keys); 
+            for (int i = number; i < keys.Length; i++) {
+                m_subfigures.Remove(keys[i]); 
+            }
+        }
+        #endregion
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Collections/ILTickCollection.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Collections/ILTickCollection.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Collections/ILTickCollection.cs	(revision 9102)
@@ -0,0 +1,878 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using ILNumerics.Drawing.Labeling;
+using System.Collections;
+
+namespace ILNumerics.Drawing.Collections {
+    /// <summary>
+    /// List of labeled ticks for an axis
+    /// </summary>
+    public class ILTickCollection : ILLabelingElement, 
+                                    IDisposable, 
+                                    IEnumerable<LabeledTick> {
+
+        #region events 
+        /// <summary>
+        /// Fires, when the collection of ticks has changed 
+        /// </summary>
+        public new event AxisChangedEventHandler Changed;
+        /// <summary>
+        /// fires, if a new labeled tick is about to be added to the collection
+        /// </summary>
+        public event LabeledTickAddingHandler LabeledTickAdding; 
+        #endregion
+
+        #region event handler 
+        /// <summary>
+        /// fires the change event
+        /// </summary>
+        protected void OnChange() {
+            if (Changed != null)
+                Changed(this,new ILAxisChangedEventArgs(m_axisName));
+        }
+        /// <summary>
+        /// fires LabeledTickAdding event
+        /// </summary>
+        /// <param name="value">existing value</param>
+        /// <param name="label">existing label</param>
+        /// <param name="index">index of new tick in collection</param>
+        /// <returns>true: a registrar requested to cancel the adding, false otherwise</returns>
+        protected bool OnLabeledTickAdding(ref float value, ref string label, int index) {
+            if (LabeledTickAdding != null) {
+                ILLabeledTickAddingArgs args = new ILLabeledTickAddingArgs(value,label,index); 
+                LabeledTickAdding(this,args); 
+                label = args.Expression; 
+                value = args.Value; 
+                return args.Cancel; 
+            }
+            return false; 
+        }
+        #endregion
+
+        #region attributes
+        private int m_ticksAllowOverlap = 10; 
+        private List<LabeledTick> m_ticks; 
+        private TickDisplay m_tickDisplay; 
+        private AxisNames m_axisName;
+        private TickDirection m_tickDirection;
+        private byte m_precision; 
+        private int m_padding; 
+        private Color m_tickColorNear; 
+        private Color m_tickColorFar; 
+        private TickMode m_tickMode; 
+        private float m_tickFraction; 
+        //internal properties 
+        internal Point m_lineStart; 
+        internal Point m_lineEnd;
+        private TickLabelRenderingHint m_renderingHint; 
+        private ILPanel m_panel; 
+        #endregion
+
+        #region properties
+        /// <summary>
+        /// determine the max number of pixels allowing a tic labels to be rendered inside the padding area of the next label 
+        /// </summary>
+        public int TicksAllowOverlap {
+            get { return m_ticksAllowOverlap; }
+            set { m_ticksAllowOverlap = value; }
+        }
+
+        /// <summary>
+        /// Get the prefered placement for tick labels or sets it
+        /// </summary>
+        /// <remarks>Tick labels will not stricly rely on this setting, but rather 
+        /// try to find the optimal tick positions depending on the current 
+        /// rendering situation, taking the hint into account.</remarks>
+        public TickLabelRenderingHint RenderingHint {
+            get {
+                return m_renderingHint; 
+            } 
+            set {
+                m_renderingHint = value; 
+                OnChange();
+            }
+        }
+        
+        /// <summary>
+        /// Positioning mode for ticks ([Auto],Manual)
+        /// </summary>
+        public TickMode Mode {
+            get {
+                return m_tickMode; 
+            }
+            set {
+                m_tickMode = value; 
+                OnChange(); 
+            }
+        }
+
+        /// <summary>
+        /// get / set the color for near ticks (label side)
+        /// </summary>
+        public Color NearColor {
+            get {
+                return m_tickColorNear; 
+            }
+            set {
+                m_tickColorNear = value; 
+                OnChange(); 
+            }
+        }
+
+        /// <summary>
+        /// get / set the color for backside ticks
+        /// </summary>
+        public Color FarColor {
+            get {
+                return m_tickColorFar; 
+            }
+            set {
+                m_tickColorFar = value; 
+                OnChange(); 
+            }
+        }
+
+        /// <summary>
+        ///  Get/ set the default color for tick labels 
+        /// </summary>
+        /// <remarks>The color may be overwritten for individual labels</remarks>
+        public Color LabelColor {
+            get {
+                return m_color; 
+            }
+            set {
+                m_color = value; 
+                OnChange(); 
+            }
+        }
+
+        /// <summary>
+        /// padding between ticks
+        /// </summary>
+        public int Padding {
+            get {
+                return m_padding; 
+            }
+            set {
+                m_padding = value; 
+                OnChange();
+            }
+        }
+
+        /// <summary>
+        /// number of digits to be displayed in axis ticks
+        /// </summary>
+        public byte Precision {
+            get {
+                return m_precision; 
+            }
+            set {
+                if (value < 16 && value > 0)
+                    m_precision = value;
+                else 
+                    throw new ILNumerics.Exceptions.ILArgumentException("precision must be in range 1..15!"); 
+                // caching: since tick labels will be redrawn every
+                // render frame, we do not invalidate the label's queues here
+                OnChange(); 
+            }
+        }
+
+        /// <summary>
+        /// Get/ set which sides ticks for axis will be displayed on
+        /// </summary>
+        public TickDisplay Display {
+            get {
+                return m_tickDisplay; 
+            }
+            set {
+                m_tickDisplay = value;
+                OnChange();
+            }
+        }
+
+        /// <summary>
+        /// How ticks are displayed (inside/outside)
+        /// </summary>
+        public TickDirection Direction {
+            get {
+                return m_tickDirection; 
+            }
+            set {
+                m_tickDirection = value; 
+                OnChange();
+            }
+        }
+
+        /// <summary>
+        /// length for ticks, fraction of the overall axis length. Default: 0.02
+        /// </summary>
+        public float TickFraction {
+            get {
+                return m_tickFraction; 
+            }
+            set {
+                m_tickFraction = value; 
+                OnChange(); 
+            }
+        }
+        
+        /// <summary>
+        /// Number of ticks currently stored into the collection
+        /// </summary>
+        public int Count {
+            get {
+                return m_ticks.Count; 
+            }
+        }
+
+        /// <summary>
+        /// The axis this tick collection is assigned to
+        /// </summary>
+        public ILAxis Axis {
+            get {
+                return m_panel.Axes[m_axisName]; }
+        }
+        #endregion
+
+        #region constructor
+        /// <summary>
+        /// creates new ILTickCollection
+        /// </summary>
+        /// <param name="axisName"></param>
+        public ILTickCollection (ILPanel panel, AxisNames axisName) 
+            : base(panel,new Font(FontFamily.GenericMonospace, 10.0f),Color.Black) {
+            m_panel = panel; 
+            m_ticks = new List<LabeledTick>(); 
+            m_axisName = axisName; 
+            m_precision = 4;
+            m_padding = 5; 
+            m_tickColorFar = Color.Black; 
+            m_tickColorNear = Color.Black; 
+            m_tickDisplay = TickDisplay.LabelSide; 
+            m_tickMode = TickMode.Auto; 
+            m_tickFraction = 0.015f; 
+            m_renderingHint = TickLabelRenderingHint.Auto; 
+        }
+        #endregion
+
+        #region public methods
+        /// <summary>
+        /// Clear the collection of labeled ticks
+        /// </summary>
+        public void Clear() {
+            m_ticks.Clear(); 
+            m_size = Size.Empty; 
+        }
+
+        /// <summary>
+        /// replace current collection of labeled ticks with a new one
+        /// </summary>
+        /// <param name="ticks"></param>
+        /// <remarks>This will fire a Change event.</remarks>
+        [Obsolete]
+        public void Replace(List<float> ticks) {
+            Set(ticks); 
+        }
+
+        /// <summary>
+        /// replace current collection of labeled ticks with a new one
+        /// </summary>
+        /// <param name="ticks">label position for every tick</param>
+        /// <param name="labels">label texts for every tick corresponding to <paramref name="ticks"/></param>
+        /// <remarks><para>
+        /// This will set the <paramref name="Mode"/> property to 'TickMode.Manual', hence preventing from 
+        /// automatic label creation on mouse perspective changes.</para>
+        /// <para>Set creates a change event.</para>
+        /// </remarks>
+        public void Set(IEnumerable<float> ticks, IEnumerable labels) {
+            Clear(); 
+            IEnumerator<float> tickCurs = ticks.GetEnumerator();     
+            foreach (var lab in labels) {
+                if (tickCurs.MoveNext()) {
+                    if (lab != null)
+                        Add(tickCurs.Current, lab.ToString());
+                    else 
+                        Add(tickCurs.Current);
+                } else {
+                    throw new Exceptions.ILArgumentException("The number of 'labels' must match the number of tick locations."); 
+                }
+            }
+            this.Mode = TickMode.Manual; 
+            OnChange();
+        }
+        /// <summary>
+        /// replace current collection of labeled ticks with a new one
+        /// </summary>
+        /// <param name="ticks">label position for every tick</param>
+        /// <remarks><para>
+        /// This will set the <paramref name="Mode"/> property to 'TickMode.Manual', hence preventing from 
+        /// automatic label creation on mouse perspective changes.</para>
+        /// <para>The <para>Precision</para> member is used to create tick label texts for all tick positions.</para>
+        /// <para>Set creates a change event.</para>
+        /// </remarks>
+        public void Set(IEnumerable<float> ticks) {
+            Clear();
+            foreach (float tick in ticks) {
+                Add(tick);
+            }
+            OnChange();
+        }
+        /// <summary>
+        /// Add a labeled tick to the ticks collection.
+        /// </summary>
+        /// <param name="value">current position</param>
+        /// <param name="label">current value</param>
+        /// <remarks>This function will fire the LabeledTickAdding event. This 
+        /// gives users the chance to modify the tick and/or the label before 
+        /// it gets added. She can also cancel the adding for the tick at all. <br/>
+        /// No Change event for the axis will be fired from this method.</remarks>
+        public void Add(float value, string label) {
+            if (OnLabeledTickAdding(ref value, ref label, m_ticks.Count)) {
+                return; 
+            }
+            ILRenderQueue queue = m_interpreter.Transform(label,
+                                  m_font,m_color,m_renderer); 
+            m_ticks.Add(new LabeledTick(value,queue)); 
+            if (m_size.Height < queue.Size.Height)
+                m_size.Height = queue.Size.Height; 
+            if (m_size.Width < queue.Size.Width) 
+                m_size.Width = queue.Size.Width; 
+            //m_tickMode = TickMode.Manual; 
+        }
+        /// <summary>
+        /// Add a labeled tick to the ticks collection
+        /// </summary>
+        /// <param name="value">position for tick</param>
+        /// <remarks>No Change event will be fired</remarks>
+        public void Add(float value) {
+            this.Add(value,value.ToString("g"+m_precision)); 
+        }
+        /// <summary>
+        /// Get maximum size of 
+        /// all tick labels in pixels on screen
+        /// </summary>
+        /// <remarks>This property does not take the orientation into account. The size 
+        /// of the content will be returned as if the orientation was straight horizontally.</remarks>
+        public override Size Size {
+            get {
+               // if (m_tickMode == TickMode.Auto && m_ticks.Count == 0) {
+               //     // first time: no labels have been added? -> assume maximum 
+               //     // size determined by precision
+               //     Graphics g = Graphics.FromImage(new Bitmap(1,1));
+               //     string measString = String.Format(".-e08" + new String('0',m_precision)); 
+               //     m_size = g.MeasureString(measString,m_font).ToSize(); 
+               //}
+               return m_size; 
+            }
+        }
+        ///// <summary>
+        ///// (Re-)measures the maximum size for all labels contained in the collection
+        ///// </summary>
+        ///// <param name="gr">graphics object, _may_ be used to measure texts (on some platforms)</param>
+        ///// <returns>maximum size</returns>
+        ///// <remarks>This function recomputes the true size for all labels and updates the internal cache. The cached value can 
+        ///// than queried by the property 'ScreenSize'.
+        ///// <para>Note: if no tick labels have been stored into the collection yet, the 
+        ///// maximum size possible for a label is returned. Therefore, the Precision member is 
+        ///// taken into account.</para></remarks>
+        //public Size MeasureMaxScreenSize(Graphics gr) {
+        //    if (m_ticks.Count == 0) {
+        //        SizeF sf = gr.MeasureString (
+        //            "-e.08" + new String('0', m_precision),m_font);
+        //        m_screenSize = new Size((int)sf.Width,(int)sf.Height); 
+        //    } else {
+        //        m_screenSize = new Size(); 
+        //        Size tmp; 
+        //        foreach (LabeledTick tick in this) {
+        //            tmp = tick.Queue.Size; 
+        //            if (tmp.Height > m_screenSize.Height) 
+        //                m_screenSize.Height = tmp.Height; 
+        //            if (tmp.Width > m_screenSize.Width) 
+        //                m_screenSize.Width = tmp.Width; 
+        //        }
+        //    }
+        //    return m_screenSize;
+        //}
+        /// <summary>
+        /// fill (replace) labels with nice labels for range  
+        /// </summary>
+        /// <param name="min">lower limit</param>
+        /// <param name="max">upper limit</param>
+        /// <param name="tickCount">maximum number of ticks</param>
+        public void CreateAuto(float min, float max, int tickCount) {
+            float dist = max - min;
+            tickCount = 50;
+            string format = String.Format("g{0}",m_precision); 
+            // find the range for values we are dealing with.
+            // how many ticks will (really) fit on the label line? 
+            if (tickCount > 1) {
+                Replace(NiceLabels(min,max,tickCount,m_renderingHint)); 
+                if (Count > 0) 
+                    return; 
+                // else: no ticks could be found at all -> fallback: show only center
+                tickCount = 1; 
+            } 
+            Clear();
+            float relevExp = (float)Math.Round(Math.Log10((max - min)));
+            if (!float.IsNaN(relevExp) && !float.IsInfinity(relevExp)) { 
+                float multRound; 
+                if (relevExp < 1) {
+                    multRound = (float) (1 / Math.Pow(10,relevExp-1)); 
+                } else {
+                    multRound = (float) Math.Pow(10,relevExp-1);
+                }
+                if (tickCount <= 1) {
+                    // If tickCount is 1, only the middle of Axis will be drawn.
+                    float ls = (float)(Math.Ceiling((max + min) / 2 / multRound) * multRound);
+                    if (ls != 0) 
+                        Add(ls,ls.ToString(format));
+                    else 
+                        Add(min,min.ToString(format));
+                } else if (tickCount == 3) {
+                    // draw max, min and the approx. center of range
+                    Add(min,min.ToString(format));
+                    Add(max,max.ToString(format));
+                    float ls = (float)(Math.Round((max + min) / 2 / multRound) * multRound);  
+                    Add(ls,ls.ToString(format)); 
+                } else { //if (tickCount == 2) {
+                    // If tickCount is less than 3 - only the max and the min will be drawn. 
+                    Add(min,min.ToString(format));
+                    Add(max,max.ToString(format));
+                }
+            } else {
+                Add(max,max.ToString(format));
+            }
+        }
+
+        /// <summary>
+        /// Determine nice looking label positions for range specified
+        /// </summary>
+        /// <param name="min">lower limit</param>
+        /// <param name="max">upper limit</param>
+        /// <param name="numMaxLabels">maximum number of labels </param>
+        /// <param name="format">format string used to convert numbers to strings</param>
+        /// <param name="hint">rendering hint, specifies preferred method</param>
+        /// <returns>list of tick labels</returns>
+        public static List<float> NiceLabels(float min, float max, int numMaxLabels, TickLabelRenderingHint hint) {
+            List<float> ret; 
+            switch (hint) {
+                case TickLabelRenderingHint.Filled:
+                    ret = NiceLabelsFill(min,max,numMaxLabels); 
+                    break;
+                case TickLabelRenderingHint.Multiple1:
+                    ret = NiceLabelsEven(min,max,numMaxLabels,1.0f);
+                    break;
+                case TickLabelRenderingHint.Multiple2:
+                    ret = NiceLabelsEven(min,max,numMaxLabels,2.0f);
+                    break;
+                case TickLabelRenderingHint.Multiple5:
+                    ret = NiceLabelsEven(min,max,numMaxLabels,5.0f);
+                    break;
+                default:
+                    //ret = NiceLabelsAuto(min,max,numMaxLabels,format);
+                    ret = loose_label(min,max,numMaxLabels);
+                    break; 
+            }
+            return ret; 
+        }
+
+        public void Draw(ILRenderProperties p, float min, float max) {
+            m_renderer.Begin(p); 
+            float clipRange = max - min; 
+            
+            ILPoint3Df mult = new ILPoint3Df(
+                        ((float)(m_lineEnd.X - m_lineStart.X) / clipRange),
+                        ((float)(m_lineEnd.Y - m_lineStart.Y) / clipRange),
+                        0);
+            float tmp;
+            Point point = new Point(0,0); 
+            Point oldMidPoint = new Point(int.MinValue,int.MinValue); 
+            Point newMidPoint = new Point(int.MinValue,int.MinValue);
+            Point oldHSize = new Point(), newHSize = new Point(); 
+            foreach (LabeledTick lt in m_ticks) {
+                if (lt.Queue.Count > 0
+                    && lt.Position >= min 
+                    && lt.Position <= max) {
+                    tmp = lt.Position-min; 
+                    point.X = (int)(m_lineStart.X + mult.X * tmp);
+                    point.Y = (int)(m_lineStart.Y + mult.Y * tmp);
+                    offsetAlignment(lt.Queue.Size, ref point); 
+                    newHSize.X = (int)(lt.Queue.Size.Width / 2.0f); 
+                    newHSize.Y = (int)(lt.Queue.Size.Height / 2.0f);
+                    newMidPoint.X = point.X + newHSize.X; 
+                    newMidPoint.Y = point.Y + newHSize.Y; 
+                    // check distance to last drawn label for tickmode auto (padding)
+                    if (m_tickMode == TickMode.Auto) {
+                        if (oldMidPoint.X != int.MinValue 
+                            && oldMidPoint.Y != int.MinValue) {
+
+                            float distX = Math.Abs(newMidPoint.X - oldMidPoint.X);
+                            float distY = Math.Abs(newMidPoint.Y - oldMidPoint.Y);
+                            if (distX < (m_padding + oldHSize.X + newHSize.X) - m_ticksAllowOverlap &&
+                                distY < (m_padding + oldHSize.Y + newHSize.Y) - m_ticksAllowOverlap) {
+                                //m_ticks.Remove(lt); 
+                                continue;
+                            }
+                        } 
+                        // bookmark outer rendering limits 
+                        if (newMidPoint.X - newHSize.X < p.MinX)
+                            p.MinX = newMidPoint.X - newHSize.X;
+                        if (newMidPoint.Y - newHSize.Y < p.MinY)
+                            p.MinY = newMidPoint.Y - newHSize.Y;
+                        if (newMidPoint.X + newHSize.X > p.MaxX)
+                            p.MaxX = newMidPoint.X + newHSize.X;
+                        if (newMidPoint.Y + newHSize.Y > p.MaxY)
+                            p.MaxY = newMidPoint.Y + newHSize.Y;
+                    }
+                    m_renderer.Draw(lt.Queue, point, m_orientation, m_color);
+                    oldMidPoint = newMidPoint;
+                    oldHSize = newHSize;
+                }
+            } 
+            m_renderer.End(p); 
+        }
+        #endregion
+
+        #region IDisposable Member
+        public new void Dispose() {
+            if (m_renderer != null) { 
+                // ???
+            }
+        }
+        #endregion
+
+        #region private helper
+
+        /// <summary>
+        /// Create nice labels, prefere even numbers over best optimal tick count
+        /// </summary>
+        /// <param name="min">min</param>
+        /// <param name="max">max</param>
+        /// <param name="numMaxLabels">max labels count</param>
+        /// <param name="format">format string used to convert numbers to strings</param>
+        /// <returns>nice label list</returns>
+        private static List<float> NiceLabelsAuto(float min, float max, int numMaxLabels, string format) {
+            float[] divisors = new float[3] {5.0f, 2.0f, 1.0f}; 
+            List<float>[] ticks = new List<float>[divisors.Length]; 
+            int count = 0, bestMatch = int.MaxValue, tmp = 0, bestMatchIdx = -1; 
+            foreach (float div in divisors) {
+                ticks[count] = NiceLabelsEven(min,max,numMaxLabels,div);  
+                if (ticks[count].Count == numMaxLabels) {
+                    return ticks[count]; 
+                } 
+                tmp = (int)Math.Abs(Math.Min(numMaxLabels,10) - ticks[count].Count); 
+                if (tmp < bestMatch) {
+                    bestMatch = tmp; 
+                    bestMatchIdx = count; 
+                }
+                count ++; 
+            }
+            // its possible for limits to exceed the resolution for float 
+            // no ticks are returned in this case 
+            return ticks[bestMatchIdx]; 
+        }
+        /// <summary>
+        /// find tick labels by distinct divisors (10,5,2). Chooses the divisor which best produces the best number according to numberTicks
+        /// </summary>
+        /// <param name="min">minimum</param>
+        /// <param name="max">maximum</param>
+        /// <param name="numberTicks">maximum number of ticks</param>
+        /// <param name="format">format string for string conversion</param>
+        /// <returns>list of tick labels</returns>
+        private static List<float> NiceLabelsFill(float min, float max, int numberTicks) {
+            // spacing may happen by divisors of 5,2,1. We test every case and choose the 
+            // one producing the best match on the number of ticks requested than. 
+            float[] divisors = new float[3] {5.0f, 2.0f, 1.0f}; 
+            List<float>[] ticks = new List<float>[divisors.Length]; 
+            int count = 0, bestMatch = int.MaxValue, tmp = 0, bestMatchIdx = -1; 
+            foreach (float div in divisors) {
+                ticks[count] = NiceLabelsEven(min,max,numberTicks,div);  
+                tmp = (int)Math.Abs(Math.Min(numberTicks,10) - ticks[count].Count); 
+                if (ticks[count].Count == numberTicks) {
+                    return ticks[count]; 
+                } else if (tmp <= bestMatch) {
+                    bestMatch = tmp; 
+                    bestMatchIdx = count; 
+                }
+                count ++; 
+            }
+            System.Diagnostics.Debug.Assert(bestMatchIdx >= 0,"No best divisor has been found. Tick creation failed.");
+            if (bestMatchIdx >= 0)
+                return ticks[bestMatchIdx]; 
+            else 
+                return ticks[0];  // rescue plan
+        }
+        private static List<float> NiceLabelsEven(float min, float max, int numberTicks, float divisor) {
+            //minimal distance required for ticks
+            float minDist = (max - min) / (numberTicks + 1); 
+            // determine prominent range for optimal spacing
+            if (Math.Abs(minDist) < 1e-10) return new List<float>(); 
+            float relevExp = (float)Math.Log10((max - min));
+            if (float.IsNaN(relevExp)) {
+                return new List<float>();    
+            }
+            float multRound; 
+            if (relevExp >= 1) {
+                return NiceLabelsEvenGE10(min,max,numberTicks,divisor); 
+            }
+            List<float> ticks = new List<float>(); 
+            relevExp = (float)Math.Round(relevExp);
+            multRound = (float) (1 / Math.Pow(10,relevExp-1)); 
+            //float step = divisor / multRound, cur = min, origStep = step;
+            float step = multRound/ divisor, cur = min, origStep = step; 
+            // TODO: check for step beeing too small for resonable min..max distance! 
+            // OR: prevent for infinite loop!
+            while (step < minDist) {
+                step += origStep; 
+            }
+            // find the first auto tick value, matching the divisor
+            cur = (float)(Math.Round((min + minDist) * multRound / divisor) / multRound * divisor); 
+            ticks.Add(cur); 
+            cur += step; 
+            // add all ticks in _between_, keep margin to axis limits!
+            while (cur < max) {
+                cur = (float)(Math.Round(cur * multRound) / multRound); 
+                ticks.Add(cur);
+                cur += step;
+                if (ticks.Count > numberTicks) {
+                    // emergency break - float cannot handle this distance!
+                    ticks.Clear(); 
+                    break; 
+                }
+            }
+            return ticks; 
+        }
+        private static List<float> NiceLabelsEvenGE10(float min, float max, int numberTicks, float divisor) {
+            //minimal distance required for ticks
+            float minDist = (max - min) / (numberTicks + 1); 
+            // determine prominent range for optimal spacing
+            List<float> ticks = new List<float>(); 
+            // has been checked, if comming from NiceLabelsEven: 
+            //if (Math.Abs(minDist) < 1e-10) return ticks; 
+            float relevExp = (float)Math.Log10((max - min));
+            if (float.IsNaN(relevExp)) {
+                return ticks;    
+            }
+            float multRound; 
+            relevExp = (float) (Math.Sign(relevExp) * Math.Floor(Math.Abs(relevExp)));
+            multRound = (float) Math.Pow(10,relevExp-1);
+            //float step = divisor / multRound, cur = min, origStep = step;
+            float step = multRound/ divisor, cur = min, origStep = step; 
+            // TODO: check for step beeing too small for resonable min..max distance! 
+            // OR: prevent for infinite loop!
+            while (step < minDist) {
+                // increase the multRRound by factor 10 
+                relevExp ++; 
+                multRound = (float) (Math.Pow(10,relevExp-1));
+                step = multRound/ divisor; 
+            }
+            // find the first auto tick value, matching the divisor
+            cur = (float)niceNumber(min,false); 
+            ticks.Add(cur); 
+            // add all ticks in _between_, keep margin to axis limits!
+            while (cur < max) {
+                cur = (float)niceNumber(cur + step,false); 
+                ticks.Add(cur);
+                if (ticks.Count > numberTicks) {
+                    // emergency break - float cannot handle this distance!
+                    ticks.Clear(); 
+                    break; 
+                }
+            }
+            return ticks; 
+        }
+
+        /// <summary>
+        /// create "nice" number in fractions of 2 or 5
+        /// </summary>
+        /// <param name="value">value</param>
+        /// <remarks>This code was adopted from Paul Heckbert
+        /// from "Graphics Gems", Academic Press, 1990. </remarks>
+        private static double niceNumber(double val, bool round) {
+            int expv; 
+            double f;                                /* fractional part of x */
+            double nf;                               /* nice, rounded fraction */
+            double aval = Math.Abs(val); 
+            double sign = Math.Sign(val); 
+
+            expv = (int)Math.Floor(Math.Log10(aval));
+            f = aval/Math.Pow(10, expv);                /* between 1 and 10 */
+            if (round) {
+                if (f<1.5) nf = 1;
+                else if (f<3) nf = 2;
+                else if (f<7) nf = 5;
+                else nf = 10;
+            } else {
+                if (f<=1) nf = 1;
+                else if (f<=2) nf = 2;
+                else if (f<=5) nf = 5;
+                else nf = 10;
+            }
+            return (nf * Math.Pow(10, expv) * sign);
+        }
+        private static List<float> loose_label(float min,float max, int numberTicks) {
+            double d;                                /* tick mark spacing */
+            double graphmin;                /* graph range min and max */
+            double range, x;
+
+            /* we expect min!=max */
+            range = niceNumber(max-min, false);
+            d = niceNumber(range/(Math.Min(numberTicks,10)-1), true);
+            double exp = Math.Pow(10,Math.Floor(Math.Log10(max - min)));
+            graphmin = Math.Floor(min / exp) * exp;  
+
+                // Math.Min(niceNumber(min - d,true),niceNumber(min - d,false));
+            //graphmax = Math.Min(niceNumber(max - d, true), niceNumber(max + d, false));
+            List<float> ticks = new List<float>();  
+            //ticks.Add(nfrac);
+            for (x = graphmin; x <= max; x = (float)(Math.Round((x + d) / d) * d)) {
+                //x = (float)(Math.Round(x/d)*d); 
+                ticks.Add((float)x);
+                if (ticks.Count > 20) break; //emergency exit if range is in floating point range
+            }
+            return ticks;
+        }
+
+        #region Oli's labels implementaion (incomplete)
+        private static List<float> niceLabels (float start, float end, int maxNumbers,string format) {
+            float[] labelPositions = berechneLabel(start,end,maxNumbers);
+            List<float> ret = new List<float>(); 
+            foreach (float pos in labelPositions) {
+                ret.Add(pos);     
+            }
+            return ret; 
+        }
+        private static float[] berechneLabel(float start, float end, int maxNumbers)
+        {
+            if (end <= start)
+                return null;
+            float strecke = Math.Abs(end - start);
+            maxNumbers++;//ï¿œberprï¿œfen!
+            int n = 0;
+            while (strecke < maxNumbers)
+            {
+                strecke *= 10;
+                n++;                
+            }
+            while (strecke > 100)
+            {
+                strecke /= 10;
+                n--;
+            }
+            start *= (float)Math.Pow(10, n);
+            int streckeIntValue = getStreckeAsNiceInt(strecke, maxNumbers);
+            /*
+            if (isPrimzahl(streckeIntValue) && streckeIntValue != maxNumbers)
+            {          
+                streckeIntValue++; //Kann zu Problemen fï¿œhren! -- ist aber auch Mist.
+            }
+            */
+
+            float step = 0;
+            int stepCount;
+            for (stepCount = maxNumbers; stepCount > 0; stepCount--)
+            {
+                step = streckeIntValue / stepCount;
+                int rest = streckeIntValue % stepCount;
+                if(rest < step && (step == 1 || step == 2 || step == 5 || step == 10 || step == 25 || step == 50 ))
+                        break;
+            }         
+            int startInt = (int)Math.Round(start, 0);
+            startInt = startInt - (startInt % (int)step);
+            if (n != 0)
+            {
+                step /= (float)(Math.Pow(10, n));
+                start = (float)startInt / (float)Math.Pow(10, n);
+            }
+            else
+                start = startInt;
+            if (!(start + stepCount * step < end))
+                stepCount--;
+            float[] ret = new float[stepCount];
+            for (int i = 1; i <= stepCount; i++)
+            {
+                ret[i - 1] = start + i * step;
+            }
+            return ret;
+        }
+        private static int getStreckeAsNiceInt(float strecke, int maxNumbers)
+        {
+            int streckeIntValue = (int)Math.Round(strecke, 0);
+            if (streckeIntValue <= 10)
+                return streckeIntValue;
+            if (streckeIntValue / 2 <= maxNumbers)
+                return streckeIntValue;
+
+            streckeIntValue = streckeIntValue - streckeIntValue % 5;
+            return streckeIntValue;
+        }
+        #endregion
+
+        #endregion
+
+        #region IEnumerable<LabeledTick> Member
+        /// <summary>
+        /// Get Enumerator, enumerating over all labeled ticks
+        /// </summary>
+        /// <returns>Enumerator</returns>
+        public IEnumerator<LabeledTick> GetEnumerator() {
+            return m_ticks.GetEnumerator(); 
+        }
+
+        #endregion
+
+        #region IEnumerable Member
+
+        /// <summary>
+        /// Get enumerator enumerating over labeled ticks
+        /// </summary>
+        /// <returns>enumerator</returns>
+        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
+            foreach (LabeledTick lt in m_ticks)
+                yield return lt; 
+        }
+
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Controls/DummyNamespaceHolders.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Controls/DummyNamespaceHolders.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Controls/DummyNamespaceHolders.cs	(revision 9102)
@@ -0,0 +1,51 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace ILNumerics.Drawing.Controls {
+    /// <summary>
+    /// this class is for downward compatibility reasons only. It serves no functionality and will silently be removed in the future
+    /// </summary>
+    public class DummyNamespaceClass {
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Controls/ILBorderFitLabel.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Controls/ILBorderFitLabel.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Controls/ILBorderFitLabel.cs	(revision 9102)
@@ -0,0 +1,218 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Windows.Forms; 
+using System.Drawing; 
+
+namespace ILNumerics.Drawing {
+    /// <summary>
+    /// Label with flexible configurable orientation of it's text 
+    /// </summary>
+    public class ILBorderFitLabel : ILMovingDockPanel {
+        private SizeF m_textSize = SizeF.Empty; 
+        private ContextMenu m_menu; 
+        private ILTextBoxAutoHide m_textBox; 
+
+        private void autoSize() {
+            // sets the height or width according to orientation & font
+            if (m_orientation == TextOrientation.Vertical) {
+                Width = Font.Height + Padding.Left + Padding.Right; 
+            } else {
+                Height = Font.Height + Padding.Top + Padding.Bottom; 
+            }
+        }
+
+        private string m_text;
+        public override string Text {
+            get {
+                return m_text;
+            }
+            set {
+                m_text = value;
+                Invalidate();
+            }
+        }
+
+        /// <summary>
+        /// The labels text
+        /// </summary>
+        public string Caption {
+            get { return m_text; }
+            set { 
+                m_text = value; 
+                Invalidate(); 
+            }
+        }
+        private VerticalAlignment m_valign; 
+        /// <summary>
+        /// vertical alignment for the text
+        /// </summary>
+        public VerticalAlignment VerticalAlign {
+            get {
+                return m_valign; 
+            }
+            set {
+                m_valign = value; 
+                Invalidate(); 
+           }
+        }
+        private HorizontalAlignment m_halign = HorizontalAlignment.Center; 
+        /// <summary>
+        /// horizontal alignment for the text
+        /// </summary>
+        public HorizontalAlignment HorizontalAlign {
+            get {
+                return m_halign; 
+            }
+            set {
+                m_halign = value; 
+                Invalidate(); 
+            }
+        }
+
+        protected override void OnPaint(PaintEventArgs e) {
+            base.OnPaint(e);
+            PointF pointF = new PointF();
+            StringFormat sf; 
+            if (m_orientation == TextOrientation.Vertical)
+                sf = new StringFormat(StringFormatFlags.DirectionVertical); 
+            else 
+                sf = new StringFormat(); 
+            m_textSize = e.Graphics.MeasureString(m_text,Font,pointF,sf);
+            #region compute horizontal position
+            switch (m_halign) {
+                case HorizontalAlignment.Center:
+                    pointF.X = (ClientSize.Width - m_textSize.Width - Padding.Horizontal) / 2 - 1; 
+                    break;
+                case HorizontalAlignment.Left:
+                    pointF.X = Padding.Left; 
+                    break;
+                case HorizontalAlignment.Right:
+                    pointF.X = ClientSize.Width - Padding.Right - m_textSize.Width - 1; 
+                    break;
+                default:
+                    break;
+            }
+            if (m_orientation == TextOrientation.Vertical) 
+                pointF.X += Font.Height; 
+            #endregion
+            #region compute vertical position
+            switch (m_valign) {
+                case VerticalAlignment.Middle:
+                    pointF.Y = (ClientSize.Height - m_textSize.Height - Padding.Top - Padding.Bottom) / 2; 
+                    break;
+                case VerticalAlignment.Upper:
+                    pointF.Y = Padding.Top; 
+                    break;
+                case VerticalAlignment.Lower:
+                    pointF.Y = ClientSize.Height - Padding.Bottom - m_textSize.Height; 
+                    break;
+                default:
+                    break;
+            }
+            #endregion
+            SolidBrush solidBrush = new SolidBrush(ForeColor);
+            e.Graphics.DrawString(m_text, this.Font, solidBrush, pointF, sf); 
+        }
+        protected override void OnResize(EventArgs eventargs) {
+            base.OnResize(eventargs);
+            Invalidate(); 
+        }
+        public ILBorderFitLabel() {
+            m_text = "Title"; 
+            m_orientation = TextOrientation.Horizontal;
+            m_halign = HorizontalAlignment.Center; 
+            m_valign = VerticalAlignment.Middle; 
+            Height = Font.Height + Padding.Top + Padding.Bottom; 
+            Width = 150;
+            this.Padding = new Padding(2); 
+            this.ForeColor = Color.White; 
+            m_menu = new ContextMenu(); 
+            MenuItem mi = new MenuItem("Edit",new EventHandler(Edit_Click)); 
+            m_menu.MenuItems.Add(mi);
+            mi.DefaultItem = true; 
+            mi.Shortcut = Shortcut.CtrlE; 
+            mi.ShowShortcut = true; 
+            
+        }
+        protected void Edit_Click(object sender, EventArgs e) {
+            EditShow(); 
+        }
+        protected override void OnMouseClick(MouseEventArgs e) {
+            base.OnMouseClick(e);
+            if (e.Button == MouseButtons.Right)  {
+                m_menu.Show(this,e.Location); 
+            }
+        }
+        private void EditShow() {
+            if (m_textBox == null) {
+                m_textBox = new ILTextBoxAutoHide(); 
+                if (Parent != null) 
+                    Parent.Controls.Add(m_textBox);
+                m_textBox.Committing += new EventHandler(m_textBox_Committing);
+            }
+            m_textBox.Text = m_text; 
+            if (m_orientation == TextOrientation.Horizontal) {
+                m_textBox.Size = Size; 
+                m_textBox.Left = Location.X;
+                m_textBox.Top = Top + (Height - m_textBox.Height) / 2; 
+            } else {
+                if (Parent != null) {
+                    m_textBox.Top = Parent.Padding.Top; 
+                    m_textBox.Left = Parent.Padding.Left; 
+                    m_textBox.Width = Parent.Width - Parent.Padding.Horizontal; 
+                    m_textBox.Height = Parent.Height - Parent.Padding.Vertical; 
+                }
+            }
+            m_textBox.Font = Font; 
+            m_textBox.Show(); 
+            m_textBox.BringToFront(); 
+            m_textBox.Focus();
+            m_textBox.SelectAll(); 
+        }
+
+        void m_textBox_Committing(object sender, EventArgs e) {
+            m_text = m_textBox.Text; 
+            Invalidate();
+        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Controls/ILColorBar.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Controls/ILColorBar.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Controls/ILColorBar.cs	(revision 9102)
@@ -0,0 +1,282 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing.Drawing2D; 
+using System.Drawing; 
+using System.Windows.Forms; 
+using System.Resources; 
+using ILNumerics.Drawing.Labeling; 
+using ILNumerics.Drawing.Misc; 
+
+
+namespace ILNumerics.Drawing {
+
+    public class ILColorBar : ILMovingDockPanel {
+        private float m_minValue; 
+        private float m_maxValue;
+        private int m_precision = 5;
+        private int m_tickLabelsPadding = 2;
+        private ILColormap m_colormap; 
+
+        /// <summary>
+        /// Colormap used to translate colors indices
+        /// </summary>
+        public ILColormap Colormap {
+            get {
+                return m_colormap;
+            }
+            internal set { 
+                m_colormap = value; 
+            }
+        }
+
+        /// <summary>
+        /// padding (in pixels) between the tick labels 
+        /// </summary>
+        public int TickLabelsPadding {
+            get { return m_tickLabelsPadding; }
+            set { m_tickLabelsPadding = value; }
+        } 
+
+        /// <summary>
+        /// Number of digits to be displayed for values 
+        /// </summary>
+        public int Precision {
+            get { return m_precision; }
+            set { m_precision = value; }
+        } 
+
+
+        /// <summary>
+        /// get / set minimum value for the values range
+        /// </summary>
+        public float MinValue {
+            get {
+                return m_minValue; 
+            }
+            set {
+                m_minValue = value; 
+            }
+        }
+        /// <summary>
+        /// get / set maximum value for the values range
+        /// </summary>
+        public float MaxValue {
+            get {
+                return m_maxValue; 
+            }
+            set {
+                m_maxValue = value; 
+            }
+        }
+
+        /// <summary>
+        /// register clipping range object as source for range and its changes
+        /// </summary>
+        /// <param name="clipping">clipping data object</param>
+        /// <returns>true, if the source was registered successfully</returns>
+        public bool RegisterRangeSource(ILClippingData clipping) {
+            if (object.Equals(clipping,null)) return false; 
+            clipping.Changed += new ILClippingDataChangedEvent(clipping_Changed); 
+            return true; 
+        }
+
+        private void clipping_Changed(object sender, ClippingChangedEventArgs e) {
+            m_minValue = e.ClippingData.ZMin; 
+            m_maxValue = e.ClippingData.ZMax;
+            if (m_minValue == m_maxValue) {
+                m_minValue -= 1f; 
+                m_maxValue += 1f;
+            }
+        }
+        /// <summary>
+        /// update range for color bar, supply color provider
+        /// </summary>
+        /// <param name="minValue">min value</param>
+        /// <param name="maxValue">max value</param>
+        /// <param name="colorProvider">color provider (not implemented)</param>
+        public void Update(float minValue, float maxValue, ILColormap colormap) {
+            m_minValue = minValue; 
+            m_maxValue = maxValue; 
+            m_colormap = colormap; 
+        }
+        /// <summary>
+        /// update data range for the color bar
+        /// </summary>
+        /// <param name="minValue">min value</param>
+        /// <param name="maxValue">max value</param>
+        public void Update(float minValue, float maxValue) {
+            m_minValue = minValue; 
+            m_maxValue = maxValue; 
+        }
+
+
+        public ILColorBar(ILColormap colormap) : base() {
+            base.BorderStyle = BorderStyle.FixedSingle; 
+            Padding = new Padding(4); 
+            StandardOrientation = TextOrientation.Vertical;
+            m_orientation = TextOrientation.Vertical;
+            Visible = true; 
+            BackColor = Color.White; 
+            m_colormap = colormap; 
+        }
+
+        protected override void OnPaint(PaintEventArgs e) {
+            if (!Visible) return; // || (m_minValue == m_maxValue)) return;
+            base.OnPaint(e);
+            // draw border 
+            Brush br = new SolidBrush(ForeColor) ;
+            Rectangle drawSpace = ClientRectangle;
+            Pen pen = new Pen(br); 
+            // draw labels 
+            drawSpace.Location = new Point (Padding.Left,Padding.Top); 
+            drawSpace.Width = ClientRectangle.Width - Padding.Horizontal;
+            drawSpace.Height = ClientRectangle.Height- Padding.Vertical; 
+            string format = String.Format("g{0}",m_precision); 
+            SizeF labsize = e.Graphics.MeasureString(String.Format(".-e08" + new String('0',m_precision)),Font); 
+            int tickCount;
+            if (m_orientation == TextOrientation.Vertical) {
+                tickCount = (int)Math.Floor((double)(drawSpace.Height - labsize.Height) / (labsize.Height + m_tickLabelsPadding));
+            } else {
+                tickCount = (int)Math.Floor((double)(drawSpace.Width - labsize.Width) / (labsize.Width + m_tickLabelsPadding));
+            }
+            List<float> labels = 
+                Collections.ILTickCollection.NiceLabels(m_minValue,m_maxValue,tickCount,TickLabelRenderingHint.Auto); 
+            tickCount = labels.Count; 
+            // draw labels
+            RectangleF dR; List<int> tickPositions = new List<int>(tickCount); 
+            if (m_orientation == TextOrientation.Vertical) {
+                dR = new RectangleF(drawSpace.Left,drawSpace.Top + drawSpace.Height - labsize.Height, labsize.Width,labsize.Height); 
+                StringFormat sf = new StringFormat(); 
+                sf.Alignment = StringAlignment.Far; 
+                sf.LineAlignment = StringAlignment.Near; 
+                // draw all values in between
+                float offsY = drawSpace.Top + drawSpace.Height;
+                float mult = (drawSpace.Height) / (m_maxValue - m_minValue);
+                foreach (float curVal in labels) {
+                    // translate into screen coords
+                    dR.Y = (int)(offsY - (curVal - m_minValue) * mult); 
+                    tickPositions.Add((int)dR.Y);
+                    dR.Y -= (labsize.Height/2);
+                    e.Graphics.DrawString(curVal.ToString(format),Font,br,dR,sf);
+                }
+                // prepare remaining space for gradient scale
+                drawSpace.X += (int)(labsize.Width + 2 * m_tickLabelsPadding); 
+                drawSpace.Width -= (int)(labsize.Width + 2 * m_tickLabelsPadding); 
+            } else {
+                // draw labels above gradient scale
+                dR = new RectangleF(drawSpace.Left,drawSpace.Top,labsize.Width,labsize.Height); 
+                StringFormat sf = new StringFormat(); 
+                sf.Alignment = StringAlignment.Near; 
+                e.Graphics.DrawString(m_minValue.ToString(format),Font,br,dR,sf); 
+                tickPositions.Add(drawSpace.Left); 
+                // draw maximum 
+                sf.Alignment = StringAlignment.Far;
+                dR.X = drawSpace.Left + drawSpace.Width - labsize.Width; 
+                e.Graphics.DrawString(m_maxValue.ToString(format),Font,br,dR,sf); 
+                tickPositions.Add(drawSpace.Left + drawSpace.Width); 
+                sf.Alignment = StringAlignment.Center;
+                // draw all values in between
+                float mult = (drawSpace.Width) / (m_maxValue - m_minValue);
+                foreach (float curVal in labels) { // = ls; curVal <= m_maxValue - m/2; curVal = (float) (curVal + m)) {
+                    // translate into screen coords
+                    dR.X = (int)((curVal - m_minValue) * mult); 
+                    if (dR.X < drawSpace.Left + labsize.Width) continue; 
+                    if (dR.X > drawSpace.Left + drawSpace.Width - labsize.Width) continue; 
+                    tickPositions.Add((int)dR.X); 
+                    dR.X -= (labsize.Width/2);
+                    e.Graphics.DrawString(curVal.ToString(format),Font,br,dR,sf);
+                }
+                // prep. rem. space for gradient scale
+                drawSpace.Y += (int)(labsize.Height + 2 * m_tickLabelsPadding); 
+                drawSpace.Height -= (int)(labsize.Height + 2 * m_tickLabelsPadding); 
+            }
+
+            // draw color gradient: border (gray)
+            pen.Color = Color.FromArgb(180,180,180); 
+            e.Graphics.DrawRectangle(pen,drawSpace);
+            drawSpace.X += 1; drawSpace.Y += 1; 
+            drawSpace.Width -= 1; drawSpace.Height -= 1; 
+            ILColorProvider hls = new ILColorProvider(0.0f,0.5f,1.0f); 
+            if (m_orientation == TextOrientation.Vertical) {
+                for (int i = drawSpace.Height; i -->0;) {
+                    pen.Color = m_colormap.Map((drawSpace.Height - i) / (double)drawSpace.Height * m_colormap.Length);
+                    e.Graphics.DrawLine(pen,drawSpace.Left, drawSpace.Top+i, drawSpace.Left + drawSpace.Width,drawSpace.Top + i);
+                }
+                // draw tick bars 
+                int le = drawSpace.Left, re = drawSpace.Left + drawSpace.Width, le2 = le + (re - le) / 4, re2 = re - (re - le) / 4; 
+                pen.Color = ForeColor; 
+                foreach (int y in tickPositions) {
+                    e.Graphics.DrawLine(pen,le,y,le2,y); 
+                    e.Graphics.DrawLine(pen,re2,y,re,y); 
+                }
+            } else {
+                for (int i = drawSpace.Width; i -->0;) {
+                    pen.Color = m_colormap.Map(i / (double)drawSpace.Width * m_colormap.Length);
+                    e.Graphics.DrawLine(pen,drawSpace.Left+i, drawSpace.Top, drawSpace.Left + i,drawSpace.Top + drawSpace.Height);
+                }
+                // draw tick bars 
+                int up = drawSpace.Top, bot = drawSpace.Top + drawSpace.Height, up2 = up + (bot - up) / 4, bot2 = bot - (bot - up) / 4; 
+                pen.Color = ForeColor; 
+                foreach (int x in tickPositions) {
+                    e.Graphics.DrawLine(pen,x,up,x,up2); 
+                    e.Graphics.DrawLine(pen,x,bot2,x,bot); 
+                }
+            }
+        }
+        protected override void OnOrientationChanged() {
+            base.OnOrientationChanged();
+            //reposition the close button
+            if (m_orientation == TextOrientation.Horizontal) {
+                
+            } else {
+
+            }
+        }
+
+        private void InitializeComponent() {
+            this.SuspendLayout();
+            this.ResumeLayout(false);
+
+        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Controls/ILColorBar.resx
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Controls/ILColorBar.resx	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Controls/ILColorBar.resx	(revision 9102)
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="$this.TrayLargeIcon" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>False</value>
+  </metadata>
+</root>
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Controls/ILMovingDockPanel.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Controls/ILMovingDockPanel.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Controls/ILMovingDockPanel.cs	(revision 9102)
@@ -0,0 +1,303 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Windows.Forms; 
+using System.Drawing; 
+
+namespace ILNumerics.Drawing {
+
+    /// <summary>
+    /// Label with flexible configurable orientation of it's text 
+    /// </summary>
+    public class ILMovingDockPanel : Panel {
+        private DockStyle m_dockStyle; 
+        private TextOrientation m_standardOrientation = TextOrientation.Horizontal; 
+        private BorderStyle m_borderStyle; 
+        private bool m_isMoving; 
+        private Size m_oldSize; 
+        private System.Drawing.Point m_moveStart;
+        private float m_bgGradientDeg = 0.0f;
+        private byte m_bgGradientStrength = 30;
+        protected Color m_backColor = SystemColors.Info; 
+        private Button m_buttonClose; 
+
+        /// <summary>
+        /// Intensity of lighting / darkner effect for background color
+        /// </summary>
+        public byte BackgroundGradientStrength {
+            get { return m_bgGradientStrength; }
+            set { 
+                m_bgGradientStrength = value; 
+                Invalidate(); 
+            }
+        } 
+        /// <summary>
+        /// orientation for background gradient effect
+        /// </summary>
+        public float BackgroundGradientDeg {
+            get { return m_bgGradientDeg; }
+            set { 
+                m_bgGradientDeg = value; 
+                Invalidate(); 
+            }
+        } 
+
+
+        protected TextOrientation m_orientation = TextOrientation.Horizontal;
+        /// <summary>
+        /// set the orientation of text (Horizontal/Vertical)
+        /// </summary>
+        public TextOrientation Orientation {
+            get { 
+                return m_orientation; 
+            }
+            set { 
+                m_orientation = value; 
+            }
+        }
+        /// <summary>
+        /// The type of orientation (hor./ vert) if the control is not docked
+        /// </summary>
+        /// <remarks>Setting this value will not alter the way the display is
+        /// currently drawn until the control returns from a docked state the next time.</remarks>
+        public TextOrientation StandardOrientation {
+            get {
+                return m_standardOrientation; 
+            }
+            set {
+                m_standardOrientation = value; 
+                OnOrientationChanged();
+            }
+        }
+
+        public new BorderStyle BorderStyle {
+            get {
+                return m_borderStyle; 
+            }
+            set {
+                m_borderStyle = value; 
+            }
+        }
+        
+        public System.Drawing.Point LocationMoveStart {
+            get {
+                return m_moveStart; 
+            }
+            set {
+                m_moveStart = value; 
+            }
+        }
+        /// <summary>
+        /// True, if the control is currently moved around by the user
+        /// </summary>
+        public bool IsMoving {
+            get {
+                return m_isMoving; 
+            }
+            set {
+                m_isMoving = value; 
+            }
+        }
+
+        protected override void OnPaint(PaintEventArgs e) {
+            base.OnPaint(e);
+            Pen pen = new Pen(new SolidBrush(ForeColor),1.0f);  
+            if (BorderStyle == BorderStyle.FixedSingle) {
+                Rectangle rect = ClientRectangle; 
+                rect.Width -= 1; 
+                rect.Height -= 1; 
+                e.Graphics.DrawRectangle( pen,rect); 
+            }
+        }
+
+        public ILMovingDockPanel() {
+            m_dockStyle = DockStyle.None;
+            m_borderStyle = BorderStyle.None; 
+            this.Padding = new Padding(2); 
+            this.MouseDoubleClick += new MouseEventHandler(ILMovingDockPanel_MouseDoubleClick);
+            this.MouseDown += new MouseEventHandler(ILMovingDockPanel_MouseDown);
+            this.MouseUp += new MouseEventHandler(ILMovingDockPanel_MouseUp);
+            this.MouseMove += new MouseEventHandler(ILMovingDockPanel_MouseMove);
+            Cursor = Cursors.SizeAll; 
+            BackColor = SystemColors.Info;
+            // create close button
+            m_buttonClose = new Button(); 
+            Bitmap bmpClose = Resources.Images.close;
+            m_buttonClose.BackgroundImage = bmpClose; 
+            m_buttonClose.Height = bmpClose.Height; 
+            m_buttonClose.Width = bmpClose.Width; 
+            Controls.Add(m_buttonClose); 
+            m_buttonClose.FlatAppearance.BorderSize = 2;
+            m_buttonClose.Cursor = Cursors.Default; 
+            m_buttonClose.Visible = false;
+            m_buttonClose.Click += new EventHandler(m_buttonClose_Click);
+            positionButtonClose(); 
+        }
+
+        #region handle close button
+        void m_buttonClose_Click(object sender, EventArgs e) {
+            this.Visible = false; 
+        }
+
+        private void positionButtonClose() {
+            if (m_orientation == TextOrientation.Horizontal) {
+                
+            } else {
+
+            }
+            m_buttonClose.Left = 2; 
+            m_buttonClose.Top = 2; 
+        }
+
+        protected override void OnMouseEnter(EventArgs e) {
+            base.OnMouseEnter(e);
+            m_buttonClose.Visible = true; 
+        }
+
+        protected override void OnMouseLeave(EventArgs e) {
+            base.OnMouseLeave(e);
+            Point p = this.PointToClient(MousePosition); 
+            if (p.X < 0 || p.Y < 0 || p.Y > ClientSize.Height || p.X > ClientSize.Width) 
+                m_buttonClose.Visible = false; 
+        }
+        
+
+        #endregion
+
+        void ILMovingDockPanel_MouseMove(object sender, MouseEventArgs e) {
+            if (e.Button != MouseButtons.Left) 
+                return; 
+            if (!m_isMoving && (Math.Abs(e.X - m_moveStart.X) > 2 || Math.Abs(e.Y - m_moveStart.Y) > 2)) {
+                m_isMoving = true;
+                this.BorderStyle = BorderStyle.FixedSingle; 
+            }
+        }
+        protected override void OnPaintBackground(PaintEventArgs e) {
+            //System.Diagnostic.Debug.WriteLine("ILBordFtLbl: paintbg");
+            base.OnPaintBackground(e);  
+            Color c1 = BackColor; 
+            int c1r = Math.Max(Math.Max(c1.R,c1.G),c1.B); 
+            c1r = Math.Min(255-c1r,m_bgGradientStrength); 
+            c1 = Color.FromArgb(100,c1.R+c1r,c1.G+c1r,c1.B+c1r); 
+            Color c2 = BackColor; 
+            c1r = Math.Min(Math.Min(c2.R,c2.G),c2.B); 
+            if (c1r > m_bgGradientStrength) c1r = m_bgGradientStrength; 
+            c2 = Color.FromArgb(200,c2.R-c1r,c2.G-c1r,c2.B-c1r); 
+            Point p = new Point(ClientRectangle.Size.Width / 2, ClientRectangle.Height / 2); 
+            System.Drawing.Drawing2D.LinearGradientBrush br = 
+                new System.Drawing.Drawing2D.LinearGradientBrush(ClientRectangle,c1,c2,m_bgGradientDeg); 
+            e.Graphics.FillRegion(br,new Region(ClientRectangle)); 
+        }
+
+        void ILMovingDockPanel_MouseUp(object sender, MouseEventArgs e) {
+            m_isMoving = false; 
+        }
+
+        void ILMovingDockPanel_MouseDown(object sender, MouseEventArgs e) {
+            if (e.Button == MouseButtons.Left) {
+                m_moveStart = e.Location; 
+            }
+        }
+
+        void ILMovingDockPanel_MouseDoubleClick(object sender, MouseEventArgs e) {
+            if (e.Button == MouseButtons.Left) {
+                System.Array ds = Enum.GetValues(typeof(DockStyle)); 
+                int cds = (int)Dock;
+                DockStyle dos = (DockStyle)((cds + 1) % ds.Length); 
+                while (dos == DockStyle.Fill) {
+                    cds++; 
+                    dos = (DockStyle)((cds + 1) % ds.Length);
+                }
+                SuspendLayout(); 
+                Dock = dos;
+                ResumeLayout(); 
+            }
+        }
+
+        public override DockStyle Dock {
+            get {
+                return m_dockStyle;
+            }
+            set {
+                if (m_dockStyle == value) return; 
+                if (m_dockStyle == DockStyle.None) {
+                    m_oldSize = this.Size;  
+                }
+                this.BorderStyle = BorderStyle.None; 
+                switch (value) {
+                    case DockStyle.Left:
+                        m_orientation = TextOrientation.Vertical;
+                        break;
+                    case DockStyle.Right:
+                        m_orientation = TextOrientation.Vertical;
+                        break;
+                    case DockStyle.Top:
+                        m_orientation = TextOrientation.Horizontal;
+                        break;
+                    case DockStyle.Bottom:
+                        m_orientation = TextOrientation.Horizontal;
+                        break;
+                    case DockStyle.Fill:
+                        m_orientation = m_standardOrientation;
+                        break;
+                    case DockStyle.None:
+                        this.BorderStyle = BorderStyle.FixedSingle;
+                        m_orientation = m_standardOrientation;
+                        break;
+                    default:
+                        m_orientation = m_standardOrientation;
+                        break;
+                }
+                m_dockStyle = value;
+                if (m_dockStyle == DockStyle.None && m_oldSize.Width > 0 && m_oldSize.Height > 0) {
+                    this.Size = m_oldSize; 
+                }
+                if (Parent != null && Parent is ILSubfigure)
+                    ((ILSubfigure)Parent).PerformLayout();
+            }
+        }
+
+        protected virtual void OnOrientationChanged () {
+            
+        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Controls/ILPanel.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Controls/ILPanel.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Controls/ILPanel.cs	(revision 9102)
@@ -0,0 +1,1974 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+#pragma warning disable 1591
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing; 
+using System.Reflection; 
+using System.Windows.Forms;
+using System.IO; 
+using ILNumerics.Drawing; 
+using ILNumerics.Drawing.Interfaces;
+using ILNumerics.Drawing.Collections; 
+using ILNumerics.Drawing.Graphs; 
+using ILNumerics.Drawing.Labeling; 
+using ILNumerics.Drawing.Misc; 
+using System.Diagnostics; 
+
+namespace ILNumerics.Drawing {
+
+    /// <summary>
+    /// Basic abstract base class for GL dependent display.
+    /// </summary>
+    /// <remarks>This control is the main plot control of ILNumerics.</remarks>
+    public abstract class ILPanel : Control {
+
+        #region attributes 
+        protected ILRendererManager m_textRendererManager; 
+        protected ILClippingData m_clippingView; 
+        protected ILAxisCollection m_axes;
+        protected ILGraphCollection m_graphs;
+        protected ILTextureManager m_textureManager; 
+        protected Point m_mouseStart; 
+        protected bool m_isDragging; 
+        protected bool m_active = false; 
+        protected bool m_drawHidden = true; 
+        protected bool m_ready = false; 
+        private bool m_isStartingUp = true; 
+        protected ILCamera m_camera;
+        protected ILCamera m_defaultView;
+        protected bool m_autoDefaultView = true; 
+        protected InteractiveModes m_selectingMode = InteractiveModes.Rotating; 
+        protected InteractiveModes m_oldSelectingMode; 
+        protected bool m_isCtrlKeyDown; 
+        protected ILPoint3Df m_scaling;
+        protected Projection m_projection = Projection.Orthographic; 
+        protected Color m_backColor = Color.FromKnownColor(KnownColor.Control);
+        protected Color m_cubeBGColor = Color.FromArgb(250, 250, 250); 
+        protected ILColormap m_colormap; 
+        protected ILLegend m_legend; 
+        protected ZoomModes m_zoomMode = ZoomModes.RollHard; 
+        protected ILZoomAction m_zoomAction; 
+        protected float m_zoomOffset = 50f;
+        protected GraphicDeviceType m_graphicsDevice; 
+        protected ILLineProperties m_selectionRectangle; 
+        protected bool m_fillBackground = true; 
+        private AutoZoomOptions m_autoZoomOptions = AutoZoomOptions.OnDataChanges; 
+        protected ILLayoutData m_layoutData = new ILLayoutData(); 
+        protected ILLightCollection m_lights = new ILLightCollection(); 
+        protected ILRenderProperties m_renderProperties; 
+        protected ILAction m_action;
+        protected List<ILGraph> m_sortingCacheList = new List<ILGraph>(); 
+        /// <summary>
+        /// pixel size of the current PlotCubeScreenRectangle
+        /// </summary>
+        protected RectangleF m_plotBoxScreenRectF;
+        protected PlotBoxScreenSizeMode m_plotBoxScreenSizeMode;
+        protected AspectRatioMode m_aspectRatio; 
+        protected double[] m_clipplanes = new double[24]; 
+        
+        private const int MAXRENDERPASSES = 2; 
+        private const float LABELS_VERTICAL_MIN_RHO = 0.8f; 
+        protected const float pi05 = (float) Math.PI / 2; 
+        protected const float pi2 = (float) Math.PI * 2; 
+        protected const float pi32 = (float) Math.PI / 2 * 3; 
+        protected const float pi4 = (float) Math.PI / 4; 
+        protected const float pi8 = (float) Math.PI / 8; 
+        #endregion
+
+        #region properties
+        /// <summary>
+        /// Gets the mode for automatic view angle updates or sets it
+        /// </summary>
+        public bool AutoDefaultView { 
+            get { return m_autoDefaultView; }
+            set { m_autoDefaultView = value; }
+        }
+        /// <summary>
+        /// Determines how the projected data plots are mapped to PlotCubeScreenRectF
+        /// </summary>
+        public AspectRatioMode AspectRatio {
+            get { return m_aspectRatio; }
+            set { m_aspectRatio = value; }
+        }
+        /// <summary>
+        /// The normalizes projected size (range 0..1) of plot cube on 2D client area, on set: also sets PlotCubeScreenMode -> Manual
+        /// </summary>
+        public RectangleF PlotBoxScreenRect {
+            get { return m_plotBoxScreenRectF; }
+            set { 
+                m_plotBoxScreenRectF = value;
+                m_plotBoxScreenSizeMode = PlotBoxScreenSizeMode.Manual; 
+                //Invalidate(); 
+            }
+        }
+        /// <summary>
+        /// Options for determining the size of the plot cube on the 2D screen client area, default: optimal
+        /// </summary>
+        public PlotBoxScreenSizeMode PlotBoxScreenSizeMode {
+            get { return m_plotBoxScreenSizeMode; }
+            set {
+                m_plotBoxScreenSizeMode = value;
+                if (value == PlotBoxScreenSizeMode.Maximum) {
+                    m_plotBoxScreenRectF = new RectangleF(0, 0, 1f, 1f);
+                }
+            }
+        }
+        /// <summary>
+        /// Access collection of lights for configuration
+        /// </summary>
+        public ILLightCollection Lights {
+            get { return m_lights; }
+        }
+        /// <summary>
+        /// Legend for panel's graphs
+        /// </summary>
+        public ILLegend Legend {
+            get {
+                return m_legend; 
+            }
+        }
+        /// <summary>
+        /// Get texture manager instance, storing all textures used in the scene
+        /// </summary>
+        internal ILTextureManager TextureManager {
+            get {
+                return m_textureManager; 
+            }
+        }
+        /// <summary>
+        /// Colormap used to translate color indices into true colors
+        /// </summary>
+        public ILColormap Colormap {
+            get {
+                return m_colormap; 
+            }
+            set {
+                m_colormap = value;
+                OnColormapChanged(); 
+            }
+        }
+        /// <summary>
+        /// Determines if background of the rendering cube will be filled with the CubeBackgroundColor property value
+        /// </summary>
+        public bool BackgroundFilled {
+            get {
+                return m_fillBackground; 
+            }
+            set {
+                m_fillBackground = value; 
+                //Invalidate(); 
+            }
+        }
+        /// <summary>
+        /// True: the control will always be drawn, even if it does not own the focus
+        /// </summary>
+        public bool DrawInactive {
+            get {
+                return m_drawHidden; 
+            }
+            set {
+                m_drawHidden = value; 
+                //Invalidate(); 
+            }
+        }
+        /// <summary>
+        /// Get/set the background color for the inner cube drawing 
+        /// </summary>
+        public Color BackColorCube {
+            get {
+                return m_cubeBGColor; 
+            }
+            set {
+                m_cubeBGColor = value; 
+                //Invalidate();
+            }
+        }
+        /// <summary>
+        /// View settings, get access to the clipping limits for all axises 
+        /// </summary>
+        public ILClippingData Limits {
+            get {
+                return m_clippingView; 
+            } 
+        }
+        /// <summary>
+        /// Get the type of device currently used for rendering
+        /// </summary>
+        public GraphicDeviceType GraphicDeviceType {
+            get {
+                return m_graphicsDevice; 
+            }
+        }
+        /// <summary>
+        /// Get/set properties for selection rectangle, drawn when zooming with the mouse
+        /// </summary>
+        public ILLineProperties SelectionRectangle {
+            get {
+                return m_selectionRectangle; 
+            }
+        }
+        /// <summary>
+        /// color of the figure background
+        /// </summary>
+        public override Color BackColor {
+            get {
+                return m_backColor; 
+            }
+            set {
+                m_backColor = value; 
+                //Invalidate();
+            }
+        }
+        /// <summary>
+        /// type of projection: orthographic (default) or perspective
+        /// </summary>
+        public Projection Projection {
+            get {
+                return m_projection; 
+            }
+            set {
+                m_projection = value; 
+                //Invalidate();
+            }
+        }
+        /// <summary>
+        /// Get or set viewport properties (distance &amp; angles)
+        /// </summary>
+        /// <remarks>Changing </remarks>
+        public ILCamera Camera {
+            get {
+                return m_camera; 
+            }
+        }
+        /// <summary>
+        /// Get the current mode for mouse interaction or set's it
+        /// </summary>
+        public InteractiveModes InteractiveMode {
+            get {
+                return m_selectingMode; 
+            } 
+            set {
+                m_selectingMode = value;
+                m_oldSelectingMode = value;
+                //if (value == InteractiveModes.Rotating)
+                //    m_axes[AxisNames.ZAxis].Visible = true;
+                //else if (value == InteractiveModes.ZoomRectangle) 
+                //    m_axes[AxisNames.ZAxis].Visible = false; 
+            }
+        }
+        /// <summary>
+        /// Gives all graphs as value collection (readonly)
+        /// </summary>
+        public ILGraphCollection Graphs {
+            get { 
+                if (m_graphs == null) 
+                    CreateControl(); 
+                return m_graphs;
+            }
+        }
+        /// <summary>
+        /// Get axes collection - holds all 3 axes
+        /// </summary>
+        public ILAxisCollection Axes {
+            get {
+                if (m_axes == null) 
+                    CreateControl();
+                return m_axes; 
+            }
+        }
+        /// <summary>
+        /// (experimental) content for graphs will be clipped outside the unit cube
+        /// </summary>
+        /// <remarks>For 2D plots, not clipping the vertex data may lead to hiding 
+        /// the labels drawn next to axes. For 3D plots Clipping may cause unexpected behavior. 
+        /// <para>Therefore Clipping will be activated for 2D plots by default and 
+        /// deactivated for 3D plots by default.</para></remarks>
+        public bool ClipViewData {
+            get {
+                return m_renderProperties.Clipping; 
+            }
+            set {
+                m_renderProperties.Clipping = value; 
+            }
+        }
+        /// <summary>
+        /// Manager providing collection of available IILTextRenderer types
+        /// </summary>
+        /// <remarks>IILTextRenderer are used to draw labels for axis of this panel (device specific).
+        /// <para>Text renderer objects must be instantiated through the ILTextRendererManager instance's
+        /// CreateInstance() method.</para></remarks>
+        public ILRendererManager TextRendererManager {
+            get {
+                return m_textRendererManager; 
+            }
+        }
+        /// <summary>
+        /// Get or set default camera position for reset of the scene
+        /// </summary>
+        /// <remarks>The default position is used when the scene is reset. That
+        /// reset is usually triggered by double clicking the panel with the mouse.
+        /// <para>setting this value to null will make the panel ignore any double
+        /// clicks, which enables the user to manually react to double click via the 
+        /// common DoubleClick event of the panel and reset the camera position from
+        /// outside the component.</para></remarks>
+        public ILCamera DefaultView {
+            get {
+                return m_defaultView; 
+            }
+            protected set {
+                if (value != null) {
+                    m_defaultView = value;
+                    m_autoDefaultView = false; 
+                } else {
+                    m_autoDefaultView = true; 
+                }
+            }
+        }
+        /// <summary>
+        /// Options for the view cube adapting data limit changes 
+        /// </summary>
+        public AutoZoomOptions AutoZoomContent {
+            get {
+                return m_autoZoomOptions; 
+            }
+            set {
+                m_autoZoomOptions = value;
+            }
+        }
+        /// <summary>
+        /// choose the ramp for zooming
+        /// </summary>
+        public ZoomModes ZoomMode {
+            get { return m_zoomMode; }
+            set { m_zoomMode = value; }
+        }
+        /// <summary>
+        /// How much the view cube will be shrinked/expanded on zooming operations (percent)
+        /// </summary>
+        public float ZoomOffset {
+            set { m_zoomOffset = value; }
+            get { return m_zoomOffset; }
+
+        }
+        protected ILZoomAction ZoomAction {
+            get {
+                return m_zoomAction; 
+            }   
+        }
+        #endregion
+
+        #region constructors
+        protected ILPanel(GraphicDeviceType graphicsDevice) : base () {
+#if TRACE 
+            Trace.TraceInformation("{0},{1} ILPanel.ctor()",DateTime.Now, Environment.TickCount); 
+#endif
+            this.DoubleBuffered = false; 
+            //BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+            m_plotBoxScreenSizeMode = PlotBoxScreenSizeMode.Optimal; 
+            m_graphicsDevice = graphicsDevice; 
+            m_textureManager = new ILTextureManager(m_graphicsDevice);
+            m_textureManager.DefaultHeight = 500; 
+            m_textureManager.DefaultWidth = 500; 
+            m_selectionRectangle = new ILLineProperties();
+            m_selectionRectangle.Antialiasing = false; 
+            m_selectionRectangle.Color = Color.Blue; 
+            m_selectionRectangle.Width = 1; 
+            m_selectionRectangle.Style = LineStyle.Solid; 
+            m_selectionRectangle.Changed += new EventHandler(m_selectionRectangle_Changed);
+            m_camera = new ILCamera((float)0.0f,0.0f,10.0f);
+            m_defaultView = new ILCamera(m_camera);
+            m_defaultView.Changed += new EventHandler(m_defaultView_Changed);
+            m_renderProperties = new ILRenderProperties ();
+            m_renderProperties.Camera = Camera; 
+            m_textRendererManager = new ILRendererManager(this); 
+            m_clippingView = new ILClippingData();
+            m_clippingView.AllowZeroVolume = false; 
+            m_layoutData = new ILLayoutData(m_camera);
+            m_clippingView.Changed += new ILClippingDataChangedEvent(m_viewLimits_Changed);
+            m_colormap = new ILColormap();
+            m_colormap.Changed += new EventHandler(m_colormap_Changed);
+            Padding = new Padding(5);
+            BackColor = Color.White;
+            Dock = DockStyle.Fill; 
+            m_legend = ILLegend.Create(this);
+            m_legend.Changed += new EventHandler(m_legend_Changed);
+            m_active = false;
+            m_ready = false; 
+        }
+
+        #endregion
+
+        #region public interface function 
+        /// <summary>
+        /// Dispose this panel, frees all devices, graph- and axis collection
+        /// </summary>
+        public new void Dispose () {
+            Dispose(false); 
+        }
+        /// <summary>
+        /// dispose this panel
+        /// </summary>
+        /// <param name="disposing">manual disposing</param>
+        /// <remarks>derived classed (ILDXPanel,ILOGLPanel) free their resources here</remarks>
+        protected override void Dispose(bool disposing) {
+#if TRACE 
+            Trace.TraceInformation("{0},{1} ILPanel.Dispose(bool) start",DateTime.Now, Environment.TickCount); 
+            Trace.Indent(); 
+#endif
+            m_ready = false; 
+            if (m_graphs != null)
+                m_graphs.Dispose(); 
+            if (m_axes != null)
+                m_axes.Dispose(); 
+            if (m_textureManager != null)
+                m_textureManager.Dispose(); 
+            base.Dispose(disposing);
+#if TRACE 
+            Trace.Unindent(); 
+            Trace.TraceInformation("{0},{1} ILPanel.Dispose(bool) end",DateTime.Now, Environment.TickCount); 
+#endif
+        }
+
+        /// <summary>
+        /// causes the panel to redraw
+        /// </summary>
+        public override void Refresh() {
+            if (InvokeRequired) {
+                Invoke((MethodInvoker) delegate () { Refresh(); }); 
+            } else {
+                base.Refresh(); 
+            }
+        }
+        #endregion
+
+        #region events
+        /// <summary>
+        /// fired, if the data limits of any graphs changed
+        /// </summary>
+        public event ILClippingDataChangedEvent DataLimitsChanged; 
+        /// <summary>
+        /// fired, if the clipping rectangle for viewing graphs changed
+        /// </summary>
+        public event ILClippingDataChangedEvent ViewLimitsChanged; 
+        /// <summary>
+        /// fires, if the current colormap has changed
+        /// </summary>
+        public event EventHandler ColormapChanged; 
+        /// <summary>
+        /// fired, if the internal graphics device reset (Direct3D devices only)
+        /// </summary>
+        public event ILGraphicsDeviceResetEvent GraphicsDeviceReset;
+        /// <summary>
+        /// fired, if the internal graphics device has been (re)created
+        /// </summary>
+        public event ILGraphicsDeviceCreatedEvent GraphicsDeviceCreated;
+        #endregion
+
+        #region event handlers
+        protected void m_defaultView_Changed(object sender, EventArgs e) {
+            m_autoDefaultView = false;
+        }
+        protected override void OnHandleCreated(EventArgs e) {
+#if TRACE 
+            Trace.TraceInformation("{0},{1} ILPanel.OnHandleCreated() start",DateTime.Now, Environment.TickCount); 
+            Trace.Indent(); 
+#endif
+            base.OnHandleCreated(e);
+            this.SetStyle(ControlStyles.AllPaintingInWmPaint,true);
+            this.SetStyle(ControlStyles.UserPaint,true);
+#if TRACE 
+            Trace.Unindent(); 
+            Trace.TraceInformation("{0},{1} ILPanel.OnHandleCreated() end",DateTime.Now, Environment.TickCount); 
+#endif
+        }
+        protected override void OnHandleDestroyed(EventArgs e) {
+#if TRACE 
+            Trace.TraceInformation("{0},{1} ILPanel.OnHandleDestroyed() start",DateTime.Now, Environment.TickCount); 
+            Trace.Indent(); 
+#endif
+            if (m_zoomAction != null) m_zoomAction.Cancel(); 
+            Dispose(); 
+            base.OnHandleDestroyed(e);
+#if TRACE 
+            Trace.Unindent(); 
+            Trace.TraceInformation("{0},{1} ILPanel.OnHandleDestroyed() end",DateTime.Now, Environment.TickCount); 
+#endif
+
+        }
+        protected virtual void OnViewLimitsChanged(ClippingChangedEventArgs e) {
+            if (ViewLimitsChanged != null) 
+                ViewLimitsChanged(this,e);  
+        }
+        protected virtual void OnDataLimitsChanged(ClippingChangedEventArgs e) {
+            if (DataLimitsChanged != null) 
+                DataLimitsChanged(this,e);  
+        }
+        protected virtual void OnGraphicsDeviceReset() {
+#if TRACE 
+            Trace.TraceInformation("{0},{1} ILPanel.OnGraphicsDeviceReset() start",DateTime.Now, Environment.TickCount); 
+            Trace.Indent(); 
+#endif
+            Configure(); 
+            if (GraphicsDeviceReset != null) {
+                GraphicsDeviceReset(this,null);
+            }
+#if TRACE 
+            Trace.Unindent(); 
+            Trace.TraceInformation("{0},{1} ILPanel.OnGraphicsDeviceReset() end",DateTime.Now, Environment.TickCount); 
+#endif
+        }
+        protected virtual void OnGraphicsDeviceCreated() {
+#if TRACE 
+            Trace.TraceInformation("{0},{1} ILPanel.OnGraphicsDeviceCreated() start",DateTime.Now, Environment.TickCount); 
+            Trace.Indent(); 
+#endif
+            IILCreationFactory graphFact = GetCreationFactory(); 
+            m_graphs = new ILGraphCollection(graphFact);
+            m_graphs.CollectionChanged += new ILGraphCollectionChangedEvent(m_graphs_OnCollectionChanged);
+            m_graphs.Limits.Changed += new ILClippingDataChangedEvent(m_dataLimits_Changed);
+            m_graphs.GraphChanged += new ILGraphChangedEvent(m_graphs_GraphChanged);
+            m_axes = new ILAxisCollection(m_clippingView,graphFact); 
+            if (GraphicsDeviceCreated!= null) {
+                GraphicsDeviceCreated(this,null);
+            }
+            //Invalidate(); 
+#if TRACE 
+            Trace.Unindent(); 
+            Trace.TraceInformation("{0},{1} ILPanel.OnGraphicsDeviceCreated() end",DateTime.Now, Environment.TickCount); 
+#endif
+        }
+
+        protected virtual void OnColormapChanged() {
+            if (ColormapChanged != null) 
+                ColormapChanged(this,null); 
+            m_graphs.Invalidate(); 
+        }
+
+        protected override void OnLostFocus(EventArgs e) {
+            base.OnLostFocus(e);
+            m_active = false; 
+        }
+        protected override void OnGotFocus(EventArgs e) {
+            base.OnGotFocus(e);
+            m_active = true; 
+        }
+        protected override void OnVisibleChanged(EventArgs e) {
+			if (IsHandleCreated && !IsDisposed) {
+	            base.OnVisibleChanged(e);
+	            if (Visible) 
+	                m_active = true; 
+	            else 
+	                m_active = false; 
+			}
+        }
+        protected override void OnSizeChanged(EventArgs e) {
+            base.OnSizeChanged(e);
+            base.Invalidate(); 
+        }
+
+        protected override void OnMouseMove(MouseEventArgs e) {
+            base.OnMouseMove(e);
+            if (m_selectingMode == InteractiveModes.Rotating) {
+                #region rotation
+                if (m_isDragging || (e.Button == System.Windows.Forms.MouseButtons.Left 
+                    && Math.Sqrt(Math.Pow(Math.Abs(e.X - m_mouseStart.X),2) + Math.Pow(Math.Abs(e.Y - m_mouseStart.Y),2)) > 3.0)) {
+                    m_isDragging = true; 
+                    m_camera.EventingSuspend(); 
+                    int distX = e.Location.X - m_mouseStart.X; 
+                    int distY = e.Location.Y - m_mouseStart.Y;
+                    float tmp = m_camera.Phi - distX / 200.0f;
+                    // if alt is pressed, lock on even angles 
+                    if (((Control.ModifierKeys & Keys.Alt) != 0)
+                        && (Math.Abs(Math.Round(tmp/pi4) - (tmp / pi4)) < 0.05)) {
+                        tmp = (float)(Math.Round(tmp / pi4) * pi4); 
+                    }
+                    m_camera.Phi = tmp; 
+                    tmp = m_camera.Rho - distY / 200.0f;
+                    // if alt is pressed, lock on even angles 
+                    if (((Control.ModifierKeys & Keys.Alt) != 0)
+                        && (Math.Abs(Math.Round(tmp/pi8) - (tmp / pi8)) < 0.05)) {
+                        tmp = (float)(Math.Round(tmp / pi8) * pi8); 
+                    }
+                    m_camera.Rho = tmp; 
+                    if (m_camera.Rho > Math.PI) m_camera.Rho = (float)Math.PI; 
+                    if (m_camera.Rho < 0) m_camera.Rho = 0.0f; 
+                    m_camera.EventingResume();
+                    m_mouseStart = e.Location; 
+                    Refresh(); 
+                }
+                #endregion
+            } else if (m_selectingMode == InteractiveModes.ZoomRectangle) {
+                #region selection rectangle
+                if (m_isDragging || (e.Button == System.Windows.Forms.MouseButtons.Left 
+                    && Math.Sqrt(Math.Pow(Math.Abs(e.X - m_mouseStart.X),2) + Math.Pow(Math.Abs(e.Y - m_mouseStart.Y),2)) > 3.0)) {
+                    m_isDragging = true; 
+                    Cursor = Cursors.Cross; 
+                    Refresh();
+                }
+                #endregion
+            } else if (m_selectingMode == InteractiveModes.Translating) {
+                if (m_isDragging || (e.Button == System.Windows.Forms.MouseButtons.Left 
+                    && Math.Sqrt(Math.Pow(Math.Abs(e.X - m_mouseStart.X),2) + Math.Pow(Math.Abs(e.Y - m_mouseStart.Y),2)) > 1.0)) {
+                    ILPoint3Df p1,p2,dummy; 
+                    Screen2World(m_mouseStart.X,Height - m_mouseStart.Y, out p1, out dummy);
+                    Screen2World(e.X, Height - e.Y, out p2, out dummy);
+                    if (m_projection == Projection.Perspective) {
+                        p1 = ILPoint3Df.normalize(p1 - m_camera.Position) * m_camera.Distance;
+                        p2 = ILPoint3Df.normalize(p2 - m_camera.Position) * m_camera.Distance;
+                    }
+                    p1 = p2 - p1; 
+                    m_camera.LookAt -= p1;  
+                    m_mouseStart = e.Location; 
+                    Refresh(); 
+                }
+            
+            }
+        }
+        protected override void OnMouseUp(MouseEventArgs e) {
+            base.OnMouseUp(e);
+            //System.Diagnostic.Debug.WriteLine("MouseUp");
+            if (m_selectingMode == InteractiveModes.ZoomRectangle && m_isDragging) {
+                Zoom(Screen2World2D(m_mouseStart.X,Height - m_mouseStart.Y),Screen2World2D(e.X, Height - e.Y));
+            }
+            m_isDragging = false; 
+            Cursor = Cursors.Default; 
+        }
+        protected override void OnMouseDown(MouseEventArgs e) {
+            base.OnMouseDown(e);
+            m_mouseStart = e.Location; 
+        }
+        protected override void OnMouseClick(MouseEventArgs e) {
+            base.OnMouseClick(e);
+            //System.Diagnostic.Debug.WriteLine("Click");
+            if (m_isDragging == false && (m_selectingMode == InteractiveModes.ZoomRectangle 
+                || m_selectingMode == InteractiveModes.Rotating)) {
+                // determine new center coords
+                ILPoint3Df near, far; 
+                Screen2World(e.X,Height - e.Y, out near, out far); //Limits.CenterF.Z);
+                if (e.Button == System.Windows.Forms.MouseButtons.Left) {
+                    Zoom(near,far,m_zoomOffset / 100); 
+                }
+                else if (e.Button == System.Windows.Forms.MouseButtons.Right)
+                    Zoom(near,far,- m_zoomOffset / 100);
+            }
+        }
+        protected override void OnMouseDoubleClick(MouseEventArgs e) {
+            base.OnMouseDoubleClick(e);
+            ResetView(true);
+            Refresh(); 
+        }
+        protected override void OnKeyDown(KeyEventArgs e) {
+            if (e.Control && !m_isCtrlKeyDown) {
+                m_oldSelectingMode = m_selectingMode; 
+                m_selectingMode = InteractiveModes.Translating; 
+                m_isCtrlKeyDown = true; 
+                Cursor = Cursors.NoMove2D; 
+                //m_isDragging = false; 
+            }
+            base.OnKeyDown(e);
+        }
+        protected override void OnKeyUp(KeyEventArgs e) {
+            if (!e.Control) {
+                if (m_isCtrlKeyDown) {
+                    m_isCtrlKeyDown = false; 
+                    m_selectingMode = m_oldSelectingMode; 
+                }
+                Cursor = Cursors.Default; 
+                //m_isDragging = false; 
+            }
+            base.OnKeyUp(e);
+        }
+        protected override void OnPaint(System.Windows.Forms.PaintEventArgs e) {
+            if (DesignMode) {
+                e.Graphics.Clear(Color.LightBlue); 
+                return; 
+            }
+            if (e.ClipRectangle.Width == 0 || e.ClipRectangle.Height == 0) {
+#if TRACE 
+                Trace.TraceInformation("{0},{1} ILPanel.OnPaint(): ClipRectangle.Size = empty -> skipping",DateTime.Now, Environment.TickCount); 
+#endif
+                return; 
+            }
+/* THIS IS PRELIMINARY IMPLEMENTATION! REASON: While using GDI renderer, 
+ * it is importatnt, to have the whole (visible) surface area invalidated
+ * and available for clipping of the graphics objects in 'e'. Otherwise 
+ * rendered objects will not show, after the buffers have swapped. The 
+ * following code helps pick those situations, where the clipping region 
+ * is only a subregion of the controls surface, but it introduces new 
+ * problems, if the whole control is (partially) obscured by other controls. 
+ * Since the GDI Renderer currently is not the recommended method of rendering,
+ * this code is commented until a better solution was found. */
+//            if (e.ClipRectangle.X > 0 || e.ClipRectangle.Y > 0) {
+//#if TRACE 
+//                Trace.TraceInformation("{0},{1} ILPanel.OnPaint(): partial clipping detected -> refreshing whole controls area",DateTime.Now, Environment.TickCount); 
+//#endif
+//                Refresh();
+//                return; 
+//            }
+            try {
+#if TRACE 
+                    Trace.TraceInformation("{0},{1} ILPanel.OnPaint(): started (re-)configure",DateTime.Now, Environment.TickCount); 
+                    Trace.Indent(); 
+#endif
+                    Configure();
+                    if (m_isStartingUp && (m_autoZoomOptions != AutoZoomOptions.Never)) {
+                        ResetView(true);
+                    }
+#if TRACE 
+                Trace.Unindent(); 
+                Trace.TraceInformation("{0},{1} ILPanel.OnPaint(): rendering started",DateTime.Now, Environment.TickCount); 
+                Trace.Indent();
+                Trace.TraceInformation(String.Format("this: {1}, ClipRectangle: {0}, Graphics.ClipBounds: L:{2} T:{3} W:{4} H:{5}"
+                    ,e.ClipRectangle.ToString()
+                    ,this.ClientRectangle.ToString()
+                    ,e.Graphics.VisibleClipBounds.Left
+                    ,e.Graphics.VisibleClipBounds.Top
+                    ,e.Graphics.VisibleClipBounds.Width
+                    ,e.Graphics.VisibleClipBounds.Height)); 
+#endif
+                m_renderProperties.Graphics = e.Graphics;
+                m_renderProperties.Reason = RenderReason.PaintEvent;
+                m_renderProperties.MinX = int.MaxValue;
+                m_renderProperties.MinY = int.MaxValue;
+                m_renderProperties.MaxX = int.MinValue;
+                m_renderProperties.MaxY = int.MinValue; 
+                RenderScene(m_renderProperties.Reset());
+#if TRACE 
+                Trace.Unindent(); 
+                Trace.TraceInformation("{0},{1} ILPanel.OnPaint(): rendering ended",DateTime.Now, Environment.TickCount); 
+#endif
+                if (m_isStartingUp) {
+                    m_isStartingUp = false;
+                    Refresh();
+                }
+                System.Diagnostics.Debug.WriteLine("Current Camera Setting: " + m_camera.ToString()); 
+            } catch (Exceptions.ILArgumentException exc) {
+#if TRACE 
+                Trace.TraceWarning("{0},{1} ILPanel.OnPaint(): rendering failed. reason: {2}",DateTime.Now, Environment.TickCount,exc.ToString()); 
+                Trace.Indent(); 
+#endif
+                System.Diagnostics.Debug.WriteLine("ILPanel.OnPaint failed: " + exc.ToString()); 
+                throw new Exceptions.ILArgumentException("rendering failed. Details attached.",exc); 
+            }
+        }
+        void m_legend_Changed(object sender, EventArgs e) {
+            Invalidate(); 
+        }
+
+        void m_graphs_GraphChanged(object sender, ILGraphChangedEventArgs args) {
+            ResetView(false); 
+        }
+        protected void m_graphs_OnCollectionChanged(object sender, ILGraphCollectionChangedEventArgs args) {
+            if (args.Reason == GraphCollectionChangeReason.Added) {
+                if (AutoDefaultView && (args.Configurator != null)) {
+                    args.Configurator.ConfigurePanel(this);
+                }
+            }
+       }
+        protected void m_viewLimits_Changed(object sender, ClippingChangedEventArgs e) {
+            if (this.InvokeRequired && IsHandleCreated) {
+                try {
+                    Invoke(new ILClippingDataChangedEvent(m_viewLimits_Changed), sender, e);
+                } catch (Exception) { }
+            } else {
+                m_camera.LookAt = m_clippingView.CenterF; 
+                OnViewLimitsChanged(e);
+            }
+        }
+        protected void m_dataLimits_Changed(object sender, ClippingChangedEventArgs e) {
+            if (m_autoDefaultView) {
+                m_defaultView.EventingSuspend();
+                bool oldDefaultViewSetting = m_autoDefaultView; 
+                m_defaultView.LookAt = m_graphs.Limits.CenterF;
+                m_defaultView.Distance = m_graphs.Limits.SphereRadius * 2;
+                m_defaultView.EventingResume(false);
+            }
+            if (m_autoZoomOptions == AutoZoomOptions.OnDataChanges) 
+                ResetView(false); 
+            OnDataLimitsChanged(e);  
+        }
+
+        protected void m_colormap_Changed(object sender, EventArgs e) {
+            OnColormapChanged(); 
+        }
+        void m_selectionRectangle_Changed(object sender, EventArgs e) {
+            // nothing to do here
+        }
+
+        #endregion event handler 
+
+        #region virtual abstract interface
+        /// <summary>
+        /// Get current rendering device (implementation dependent)
+        /// </summary>
+        /// <returns></returns>
+        public abstract object GetDeviceContext(); 
+        /// <summary>
+        /// Causes a reconfiguration of all axes and graphs on the next paint event
+        /// </summary>
+        /// <remarks>Call this method after any changes to vertex relevant data. It causes all drawable objects to clear their caches and recalculate all vertex data.</remarks>
+        protected new void Invalidate() {
+            if (!m_ready) return;
+            m_ready = false; 
+            m_graphs.Invalidate(); 
+            m_axes.Invalidate();
+            //base.Invalidate(this.ClientRectangle, true); <- this would cause an immediate redraw also. Use Refresh() for this!
+        }
+        /// <summary>
+        /// update viewing limits to show all data, rotate the scene to default (-> DefaultView)
+        /// </summary>
+        public virtual void ResetView() {
+            ResetView(true);
+        }
+        /// <summary>
+        /// update viewing limits to show all data, optionally reset the scene rotation
+        /// </summary>
+        /// <param name="resetRotation">true: rotate the scene to the default (-> DefaultView)</param>
+        public virtual void ResetView(bool resetRotation) {
+            if (m_zoomAction != null)
+                m_zoomAction.Cancel();
+            m_clippingView.EventingSuspend(); 
+            m_clippingView.CopyFrom(m_graphs.Limits); 
+            m_clippingView.Update(m_clippingView.CenterF,1.1f); 
+            m_clippingView.EventingResume(); 
+            if (m_defaultView != null && resetRotation) {
+                m_camera.LookAt = m_defaultView.LookAt; 
+                m_camera.Phi = m_defaultView.Phi;
+                m_camera.Rho = m_defaultView.Rho;
+                m_camera.Distance = m_defaultView.Distance;
+            }
+        }
+        /// <summary>
+        /// Move &amp; shrink/expand current view cube along a given line
+        /// </summary>
+        /// <param name="nearLineEnd"></param>
+        /// <param name="farLineEnd"></param>
+        /// <param name="offset"></param>
+        protected virtual void Zoom(ILPoint3Df nearLineEnd, ILPoint3Df farLineEnd, float offset) {
+            ILPoint3Df minCorner, maxCorner; 
+            m_clippingView.GetZoomParameter(nearLineEnd,farLineEnd,offset, out minCorner, out maxCorner);
+            Zoom(minCorner,maxCorner);
+            //m_camera.LookAt = m_clippingView.CenterF; 
+        }
+        /// <summary>
+        /// move the center of the viewing cube and expand / shrink the volume by offset
+        /// </summary>
+        /// <param name="center">new center</param>
+        /// <param name="offset">offset multiplicator, 1f means: no change</param>
+        protected virtual void Zoom(ILPoint3Df center, float offset) {
+            m_clippingView.Update(center,offset);
+            Refresh();
+        }
+        /// <summary>
+        /// Zoome the scene to new limits
+        /// </summary>
+        /// <param name="luCorner">'upper left' (first) corner of the new viewing cube</param>
+        /// <param name="rbCorner">'bottom right' (opposed) corner of the viewing cube</param>
+        protected virtual void Zoom(ILPoint3Df luCorner, ILPoint3Df rbCorner) {
+            if (m_zoomAction != null)
+                m_zoomAction.Cancel();
+            ILActionRamp ramp;
+            switch (m_zoomMode) {
+                case ZoomModes.Jump:
+                    ramp = ILActionRamp.NoRamp; 
+                    break;
+                case ZoomModes.RollSoft:
+                    ramp = ILActionRamp.Soft; 
+                    break;
+                case ZoomModes.RollHard:
+                    ramp = ILActionRamp.Hard; 
+                    break;
+                case ZoomModes.RollOverride:
+                    ramp = ILActionRamp.Override; 
+                    break;
+                default:
+                    ramp = ILActionRamp.Linear;
+                    break;
+            }
+            m_zoomAction = new ILZoomAction(m_clippingView.Min, luCorner, m_clippingView.Max, rbCorner, ramp, this);
+            m_zoomAction.Run();
+        }
+
+
+        /// <summary>
+        /// Transform two coordinates for a line from world to screen coordinates
+        /// </summary>
+        /// <param name="start">1st coordinate (world)</param>
+        /// <param name="end">2nd coordinate (world)</param>
+        /// <param name="start2D">[output] 1st coordinate (screen pixels)</param>
+        /// <param name="end2D">[output] 2nd coordinate (screen pixels)</param>
+        /// <remarks>This function is provided by the concrete derived class, using the
+        /// current rendering framework.</remarks>
+        public abstract void World2Screen(ILPoint3Df start, ILPoint3Df end, out Point start2D, out Point end2D);
+
+        /// <summary>
+        /// Transform from a point on screen into world coordinates [depricated]
+        /// </summary>
+        /// <param name="x">screen x</param>
+        /// <param name="y">screen y: GL viewport coord! -> (0,0) is lower left corner!</param>
+        /// <returns>world coordinate point</returns>
+        public abstract ILPoint3Df Screen2World2D(int x, int y);
+        /// <summary>
+        /// gives the line in world coords, a specific point on screen lays on
+        /// </summary>
+        /// <param name="x">screen x</param>
+        /// <param name="y">screen y: GL viewport coord! -> (0,0) is lower left corner</param>
+        /// <param name="farClip">far end point of the resulting line in world coords</param>
+        /// <param name="nearClip">near end point of the resulting line in world coords</param>
+        public abstract void Screen2World(int x, int y, out ILPoint3Df nearClip, out ILPoint3Df farClip); 
+        
+        /// <summary>
+        /// Transform world coordinate to screen coordinate under current transformation
+        /// </summary>
+        /// <param name="worldPoint">world coordinate</param>
+        /// <returns>screen location</returns>
+        /// <remarks>the actual transform is carried out in the derived specialized class,
+        /// where the current transformation matrices are known</remarks>
+        public abstract Point World2Screen(ILPoint3Df worldPoint);
+        /// <summary>
+        /// Transform world coordinate to screen coordinate, provide (custom) modelview matrix
+        /// </summary>
+        /// <param name="worldPoint"></param>
+        /// <param name="modelview">(custom) model view matrix. The parameter must match the format required by the deriving concrete ILPanel class. ILOGLPanel: double[16]</param>
+        /// <returns>screen location</returns>
+        /// <remarks>the actual transform is carried out in the derived specialized class,
+        /// where the current transformation matrices are known</remarks>
+        public abstract Point World2Screen(ILPoint3Df worldPoint, double[] modelview); 
+
+        /// <summary>
+        /// Draws content of this subfigure into predefined bitmap
+        /// </summary>
+        /// <param name="bitmap">predefined bitmap to draw content into. The size must have been initialized according to 'bounds'.</param>
+        /// <param name="bounds">Rectangle specifying the region to be copied.</param>
+        public new abstract void DrawToBitmap(Bitmap bitmap, Rectangle bounds); 
+        #endregion
+
+        #region helper functions 
+        /// <summary>
+        /// draws the selection rectangle with GDI functions
+        /// </summary>
+        /// <param name="endPoint">end point</param>
+        /// <remarks>The start point is stored in the member m_mouseStart.</remarks>
+        protected virtual void drawSelectionRect(Point endPoint) {
+            Graphics g = Graphics.FromHwnd(this.Handle);
+            Pen pen = new Pen(m_selectionRectangle.Color, 1.0f);
+            Point[] points = new Point[3];
+            // upper left corner
+            points[0] = new Point(m_mouseStart.X, m_mouseStart.Y + (endPoint.Y - m_mouseStart.Y) / 4);
+            points[1] = new Point(m_mouseStart.X, m_mouseStart.Y);
+            points[2] = new Point(m_mouseStart.X + (endPoint.X - m_mouseStart.X) / 4, m_mouseStart.Y);
+            g.DrawLines(pen, points);
+            // lower left corner 
+            points[0] = new Point(m_mouseStart.X, endPoint.Y - (endPoint.Y - m_mouseStart.Y) / 4);
+            points[1] = new Point(m_mouseStart.X, endPoint.Y);
+            points[2] = new Point(m_mouseStart.X + (endPoint.X - m_mouseStart.X) / 4, endPoint.Y);
+            g.DrawLines(pen, points);
+            // lower right corner 
+            points[0] = new Point(endPoint.X, endPoint.Y - (endPoint.Y - m_mouseStart.Y) / 4);
+            points[1] = new Point(endPoint.X, endPoint.Y);
+            points[2] = new Point(endPoint.X - (endPoint.X - m_mouseStart.X) / 4, endPoint.Y);
+            g.DrawLines(pen, points);
+            // upper right corner 
+            points[0] = new Point(endPoint.X, m_mouseStart.Y + (endPoint.Y - m_mouseStart.Y) / 4);
+            points[1] = new Point(endPoint.X, m_mouseStart.Y);
+            points[2] = new Point(endPoint.X - (endPoint.X - m_mouseStart.X) / 4, m_mouseStart.Y);
+            g.DrawLines(pen, points);
+        }
+        public static short StippleFromLineStyle(LineStyle style, ref int stipFactr) {
+            short ret = 1; 
+            switch (style) {
+                case LineStyle.Dashed:
+                    ret = (short)255;
+                    stipFactr = 2;
+                    break;
+                case LineStyle.PointDash:
+                    ret = (short)255 + 4096;
+                    stipFactr = 1;
+                    break;
+                case LineStyle.Dotted:
+                    ret = (short)13107; // 3 + 48 + 768 + 8192 + 4096;
+                    stipFactr = 2;
+                    break;
+                case LineStyle.UserPattern:
+                    break;
+                    // ret = 0; 
+                case LineStyle.None:
+                    break;
+                default:      // solid
+                    ret = (short)-1;
+                    break;
+            }
+            return ret; 
+        }
+        private void calculateDefaultView(bool setPositions, bool setDirection) {
+            m_defaultView.EventingSuspend();
+            if (setPositions) {
+                m_defaultView.LookAt = m_graphs.Limits.CenterF;
+                m_defaultView.Distance = m_clippingView.SphereRadius * 2f;
+            }
+            if (setDirection) {
+                m_defaultView.Phi = 0; // -(float)Math.PI / 2;
+                m_defaultView.Rho = 0;
+            }
+            m_defaultView.EventingResume(false);
+        }
+        #endregion
+
+        #region private rendering setup helper
+        protected void helperUpdateMatrices(float width2D, float height2D, out float worldSceneWidth, out float worldSceneHeight, out ILPoint3Df top, out ILPoint3Df moveOffset)
+        {
+            float localPlotCubeScreenRectLeft;
+            float localPlotCubeScreenRectWidth;
+
+            float localPlotCubeScreenRectTop;
+            float localPlotCubeScreenRectHeight;
+
+            float offsetX;
+            float offsetY;
+
+            localPlotCubeScreenRectHeight = m_plotBoxScreenRectF.Height;
+            localPlotCubeScreenRectWidth = m_plotBoxScreenRectF.Width;
+            localPlotCubeScreenRectTop = m_plotBoxScreenRectF.Top;
+            localPlotCubeScreenRectLeft = m_plotBoxScreenRectF.Left;
+
+            if (AspectRatio == AspectRatioMode.StretchToFill)
+            {
+                worldSceneWidth = width2D / localPlotCubeScreenRectWidth;
+                worldSceneHeight = height2D / localPlotCubeScreenRectHeight;
+            }
+            else
+            { //if (RenderAspectRatioMode == RenderAspectRatioMode.MaintainRatios) {
+                float plotCubeScreenRectAspectRatio =
+                    (m_plotBoxScreenRectF.Width * ClientSize.Width)
+                    / (m_plotBoxScreenRectF.Height * ClientSize.Height);
+                float dataAspectRatio = width2D / height2D;
+                if (plotCubeScreenRectAspectRatio > dataAspectRatio)
+                {
+                    // width > height
+                    worldSceneHeight = height2D;
+                    worldSceneWidth = worldSceneHeight * dataAspectRatio;
+                    // enlarge the scene, so we have rendering margin outside the data cube
+                    worldSceneHeight /= localPlotCubeScreenRectHeight;
+                    worldSceneWidth /= (localPlotCubeScreenRectWidth * (dataAspectRatio / plotCubeScreenRectAspectRatio));
+                }
+                else
+                {
+                    // height >= width
+                    worldSceneWidth = width2D;
+                    worldSceneHeight = worldSceneWidth / dataAspectRatio;
+                    // enlarge the scene, so we have rendering margin outside the data cube
+                    worldSceneWidth /= localPlotCubeScreenRectWidth;
+                    worldSceneHeight /= (localPlotCubeScreenRectHeight / (dataAspectRatio / plotCubeScreenRectAspectRatio));
+                }
+            }
+            // one more pixel please...
+            worldSceneHeight = (worldSceneHeight / ClientSize.Height * (ClientSize.Height + 1));
+            worldSceneWidth = (worldSceneWidth / ClientSize.Width * (ClientSize.Width + 1));
+            // if PlotCubeScreenRect is not centered, we move the scene out of center accordingly (..further down)
+            top = new ILPoint3Df(-m_camera.SinPhi * m_camera.CosRho, m_camera.CosPhi * m_camera.CosRho, m_camera.SinRho);
+            ILPoint3Df moveX = ILPoint3Df.crossN(m_camera.Position - m_camera.LookAt, top);
+            offsetX = -(localPlotCubeScreenRectLeft + (localPlotCubeScreenRectWidth / 2f) - 0.5f) * worldSceneWidth;
+            offsetY = -(localPlotCubeScreenRectTop + (localPlotCubeScreenRectHeight / 2f) - 0.5f) * worldSceneHeight;
+            moveOffset = top * offsetY + moveX * offsetX;
+        }
+        protected virtual void RenderScene(ILRenderProperties p) {
+            //System.Diagnostics.Debug.Print("m_camera:{0}", m_camera); 
+            if (!DesignMode) {
+                lock (m_sortingCacheList) {
+                    iRenderingState1(p); //make current 
+                    // configure axes (determine tick labels in mode 'auto')
+                    m_axes.XAxis.Configure(p);
+                    m_axes.YAxis.Configure(p);
+                    m_axes.ZAxis.Configure(p);
+
+
+                    //computeLayoutData(p);
+                    float rotatedViewLimitX, rotatedViewLimitY, rotatedViewLimitZ;
+                    GetTransformedSize(out rotatedViewLimitX, out rotatedViewLimitY, out rotatedViewLimitZ);
+
+                    // determine needed margins according to current tic label collections (which are left over from last rendering run or empty) 
+                    Size ticLabelsMargins = GetMaxTicLabelSize(p.Graphics);
+                    updatePlotCubeScreenRect(rotatedViewLimitX, rotatedViewLimitY, ticLabelsMargins);
+                    p.PassCount = 0;
+                    for (; p.PassCount < MAXRENDERPASSES; p.PassCount++) {
+                        UpdateMatrices(rotatedViewLimitX, rotatedViewLimitY, rotatedViewLimitZ);
+
+                        updateTickLabelLines();
+                        updateLabelPositions(p);
+                        if (p.PassCount == 0) {
+                        }
+                        iRenderingState2(p);  // do the actual drawing
+                        //iRenderingState3(p); 
+                        #region check if we can fit the plot cube more precisely
+                        if (m_plotBoxScreenSizeMode == PlotBoxScreenSizeMode.StrictOptimal) {
+                            float t = m_plotBoxScreenRectF.Top;
+                            float l = m_plotBoxScreenRectF.Left;
+                            float r = m_plotBoxScreenRectF.Right;
+                            float b = m_plotBoxScreenRectF.Bottom, tmp;
+                            bool resize = false;
+                            tmp = (float)p.MinX / ClientSize.Width;
+                            if (tmp < l) {
+                                if (p.MinX != 0) {
+                                    l -= tmp;
+                                    resize = true;
+                                }
+                            } else if (l > 0) {
+                                l = 0;
+                                resize = true;
+                            }
+                            tmp = (float)p.MaxX / ClientSize.Width;
+                            if (tmp > r) {
+                                if (p.MaxX != (ClientSize.Width - 1)) {
+                                    r += (1 - tmp);
+                                    resize = true;
+                                }
+                            } else if (r < 1) {
+                                r = (float)(ClientSize.Width - 1) / ClientSize.Width;
+                                resize = true;
+                            }
+                            tmp = (float)p.MinY / ClientSize.Height;
+                            if (tmp < t) {
+                                if (p.MinY != 0) {
+                                    t -= tmp;
+                                    resize = true;
+                                }
+                            } else if (t > 0) {
+                                t = 0;
+                                resize = true;
+                            }
+                            tmp = (float)p.MaxY / ClientSize.Height;
+                            if (tmp > b) {
+                                if (p.MaxY != (ClientSize.Height - 1)) {
+                                    b += (1 - tmp);
+                                    resize = true;
+                                }
+                            } else if (b < 1) {
+                                b = (float)(ClientSize.Height - 1) / ClientSize.Height;
+                                resize = true;
+                            }
+                            if (resize) {
+                                // ... there is still room left we can use for enlarging the render cube
+                                m_plotBoxScreenRectF = new RectangleF(l, t, r - l, b - t);
+                                p.Reason = RenderReason.RecalcLabels;
+                                p.MaxY = int.MinValue;
+                                p.MaxX = int.MinValue;
+                                p.MinY = int.MaxValue;
+                                p.MinX = int.MaxValue;
+                            }
+                            continue;
+                        }
+                        #endregion
+                        break;
+                    }
+                    iRenderingState3(p);
+                }
+
+            }
+        }
+        protected abstract void iRenderingState1(ILRenderProperties p); 
+        /// <summary>
+        /// [internal] Configure this panel, to make it ready for output, set "m_ready = true" at end!
+        /// </summary>
+        protected virtual void Configure() {
+            foreach (ILGraph graph in m_graphs) {
+                graph.Configure();
+            }
+            // update clipping view 
+            m_clipplanes[0] = -1.0; m_clipplanes[3] = m_clippingView.Max.X;
+            m_clipplanes[4] = 1.0; m_clipplanes[7] = -m_clippingView.Min.X;
+            m_clipplanes[9] = -1.0; m_clipplanes[11] = m_clippingView.Max.Y;
+            m_clipplanes[13] = 1.0; m_clipplanes[15] = -m_clippingView.Min.Y;
+            m_clipplanes[18] = -1.0; m_clipplanes[19] = m_clippingView.Max.Z;
+            m_clipplanes[22] = 1.0; m_clipplanes[23] = -m_clippingView.Min.Z;
+
+            m_ready = true;
+        }
+        /// <summary>
+        /// draw the scene: all axes, graphs, background etc. (device dependant)
+        /// </summary>
+        /// <param name="p"></param>
+        protected abstract void iRenderingState2(ILRenderProperties p);
+        protected abstract void iRenderingState3(ILRenderProperties p);
+        protected abstract void UpdateMatrices(float width2D, float height2D, float depth2D);
+        /// <summary>
+        /// initialize all device specific classes, first called after the panel has been created
+        /// </summary>
+        /// <remarks>derived types should init all devices here</remarks>
+        protected virtual void Initialize() { }
+        protected PointF GetXTickLabelLine(out Point start2D, out Point end2D) {
+            PointF anchor = new PointF(0,0); // TickLabelAlign.left;
+            ILPoint3Df start = new ILPoint3Df(), end = new ILPoint3Df();
+            ILTickCollection ticks = m_axes[0].LabeledTicks;
+            float tickLen = (ticks.Direction == TickDirection.Outside) ?
+                             ticks.TickFraction : 0f;
+            float padX = ticks.Padding, padY = padX;
+            switch (m_camera.Quadrant) {
+                case CameraQuadrant.TopLeftFront:
+                    start.X = m_clippingView.Min.X;
+                    start.Y = m_clippingView.Min.Y - tickLen;
+                    start.Z = m_clippingView.Min.Z;
+                    end.X = m_clippingView.Max.X;
+                    end.Y = start.Y;
+                    end.Z = start.Z;
+                    anchor = new PointF(0,0); //TickLabelAlign.left | TickLabelAlign.top;
+                    padX = -m_camera.SinPhi * padX;
+                    padY = (m_camera.CosPhi - m_camera.SinRho * m_camera.SinPhi) * (padY) + m_camera.SinPhi * ticks.Font.Height / 2;
+                    break;
+                case CameraQuadrant.TopLeftBack:
+                    start.X = m_clippingView.Min.X;
+                    start.Y = m_clippingView.Max.Y + tickLen;
+                    start.Z = m_clippingView.Min.Z;
+                    end.X = m_clippingView.Max.X;
+                    end.Y = start.Y;
+                    end.Z = start.Z;
+                    anchor = new PointF(1,0); //TickLabelAlign.right | TickLabelAlign.top;
+                    padX *= m_camera.SinPhi;
+                    padY = (-m_camera.CosPhi - m_camera.SinRho * m_camera.SinPhi) * padY + m_camera.SinPhi * ticks.Font.Height / 2;
+                    break;
+                case CameraQuadrant.TopRightBack:
+                    start.X = m_clippingView.Min.X;
+                    start.Y = m_clippingView.Max.Y + tickLen;
+                    start.Z = m_clippingView.Min.Z;
+                    end.X = m_clippingView.Max.X;
+                    end.Y = start.Y;
+                    end.Z = start.Z;
+                    anchor = new PointF(0,0); //TickLabelAlign.left | TickLabelAlign.top;
+                    padX *= m_camera.SinPhi;
+                    padY = (-m_camera.CosPhi + m_camera.SinRho * m_camera.SinPhi) * padY - m_camera.SinPhi * ticks.Font.Height / 2;
+                    break;
+                case CameraQuadrant.TopRightFront:
+                    start.X = m_clippingView.Min.X;
+                    start.Y = m_clippingView.Min.Y - tickLen;
+                    start.Z = m_clippingView.Min.Z;
+                    end.X = m_clippingView.Max.X;
+                    end.Y = start.Y;
+                    end.Z = start.Z;
+                    if (m_camera.Is2DView) {
+                        anchor = new PointF(.5f, 0); //TickLabelAlign.center | TickLabelAlign.top;
+                    } else {
+                        anchor = new PointF(1,0); //TickLabelAlign.right | TickLabelAlign.top;
+                    }
+                    padX *= -m_camera.SinPhi;
+                    padY = (m_camera.CosPhi + m_camera.SinRho * m_camera.SinPhi) * padY - m_camera.SinPhi * ticks.Font.Height / 2;
+                    break;
+                case CameraQuadrant.BottomLeftFront:
+                    start.X = m_clippingView.Min.X;
+                    start.Y = m_clippingView.Max.Y + tickLen;
+                    start.Z = m_clippingView.Min.Z;
+                    end.X = m_clippingView.Max.X;
+                    end.Y = start.Y;
+                    end.Z = start.Z;
+                    anchor = new PointF(1,0); //TickLabelAlign.right | TickLabelAlign.top;
+                    padX *= m_camera.SinPhi;
+                    padY = (m_camera.CosPhi - m_camera.SinRho * m_camera.SinPhi) * padY + m_camera.SinPhi * ticks.Font.Height / 2;
+                    break;
+                case CameraQuadrant.BottomLeftBack:
+                    start.X = m_clippingView.Min.X;
+                    start.Y = m_clippingView.Min.Y - tickLen;
+                    start.Z = m_clippingView.Min.Z;
+                    end.X = m_clippingView.Max.X;
+                    end.Y = start.Y;
+                    end.Z = start.Z;
+                    anchor = new PointF(0,0); //TickLabelAlign.left | TickLabelAlign.top;
+                    padX *= -m_camera.SinPhi;
+                    padY = (-m_camera.CosPhi - m_camera.SinRho * m_camera.SinPhi) * padY + m_camera.SinPhi * ticks.Font.Height / 2;
+                    break;
+                case CameraQuadrant.BottomRightBack:
+                    start.X = m_clippingView.Min.X;
+                    start.Y = m_clippingView.Min.Y - tickLen;
+                    start.Z = m_clippingView.Min.Z;
+                    end.X = m_clippingView.Max.X;
+                    end.Y = start.Y;
+                    end.Z = start.Z;
+                    anchor = new PointF(1,0); //TickLabelAlign.right | TickLabelAlign.top;
+                    padX *= -m_camera.SinPhi;
+                    padY = (-m_camera.CosPhi + m_camera.SinRho * m_camera.SinPhi) * padY - m_camera.SinPhi * ticks.Font.Height / 2;
+                    break;
+                default:    // BottomRightFront
+                    start.X = m_clippingView.Min.X;
+                    start.Y = m_clippingView.Max.Y + tickLen;
+                    start.Z = m_clippingView.Min.Z;
+                    end.X = m_clippingView.Max.X;
+                    end.Y = start.Y;
+                    end.Z = start.Z;
+                    anchor = new PointF(0,0); //TickLabelAlign.left | TickLabelAlign.top;
+                    padX *= m_camera.SinPhi;
+                    padY = (m_camera.CosPhi + m_camera.SinRho * m_camera.SinPhi) * padY - m_camera.SinPhi * ticks.Font.Height / 2;
+                    break;
+            }
+            World2Screen(start, end, out start2D, out end2D);
+            // align in screen coords 
+//            int offY = (int)((m_camera.SinRho - (m_camera.SinPhi % Math.PI))
+//                        * m_axes[0].LabeledTicks.Font.Height / 2
+//                        + padY);
+            // add padding 
+            //System.Diagnostics.Debug.WriteLine(m_camera.Phi); 
+            start2D.Y += (int)padY + 1;
+            end2D.Y += (int)padY + 1;
+            start2D.X += (int)(padX + 1);
+            end2D.X += (int)(padX + 1);
+            return anchor;
+        }
+        protected PointF GetYTickLabelLine(out Point start2D, out Point end2D) {
+            PointF anchor; // = new PointF(0,0); // TickLabelAlign.left;
+            ILPoint3Df start = new ILPoint3Df(), end = new ILPoint3Df();
+            ILTickCollection ticks = m_axes[1].LabeledTicks;
+            float tickLen = (ticks.Direction == TickDirection.Outside) ?
+                ticks.TickFraction : 0f;
+            float padX = ticks.Padding, padY = padX;
+            if (m_camera.Is2DView) {
+                start.X = m_clippingView.Min.X - tickLen;
+                start.Y = m_clippingView.Min.Y;
+                start.Z = m_clippingView.Min.Z;
+                end.X = start.X;
+                end.Y = m_clippingView.Max.Y;
+                end.Z = start.Z;
+                anchor = new PointF(1, 0); // TickLabelAlign.right | TickLabelAlign.top;
+                padX *= -m_camera.CosPhi;
+                padY = (-m_camera.SinPhi + m_camera.SinRho * m_camera.CosPhi) * padY - m_camera.CosPhi * ticks.Font.Height / 2;
+            } else {
+                switch (m_camera.Quadrant) {
+                    case CameraQuadrant.TopLeftFront:
+                        start.X = m_clippingView.Min.X - tickLen;
+                        start.Y = m_clippingView.Min.Y;
+                        start.Z = m_clippingView.Min.Z;
+                        end.X = start.X;
+                        end.Y = m_clippingView.Max.Y;
+                        end.Z = start.Z;
+                        anchor = new PointF(1, 0); // TickLabelAlign.right | TickLabelAlign.top;
+                        padX *= -m_camera.CosPhi;
+                        padY = (-m_camera.SinPhi + m_camera.SinRho * m_camera.CosPhi) * padY - m_camera.CosPhi * ticks.Font.Height / 2;
+                        break;
+                    case CameraQuadrant.TopLeftBack:
+                        start.X = m_clippingView.Min.X - tickLen;
+                        start.Y = m_clippingView.Min.Y;
+                        start.Z = m_clippingView.Min.Z;
+                        end.X = start.X;
+                        end.Y = m_clippingView.Max.Y;
+                        end.Z = start.Z;
+                        anchor = new PointF(0, 0); // TickLabelAlign.left | TickLabelAlign.top;
+                        padX *= -m_camera.CosPhi;
+                        padY = (-m_camera.SinPhi - m_camera.SinRho * m_camera.CosPhi) * padY + m_camera.CosPhi * ticks.Font.Height / 2;
+                        break;
+                    case CameraQuadrant.TopRightBack:
+                        start.X = m_clippingView.Max.X + tickLen;
+                        start.Y = m_clippingView.Min.Y;
+                        start.Z = m_clippingView.Min.Z;
+                        end.X = start.X;
+                        end.Y = m_clippingView.Max.Y;
+                        end.Z = start.Z;
+                        anchor = new PointF(1,0); // TickLabelAlign.right | TickLabelAlign.top;
+                        padX *= m_camera.CosPhi;
+                        padY = (m_camera.SinPhi - m_camera.SinRho * m_camera.CosPhi) * padY + m_camera.CosPhi * ticks.Font.Height / 2;
+                        break;
+                    case CameraQuadrant.TopRightFront:
+                        start.X = m_clippingView.Max.X + tickLen;
+                        start.Y = m_clippingView.Min.Y;
+                        start.Z = m_clippingView.Min.Z;
+                        end.X = start.X;
+                        end.Y = m_clippingView.Max.Y;
+                        end.Z = start.Z;
+                        anchor = new PointF(0,0); // TickLabelAlign.left | TickLabelAlign.top;
+                        padX *= m_camera.CosPhi;
+                        padY = (m_camera.SinPhi + m_camera.SinRho * m_camera.CosPhi) * padY - m_camera.CosPhi * ticks.Font.Height / 2;
+                        break;
+                    case CameraQuadrant.BottomLeftFront:
+                        start.X = m_clippingView.Max.X + tickLen;
+                        start.Y = m_clippingView.Min.Y;
+                        start.Z = m_clippingView.Min.Z;
+                        end.X = start.X;
+                        end.Y = m_clippingView.Max.Y;
+                        end.Z = start.Z;
+                        anchor = new PointF(0,0); //  TickLabelAlign.left | TickLabelAlign.top;
+                        padX *= m_camera.CosPhi;
+                        padY = (-m_camera.SinPhi + m_camera.SinRho * m_camera.CosPhi) * padY - m_camera.CosPhi * ticks.Font.Height / 2;
+                        break;
+                    case CameraQuadrant.BottomLeftBack:
+                        start.X = m_clippingView.Max.X + tickLen;
+                        start.Y = m_clippingView.Min.Y;
+                        start.Z = m_clippingView.Min.Z;
+                        end.X = start.X;
+                        end.Y = m_clippingView.Max.Y;
+                        end.Z = start.Z;
+                        anchor = new PointF(1,0); // TickLabelAlign.right | TickLabelAlign.top;
+                        padX *= m_camera.CosPhi;
+                        padY = (-m_camera.SinPhi - m_camera.SinRho * m_camera.CosPhi) * padY + m_camera.CosPhi * ticks.Font.Height / 2;
+                        break;
+                    case CameraQuadrant.BottomRightBack:
+                        start.X = m_clippingView.Min.X - tickLen;
+                        start.Y = m_clippingView.Min.Y;
+                        start.Z = m_clippingView.Min.Z;
+                        end.X = start.X;
+                        end.Y = m_clippingView.Max.Y;
+                        end.Z = start.Z;
+                        anchor = new PointF(0,0); // TickLabelAlign.left | TickLabelAlign.top;
+                        padX *= -m_camera.CosPhi;
+                        padY = (m_camera.SinPhi - m_camera.SinRho * m_camera.CosPhi) * padY + m_camera.CosPhi * ticks.Font.Height / 2;
+                        break;
+                    default:    // BottomRightFront
+                        start.X = m_clippingView.Min.X - tickLen;
+                        start.Y = m_clippingView.Min.Y;
+                        start.Z = m_clippingView.Min.Z;
+                        end.X = start.X;
+                        end.Y = m_clippingView.Max.Y;
+                        end.Z = start.Z;
+                        anchor = new PointF(1,0); // TickLabelAlign.right | TickLabelAlign.top;
+                        padX *= -m_camera.CosPhi;
+                        padY = (m_camera.SinPhi + m_camera.SinRho * m_camera.CosPhi) * padY - m_camera.CosPhi * ticks.Font.Height / 2;
+                        break;
+                }
+            }
+            World2Screen(start, end, out start2D, out end2D);
+            // align in screen coords 
+            //int offY = (int)(Math.Abs(m_camera.CosPhi) * ticks.Font.Height / 2);
+            //offY -= (int)(Math.Sin(m_camera.Rho) * ticks.Font.Height / 2); 
+            start2D.Y += (int)padY;
+            end2D.Y += (int)padY;
+            start2D.X += (int)padX;
+            end2D.X += (int)padX;
+            return anchor;
+        }
+        protected PointF GetZTickLabelLine(out Point start2D, out Point end2D) {
+            PointF anchor = new PointF(1, .5f); // TickLabelAlign.vertCenter | TickLabelAlign.right;
+            ILPoint3Df start = new ILPoint3Df(), end = new ILPoint3Df();
+            ILTickCollection ticks = m_axes[2].LabeledTicks;
+            float tickLen = 0;
+            if (ticks.Direction == TickDirection.Outside)
+                tickLen = ticks.TickFraction;
+            start.Z = m_clippingView.Min.Z;
+            switch (m_camera.Quadrant) {
+                case CameraQuadrant.TopLeftFront:
+                    start.X = m_clippingView.Min.X - tickLen;
+                    start.Y = m_clippingView.Max.Y + tickLen;
+                    break;
+                case CameraQuadrant.TopLeftBack:
+                    start.X = m_clippingView.Max.X + tickLen;
+                    start.Y = m_clippingView.Max.Y + tickLen;
+                    break;
+                case CameraQuadrant.TopRightBack:
+                    start.X = m_clippingView.Max.X + tickLen;
+                    start.Y = m_clippingView.Min.Y - tickLen;
+                    break;
+                case CameraQuadrant.TopRightFront:
+                    start.X = m_clippingView.Min.X - tickLen;
+                    start.Y = m_clippingView.Min.Y - tickLen;
+                    break;
+                case CameraQuadrant.BottomLeftFront:
+                    start.X = m_clippingView.Min.X - tickLen;
+                    start.Y = m_clippingView.Max.Y + tickLen;
+                    break;
+                case CameraQuadrant.BottomLeftBack:
+                    start.X = m_clippingView.Max.X + tickLen;
+                    start.Y = m_clippingView.Max.Y + tickLen;
+                    break;
+                case CameraQuadrant.BottomRightBack:
+                    start.X = m_clippingView.Max.X + tickLen;
+                    start.Y = m_clippingView.Min.Y - tickLen;
+                    break;
+                case CameraQuadrant.BottomRightFront:
+                    start.X = m_clippingView.Min.X - tickLen;
+                    start.Y = m_clippingView.Min.Y - tickLen;
+                    break;
+                default:
+                    break;
+            }
+            end = start;
+            end.Z = m_clippingView.Max.Z;
+            World2Screen(start, end, out start2D, out end2D);
+            start2D.X -= (ticks.Padding - 1);
+            end2D.X -= (ticks.Padding - 1);
+            return anchor;
+        }
+        /// <summary>
+        /// Get size of projected view cube - after (!) rotation but before projection -> world space
+        /// includes the bounding box, tightly enclosing the current view limits setting 
+        /// No labels, No ticks included!! Just the data cube with roatation!
+        /// </summary>
+        /// <param name="x">out, screen size for X</param>
+        /// <param name="y">out, screen size for Y</param>
+        /// <param name="z">out, screen size for Z</param>
+        protected virtual void GetTransformedSize(out float x, out float y, out float z) {
+            float xSize = m_clippingView.WidthF;   // the unrotated width - without labels size
+            float ySize = m_clippingView.HeightF;  // dito for height
+            float zSize = m_clippingView.DepthF;
+            if (m_camera.Rho != 0.0f || m_camera.Phi != 0.0f) { // standard 2D view?
+                float cosPhi = Math.Abs(m_camera.CosPhi);
+                float sinPhi = Math.Abs(m_camera.SinPhi);
+                x = (cosPhi * xSize + sinPhi * ySize); //zSize * Math.Abs(m_camera.SinRho) + (Math.Abs(m_camera.CosRho) * 
+                y = zSize * Math.Abs(m_camera.SinRho)
+                          + (Math.Abs(m_camera.CosRho) * (sinPhi * xSize + cosPhi * ySize));
+                z = zSize * Math.Abs(m_camera.CosRho)
+                          + (Math.Abs(m_camera.SinRho) * (sinPhi * xSize + cosPhi * ySize));
+            } else {
+                x = xSize;
+                y = ySize;
+                z = zSize;
+            }
+        }
+
+        private void axisLabelVertical2D(ILAxis axis) {
+            ILLabel label = axis.Label;
+            ILTickCollection ticks = axis.LabeledTicks;
+            Size tickSize = ticks.Size, labelSize = label.Size;
+            label.Orientation = TextOrientation.Vertical;
+            label.Anchor = new PointF(.5f, 0); 
+            label.m_position.X = ticks.m_lineEnd.X - tickSize.Width - ticks.Padding - label.Padding;
+            switch (label.Alignment) {
+                case LabelAlign.Center:
+                    label.m_position.Y = (ticks.m_lineEnd.Y + ticks.m_lineStart.Y) / 2;
+                    break;
+                case LabelAlign.Upper:
+                    label.m_position.Y = ticks.m_lineEnd.Y + labelSize.Width / 2;
+                    break;
+                default:        // lower 
+                    label.m_position.Y = ticks.m_lineStart.Y - labelSize.Width / 2;
+                    break;
+            }
+            if (label.m_position.Y < labelSize.Width / 2) {
+                label.m_position.Y = labelSize.Width / 2;
+            }
+            if (label.m_position.Y > ClientSize.Height - 1 - labelSize.Width / 2) {
+                label.m_position.Y = ClientSize.Height - 1 - labelSize.Width / 2;
+            }
+        }
+        private void positionZAxisLabel(ILAxis axis) {
+            ILLabel label = axis.Label;
+            ILTickCollection ticks = axis.LabeledTicks;
+            Size tickSize = ticks.Size, labelSize = label.Size;
+            label.Orientation = TextOrientation.Vertical;
+            label.Anchor = new PointF(.5f, 0); 
+            switch (label.Alignment) {
+                case LabelAlign.Center:
+                    label.m_position.Y = (ticks.m_lineStart.Y + ticks.m_lineEnd.Y) / 2;
+                    break;
+                case LabelAlign.Upper:
+                    label.m_position.Y = ticks.m_lineEnd.Y - labelSize.Width / 2;
+                    break;
+                default:        // lower 
+                    label.m_position.Y = ticks.m_lineStart.Y + labelSize.Width / 2 ;
+                    break;
+            }
+            label.m_position.X = ticks.m_lineStart.X - tickSize.Width - ticks.Padding - label.Padding;
+            if (label.m_position.Y < labelSize.Width / 2) {
+                label.m_position.Y = labelSize.Width / 2; 
+            }
+            if (label.m_position.Y > ClientSize.Height - 1 - labelSize.Width / 2) {
+                label.m_position.Y = ClientSize.Height - 1 - labelSize.Width / 2;
+                //label.Orientation = TextOrientation.Horizontal;
+                //label.m_position.X = label.Padding;
+                //label.m_position.Y = label.Padding;
+            }
+        }
+        private void axisLabel_BottomRightTopLeft(ILRenderProperties p, ILAxis axis) {
+            ILLabel label = axis.Label;
+            ILTickCollection ticks = axis.LabeledTicks;
+            Size tickSize = ticks.Size, labelSize = label.Size;
+            label.Anchor = new PointF(.5f, 0);
+            bool horiz = decideLabelHorizontalOrientation(p, m_camera, axis);
+            if (horiz) {
+                #region Horizontal
+                label.Orientation = TextOrientation.Horizontal;
+                switch (label.Alignment) {
+                    case LabelAlign.Center:
+                        label.m_position.X = (ticks.m_lineStart.X + ticks.m_lineEnd.X) / 2;
+                        break;
+                    case LabelAlign.Upper:
+                        label.m_position.X = ticks.m_lineEnd.X + labelSize.Width / 2;
+                        break;
+                    default:        // lower 
+                        label.m_position.X = ticks.m_lineStart.X - labelSize.Width / 2;
+                        break;
+                }
+                label.m_position.Y = ticks.m_lineStart.Y + tickSize.Height + ticks.Padding + label.Padding;
+                if (label.m_position.X < labelSize.Width / 2) {
+                    label.m_position.X = labelSize.Width / 2; 
+                }
+                #endregion
+            } else {
+                #region Vertical
+                label.Orientation = TextOrientation.Vertical; 
+                switch (label.Alignment) {
+                    case LabelAlign.Center:
+                        label.m_position.Y = (ticks.m_lineStart.Y + ticks.m_lineEnd.Y) / 2;
+                        break;
+                    case LabelAlign.Upper:
+                        label.m_position.Y = ticks.m_lineEnd.Y + labelSize.Width / 2;
+                        break;
+                    default:        // lower 
+                        label.m_position.Y = ticks.m_lineStart.Y - labelSize.Width / 2;
+                        break;
+                }
+                label.m_position.X = ticks.m_lineEnd.X - tickSize.Width - label.Padding - ticks.Padding;
+                if (label.m_position.Y < labelSize.Width / 2)
+                    label.m_position.Y = labelSize.Width / 2;
+                if (label.m_position.Y > ClientSize.Height - 1 - labelSize.Width / 2) {
+                    label.m_position.Y = ClientSize.Height - 1 - labelSize.Width / 2;
+                }
+                #endregion
+            }
+        }
+        private void axisLabel_BottomLeftTopRight(ILRenderProperties p,  ILAxis axis) {
+            ILLabel label = axis.Label;
+            ILTickCollection ticks = axis.LabeledTicks;
+            Size tickSize = ticks.Size, labelSize = label.Size;
+            bool horiz = decideLabelHorizontalOrientation(p, m_camera, axis);
+            if (horiz) {
+                #region Horizontal
+                label.Orientation = TextOrientation.Horizontal;
+                label.Anchor = new PointF(0.5f,0); 
+                switch (label.Alignment) {
+                    case LabelAlign.Center:
+                        label.m_position.X = (ticks.m_lineEnd.X + ticks.m_lineStart.X) / 2;
+                        break;
+                    case LabelAlign.Upper:
+                        label.m_position.X = ticks.m_lineEnd.X - label.Size.Width / 2;
+                        break;
+                    default:        // lower 
+                        label.m_position.X = ticks.m_lineStart.X + label.Size.Width / 2;
+                        break;
+                }
+                label.m_position.Y = ticks.m_lineStart.Y + tickSize.Height + ticks.Padding + label.Padding;
+                if (label.m_position.X > ClientSize.Width - labelSize.Width / 2) {
+                    label.m_position.X = ClientSize.Width - labelSize.Width / 2;
+                }
+                #endregion
+            } else {
+                #region Vertical
+                label.Orientation = TextOrientation.Vertical;
+                label.Anchor = new PointF(0.5f, 1);
+                switch (label.Alignment) {
+                    case LabelAlign.Center:
+                        label.m_position.Y = (ticks.m_lineEnd.Y + ticks.m_lineStart.Y) / 2;
+                        break;
+                    case LabelAlign.Upper:
+                        label.m_position.Y = ticks.m_lineEnd.Y + labelSize.Width / 2;
+                        break;
+                    default:        // lower 
+                        label.m_position.Y = ticks.m_lineStart.Y - labelSize.Width / 2;
+                        break;
+                }
+                label.m_position.X = ticks.m_lineEnd.X + tickSize.Width + ticks.Padding + label.Padding;
+                if (label.m_position.Y > ClientSize.Height - 1 - labelSize.Width / 2) {
+                    label.m_position.Y = ClientSize.Height - 1 - labelSize.Width / 2;
+                }
+                #endregion
+            }
+        }
+        private void axisLabel_TopRightBottomLeft(ILRenderProperties p, ILAxis axis) {
+            ILLabel label = axis.Label;
+            ILTickCollection ticks = axis.LabeledTicks;
+            Size tickSize = ticks.Size, labelSize = label.Size;
+            bool horiz = decideLabelHorizontalOrientation(p, m_camera, axis);
+            label.Anchor = new PointF(.5f, 0); 
+            if (horiz) {
+                #region Horizontal
+                label.Orientation = TextOrientation.Horizontal;
+                switch (label.Alignment) {
+                    case LabelAlign.Center:
+                        label.m_position.X = (ticks.m_lineEnd.X + ticks.m_lineStart.X) / 2;
+                        break;
+                    case LabelAlign.Upper:
+                        label.m_position.X = ticks.m_lineEnd.X + labelSize.Width / 2;
+                        break;
+                    default:        // lower 
+                        label.m_position.X = ticks.m_lineStart.X - labelSize.Width / 2;
+                        break;
+                }
+                label.m_position.Y = ticks.m_lineEnd.Y + tickSize.Height + ticks.Padding + label.Padding;
+                if (label.m_position.X < labelSize.Width / 2)
+                    label.m_position.X = labelSize.Width / 2; 
+                if (label.m_position.X > ClientSize.Width - labelSize.Width / 2 - 1)
+                    label.m_position.X = ClientSize.Width - labelSize.Width / 2 - 1; 
+                #endregion
+            } else {
+                #region Vertical 
+                label.Orientation = TextOrientation.Vertical; 
+                switch (label.Alignment) {
+                    case LabelAlign.Center:
+                        label.m_position.Y = (ticks.m_lineEnd.Y + ticks.m_lineStart.Y) / 2;
+                        break;
+                    case LabelAlign.Upper:
+                        label.m_position.Y = ticks.m_lineEnd.Y - labelSize.Width / 2;
+                        break;
+                    default:        // lower 
+                        label.m_position.Y = ticks.m_lineStart.Y + labelSize.Width / 2; 
+                        break;
+                }
+                label.m_position.X = ticks.m_lineStart.X + tickSize.Width + ticks.Padding + label.Padding;
+                if (label.m_position.Y < labelSize.Width / 2) {
+                    label.m_position.Y = labelSize.Width / 2;
+                }
+                if (label.m_position.Y > ClientSize.Height - 1 - labelSize.Width  / 2) {
+                    label.m_position.Y = ClientSize.Height - 1 - labelSize.Width  / 2;
+                }
+                #endregion
+            }
+        }
+        private void axisLabel_TopLeftBottomRight(ILRenderProperties p, ILAxis axis) {
+            ILLabel label = axis.Label;
+            ILTickCollection ticks = axis.LabeledTicks;
+            Size tickSize = ticks.Size, labelSize = label.Size;
+            bool horiz = decideLabelHorizontalOrientation(p, m_camera, axis);
+            label.Anchor = new PointF(.5f, 0); 
+            if (horiz) {
+                #region Horizontal
+                label.Orientation = TextOrientation.Horizontal;
+                switch (label.Alignment) {
+                    case LabelAlign.Center:
+                        label.m_position.X = (ticks.m_lineEnd.X + ticks.m_lineStart.X) / 2;
+                        break;
+                    case LabelAlign.Upper:
+                        label.m_position.X = ticks.m_lineEnd.X - labelSize.Width / 2;
+                        break;
+                    default:        // lower 
+                        label.m_position.X = ticks.m_lineStart.X + labelSize.Width / 2;
+                        break;
+                }
+                label.m_position.Y = ticks.m_lineEnd.Y + tickSize.Height + ticks.Padding + label.Padding;
+                if (label.m_position.X < labelSize.Width / 2) {
+                    label.m_position.X = labelSize.Width / 2;
+                }
+                #endregion
+            } else {
+                #region Vertical
+                label.Orientation = TextOrientation.Vertical;
+                switch (label.Alignment) {
+                    case LabelAlign.Center:
+                        label.m_position.Y = (ticks.m_lineEnd.Y + ticks.m_lineStart.Y) / 2;
+                        break;
+                    case LabelAlign.Upper:
+                        label.m_position.Y = ticks.m_lineEnd.Y - labelSize.Width / 2;
+                        break;
+                    default:        // lower 
+                        label.m_position.Y = ticks.m_lineStart.Y + labelSize.Width / 2;
+                        break;
+                }
+                label.m_position.X = ticks.m_lineStart.X - tickSize.Width - ticks.Padding - label.Padding;
+                if (label.m_position.Y < labelSize.Width / 2) {
+                    label.m_position.Y = labelSize.Width / 2;
+                }
+                if (label.m_position.Y > ClientSize.Height - 1 - labelSize.Width / 2) {
+                    label.m_position.Y = ClientSize.Height - 1 - labelSize.Width / 2;
+                }
+                #endregion
+            }
+        }
+
+        // return true if the label needs horizontal orientation
+        private bool decideLabelHorizontalOrientation(ILRenderProperties p, ILCamera m_camera, ILAxis axis) {
+            if (p.Reason == RenderReason.RecalcLabels) {
+                return axis.Label.Orientation == TextOrientation.Horizontal; 
+            }
+            float offX = axis.LabeledTicks.m_lineStart.X - axis.LabeledTicks.m_lineEnd.X;
+            float offY = axis.LabeledTicks.m_lineStart.Y - axis.LabeledTicks.m_lineEnd.Y;
+            return offY * offY < offX * offX;  
+            //if (axis.Index == 0) {
+            //    b = (float)((1.0 - m_camera.SinRho * 0.9) * Math.Sin(m_camera.Phi * 2.0f)); 
+            //} else if (axis.Index == 1) {
+
+            //}
+            //return (m_camera.SinRho >= LABELS_VERTICAL_MIN_RHO
+            //    || Math.Sign(Math.Cos(m_camera.Phi * 2.0)) != (axis.Index * 2 - 1));
+        }
+        private int GetMargin4OptimalLabelX() {
+            return 0; 
+        }
+        private int GetMargin4OptimalLabelY() {
+            return 0;
+        }
+        private Size GetMaxTicLabelSize(Graphics gr) {
+            Size ret = m_axes.MeasureMaxTickLabelSize(gr);    
+            // add label sizes 
+            int maxHeight = 0; 
+            if (m_axes[0].Label.Visible && !String.IsNullOrEmpty(m_axes[0].Label.Text)) {
+                maxHeight = m_axes[0].Label.Size.Height;
+            }
+            if (m_axes[1].Label.Visible && !String.IsNullOrEmpty(m_axes[1].Label.Text)) {
+                if (maxHeight < m_axes[1].Label.Size.Height)
+                    maxHeight = m_axes[1].Label.Size.Height;
+            }
+            if (m_axes[2].Label.Visible && !String.IsNullOrEmpty(m_axes[2].Label.Text)) {
+                if (maxHeight < m_axes[2].Label.Size.Height)
+                    maxHeight = m_axes[2].Label.Size.Height;
+            }
+            ret = new Size(ret.Width + maxHeight, ret.Height + maxHeight); 
+            return ret; 
+        }
+
+        /// <summary>
+        /// calculate the real pixels of the plot cube rectangle for drawing into
+        /// </summary>
+        /// <param name="xSize"></param>
+        /// <param name="ySize"></param>
+        private void updatePlotCubeScreenRect(float xSize, float ySize, Size tickLabelMargins) {
+            switch (PlotBoxScreenSizeMode) {
+                //case PlotCubeScreenSizeMode.Maximum: // <- will be done in PlotCubeScreenSizeMode.set()
+                //    m_plotCubeScreenRectF = new RectangleF(0.0f, 0.0f, 1.0f, 1.0f); 
+                //    break;
+                case PlotBoxScreenSizeMode.Optimal:
+                case PlotBoxScreenSizeMode.StrictOptimal:
+                    float saveX, saveY;
+                    saveX = ((float)tickLabelMargins.Width / ClientSize.Width);
+                    if (saveX < 0) saveX = 0;
+                    if (saveX > 1) saveX = 1;
+                    saveY = ((float)tickLabelMargins.Height / ClientSize.Height);
+                    if (saveY < 0) saveY = 0;
+                    if (saveY > 1) saveY = 1; 
+                    m_plotBoxScreenRectF = new RectangleF(saveX, saveY, 1f - (2 * saveX), 1f - (2 * saveY));
+                    break;
+                default: // manual: use predefined PlotCubeScreenRectF
+                    break;
+            }
+        }
+
+        private void updateLabelPositions(ILRenderProperties p) {
+            positionZAxisLabel(m_axes[2]);
+            switch (m_camera.Quadrant) {
+                case CameraQuadrant.TopRightFront:
+                    axisLabel_TopLeftBottomRight(p, m_axes[0]);
+                    // special case: 2D view? 
+                    if (m_camera.SinPhi < 1e-5 && m_camera.SinRho < 1e-5) {
+                        axisLabelVertical2D(m_axes[1]);
+                    } else {
+                        axisLabel_BottomLeftTopRight(p, m_axes[1]);
+                    }
+                    break;
+                case CameraQuadrant.TopRightBack:
+                    axisLabel_TopRightBottomLeft(p, m_axes[0]);
+                    axisLabel_TopLeftBottomRight(p, m_axes[1]);
+                    break;
+                case CameraQuadrant.TopLeftFront:
+                    axisLabel_BottomLeftTopRight(p, m_axes[0]);
+                    axisLabel_BottomRightTopLeft(p, m_axes[1]);
+                    break;
+                case CameraQuadrant.TopLeftBack:
+                    axisLabel_BottomRightTopLeft(p, m_axes[0]);
+                    axisLabel_TopRightBottomLeft(p, m_axes[1]);
+                    break;
+                case CameraQuadrant.BottomLeftFront:
+                    axisLabel_TopLeftBottomRight(p, m_axes[0]);
+                    axisLabel_TopRightBottomLeft(p, m_axes[1]);
+                    break;
+                case CameraQuadrant.BottomLeftBack:
+                    axisLabel_TopRightBottomLeft(p, m_axes[0]);
+                    axisLabel_BottomRightTopLeft(p, m_axes[1]);
+                    break;
+                case CameraQuadrant.BottomRightBack:
+                    axisLabel_BottomRightTopLeft(p, m_axes[0]);
+                    axisLabel_BottomLeftTopRight(p, m_axes[1]);
+                    break;
+                case CameraQuadrant.BottomRightFront:
+                    axisLabel_BottomLeftTopRight(p, m_axes[0]);
+                    axisLabel_TopLeftBottomRight(p, m_axes[1]);
+                    break;
+                default:
+                    break;
+            }
+        }
+
+        private void updateTickLabelLines() {
+            // determine tick label lines
+            ILTickCollection ticks = m_axes[2].LabeledTicks;
+            ticks.m_anchor = GetZTickLabelLine(out ticks.m_lineStart, out ticks.m_lineEnd);
+            ticks = m_axes[1].LabeledTicks;
+            ticks.m_anchor = GetYTickLabelLine(out ticks.m_lineStart, out ticks.m_lineEnd);
+            ticks = m_axes[0].LabeledTicks;
+            ticks.m_anchor = GetXTickLabelLine(out ticks.m_lineStart, out ticks.m_lineEnd);
+        }
+        #endregion
+
+        #region factory member
+
+        /// <summary>
+        /// create OpenGL panel 
+        /// </summary>
+        /// <returns>OpenGL panel</returns>
+        public static ILPanel Create () {
+            return Create(GraphicDeviceType.OpenGL); 
+        }
+        /// <summary>
+        /// create graphic device specific panel 
+        /// </summary>
+        /// <param name="type">specify GL type. Supported are: OpenGL (recommended) or Direct3D (alpha state)</param>
+        /// <returns>GL specific panel</returns>
+        public static ILPanel Create (GraphicDeviceType type) {
+            ILPanel ret; Type panelType; Assembly assembly; 
+            string myPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); 
+            switch (type) {
+                case GraphicDeviceType.Direct3D:
+                    //must create DXPanel dynamically ? 
+                    // actually not, because DX is split into individual assembly
+                    // but under mono it seems the runtime tries to load the d3d part 
+                    // anyway, so we do without a compile time reference.
+                    assembly = Assembly.LoadFile(Path.Combine(myPath,"ILNumerics.DrawingD3D.dll")); 
+                    panelType = assembly.GetType("ILNumerics.Drawing.Platform.OpenGL.ILDXPanel"); 
+                    ret = (ILPanel)panelType.InvokeMember("ILDXPanel", 
+                            BindingFlags.DeclaredOnly | BindingFlags.Public 
+                            | BindingFlags.NonPublic | BindingFlags.Instance 
+                            | BindingFlags.CreateInstance, 
+                            null, null, null);
+                    return ret; 
+                default:
+                    // the default is to use OpenGL, which is included into the main assembly (this one)
+                    assembly = Assembly.GetExecutingAssembly(); 
+                    panelType = assembly.GetType("ILNumerics.Drawing.Platform.OpenGL.ILOGLPanel"); 
+                    ret = (ILPanel)panelType.InvokeMember("ILOGLPanel", 
+                            BindingFlags.DeclaredOnly | BindingFlags.Public 
+                            | BindingFlags.NonPublic | BindingFlags.Instance 
+                            | BindingFlags.CreateInstance, 
+                            null, null, null);
+                    return ret; 
+            }
+        }
+
+        /// <summary>
+        /// Create GL dependend graph factory 
+        /// </summary>
+        /// <returns>ILGraphFactory,will be used for creating all graphs</returns>
+        /// <remarks>derived types may return GL dependend factory</remarks>
+        internal abstract IILCreationFactory GetCreationFactory(); 
+        #endregion
+
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Controls/ILSubfigure.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Controls/ILSubfigure.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Controls/ILSubfigure.cs	(revision 9102)
@@ -0,0 +1,322 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Windows.Forms; 
+using System.Drawing; 
+using System.Configuration; 
+using System.Reflection; 
+using ILNumerics.Algorithms; 
+using System.Diagnostics; 
+using System.IO; 
+
+namespace ILNumerics.Drawing {
+
+    /// <summary>
+    /// Plot control, provides ILPanel, colorbar and title
+    /// </summary>
+    public class ILSubfigure : UserControl {
+
+        #region attributes 
+        private ILPanel m_panel; 
+        private ILColorBar m_colorbar;
+        private ILBorderFitLabel m_title; 
+        private bool m_isInitializing; 
+        #endregion
+
+        #region properties
+        public override System.Drawing.Color BackColor {
+            get {
+                return base.BackColor;
+            }
+            set {
+                base.BackColor = value;
+                m_panel.BackColor = value; 
+            }
+        }
+        /// <summary>
+        /// Gives access to the panel of the figure
+        /// </summary>
+        public ILPanel Panel {
+            get {
+                return m_panel; 
+            }
+        }
+        /// <summary>
+        /// Gives access to the colorbar of the figure
+        /// </summary>
+        public ILColorBar ColorBar {
+            get {
+                return m_colorbar; 
+            }
+        }
+        /// <summary>
+        /// Gives the title control
+        /// </summary>
+        public ILBorderFitLabel Title {
+            get {
+                return m_title; 
+            }
+        }
+        #endregion
+
+        #region constructors 
+        public ILSubfigure () {
+            m_isInitializing = true; 
+            // setup trace listener 
+            string logfile = System.Configuration.ConfigurationManager.AppSettings["logfile"];
+            if (!String.IsNullOrEmpty(logfile)) {
+                File.Delete(logfile); 
+                DefaultTraceListener defTraceListener = new DefaultTraceListener();
+                Trace.Listeners.Add(defTraceListener); 
+                defTraceListener.LogFileName = logfile; 
+                Trace.WriteLine(String.Format("{0} - ILSubfigure.ctor()",DateTime.Now));
+            }
+            this.Dock = DockStyle.Fill; 
+            m_panel = ILPanel.Create(getDefaultDeviceType()); 
+            m_panel.DrawInactive = true; 
+            if (Trace.IndentLevel > 0) 
+                Trace.TraceInformation("{0} - ILSubfigure.ctor() - panel created {1}",DateTime.Now,m_panel.GraphicDeviceType);
+            m_colorbar = new ILColorBar(m_panel.Colormap); 
+            m_colorbar.RegisterRangeSource(m_panel.Graphs.Limits);
+            m_panel.ColormapChanged += new EventHandler(m_panel_ColormapChanged);
+            m_title = new ILBorderFitLabel();
+            m_panel.Graphs.CollectionChanged += new ILGraphCollectionChangedEvent(Graphs_CollectionChanged);
+            SetDefaults(); 
+            m_panel.Invalidate();
+            m_isInitializing = false; 
+        }
+
+        void m_panel_ColormapChanged(object sender, EventArgs e) {
+            m_colorbar.Colormap = m_panel.Colormap; 
+            m_colorbar.Invalidate(); 
+        }
+
+        void Graphs_CollectionChanged(object sender, ILGraphCollectionChangedEventArgs args) {
+            switch (args.Reason) {
+                case GraphCollectionChangeReason.Added:
+                    if (args.Graph.Type == GraphType.Plot2D) {
+                        m_colorbar.Visible = false; 
+                        m_panel.ClipViewData = true; 
+                    } else if (args.Graph.Type == GraphType.Surf) {
+                        m_colorbar.Visible = true; 
+                        m_panel.ClipViewData = false; 
+                    } else if (args.Graph.Type == GraphType.Imagesc) {
+                        m_colorbar.Visible = false; 
+                        m_panel.ClipViewData = false; 
+                    }
+                    break;
+                case GraphCollectionChangeReason.Deleted:
+                    break;
+                case GraphCollectionChangeReason.Changed:
+                    break;
+                default:
+                    break;
+            }
+
+        }
+        #endregion
+
+        #region overrides 
+        protected override void OnLayout(LayoutEventArgs e) {
+            if (m_isInitializing) return; 
+            base.OnLayout(e);
+#if TRACE             
+            Trace.TraceInformation("{0},{1} ILSubfigure.OnLayout(), m_isInitializing is false",DateTime.Now,Environment.TickCount); 
+#endif
+
+            layoutChilds(); 
+        }
+        protected override void OnLoad(EventArgs e) {
+            base.OnLoad(e);
+#if TRACE             
+            Trace.TraceInformation("{0},{1} ILSubfigure.OnLoad ",DateTime.Now,Environment.TickCount); 
+#endif
+            SuspendLayout(); 
+            Controls.Add(m_colorbar);
+            Controls.Add(m_title); 
+            Controls.Add(m_panel);
+#if TRACE             
+            Trace.TraceInformation("{0},{1} ILSubfigure.OnLoad ",DateTime.Now,Environment.TickCount); 
+#endif
+
+            ResumeLayout(); 
+            m_isInitializing = false; 
+            if (DesignMode) {
+#if TRACE             
+                Trace.TraceInformation("{0},{1} ILSubfigure.OnLoad: DesignMode detected",DateTime.Now,Environment.TickCount); 
+#endif
+                try {
+                    SetStyle(ControlStyles.Opaque, true);
+                    SetStyle(ControlStyles.ResizeRedraw, true);
+                    m_panel.Graphs.AddSurfGraph(ILMath.tosingle(ILSpecialData.sinc(14,20)));
+#if TRACE             
+                    Trace.TraceInformation("{0},{1} ILSubfigure.OnLoad:DesignMode: SurfGraph added",DateTime.Now,Environment.TickCount); 
+#else 
+                } catch (Exception) {
+#endif
+#if TRACE             
+                } catch (Exception exc) {
+                    Trace.TraceWarning("{0},{1} ILSubfigure.OnLoad:DesignMode: failure added surf graph: {2}",DateTime.Now,Environment.TickCount,exc.ToString()); 
+#endif
+                }
+            }
+            Invalidate(true);
+        }
+        protected void SetDefaults () {
+            BackColor = System.Drawing.Color.FromArgb(250,250,250); 
+            m_title.Text = "ILNumerics.Drawing Subfigure"; 
+            m_title.Visible = true; 
+            m_title.Dock = DockStyle.Top; 
+            m_title.BackColor = Color.White; 
+            m_title.ForeColor = Color.DarkBlue; 
+            m_colorbar.Dock = DockStyle.Left; 
+        }
+        /// <summary>
+        /// Draws content of this subfigure into predefined bitmap
+        /// </summary>
+        /// <param name="bitmap">predefined bitmap to draw content into. The size must have been initialized according to 'bounds'.</param>
+        /// <param name="bounds">Rectangle specifying the region to be copied.</param>
+        public virtual new void DrawToBitmap(Bitmap bitmap, Rectangle bounds) {
+            base.DrawToBitmap(bitmap,bounds);
+            Bitmap tmpbmp = new Bitmap(m_panel.Size.Width,m_panel.Size.Height); 
+            m_panel.DrawToBitmap(tmpbmp,new Rectangle(0,0,tmpbmp.Width,tmpbmp.Height)); 
+            // merge both bitmaps 
+            using (Graphics gr = Graphics.FromImage( bitmap )) {
+                gr.DrawImage(tmpbmp,m_panel.Location); 
+            }
+        }
+        #endregion
+
+        #region helper functions 
+        private GraphicDeviceType getDefaultDeviceType () {
+            GraphicDeviceType ret = GraphicDeviceType.OpenGL; 
+            // lets see, if a configuration for the app is found
+            string useD3D = ConfigurationManager.AppSettings["useDirect3D"];
+            if (String.IsNullOrEmpty(useD3D)) {
+                // look for an ILNumerics.Drawing.dll.config file and probe this for the setting
+                string path = Assembly.GetExecutingAssembly().GetModules()[0].FullyQualifiedName;
+                Configuration c = ConfigurationManager.OpenExeConfiguration(path);
+                KeyValueConfigurationElement kvelem = c.AppSettings.Settings["useDirect3D"];
+                if (kvelem != null) 
+                    useD3D = kvelem.Value; 
+            }
+
+            if (String.IsNullOrEmpty(useD3D)) 
+                return ret;
+            if (useD3D.Trim() == "1") {
+                switch (Environment.OSVersion.Platform) {
+                    case PlatformID.Unix:
+                        System.Diagnostics.Debug.WriteLine("The Direct3D device is not available on Unix platform! Switching to OpenGL."); 
+                        break;
+                    default:
+                        ret = GraphicDeviceType.Direct3D; 
+                        break;
+                }
+            }
+            return ret; 
+        }
+
+        private void layoutMovingDock(ref Rectangle crect, ILMovingDockPanel panel
+                                ,int width ,int height) {
+            panel.Visible = false;
+            switch (panel.Dock) {
+                case DockStyle.Bottom:
+                    panel.Height = height;
+                    panel.Width = crect.Width;
+                    panel.Top = crect.Top + crect.Height - panel.Height;
+                    panel.Left = crect.X;
+                    crect.Height -= panel.Height;
+                    break;
+                case DockStyle.Left:
+                    panel.Height = crect.Height;
+                    panel.Width = width;
+                    panel.Top = crect.Y;
+                    panel.Left = crect.X;
+                    crect.Width -= panel.Width;
+                    crect.X += panel.Width;
+                    break;
+                case DockStyle.None:
+                    //panel.Top = (int)(ClientSize.Height / 4); 
+                    //panel.Left = (int)(ClientSize.Width / 4);
+                    //panel.Width = width;
+                    //panel.Height = height;
+                    break;
+                case DockStyle.Right:
+                    panel.Width = width;
+                    panel.Height = crect.Height;
+                    panel.Top = crect.Y;
+                    panel.Left = crect.Left + crect.Width - panel.Width;
+                    crect.Width -= panel.Width;
+                    break;
+                case DockStyle.Top:
+                    panel.Height = height;
+                    panel.Width = crect.Width;
+                    panel.Top = crect.Y;
+                    panel.Left = crect.X;
+                    crect.Height -= panel.Height;
+                    crect.Y += panel.Height;
+                    break;
+                default:
+                    break;
+            }
+            panel.Visible = true;
+        }
+
+        private void layoutChilds() {
+            Rectangle crect = this.ClientRectangle;
+            if (m_title.Visible) {
+                layoutMovingDock(ref crect, m_title, m_title.Padding.Horizontal + m_title.Font.Height, m_title.Padding.Vertical + m_title.Font.Height);
+            }
+            if (m_colorbar.Visible) {
+                layoutMovingDock(ref crect, m_colorbar, 100, 40);
+            }
+
+            if (m_panel != null && crect.Width - Padding.Vertical > 2 && crect.Height - Padding.Horizontal > 2) {
+                m_panel.Location = crect.Location;
+                m_panel.Size = crect.Size;
+            }
+        }
+
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Controls/ILTextBoxAutoHide.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Controls/ILTextBoxAutoHide.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Controls/ILTextBoxAutoHide.cs	(revision 9102)
@@ -0,0 +1,80 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Windows.Forms; 
+
+namespace ILNumerics.Drawing {
+
+    public class ILTextBoxAutoHide : TextBox {
+
+        public event EventHandler Committing; 
+        protected void OnCommit() {
+            if (Committing != null) {
+                Committing(this,new EventArgs()); 
+            }
+        }
+
+        public ILTextBoxAutoHide () : base () {
+            BorderStyle = BorderStyle.None; 
+            TextAlign = HorizontalAlignment.Center; 
+        }
+        protected override void OnGotFocus(EventArgs e) {
+            base.OnGotFocus(e);
+            SelectAll(); 
+        }
+        
+        protected override void OnLostFocus(EventArgs e) {
+            base.OnLostFocus(e);
+            this.Hide(); 
+        }
+        protected override void OnKeyPress(KeyPressEventArgs e) {
+            base.OnKeyPress(e);
+            if (e.KeyChar == (char)Keys.Enter) { 
+                OnCommit(); 
+                Hide();
+            } else if (e.KeyChar == (char)Keys.Escape) {
+                Hide();     
+            }
+
+        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Graphs/ILFilledGraph.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Graphs/ILFilledGraph.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Graphs/ILFilledGraph.cs	(revision 9102)
@@ -0,0 +1,637 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+#pragma warning disable 1591
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Exceptions; 
+using ILNumerics.Drawing.Misc; 
+using ILNumerics.Misc;  
+
+namespace ILNumerics.Drawing.Graphs {
+    /// <summary>
+    /// Class representing abstract implementation of filled graphs
+    /// </summary>
+    public abstract class ILFilledGraph : ILGraph {
+    
+        #region attributes / properties 
+        protected float[] m_xCoords; 
+        protected float[] m_yCoords; 
+        protected ILArray<float> m_colors = ILMath.returnType<float>();
+        protected ILArray<float> m_sourceArray = ILMath.returnType<float>(); 
+        protected int m_Vertcount;
+        protected int m_rows, m_cols;  
+        protected bool m_vertexReady, m_indexReady;
+        protected uint[] m_indices; 
+        protected uint[] m_gridIndices; 
+        protected int m_gridIndicesCount; 
+        protected int m_indicesCount;
+        protected int m_oldSubQuadrant; 
+        protected int m_stripesCount; 
+        protected int m_stripesLen; 
+        protected int m_gridStripsLen; 
+        protected int m_gridStripsLenOnce; 
+        protected int m_gridStripsCount; 
+        protected bool m_shadeVertexDirectionLowHigh = false; 
+        protected static readonly float MAXHUEVALUE = Misc.ILColorProvider.MAXHUEVALUE;
+        protected static readonly float CAMERA_ANG_OFFSET = - (float)(Math.PI / 4);  
+        // visible properties
+        protected float m_opacity;
+        protected bool m_filled; 
+        protected ILLineProperties m_wireLines; 
+        /// <summary>
+        /// Wireframe line properties
+        /// </summary>
+        public ILLineProperties Wireframe {
+            get {
+                return m_wireLines; 
+            }
+        }
+
+        /// <summary>
+        /// Get / set the transparency for the graph (percent)
+        /// </summary>
+        /// <remarks>1.0f (opaque) ... 0.0f (transparent)</remarks>
+        public float Opacity {
+            get {
+                return m_opacity;
+            }
+            set {
+                m_opacity = value; 
+                Invalidate(); 
+                OnChanged("Opacity"); 
+            }
+        }
+        /// <summary>
+        /// Determine, if the tiles (rectangle areas between data points) 
+        /// constructing the surface will be filled or invisible
+        /// </summary>
+        public bool Filled {
+            get {
+                return m_filled; 
+            }
+            set {
+                m_filled = value;
+                OnChanged("Filled"); 
+            }
+        }
+        /// <summary>
+        ///  get a reference to the internal data array
+        /// </summary>
+        /// <remarks>modifications to the array returned will 
+        /// <b>not</b> alter the data the graph is based on.</remarks>
+        public ILRetArray<float> Data {
+            get {
+                return m_sourceArray.C; 
+            }
+        }
+        #endregion
+
+        #region constructor
+        /// <summary>
+        /// construct new filled graph
+        /// </summary>
+        /// <param name="panel">panel hosting the graph</param>
+        /// <param name="X">X coords, if null, range 0..[cols of Z] will be created</param>
+        /// <param name="Y">Y coords, if null, range 0..[rows of Z] will be created</param>
+        /// <param name="Z">Z coords (heights)</param>
+        /// <param name="C">Colors for Z</param>
+        /// <param name="clippingContainer">gloabal limits of panel</param>
+        public ILFilledGraph(ILPanel panel, ILArray<float> X, ILArray<float> Y,
+                              ILArray<float> Z, ILArray<float> C, ILClippingData clippingContainer)
+            : base(panel, clippingContainer) {
+            using (ILScope.Enter(X, Y, Z, C)) {
+                #region argument checking
+                m_localClipping.EventingSuspend();
+                if (Z == null || !Z.IsMatrix)
+                    throw new ILArgumentException("ILFilledGraph: Z must be matrix!");
+                if (!Z.IsNumeric)
+                    throw new ILArgumentException("ILFilledGraph: Z must be numeric!");
+                m_sourceArray.a = ILMath.tosingle(Z);
+                m_rows = m_sourceArray.Size[0];
+                m_cols = m_sourceArray.Size[1];
+                ILArray<float> tmp;
+                if (!object.Equals(X, null) && !X.IsEmpty) {
+                    if (!X.IsMatrix || !X.IsNumeric) {
+                        throw new ILArgumentException("ILFilledGraph: X must be numeric matrix!");
+                    }
+                    if (X.Size.IsSameSize(Z.Size)) {
+                        tmp = ILMath.tosingle(X);
+                        tmp.ExportValues(ref m_xCoords);
+                        m_localClipping.XMax = tmp.MaxValue;
+                        m_localClipping.XMin = tmp.MinValue;
+                    } else {
+                        throw new ILArgumentException("ILFilledGraph: X must be of same size than Z!");
+                    }
+                } else {
+                    ILMath.tosingle(ILMath.repmat(ILMath.counter(0.0, 1.0, 1, m_cols), m_rows, 1)).ExportValues(ref m_xCoords);
+                    m_localClipping.XMin = 0;
+                    m_localClipping.XMax = m_cols - 1;
+                }
+                if (!object.Equals(Y, null) && !Y.IsEmpty) {
+                    if (!Y.IsMatrix || !Y.IsNumeric) {
+                        throw new ILArgumentException("ILFilledGraph: Y must be numeric matrix!");
+                    }
+                    if (Y.Size.IsSameSize(Z.Size)) {
+                        tmp = ILMath.tosingle(Y);
+                        tmp.ExportValues(ref m_yCoords);
+                        m_localClipping.YMax = tmp.MaxValue;
+                        m_localClipping.YMin = tmp.MinValue;
+                    } else {
+                        throw new ILArgumentException("ILFilledGraph: Y must be same size than Z!");
+                    }
+                } else {
+                    ILMath.tosingle(ILMath.repmat(ILMath.counter(0.0, 1.0, m_rows, 1), 1, m_cols)).ExportValues(ref m_yCoords);
+                    m_localClipping.YMax = m_rows - 1;
+                    m_localClipping.YMin = 0;
+                }
+                if (object.Equals(C, null) || C.IsEmpty) {
+                    m_colors.a = ILMath.empty<float>();
+                } else {
+                    m_colors.a = ILMath.tosingle(C);
+                }
+                m_localClipping.ZMax = m_sourceArray.MaxValue;
+                m_localClipping.ZMin = m_sourceArray.MinValue;
+                #endregion
+                m_Vertcount = m_rows * m_cols;
+                m_vertexReady = false;
+                m_indexReady = false;
+                // default view properties
+                m_opacity = 1.0f;
+                m_wireLines = new ILLineProperties();
+                m_wireLines.Changed += new EventHandler(m_wireLines_Changed);
+                m_filled = true;
+                m_localClipping.EventingResume();
+            }
+        }
+        #endregion
+
+        #region protected/private helper
+                
+        protected virtual void CreateVertices() {}
+        
+        /// <summary>
+        /// Create indices for filled graphs
+        /// </summary>
+        /// <remarks>Indices will be ordered to assemble individual triangles.</remarks>
+        protected virtual void CreateIndices() {
+            #region interpolate shading faster, less exact (obsolete)
+            //if (m_panel.Camera.CosPhiShift  > 0) {
+            //    if (m_panel.Camera.SinPhiShift > 0) {
+            //        System.Diagnostics.Debug.WriteLine("CosPhi > 0 & SinPhi > 0 (front)");
+            //        // looking from front
+            //        checkVertexIndicesLength(m_cols * 2, m_rows-1);
+            //        if (m_panel.Camera.LooksFromLeft) {
+            //            pos1 = m_Vertcount-1; pos2 = pos1 - m_cols;
+            //            for (int r = m_rows-1; r --> 0;) {
+            //                for (int c = m_cols; c--> 0;) {
+            //                    m_indices[posI++] = (uint)pos1--; 
+            //                    m_indices[posI++] = (uint)pos2--; 
+            //                }
+            //            }
+            //        } else {
+            //            // looks from right
+            //            pos1 = m_Vertcount-m_cols; pos2 = pos1 - m_cols;
+            //            for (int r = m_rows-1; r --> 0;) {
+            //                for (int c = m_cols; c--> 0;) {
+            //                    m_indices[posI++] = (uint)pos2++; 
+            //                    m_indices[posI++] = (uint)pos1++; 
+            //                }
+            //                pos1 -= (m_cols * 2); 
+            //                pos2 -= (m_cols * 2); 
+            //            }
+            //        }
+            //    } else {
+            //        System.Diagnostics.Debug.WriteLine("CosPhi > 0 & SinPhi < 0 (left)"); 
+            //        // looking from left
+            //        checkVertexIndicesLength(m_rows * 2, m_cols-1);
+            //        pos1 = m_Vertcount-1; pos2 = m_Vertcount-2;
+            //        for (int c = m_cols-1; c --> 0;) {
+            //            for (int r = m_rows; r --> 0;) {
+            //                m_indices[posI++] = (uint)pos1; 
+            //                m_indices[posI++] = (uint)pos2; 
+            //                pos1 -= m_cols; 
+            //                pos2 -= m_cols; 
+            //            }
+            //            pos1 += (m_Vertcount-1); 
+            //            pos2 = pos1-1; 
+            //        }
+            //    }
+            //} else {
+            //    if (m_panel.Camera.SinPhiShift > 0) {
+            //        // looking from right
+            //        System.Diagnostics.Debug.WriteLine("CosPhi < 0 & SinPhi > 0 (right)"); 
+            //        checkVertexIndicesLength(m_rows * 2, m_cols-1);
+            //        pos1 = m_Vertcount-1; pos2 = m_Vertcount-2;
+            //        for (int c = m_cols-1; c --> 0;) {
+            //            for (int r = m_rows-1; r --> 0;) {
+            //                m_indices[posI++] = (uint)pos1; 
+            //                m_indices[posI++] = (uint)pos2; 
+            //                pos1 -= m_cols; 
+            //                pos2 -= m_cols; 
+            //            }
+            //            pos1 += m_Vertcount; 
+            //            pos2 += m_Vertcount; 
+            //        }
+            //    } else {
+            //        // looking from back
+            //        System.Diagnostics.Debug.WriteLine("CosPhi < 0 & SinPhi < 0 (back)"); 
+            //        checkVertexIndicesLength(m_cols * 2, m_rows-1);
+            //        pos1 = m_cols-1; pos2 = pos1+m_cols;
+            //        for (int r = m_rows-1; r-->0;) {
+            //            for (int c = m_cols; c-->0;) {
+            //                m_indices[posI++] = (uint)pos2--; 
+            //                m_indices[posI++] = (uint)pos1--; 
+            //            }                  
+            //            pos1 += m_cols*2; 
+            //            pos2 += m_cols*2; 
+            //        }
+            //    }
+            //} 
+            //
+            #endregion
+            #region both shading modes WITH transparency, draws individual triangles 
+            // DrawMode "trianglestrips" will not work here! -> 
+            // We must specify each triangle seperately!
+            // Also we must divide the whole camera angle range in 8 (!) areas 
+            // and handle each individually by different index arrays. 
+            // This all is more exact but less performant ...
+            int pos1,pos2,posI = 0;
+            if (m_panel.Camera.CosPhiShift > 0) {
+                if (m_panel.Camera.SinPhiShift > 0) {
+                    #region looking from front
+                    //System.Diagnostics.Debug.WriteLine("CosPhi > 0 & SinPhi > 0 (front)");
+                    checkVertexIndicesLength((m_cols - 1) * 6,m_rows-1);
+                    if (m_panel.Camera.LooksFromLeft) {
+                        m_oldSubQuadrant = 7; 
+                        pos1 = m_Vertcount-1; pos2 = pos1-m_cols;
+                        for (int r = m_rows-1; r --> 0; ) {
+                            for (int c = m_cols-1; c-->0;) {
+                                m_indices[posI++] = (uint)pos1-1; 
+                                m_indices[posI++] = (uint)pos2-1; 
+                                m_indices[posI++] = (uint)pos1; 
+                                m_indices[posI++] = (uint)pos2--; 
+                                m_indices[posI++] = (uint)pos2; 
+                                m_indices[posI++] = (uint)pos1--; 
+                            }
+                            pos1--; 
+                            pos2--; 
+                        }
+                    } else {
+                        m_oldSubQuadrant = 0; 
+                        pos1 = m_Vertcount-2*m_cols; pos2 = m_Vertcount-m_cols;
+                        for (int r = m_rows-1; r --> 0; ) {
+                            for (int c = m_cols-1; c-->0;) {
+                                m_indices[posI++] = (uint)pos2++; 
+                                m_indices[posI++] = (uint)pos1; 
+                                m_indices[posI++] = (uint)pos2; 
+                                m_indices[posI++] = (uint)pos1+1; 
+                                m_indices[posI++] = (uint)pos1++; 
+                                m_indices[posI++] = (uint)pos2; 
+                            }
+                            pos1 -= (m_cols * 2 - 1); 
+                            pos2 -= (m_cols * 2 - 1); 
+                        }
+                    }
+                    #endregion
+                } else {
+                    #region looking from left 
+                    //System.Diagnostics.Debug.WriteLine("CosPhi > 0 & SinPhi < 0 (left)"); 
+                    checkVertexIndicesLength((m_rows - 1) * 6,m_cols-1);
+                    if (m_panel.Camera.LooksFromFront) {
+                        m_oldSubQuadrant = 6; 
+                        pos1 = m_Vertcount-2; pos2 = pos1 + 1;
+                        for (int r = m_cols-1; r --> 0; ) {
+                            for (int c = m_rows-1; c-->0;) {
+                                m_indices[posI++] = (uint)(pos2-m_cols); 
+                                m_indices[posI++] = (uint)(pos1-m_cols); 
+                                m_indices[posI++] = (uint)pos2; 
+                                m_indices[posI++] = (uint)pos1; pos1 -= m_cols; 
+                                m_indices[posI++] = (uint)pos1;
+                                m_indices[posI++] = (uint)pos2; pos2 -= m_cols; 
+                            }
+                            pos1 += (m_Vertcount - m_cols - 1); 
+                            pos2 += (m_Vertcount - m_cols - 1); 
+                        }
+                    } else {
+                        m_oldSubQuadrant = 5; 
+                        pos1 = m_cols-2; pos2 = pos1 + 1;
+                        for (int r = m_cols-1; r --> 0; ) {
+                            for (int c = m_rows-1; c-->0;) {
+                                m_indices[posI++] = (uint)pos1; 
+                                m_indices[posI++] = (uint)pos2; pos2 += m_cols;  
+                                m_indices[posI++] = (uint)pos2;
+                                m_indices[posI++] = (uint)pos1; pos1 += m_cols; 
+                                m_indices[posI++] = (uint)pos1; 
+                                m_indices[posI++] = (uint)pos2; 
+                            }
+                            pos1 -= (m_Vertcount - m_cols + 1); 
+                            pos2 -= (m_Vertcount - m_cols + 1);
+                        }
+                    }
+                    #endregion
+                }
+            } else {
+                if (m_panel.Camera.SinPhiShift > 0) {
+                    #region looking from right
+                    checkVertexIndicesLength((m_rows - 1) * 6,m_cols-1);
+                    //System.Diagnostics.Debug.WriteLine("CosPhi < 0 & SinPhi > 0 (right)");
+                    if (m_panel.Camera.LooksFromFront) {
+                        m_oldSubQuadrant = 1; 
+                        pos1 = m_Vertcount-m_cols; pos2 = pos1+1;
+                        for (int r = m_cols-1; r --> 0; ) {
+                            for (int c = m_rows-1; c-->0;) {
+                                m_indices[posI++] = (uint)pos1; pos1 -= m_cols; 
+                                m_indices[posI++] = (uint)pos1; 
+                                m_indices[posI++] = (uint)pos2; 
+                                m_indices[posI++] = (uint)pos1; 
+                                m_indices[posI++] = (uint)(pos2-m_cols);
+                                m_indices[posI++] = (uint)pos2; pos2 -= m_cols; 
+                            }
+                            pos1 += (m_Vertcount - m_cols + 1); 
+                            pos2 += (m_Vertcount - m_cols + 1);
+                        }
+                    } else {
+                        m_oldSubQuadrant = 2; 
+                        pos1 = 0; pos2 = 1;
+                        for (int r = m_cols-1; r --> 0; ) {
+                            for (int c = m_rows-1; c-->0;) {
+                                m_indices[posI++] = (uint)pos1; 
+                                m_indices[posI++] = (uint)(pos1+m_cols); 
+                                m_indices[posI++] = (uint)(pos2+m_cols); 
+                                m_indices[posI++] = (uint)pos1; pos1 += m_cols; 
+                                m_indices[posI++] = (uint)pos2; pos2 += m_cols; 
+                                m_indices[posI++] = (uint)pos2; 
+                            }
+                            pos1 -= (m_Vertcount - m_cols - 1); 
+                            pos2 -= (m_Vertcount - m_cols - 1);
+                        }
+                    }
+                    #endregion
+                } else {
+                    #region looking from back
+                    //System.Diagnostics.Debug.WriteLine("CosPhi < 0 & SinPhi < 0 (back)"); 
+                    checkVertexIndicesLength((m_cols - 1) * 6,m_rows-1);
+                    if (m_panel.Camera.LooksFromLeft) {
+                        m_oldSubQuadrant = 4; 
+                        pos1 = m_cols-1; pos2 = pos1+m_cols;
+                        for (int r = m_rows-1; r --> 0; ) {
+                            for (int c = m_cols-1; c-->0;) {
+                                m_indices[posI++] = (uint)pos1--; 
+                                m_indices[posI++] = (uint)pos1; 
+                                m_indices[posI++] = (uint)pos2; 
+                                m_indices[posI++] = (uint)pos2-1; 
+                                m_indices[posI++] = (uint)pos1; 
+                                m_indices[posI++] = (uint)pos2--; 
+                            }
+                            pos1 += (2*m_cols-1); 
+                            pos2 += (2*m_cols-1); 
+                        }
+                    } else {
+                        m_oldSubQuadrant = 3; 
+                        pos1 = 0; pos2 = pos1+m_cols;
+                        for (int r = m_rows-1; r --> 0; ) {
+                            for (int c = m_cols-1; c-->0;) {
+                                m_indices[posI++] = (uint)pos1; 
+                                m_indices[posI++] = (uint)pos1+1; 
+                                m_indices[posI++] = (uint)pos2+1; 
+                                m_indices[posI++] = (uint)pos1++; 
+                                m_indices[posI++] = (uint)pos2++; 
+                                m_indices[posI++] = (uint)pos2; 
+                            }
+                            pos1 ++; 
+                            pos2 ++; 
+                        }
+                    }
+                    #endregion
+                }
+            } 
+            #endregion
+            if (m_wireLines.Visible) {
+                #region create grid line indices
+                posI = 0; 
+                if (m_panel.Camera.CosPhiShift > 0) {
+                    if (m_panel.Camera.SinPhiShift > 0) {
+                        #region looking from front
+                        //System.Diagnostics.Debug.WriteLine("CosPhi > 0 & SinPhi > 0 (front)");
+                        checkGridIndicesLength((m_cols-1) * 4 + 2,m_rows-1); 
+                        pos1 = m_Vertcount-m_cols; 
+                        pos2 = m_Vertcount-m_cols;
+                        // first row is special:
+                        for (int c = m_cols-1; c-->0;) {
+                            m_gridIndices[posI++] = (uint)pos1++; 
+                            m_gridIndices[posI++] = (uint)pos1; 
+                        }
+                        pos1 -= 2*m_cols-1; 
+                        for (int r = m_rows-1; r-->0;) {
+                            // first column is special: 
+                            m_gridIndices[posI++] = (uint)pos1; 
+                            m_gridIndices[posI++] = (uint)pos2; 
+                            for (int c = m_cols-1; c-->0;) {
+                                m_gridIndices[posI++] = (uint)pos1++; 
+                                m_gridIndices[posI++] = (uint)pos1; 
+                                m_gridIndices[posI++] = (uint)pos1; 
+                                m_gridIndices[posI++] = (uint)++pos2; 
+                            }
+                            pos1 -= (m_cols * 2 - 1); 
+                            pos2 -= (m_cols * 2 - 1);
+                        }
+                        #endregion
+                    } else {
+                        #region looking from left
+                        //System.Diagnostics.Debug.WriteLine("CosPhi > 0 & SinPhi < 0 (left)"); 
+                        checkGridIndicesLength((m_rows-1) * 4 + 2,m_cols-1); 
+                        pos1 = m_Vertcount-1; 
+                        pos2 = m_Vertcount-1-m_cols;
+                        // first col is special:
+                        for (int c = m_rows-1; c-->0;) {
+                            m_gridIndices[posI++] = (uint)pos2; pos2 -= m_cols; 
+                            m_gridIndices[posI++] = (uint)pos1; pos1 -= m_cols; 
+                        }
+                        pos2 = m_Vertcount - 1 - m_cols; 
+                        pos1 = m_Vertcount - 2; 
+                        for (int r = m_cols-1; r-->0;) {
+                            // first row is special: 
+                            m_gridIndices[posI++] = (uint)pos1; 
+                            m_gridIndices[posI++] = (uint)pos1+1; 
+                            for (int c = m_rows-1; c-->0;) {
+                                m_gridIndices[posI++] = (uint)(pos1-m_cols);  
+                                m_gridIndices[posI++] = (uint)pos1; pos1 -= m_cols; 
+                                m_gridIndices[posI++] = (uint)pos1; 
+                                m_gridIndices[posI++] = (uint)pos2; pos2 -= m_cols;  
+                            }
+                            pos1 += (m_Vertcount - m_cols -1);
+                            pos2 += (m_Vertcount - m_cols -1);
+                        }
+                        #endregion
+                    }
+                } else {
+                    if (m_panel.Camera.SinPhiShift > 0) {
+                        #region looking from right
+                        //System.Diagnostics.Debug.WriteLine("CosPhi < 0 & SinPhi > 0 (right)"); 
+                        checkGridIndicesLength((m_rows-1) * 4 + 2,m_cols-1); 
+                        pos1 = 0; 
+                        pos2 = 1; 
+                        // first col is special:
+                        for (int c = m_rows-1; c-->0;) {
+                            m_gridIndices[posI++] = (uint)pos1; pos1 += m_cols; 
+                            m_gridIndices[posI++] = (uint)pos1; 
+                        }
+                        pos1 = m_cols; 
+                        for (int r = m_cols-1; r-->0;) {
+                            // first row is special: 
+                            m_gridIndices[posI++] = (uint)pos2-1; 
+                            m_gridIndices[posI++] = (uint)pos2; 
+                            for (int c = m_rows-1; c-->0;) {
+                                m_gridIndices[posI++] = (uint)pos1;   
+                                m_gridIndices[posI++] = (uint)pos1+1; pos1 += m_cols;  
+                                m_gridIndices[posI++] = (uint)pos2; pos2 += m_cols;  
+                                m_gridIndices[posI++] = (uint)pos2; 
+                            }
+                            pos1 -= (m_Vertcount - m_cols -1);
+                            pos2 -= (m_Vertcount - m_cols -1);
+                        }
+                          #endregion
+                    } else {
+                        #region looking from back 
+                        //System.Diagnostics.Debug.WriteLine("CosPhi < 0 & SinPhi < 0 (back)"); 
+                        checkGridIndicesLength((m_cols-1) * 4 + 2,m_rows-1); 
+                        pos1 = m_cols-1; pos2 = pos1-1;
+                        for (int c = m_cols-1; c-->0;) {
+                            m_gridIndices[posI++] = (uint)pos2--; 
+                            m_gridIndices[posI++] = (uint)pos1--; 
+                        }
+                        pos2 = m_cols*2-1; 
+                        pos1 = m_cols-1; 
+                        for (int r = m_rows-1; r-->0;) {
+                            // first column is special: 
+                            m_gridIndices[posI++] = (uint)pos1; 
+                            m_gridIndices[posI++] = (uint)pos2; 
+                            for (int c = m_cols-1; c-->0;) {
+                                m_gridIndices[posI++] = (uint)(pos2-1); 
+                                m_gridIndices[posI++] = (uint)pos2--; 
+                                m_gridIndices[posI++] = (uint)--pos1; 
+                                m_gridIndices[posI++] = (uint)pos2; 
+                            }
+                            pos1 += (2*m_cols-1); 
+                            pos2 += (2*m_cols-1);
+                        }
+                        #endregion
+                    }
+                } 
+                #endregion
+                }
+            m_indexReady = true; 
+        }
+        /// <summary>
+        /// checks the length of index vector and allocate more memory if needed
+        /// </summary>
+        /// <param name="vertStrCount">Number of stripes to be drawn</param>
+        /// <param name="vertStrLen">Number of indices for each stripe</param>
+        protected void checkVertexIndicesLength(int vertStrLen, int vertStrCount) {
+            m_indicesCount = vertStrCount * vertStrLen;
+            if (m_indices != null && m_indices.Length < m_indicesCount) {
+                ILMemoryPool.Pool.Free(m_indices);
+            }
+            if (m_indices == null || m_indices.Length < m_indicesCount) {
+                m_indices = ILMemoryPool.Pool.New<uint>(m_indicesCount);
+            }
+            m_stripesCount = vertStrCount; 
+            m_stripesLen = vertStrLen; 
+        }
+        /// <summary>
+        /// checks the length of grid index vector and allocate more if needed
+        /// </summary>
+        /// <param name="gridStrCount">Number of stripes to be drawn</param>
+        /// <param name="gridStrLen">Number of indices for each stripe</param>
+        protected void checkGridIndicesLength(int gridStrLen, int gridStrCount) {
+            m_gridStripsLenOnce = (gridStrLen -2) / 2 + 2; 
+            m_gridIndicesCount = gridStrLen * gridStrCount + m_gridStripsLenOnce; 
+            if (m_gridIndices != null && m_gridIndices.Length < m_gridIndicesCount) {
+                ILMemoryPool.Pool.Free(m_gridIndices);
+            }
+            if (m_gridIndices == null || m_gridIndices.Length < m_gridIndicesCount) {
+                m_gridIndices = ILMemoryPool.Pool.New<uint>(m_gridIndicesCount);
+            }
+            m_gridStripsCount = gridStrCount; 
+            m_gridStripsLen = gridStrLen; 
+        }
+        /// <summary>
+        /// Dispose off this filled graph (grid-)indices
+        /// </summary>
+        public override void Dispose() {
+            if (m_indices != null) {
+                ILMemoryPool.Pool.Free<uint>(m_indices); 
+            }
+            if (m_gridIndices != null) {
+                ILMemoryPool.Pool.Free<uint>(m_gridIndices); 
+            }
+            base.Dispose();
+        }
+        /// <summary>
+        /// checks &amp; if neccessary triggers recreation of all vertices and indices
+        /// </summary>
+        /// <remarks>This function is called by the enclosing panel, e.g. when rotation
+        /// occours, which makes a reconfiguration neccessary. It internally calls CreateVertices() 
+        /// and CreateIndices().</remarks>
+        internal override void Configure() {
+            m_isReady = false; 
+            if (!m_vertexReady) CreateVertices(); 
+            if (!m_indexReady) CreateIndices(); 
+            m_isReady = true; 
+        }
+
+        protected override void OnChanged(string source) {
+            base.OnChanged(source);
+            m_vertexReady = false; 
+        }
+
+        protected void m_wireLines_Changed(object sender, EventArgs args) {
+            OnWireLinesChanged(); 
+        }
+        protected virtual void OnWireLinesChanged () {
+            m_indexReady = false; 
+            OnChanged("Wirelines"); 
+        }
+        #endregion
+
+     }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Graphs/ILGraph.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Graphs/ILGraph.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Graphs/ILGraph.cs	(revision 9102)
@@ -0,0 +1,180 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing; 
+using ILNumerics.Drawing; 
+using ILNumerics.Exceptions; 
+using ILNumerics.Drawing.Misc; 
+using ILNumerics.Drawing.Labeling; 
+using ILNumerics.Drawing.Interfaces; 
+
+namespace ILNumerics.Drawing.Graphs {
+    /// <summary>
+    /// graph for drawings into ILPanel
+    /// </summary>
+    /// <remarks>Use the ILGraphCollection returned from ILPanel.Graphs and its Add... functions to create new graphs.</remarks>
+    public abstract class ILGraph : IDisposable {
+
+        #region events 
+        
+        public event ILGraphChangedEvent Changed; 
+        protected virtual void OnChanged(string source) {
+            if (Changed != null) 
+                Changed(this, new ILGraphChangedEventArgs(source));
+        }
+
+        #endregion
+
+        #region members / properties
+        protected bool m_isReady; 
+        protected ILClippingData m_localClipping; 
+        protected ILClippingData m_globalClipping; 
+        protected GraphType m_graphType; 
+        protected ILPanel m_panel; 
+        protected ILLabel m_label; 
+
+        /// <summary>
+        ///  the label of the graph (readonly)
+        /// </summary>
+        public ILLabel Label {
+            get { 
+                return m_label; 
+            }
+        }
+        /// <summary>
+        /// data limits of the graphs current data (readonly)
+        /// </summary>
+        public ILClippingData Limits {
+            get { 
+                return m_localClipping;
+            }
+            internal set {
+                m_localClipping = value; 
+            }
+        }
+        /// <summary>
+        /// The type of graph (Plot2D, Surf, ImageSC, ...)
+        /// </summary>
+        public GraphType Type {
+            get {
+                return m_graphType; 
+            }
+        }
+        /// <summary>
+        /// The hosting panel
+        /// </summary>
+        public ILPanel Panel {
+            get {
+                return m_panel; 
+            }
+        }
+        #endregion
+
+        #region constructors
+        
+        internal ILGraph(ILPanel panel, ILClippingData clippingContainer) {
+            m_panel = panel; 
+            m_localClipping = new ILClippingData();
+            m_localClipping.Changed += new ILClippingDataChangedEvent(m_localClipping_Changed);
+            m_globalClipping = clippingContainer;
+            m_globalClipping.Changed += new ILClippingDataChangedEvent(m_globalClipping_Changed);
+            // store incoming data arrays as ILArray<float>
+            //m_sourceArray = sourceArray.CreateReference();
+            m_label = new ILLabel(m_panel);
+            m_label.Color = Color.Black; 
+            m_label.Changed += new EventHandler(m_label_Changed);
+            m_isReady = false;
+        }
+
+
+        #endregion 
+
+        #region event handler 
+        
+        protected virtual void m_localClipping_Changed(object sender, ClippingChangedEventArgs e) {
+            // override this event in derived class, if neccessary
+        }
+        protected virtual void m_globalClipping_Changed(object sender, ClippingChangedEventArgs e) {
+            // override this event in derived class, if neccessary
+        }
+        protected virtual void m_label_Changed(object sender, EventArgs e) {
+            // override this event in derived class, if neccessary
+        }
+
+        #endregion
+
+        #region abstract / interface member
+        /// <summary>
+        /// configures all parameters + cache, called before drawing
+        /// </summary>
+        internal abstract void Configure();
+        /// <summary>
+        /// invalidate and recalculate this graphs data, this must be called after changes to relevant graph properties
+        /// </summary>
+        public virtual void Invalidate() {
+            m_isReady = false; 
+        }
+        /// <summary>
+        /// draws the graph into the panel
+        /// </summary>
+        /// <param name="p">extended drawing properties</param>
+        public abstract void Draw(ILRenderProperties p); 
+        /// <summary>
+        /// clear ressources of the graph
+        /// </summary>
+        public virtual void Dispose() {
+            m_globalClipping.Changed -= new ILClippingDataChangedEvent(m_globalClipping_Changed); 
+            if (m_label != null) {
+                m_label.Changed -= m_label_Changed; 
+                m_label.Dispose(); 
+            }
+        }
+        /// <summary>
+        /// determine general type of graph (2D/3D) 
+        /// </summary>
+        /// <returns>true for 3D graphs (e.g. surf, scene graph) and false for 2D graphs (plot2D)</returns>
+        public abstract bool Is3DGraph();
+
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Graphs/ILImageSCGraph.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Graphs/ILImageSCGraph.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Graphs/ILImageSCGraph.cs	(revision 9102)
@@ -0,0 +1,115 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing; 
+using ILNumerics.Drawing; 
+using ILNumerics.Drawing.Interfaces; 
+
+namespace ILNumerics.Drawing.Graphs {
+    /// <summary>
+    /// class rendering plain color-coded area graphs
+    /// </summary>
+    /// <remarks>This class derives from ILFilledGraph and adds a ZPosition property.</remarks>
+    public abstract class ILImageSCGraph : ILFilledGraph, IILLegendRenderer, IILPanelConfigurator {
+
+        #region attributes 
+        protected float m_zPosition;
+        #endregion
+
+        #region Properties
+        /// <summary>
+        /// Z position for ImageSC graph (default: -Inf)
+        /// </summary>
+        /// <remarks>The position of the ImageSC plane is specified by a Z coordinate.
+        /// The coordinate can set to the following values: 
+        /// <list type="bullet">
+        /// <item>any single precision value, will position the plane on that specific value</item>
+        /// <item><i>negative infinity</i>, will position the plane on the bottom of the viewing cube</item>
+        /// <item><i>positive infinity</i>, position the plane on top of the unit cube.</item></list>
+        /// </remarks>
+        public float ZPosition {
+            get {
+                return m_zPosition; 
+            }
+            set {
+                m_zPosition = value; 
+                OnChanged("ZPosition"); 
+            }
+        }
+        #endregion
+
+        #region constructor
+        public ILImageSCGraph(ILPanel panel, ILArray<float> X, ILArray<float> Y,
+                                ILArray<float> Z, ILArray<float> C,
+                                ILClippingData clippingContainer)
+            : base(panel, X, Y, Z, C, clippingContainer) {
+            using (ILScope.Enter(X, Y, Z, C)) {
+                m_cols = m_sourceArray.Size[1] + 1;
+                m_rows = m_sourceArray.Size[0] + 1;
+                m_Vertcount = m_rows * m_cols;
+                // defaults
+                m_zPosition = float.NegativeInfinity;
+            }
+        }
+        #endregion
+
+        public override bool Is3DGraph() {
+            return true;
+        }
+
+        #region IILPanelConfigurator
+        public void ConfigurePanel(ILPanel panel) {
+            panel.InteractiveMode = InteractiveModes.ZoomRectangle;
+            panel.AspectRatio = AspectRatioMode.StretchToFill;
+            panel.PlotBoxScreenSizeMode = PlotBoxScreenSizeMode.StrictOptimal;
+            panel.ClipViewData = false;
+            panel.DefaultView.Set(0f, 0f, panel.DefaultView.Distance);
+        }
+        #endregion
+
+        #region IILRenderToLegend
+        public abstract void DrawToLegend(ILRenderProperties p, Rectangle sampleRect, Rectangle labelRect);
+        public Size LabelSize { get { return m_label.Size; } }
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Graphs/ILPlot2DGraph.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Graphs/ILPlot2DGraph.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Graphs/ILPlot2DGraph.cs	(revision 9102)
@@ -0,0 +1,284 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing; 
+using ILNumerics; 
+using ILNumerics.Drawing; 
+using ILNumerics.Exceptions; 
+using ILNumerics.Drawing.Marker;
+using ILNumerics.Drawing.Interfaces; 
+using ILNumerics.Drawing.Shapes; 
+
+namespace ILNumerics.Drawing.Graphs {
+    /// <summary>
+    /// 2D line &amp; point graph
+    /// </summary>
+    public abstract class ILPlot2DGraph : ILGraph, IILLegendRenderer, IILPanelConfigurator {
+
+        #region attributes
+        protected C4bV3f[] m_vertices; 
+        protected int m_vertexCount; 
+        protected ILLineProperties m_properties; 
+        protected ILMarker m_marker;
+        int m_autoLimitsUpdateCount = 0;
+        int m_updateCount = 0; 
+        protected int m_startID;
+
+        #endregion
+
+        #region properties
+        /// <summary>
+        /// number of subsequent updates ('Queue') before limits get recalculated. Default: 0 (recalculate on every update)
+        /// </summary>
+        public int AutoLimitsUpdateCount {
+            get { return m_autoLimitsUpdateCount; }
+            set { m_autoLimitsUpdateCount = value; }
+        } 
+        /// <summary>
+        /// Get properties of lines
+        /// </summary>
+        public ILLineProperties Line {
+            get {
+                return m_properties; 
+            }
+        }
+        /// <summary>
+        /// Get properties of markers
+        /// </summary>
+        public ILMarker Marker {
+            get {
+                return m_marker; 
+            }
+        }
+        /// <summary>
+        /// access to internal vertex array
+        /// </summary>
+        /// <remarks><para>after altering vertex data, one must call 
+        /// Invalidate() to signal those changes.</para></remarks>
+        public C4bV3f[] Vertices {
+            get {
+                return m_vertices; 
+            }
+        }
+        /// <summary>
+        /// Invalidate the graph after vertex data have been changed.
+        /// </summary>
+        public override void Invalidate() {
+            base.Invalidate(); 
+            updateClipping();  
+            OnChanged("Data"); 
+        }
+        /// <summary>
+        /// draws a small example of the visual output 
+        /// </summary>
+        /// <param name="p">render properties</param>
+        /// <param name="sampleArea">area to draw the line + marker into</param>
+        /// <param name="labelArea">area to draw corresponding label into</param>
+        /// <remarks>derived classes implement this for current device contexts</remarks>
+        public virtual void DrawToLegend(ILRenderProperties p, Rectangle sampleArea, Rectangle labelArea) {
+            //if (g == null) throw new ILArgumentException ("ILGraph: DrawIntoLegend: invalid graphics object (null)"); 
+            //throw new NotImplementedException ("ILGraph cannot draw to bitmap yet!"); 
+        }
+
+        /// <summary>
+        /// Size of label
+        /// </summary>
+        /// <value>size</value>
+        public Size LabelSize { get { return m_label.Size; } }
+        #endregion
+
+        #region constructor
+        /// <summary>
+        /// [internal] constructor - do not use this! Use ILPanel.Graphs.Add...() instead!
+        /// </summary>
+        /// <param name="panel">panel hosting the scene</param>
+        /// <param name="sourceArray">data array</param>
+        /// <param name="clippingContainer">hosting panels clipping data</param>
+        public ILPlot2DGraph(ILPanel panel, ILArray<float> sourceArray,
+                              ILClippingData clippingContainer)
+            : base(panel, clippingContainer) {
+            using (ILScope.Enter(sourceArray)) {
+                if (object.Equals(sourceArray, null) || !sourceArray.IsVector || !sourceArray.IsNumeric)
+                    throw new ILArgumentException("Plot2D: supplied data must be numeric (real valued) vector!");
+                int pos = 0;
+                ILArray<float> data;
+                C4bV3f vert = new C4bV3f();
+                data = (ILArray<float>)sourceArray;
+                m_vertices = new C4bV3f[data.Length + 1];
+                m_vertexCount = m_vertices.Length;
+                m_updateCount = 0;
+                m_startID = 0;
+                m_properties = new ILLineProperties();
+                m_properties.Color = Color.DarkBlue;
+                m_properties.Width = 2; 
+                //m_properties.Antialiasing = true;
+                m_properties.Changed += new EventHandler(m_properties_Changed);
+                foreach (float val in data) {
+                    vert.Position = new ILPoint3Df(pos, val, 0);
+                    vert.Color = Color.Red;
+                    m_vertices[pos++] = vert;
+                }
+                m_marker = new ILMarker(panel);
+                m_marker.Changed += new EventHandler(m_properties_Changed);
+                m_graphType = GraphType.Plot2D;
+                m_localClipping.Set(new ILPoint3Df(0, data.MinValue, 0), new ILPoint3Df(data.Length - 1, data.MaxValue, 0));
+            }
+        }
+        /// <summary>
+        /// [internal] constructor - do not use this! Use ILPanel.Graphs.Add...() instead!
+        /// </summary>
+        /// <param name="panel">panel hosting the scene</param>
+        /// <param name="XData">x data array</param>
+        /// <param name="YData">y data array</param>
+        /// <param name="clippingContainer">hosting panels clipping data</param>
+        internal ILPlot2DGraph(ILPanel panel, ILArray<float> XData, ILArray<float> YData,
+                              ILClippingData clippingContainer) 
+            : base (panel,clippingContainer) {
+                using (ILScope.Enter(XData, YData)) {
+                    if (!XData.IsVector)
+                        throw new ILArgumentException("Plot2D: supplied data must be a real vector!");
+                    if (!YData.IsVector)
+                        throw new ILArgumentException("Plot2D: XData and YData must be real vectors!");
+                    if (YData.Length != XData.Length)
+                        throw new ILArgumentException("Plot2D: XData and YData must have the same length!");
+                    int pos = 0;
+                    ILArray<float> dataX, dataY;
+                    C4bV3f vert = new C4bV3f();
+                    dataX = (ILArray<float>)XData;
+                    dataY = (ILArray<float>)YData;
+                    m_vertices = new C4bV3f[dataX.Length + 1];
+                    m_vertexCount = m_vertices.Length;
+                    m_startID = m_vertexCount - 1;
+                    m_updateCount = 0;
+                    m_properties = new ILLineProperties();
+                    m_properties.Color = Color.DarkBlue;
+                    m_properties.Changed += new EventHandler(m_properties_Changed);
+                    foreach (float val in dataX) {
+                        vert.Position = new ILPoint3Df(val, dataY.GetValue(pos), 0);
+                        vert.Color = m_properties.Color;
+                        m_vertices[pos++] = vert;
+                    }
+                    m_marker = new ILMarker(panel);
+                    m_marker.Changed += new EventHandler(m_marker_Changed);
+                    m_graphType = GraphType.Plot2D;
+                    updateClipping();
+                }
+        }
+        public void Queue(IILVertexDefinition vertex) {
+            if (m_startID == 0) {
+                SetVertex(m_vertexCount-1,vertex); 
+                m_startID = 1; 
+            } else {
+                SetVertex(m_startID,vertex);
+                m_vertices[0] = m_vertices[m_vertexCount-1]; 
+                m_startID++;
+            }
+            if (m_startID == m_vertexCount-1) {
+                m_startID = 0; 
+            }
+            if (m_updateCount++ < m_autoLimitsUpdateCount) {
+                m_localClipping.Update(vertex.Position,vertex.Position); 
+            } else {
+                m_updateCount = 0; 
+                Invalidate();
+            }
+        }
+
+        #endregion
+
+        #region private helper 
+        public void SetVertex(int vertexID,IILVertexDefinition vertex) {
+            C4bV3f curVert = m_vertices[vertexID]; 
+            if (vertex.StoresColor) {
+                curVert.Color = vertex.Color; 
+            }
+            curVert.Position = vertex.Position; 
+            m_vertices[vertexID] = curVert; 
+        }
+
+        /// <summary>
+        /// called, if a property for markers have changed
+        /// </summary>
+        /// <param name="sender">this graph instance</param>
+        /// <param name="e">(no args)</param>
+        /// <remarks>derived classes should override this function in order to 
+        /// (re-)configure vertex ressources etc.</remarks>
+        protected virtual void m_marker_Changed(object sender, EventArgs e) {
+            m_isReady = false; 
+        }
+        private void updateClipping() {
+            ILPoint3Df max = ILPoint3Df.MinValue; 
+            ILPoint3Df min = ILPoint3Df.MaxValue;
+            for (int i = 0; i < m_vertexCount; i++) {
+                C4bV3f vert = m_vertices[i]; 
+                max = ILPoint3Df.Max(vert.Position,max); 
+                min = ILPoint3Df.Min(vert.Position,min); 
+            }
+            m_localClipping.Set ( min, max ); 
+        }
+        /// <summary>
+        /// called, if a property for lines have changed
+        /// </summary>
+        /// <param name="sender">this graph instance</param>
+        /// <param name="e">(no args)</param>
+        /// <remarks>derived classes should override this function in order to 
+        /// (re-)configure vertex ressources etc.</remarks>
+        protected virtual void m_properties_Changed(object sender, EventArgs e) {
+            m_isReady = false;
+        }
+        public override bool Is3DGraph() {
+            return false;
+        }
+        #endregion
+
+        #region IILPanelConfigurator
+        public void ConfigurePanel(ILPanel panel) {
+            panel.InteractiveMode = InteractiveModes.ZoomRectangle;
+            panel.AspectRatio = AspectRatioMode.StretchToFill;
+            panel.PlotBoxScreenSizeMode = PlotBoxScreenSizeMode.Optimal;
+            panel.ClipViewData = true;
+            panel.DefaultView.Set(0f, 0f, panel.DefaultView.Distance);
+        }
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Graphs/ILSceneGraph.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Graphs/ILSceneGraph.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Graphs/ILSceneGraph.cs	(revision 9102)
@@ -0,0 +1,220 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Collections; 
+using System.Text;
+using ILNumerics.Drawing; 
+using ILNumerics.Drawing.Interfaces; 
+using ILNumerics.Drawing.Shapes;
+using ILNumerics; 
+
+namespace ILNumerics.Drawing.Graphs {
+    /// <summary>
+    /// The class implements a scene graph (tree), capable 
+    /// of holding, managing and drawing all kinds of shapes.
+    /// </summary>
+    public class ILSceneGraph : ILGraph {
+
+        #region eventing
+        /// <summary>
+        /// fires, once somewhere in the graph a node was added
+        /// </summary>
+        public event SceneGraphNodeHandler NodeAdded; 
+        void OnNodeAdded(ILSceneGraphNodeEventArgs args) {
+            if (NodeAdded != null) {
+                NodeAdded(this, args);  
+            }
+        }
+        public event SceneGraphNodeHandler NodeRemoved; 
+        void OnNodeRemoved(ILSceneGraphNodeEventArgs args) {
+            if (NodeRemoved != null) {
+                NodeRemoved(this, args);  
+            }
+        }
+
+        void m_root_Invalidated(object sender, EventArgs e) {
+            base.Invalidate();
+        }
+        void m_root_SizeChanged(object sender, EventArgs e) {
+            m_localClipping.Set(m_root.PositionMin, m_root.PositionMax);
+        }
+        void m_root_NodeAdded(object sender, ILSceneGraphNodeEventArgs args) {
+            OnNodeAdded(args); 
+        }
+        void m_root_NodeRemoved(object sender, ILSceneGraphNodeEventArgs args) {
+            OnNodeRemoved(args);
+        }
+
+        #endregion
+
+        #region attributes
+        private ILSceneGraphRoot m_root; 
+        #endregion
+
+        #region properties
+        /// <summary>
+        /// root node of the scene graph
+        /// </summary>
+        public ILSceneGraphInnerNode Root {
+            get {return m_root; }
+        }
+        #endregion
+
+        #region constructors
+        /// <summary>
+        /// (internal) create new scene graph 
+        /// </summary>
+        /// <param name="panel">panel hosting the scene</param>
+        /// <param name="clipping">clipping data object, usually member of the panel</param>
+        internal ILSceneGraph (ILPanel panel, ILClippingData clipping) 
+            : base(panel,clipping) {
+            m_root = new ILSceneGraphRoot(panel);
+            m_root.Invalidated += new EventHandler(m_root_Invalidated);
+            m_root.SizeChanged += new EventHandler(m_root_SizeChanged);
+            m_root.NodeAdded += new SceneGraphNodeHandler(m_root_NodeAdded);
+            m_root.NodeRemoved += new SceneGraphNodeHandler(m_root_NodeRemoved);
+            m_graphType = GraphType.SceneGraph; 
+        }
+
+        #endregion
+
+        #region public interface
+        /// <summary>
+        /// Determines if this graph renders in 3D, may overridden in derived class
+        /// </summary>
+        /// <returns></returns>
+        public override bool Is3DGraph() {
+            return true;
+        }
+        /// <summary>
+        /// (internal use) draws the whole scene graph
+        /// </summary>
+        /// <param name="p"></param>
+        public override void Draw(ILRenderProperties p) {
+            m_root.Draw(p); 
+        }
+        /// <summary>
+        /// (internal use) configures and prepares the scene graph for rendering
+        /// </summary>
+        internal override void Configure() {
+            if (!m_isReady) {
+                m_root.Configure();
+                m_isReady = true;
+            }
+        }
+        /// <summary>
+        /// add new node to root node
+        /// </summary>
+        /// <param name="node"></param>
+        public void AddNode(ILSceneGraphNode node) {
+            AddNode(node, m_root);
+        }
+        /// <summary>
+        /// add a shape to the root node
+        /// </summary>
+        /// <param name="shape"></param>
+        public void AddNode(ILShape shape) {
+            ILSceneGraphShapedLeaf node = new ILSceneGraphShapedLeaf(m_panel);
+            node.Shape = shape; 
+            AddNode(node, m_root);
+        }
+        /// <summary>
+        /// add new node as child of another node
+        /// </summary>
+        /// <param name="node"></param>
+        /// <param name="parent"></param>
+        public void AddNode(ILSceneGraphNode node, ILSceneGraphInnerNode parent) {
+            parent.Add(node);             
+        }
+        /// <summary>
+        /// collect all shapes contained in any scene graph nodes
+        /// </summary>
+        /// <returns></returns>
+        public List<ILShape> GetAllShapes() {
+            List<ILShape> ret = new List<ILShape>();
+            getAllShapes(m_root, ret);
+            return ret;  
+        }
+        #endregion
+
+        #region private helpers
+        private void getAllShapes(ILSceneGraphNode node, List<ILShape> ret) {
+            foreach (ILSceneGraphNode n in node) {
+                if (n is ILSceneGraphShapedLeaf) {
+                    ILSceneGraphShapedLeaf snode = n as ILSceneGraphShapedLeaf;
+                    if (snode.Shape != null)
+                        ret.Add(snode.Shape);
+                }
+                //getAllShapes(n,ret); 
+            }
+        }
+
+        #endregion
+
+        #region IEnumerable<ILShape> Member
+
+        //public IEnumerator<ILShape> GetEnumerator() {
+        //    List<ILShape> ret = new List<ILShape>(); 
+        //    getAllShapes(m_root,ret); 
+        //    return ret.GetEnumerator();  
+        //}
+
+        //#endregion
+
+        //#region IEnumerable Member
+
+        //IEnumerator GetEnumerator() {
+        //    List<ILShape> ret = new List<ILShape>(); 
+        //    getAllShapes(m_root,ret); 
+        //    return ret.GetEnumerator();  
+        //}
+
+        //#endregion
+
+        //#region IILPanelConfigurator
+        //public override void ConfigurePanel(ILPanel panel) {
+        //    panel.InteractiveMode = InteractiveModes.Rotating;
+        //    panel.DefaultView.Set(5.8f, 1.17f, panel.DefaultView.Distance);
+        //}
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Graphs/ILSceneGraphInnerNode.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Graphs/ILSceneGraphInnerNode.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Graphs/ILSceneGraphInnerNode.cs	(revision 9102)
@@ -0,0 +1,282 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Drawing; 
+using ILNumerics.Drawing.Shapes;
+
+namespace ILNumerics.Drawing.Graphs {
+    /// <summary>
+    /// scene graph inner node, collection of children
+    /// </summary>
+    public class ILSceneGraphInnerNode : ILSceneGraphNode, ICollection<ILSceneGraphNode>,
+            IList<ILSceneGraphNode> {
+
+        #region attributes
+        private List<ILSceneGraphNode> m_childs;
+        private ILArray<float> m_centers;
+        #endregion
+
+        #region constructors
+        public ILSceneGraphInnerNode(ILPanel panel) 
+        :base (panel) {
+
+            m_centers = ILMath.returnType<float>();
+            m_childs = new List<ILSceneGraphNode>(); 
+
+        }
+
+        #endregion
+
+        #region public interface
+        /// <summary>
+        /// recompute the size spanned by this node, may fires Changed() event
+        /// </summary>
+        internal override void Configure() {
+            if (m_invalidated) {
+                // configure childs (compute limits) first
+                foreach (ILSceneGraphNode child in m_childs) {
+                    child.Configure();
+                }
+                bool sizechanged = false;
+                ILPoint3Df oldMin = m_positionMin;
+                ILPoint3Df oldMax = m_positionMax;
+                ComputeNodeLimits();
+                if (oldMin != m_positionMin) sizechanged = true;
+                if (oldMax != m_positionMax) sizechanged = true;
+                m_invalidated = false;
+                if (sizechanged)
+                    OnSizeChanged();
+            }
+        }
+        internal override void Draw(ILRenderProperties props) {
+            if (!m_visible) {
+                return;
+            }
+            if (m_childs != null && m_childs.Count > 0) {
+                ILArray<int> indices = Computation.GetSortedIndices(
+                                     m_centers, m_panel.Camera.Position);
+                foreach (int i in indices) {
+                    if (m_childs[i].Visible)
+                        m_childs[i].Draw(props);
+                }
+            }
+        }
+        public override void Invalidate() {
+            base.Invalidate();
+            m_centers.a = ILMath.empty<float>(ILSize.Empty00); 
+        }
+        /// <summary>
+        /// compute limits of the cube tightly enclosing the branch below this node
+        /// </summary>
+        /// <returns></returns>
+        protected override void ComputeNodeLimits() {
+            if (m_childs == null || m_childs.Count == 0) {
+                m_positionMin = ILPoint3Df.Empty;
+                m_positionMax = ILPoint3Df.Empty;
+                return; 
+            }
+            // acquire maximum position
+            ILPoint3Df curMax = ILPoint3Df.MinValue;
+            ILPoint3Df curMin = ILPoint3Df.MaxValue;
+            foreach (ILSceneGraphNode node in m_childs) {
+                curMin = ILPoint3Df.Min(node.PositionMin, curMin);
+            }
+            curMax = ILPoint3Df.MinValue;
+            foreach (ILSceneGraphNode node in m_childs) {
+                curMax = ILPoint3Df.Max(node.PositionMax, curMax);
+            }
+            m_positionMax = curMax;
+            m_positionMin = curMin;
+            m_center = (m_positionMax + m_positionMin) / 2;
+            // stores childs centers for sorting
+            if (m_centers.IsEmpty)
+                m_centers.a = ILMath.zeros<float>(m_childs.Count, 3);
+            for (int i = m_childs.Count; i-- > 0; ) {
+                ILPoint3Df center = m_childs[i].Center;
+                m_centers.SetValue(center.X, i, 0);
+                m_centers.SetValue(center.Y, i, 1);
+                m_centers.SetValue(center.Z, i, 2);
+            }
+        }
+        internal override void CollectAllChildren(List<ILSceneGraphNode> nodes) {
+            nodes.Add(this); //    base.CollectAllChildren(nodes); // add self
+            if (m_childs != null) {
+                foreach (ILSceneGraphNode child in m_childs) {
+                    child.CollectAllChildren(nodes);
+                }
+            }
+        }
+        public virtual void Add(ILShape shape) {
+            ILSceneGraphShapedLeaf node = new ILSceneGraphShapedLeaf(m_panel);
+            node.Parent = this; 
+            node.Shape = shape;
+            m_childs.Add(node);
+            Invalidate(); 
+            OnNodeAdded(node); 
+        }
+        public virtual void Remove(ILShape shape) {
+            ILSceneGraphNode node = null; 
+            foreach (ILSceneGraphNode n in m_childs) {
+                if (n is ILSceneGraphShapedLeaf) { 
+                    if (object.Equals((n as ILSceneGraphShapedLeaf).Shape,shape)) {
+                        node = n; 
+                        break; 
+                    }
+                }
+            }
+            if (node != null) {
+                m_childs.Remove(node); 
+                OnNodeRemoved(node); 
+            }
+        }      
+        #endregion
+
+        #region IList<ILSceneGraphNode> Member
+
+        public virtual ILSceneGraphNode this[int i] {
+            get {
+                return m_childs[i];
+            }
+            set {
+                m_childs[i] = value;
+                Invalidate(); 
+            }
+        }
+
+        public virtual int IndexOf(ILSceneGraphNode item) {
+            return m_childs.IndexOf(item);
+        }
+
+        public virtual void Insert(int index, ILSceneGraphNode item) {
+            m_childs.Insert(index, item);
+            Invalidate(); 
+        }
+
+        public virtual void RemoveAt(int index) {
+            m_childs.RemoveAt(index);
+            Invalidate(); 
+        }
+        #endregion
+
+        #region ICollection<ILSceneGraphNode> Member
+        /// <summary>
+        /// add a single node to the end of child collection
+        /// </summary>
+        /// <param name="item">node to add </param>
+        public virtual void Add(ILSceneGraphNode item) {
+            m_childs.Add(item);
+            item.Parent = this;
+            item.Invalidate();
+            OnNodeAdded(item);
+        }
+        /// <summary>
+        /// wipe all nodes from the collection 
+        /// </summary>
+        public virtual void Clear() {
+            m_childs.Clear();
+            Invalidate(); 
+        }
+        /// <summary>
+        /// Determine, if this collection contains a specific node item
+        /// </summary>
+        /// <param name="item"></param>
+        /// <returns></returns>
+        public bool Contains(ILSceneGraphNode item) {
+            return m_childs.Contains(item);
+        }
+
+        public void CopyTo(ILSceneGraphNode[] array, int arrayIndex) {
+            m_childs.CopyTo(array, arrayIndex);
+        }
+        /// <summary>
+        /// Number of children contained in this node
+        /// </summary>
+        public virtual int Count {
+            get { return m_childs.Count; }
+        }
+        /// <summary>
+        /// determine if this collection is readonly, (returns 'false')
+        /// </summary>
+        public bool IsReadOnly {
+            get { return false; }
+        }
+        /// <summary>
+        /// remove a single child node from the collection
+        /// </summary>
+        /// <param name="item">node to be removed</param>
+        /// <returns>true</returns>
+        public virtual bool Remove(ILSceneGraphNode item) {
+            m_childs.Remove(item);
+            Invalidate();
+            return true; 
+        }
+
+        #endregion
+
+        #region private helpers
+
+        private class Computation : ILNumerics.ILMath {
+            /// <summary>
+            /// compute distance to camera and return sorted indices for rendering
+            /// </summary>
+            /// <param name="centers">current primitive centers</param>
+            /// <param name="position">current camera position</param>
+            /// <returns>sorted indices of primitives in descending order</returns>
+            internal static ILRetArray<int> GetSortedIndices(ILInArray<float> centers, ILPoint3Df position) {
+                using (ILScope.Enter(centers)) {
+                    ILArray<float> pos = array<float>(size(1,3), -position.X, -position.Y, -position.Z);
+                    // move camera outside of centers
+                    pos.a *= maxall(abs(centers));
+                    //pos.a = repmat(pos, centers.Dimensions[0], 1);
+                    // compute distances
+                    ILArray<float> dist = sum(pow(centers - pos, 2), 1);
+                    ILArray<double> ret = empty();
+                    sort(dist, ret, 0, false);
+                    return toint32(ret);
+                }
+            }
+        }
+
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Graphs/ILSceneGraphNode.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Graphs/ILSceneGraphNode.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Graphs/ILSceneGraphNode.cs	(revision 9102)
@@ -0,0 +1,253 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Collections;
+using System.Text;
+using ILNumerics.Drawing.Collections; 
+using ILNumerics.Drawing.Shapes; 
+using ILNumerics.Drawing; 
+
+namespace ILNumerics.Drawing.Graphs {
+    /// <summary>
+    /// abstract base class for all scene graph nodes
+    /// </summary>
+    public abstract class ILSceneGraphNode : 
+                //ICollection<ILSceneGraphNode>,
+                IEnumerable<ILSceneGraphNode>
+                ,IEnumerable {
+        
+        #region attributes 
+        protected ILSceneGraphNode m_parent; 
+        protected ILPoint3Df m_center;
+        protected ILPoint3Df m_positionMin; 
+        protected ILPoint3Df m_positionMax; 
+        protected bool m_invalidated;
+        protected bool m_visible;
+        protected ILPanel m_panel; // needed for camera position
+        protected bool m_eventingSuspended; 
+        #endregion
+
+        #region constructors
+        internal ILSceneGraphNode(ILPanel panel) {
+            m_panel = panel; 
+            m_invalidated = true;
+            m_visible = true; 
+        }
+        #endregion
+
+        #region eventing
+        /// <summary>
+        /// fires when the size of the cube tigthly enclosing the shape has changed
+        /// </summary>
+        public event EventHandler SizeChanged;
+        protected virtual void OnSizeChanged() {
+            if (SizeChanged != null && !m_eventingSuspended)
+                SizeChanged(this, new EventArgs());
+        }
+        /// <summary>
+        /// fires when the (size)cache of the node was invalidated
+        /// </summary>
+        public event EventHandler Invalidated;
+        protected virtual void OnInvalidated() {
+            if (Invalidated != null && !m_eventingSuspended)
+                Invalidated(this, new EventArgs());
+        }
+        protected virtual void OnNodeAdded(ILSceneGraphNode node) {
+            if (m_parent != null && !m_eventingSuspended) {
+                m_parent.OnNodeAdded(node); 
+            }
+        }
+        protected virtual void OnNodeRemoved(ILSceneGraphNode node) {
+            if (m_parent != null && !m_eventingSuspended) {
+                m_parent.OnNodeRemoved(node); 
+            }
+        }
+        /// <summary>
+        /// stop firing events from this node
+        /// </summary>
+        public void EventingSuspend() {
+            m_eventingSuspended = true; 
+        }
+        /// <summary>
+        /// resume firing events from this node
+        /// </summary>
+        public void EventingResume() {
+            m_eventingSuspended = false; 
+        }
+
+        #endregion
+
+        #region properties
+
+        /// <summary>
+        /// Get/set visiblility for the scene graph branch 
+        /// </summary>
+        public bool Visible {
+            get { return m_visible; }
+            set { m_visible = value; 
+            }
+        }
+        /// <summary>
+        /// reference to the scene graph node this node is a child of
+        /// </summary>
+        public ILSceneGraphNode Parent {
+            get {
+                return m_parent; 
+            }
+            set {
+                m_parent = value; 
+            }
+        }
+        /// <summary>
+        /// the minimum coordinate of a cube tightly enclosing the node (and all childs) 
+        /// </summary>
+        /// <returns></returns>
+        public virtual ILPoint3Df PositionMin {
+            get {
+                if (m_positionMin.IsEmtpy()) {
+                    ComputeNodeLimits();
+                }
+                return m_positionMin;
+            }
+        }
+        /// <summary>
+        /// the maximum coordinate of a cube tightly enclosing the node (and all childs) 
+        /// </summary>
+        /// <returns></returns>
+        public virtual ILPoint3Df PositionMax {
+            get {
+                if (m_positionMax.IsEmtpy()) {
+                    ComputeNodeLimits();
+                }
+                return m_positionMax;
+            }
+        }
+        /// <summary>
+        /// current geometric center according of scene graph branch
+        /// </summary>
+        public virtual ILPoint3Df Center {
+            get {
+                if (m_center.IsEmtpy()) {
+                    ComputeNodeLimits(); 
+                }
+                return m_center;
+            }
+        }
+        #endregion
+
+        #region public interface 
+        /// <summary>
+        /// invalidate geometry cache for this and all nodes up to root
+        /// </summary>
+        public virtual void Invalidate() {
+            m_center = ILPoint3Df.Empty;
+            m_positionMin = ILPoint3Df.Empty;
+            m_positionMax = ILPoint3Df.Empty;
+            m_invalidated = true;
+            if (Parent != null) {
+                Parent.Invalidate();
+            } else {
+                OnInvalidated();
+            }
+        }
+        /// <summary>
+        /// recompute the size spanned by this node, may fires Changed() event
+        /// </summary>
+        internal abstract void Configure(); 
+        /// <summary>
+        /// draw all children contained in this node
+        /// </summary>
+        /// <param name="props">extended rendering properties</param>
+        internal abstract void Draw(ILRenderProperties props);
+
+        #endregion
+
+        #region private helper 
+        /// <summary>
+        /// compute limits of the cube tightly enclosing the branch below this node
+        /// </summary>
+        /// <returns></returns>
+        protected abstract void ComputeNodeLimits(); 
+
+        //protected void invalidateChilds(ILSceneGraphNode parent) {
+        //    parent.m_center = ILPoint3Df.Empty;
+        //    parent.m_positionMin = ILPoint3Df.Empty;
+        //    parent.m_positionMax = ILPoint3Df.Empty;
+        //    foreach (ILSceneGraphNode child in parent.m_childs) {
+        //        child.invalidateChilds(child);
+        //    }
+        //}
+        #endregion
+
+        #region IEnumerable<ILSceneGraphNode> Member
+
+        /// <summary>
+        /// Create &amp; returns a typed enumerator
+        /// </summary>
+        /// <returns>enumerator of all scene graph nodes below this node</returns>
+        public IEnumerator<ILSceneGraphNode> GetEnumerator() {
+            List<ILSceneGraphNode> ret = new List<ILSceneGraphNode>();
+            CollectAllChildren(ret);
+            return ret.GetEnumerator(); 
+        }
+        #endregion
+
+        #region IEnumerable Member
+        /// <summary>
+        /// Create and return untyped enumerator
+        /// </summary>
+        /// <returns>IEnumerator of all scene graph nodes below this node</returns>
+        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
+            List<ILSceneGraphNode> children = new List<ILSceneGraphNode>();
+            CollectAllChildren(children);
+            foreach (ILSceneGraphNode node in children) {
+                yield return node; 
+            }
+        }
+        internal virtual void CollectAllChildren(List<ILSceneGraphNode> nodes) {
+            nodes.Add(this); 
+        }
+        
+        #endregion
+
+    }
+
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Graphs/ILSceneGraphRootNode.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Graphs/ILSceneGraphRootNode.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Graphs/ILSceneGraphRootNode.cs	(revision 9102)
@@ -0,0 +1,68 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Drawing; 
+
+namespace ILNumerics.Drawing.Graphs {
+
+    /// <summary>
+    /// the root node of every scene graph (internal use only) 
+    /// </summary>
+    internal class ILSceneGraphRoot : ILSceneGraphInnerNode {
+        
+        public event SceneGraphNodeHandler NodeAdded; 
+        public event SceneGraphNodeHandler NodeRemoved;  
+        
+        public ILSceneGraphRoot(ILPanel panel) : base(panel) { }
+
+        protected override void OnNodeAdded(ILSceneGraphNode node) {
+            if (NodeAdded != null && !m_eventingSuspended) {
+                NodeAdded(this, new ILSceneGraphNodeEventArgs(node)); 
+            }
+        }
+        protected override void OnNodeRemoved(ILSceneGraphNode node) {
+            if (NodeRemoved != null && !m_eventingSuspended) {
+                NodeRemoved(this, new ILSceneGraphNodeEventArgs(node)); 
+            }
+        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Graphs/ILSceneGraphShapedLeaf.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Graphs/ILSceneGraphShapedLeaf.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Graphs/ILSceneGraphShapedLeaf.cs	(revision 9102)
@@ -0,0 +1,171 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Drawing; 
+using ILNumerics.Drawing.Shapes; 
+
+namespace ILNumerics.Drawing.Graphs {
+
+    /// <summary>
+    /// a scene graph node, holding a single shape
+    /// </summary>
+    public class ILSceneGraphShapedLeaf : ILSceneGraphNode {
+
+        #region attributes
+        ILShape m_shape; 
+        #endregion
+
+        /// <summary>
+        /// create a new shaped leaf
+        /// </summary>
+        /// <param name="panel"></param>
+        public ILSceneGraphShapedLeaf(ILPanel panel) : base(panel) { }
+
+        #region properties
+        /// <summary>
+        /// Get / set the shape of the scene graph node
+        /// </summary>
+        public ILShape Shape {
+            get {
+                return m_shape;
+            }
+            set {
+                m_shape = value;
+                if (value != null) {
+                    value.SceneGraphNode = this; 
+                }
+            }
+        }
+        #endregion
+        /// <summary>
+        /// the minimum position of contained shape 
+        /// </summary>
+        public override ILPoint3Df PositionMin {
+            get {
+                if (m_shape != null)
+                    return m_shape.PositionMin;
+                else {
+                    return ILPoint3Df.Empty; 
+                }
+            }
+        }
+        /// <summary>
+        /// the maximum position of contained shape 
+        /// </summary>
+        public override ILPoint3Df PositionMax {
+            get {
+                if (m_shape != null)
+                    return m_shape.PositionMax;
+                else {
+                    return ILPoint3Df.Empty;
+                }
+            }
+        }
+        /// <summary>
+        /// the computed center of contained shape 
+        /// </summary>
+        public override ILPoint3Df Center {
+            get {
+                if (m_shape != null)
+                    return m_shape.Center;
+                else {
+                    return ILPoint3Df.Empty;
+                }
+            }
+        }
+        /// <summary>
+        /// invalidate this and all nodes up to root
+        /// </summary>
+        public override void Invalidate() {
+            Invalidate(false);         
+        }
+        /// <summary>
+        /// invalidate this node and all nodes up to root
+        /// </summary>
+        /// <param name="invalidateShape">true: invalidate the shape also</param>
+        public void Invalidate(bool invalidateShape) {
+            base.Invalidate();
+            if (invalidateShape && m_shape != null) {
+                m_shape.Invalidate(); 
+            }
+        }
+        /// <summary>
+        /// recompute the size spanned by this node, may fires Changed() event
+        /// </summary>
+        internal override void Configure() {
+            if (m_invalidated && m_shape != null) {
+                bool sizechanged = false;
+                m_shape.Configure();
+                if (m_shape.PositionMin != m_positionMin) sizechanged = true;
+                if (m_shape.PositionMax != m_positionMax) sizechanged = true;
+                m_positionMax = m_shape.PositionMax;
+                m_positionMin = m_shape.PositionMin; 
+                m_invalidated = false;
+                if (sizechanged)
+                    OnSizeChanged();
+            }
+        }
+        /// <summary>
+        /// Draw this shape contained in this node (internal use)  
+        /// </summary>
+        /// <param name="props"></param>
+        internal override void Draw(ILRenderProperties props) {
+            if (m_shape != null) {
+                m_shape.Draw(props); 
+            }
+        }
+        /// <summary>
+        /// compute limits of the cube tightly enclosing the branch below this node
+        /// </summary>
+        /// <returns></returns>
+        protected override void ComputeNodeLimits() {
+            if (m_shape != null) {
+                m_positionMin = m_shape.PositionMin;
+                m_positionMax = m_shape.PositionMax;
+            } else {
+                m_positionMax = ILPoint3Df.Empty;
+                m_positionMin = ILPoint3Df.Empty; 
+            }
+        }
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Graphs/ILSurfaceGraph.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Graphs/ILSurfaceGraph.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Graphs/ILSurfaceGraph.cs	(revision 9102)
@@ -0,0 +1,169 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing; 
+using ILNumerics.Drawing; 
+using ILNumerics.Drawing.Interfaces; 
+
+namespace ILNumerics.Drawing.Graphs {
+    /// <summary>
+    /// Surface graph
+    /// </summary>
+    public abstract class ILSurfaceGraph : ILFilledGraph, IILLegendRenderer, IILPanelConfigurator {
+
+        #region attributes
+        protected ShadingStyles m_shading;
+        #endregion
+
+        #region properties
+        /// <summary>
+        /// determine, how the color for surface tiles will be drawn
+        /// </summary>
+        /// <remarks>Interpolated will interpolate the color for the 
+        /// tiles between all corner data points. Flat will draw the area of the 
+        /// tile in a single color. The color than reflects the average value of 
+        /// all corner data points.</remarks>
+        public ShadingStyles Shading {
+            get {
+                return m_shading; 
+            }
+            set {
+                m_shading = value; 
+                OnChanged("Shading"); 
+            }
+        }
+        #endregion
+
+        #region constructor
+        /// <summary>
+        /// construct new surface graph, provide all 3 coordinates
+        /// </summary>
+        /// <param name="panel">panel this graph is to be hosted in</param>
+        /// <param name="X">X coordinates</param>
+        /// <param name="Y">Y coordinates</param>
+        /// <param name="Z">Z coordinates</param>
+        /// <param name="C">Color values</param>
+        /// <param name="clippingContainer"></param>
+        public ILSurfaceGraph(ILPanel panel, ILArray<float> X, ILArray<float> Y,
+                               ILArray<float> Z, ILArray<float> C, ILClippingData clippingContainer)
+            : base(panel, X, Y, Z, C, clippingContainer) {
+            using (ILScope.Enter(X, Y, Z, C)) {
+                m_graphType = GraphType.Surf;
+                m_wireLines.Width = 1;
+                m_wireLines.Antialiasing = false;
+                m_wireLines.Color = System.Drawing.Color.Blue;
+                m_opacity = 0.84f;
+            }
+        }
+        #endregion
+
+        #region ILFilledGraph overloads 
+        /// <summary>
+        /// create indices for ILSurfaceGraph triangles 
+        /// </summary>
+        /// <remarks>If possible, the indices will assemble triangle strips. If not -
+        /// the base implementation will be used to create individual triangles.</remarks>
+        protected override void CreateIndices() {
+            if (m_opacity == 1.0f &&  m_shading == ShadingStyles.Interpolate) {
+                #region no transparency
+                // simple case: DepthTest on, we can do fast drawing
+                // with low number on indices needed (triangle strips)
+                checkVertexIndicesLength(m_cols * 2,m_rows-1); 
+                int pos1 = 0, pos2 = m_cols, posI = 0; 
+                while (posI < m_indicesCount) {
+                    m_indices[posI++] = (uint)pos2++; 
+                    m_indices[posI++] = (uint)pos1++;
+                }
+                #endregion
+                if (m_wireLines.Visible) {
+                    #region looking from front
+                    posI = 0; 
+                    System.Diagnostics.Debug.WriteLine("CosPhi > 0 & SinPhi > 0 (grid front)");
+                    checkGridIndicesLength((m_cols-1) * 4 + 2,m_rows-1); 
+                    pos1 = m_Vertcount-m_cols; 
+                    pos2 = m_Vertcount-m_cols;
+                    // first row is special:
+                    for (int c = m_cols-1; c-->0;) {
+                        m_gridIndices[posI++] = (uint)pos1++; 
+                        m_gridIndices[posI++] = (uint)pos1; 
+                    }
+                    pos1 -= 2*m_cols-1; 
+                    for (int r = m_rows-1; r-->0;) {
+                        // first column is special: 
+                        m_gridIndices[posI++] = (uint)pos2; 
+                        m_gridIndices[posI++] = (uint)pos1; 
+                        for (int c = m_cols-1; c-->0;) {
+                            m_gridIndices[posI++] = (uint)pos1++; 
+                            m_gridIndices[posI++] = (uint)pos1; 
+                            m_gridIndices[posI++] = (uint)++pos2; 
+                            m_gridIndices[posI++] = (uint)pos1; 
+                        }
+                        pos1 -= (m_cols * 2 - 1); 
+                        pos2 -= (m_cols * 2 - 1);
+                    }
+                    #endregion
+                }
+            } else {
+                // create regular individual triangles 
+                base.CreateIndices();
+            }
+        }
+        public override bool Is3DGraph() {
+            return true;
+        }
+
+        #endregion
+
+        #region IILLegendRenderer
+        public abstract void DrawToLegend(ILRenderProperties p, Rectangle sampleRect, Rectangle labelRect);
+        public Size LabelSize { get { return m_label.Size; } }
+        #endregion 
+
+        #region IILPanelConfigurator
+        public void ConfigurePanel(ILPanel panel) {
+            panel.InteractiveMode = InteractiveModes.Rotating;
+            panel.DefaultView.Set(5.8f, 1.17f, panel.DefaultView.Distance); 
+        }
+
+        #endregion
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Interfaces/IILGraphFactory.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Interfaces/IILGraphFactory.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Interfaces/IILGraphFactory.cs	(revision 9102)
@@ -0,0 +1,81 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using ILNumerics.Drawing.Graphs;
+using System.Collections.Generic; 
+using ILNumerics.Drawing.Shapes; 
+
+namespace ILNumerics.Drawing.Interfaces {
+    /// <summary>
+    /// interface for a painter factory, capable of creating device dependend axes and graphs 
+    /// </summary>
+    /// <remarks>The interface is implemented by (device dependent) panel implementations. 
+    /// It is used to create the ILPanel's object hirarchy on startup. </remarks>
+    internal interface IILCreationFactory { 
+        /// <summary>
+        /// create an axis 
+        /// </summary>
+        /// <param name="name">axis name</param>
+        /// <param name="clippingView">clipping of the host</param>
+        /// <param name="parameters">additional parameters</param>
+        /// <returns>newly created axis object</returns>
+        ILAxis CreateAxis(AxisNames name, ILClippingData clippingView, params object[] parameters);
+        /// <summary>
+        /// Create a new specific ILGraph object (device dependent)
+        /// </summary>
+        /// <param name="data">numeric data for the new graph</param>
+        /// <param name="graphType">type of graph</param>
+        /// <param name="additionalParams">additional parameter</param>
+        /// <returns>newly created graph instance</returns>
+        ILGraph CreateGraph(ILInArray<float> data, GraphType graphType, params ILArray<float>[] additionalParams);
+        /// <summary>
+        /// create a new device dependant scene graph
+        /// </summary>
+        /// <returns>scene graph</returns>
+        ILSceneGraph CreateSceneGraph();
+
+        /// <summary>
+        /// create vertex renderer for rendering arbitrary vertices. 
+        /// </summary>
+        /// <param name="vertexType">underlying vertex type (value type)</param>
+        /// <returns>vertex renderer</returns>
+        ILVertexRenderer CreateVertexRenderer(Type vertexType, ILShape shape);
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Interfaces/IILLegendRenderer.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Interfaces/IILLegendRenderer.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Interfaces/IILLegendRenderer.cs	(revision 9102)
@@ -0,0 +1,60 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing; 
+using ILNumerics.Drawing.Labeling; 
+
+namespace ILNumerics.Drawing.Interfaces {
+    public interface IILLegendRenderer {
+        /// <summary>
+        /// Draws a small example of the visual output 
+        /// </summary>
+        /// <param name="p">Extended render properties</param>
+        /// <param name="sampleArea">Area to draw the line + marker into</param>
+        /// <param name="labelArea">Area to draw corresponding label into</param>
+        void DrawToLegend(ILRenderProperties p, Rectangle sampleArea, Rectangle labelArea); 
+        /// <summary>
+        /// Size of text label
+        /// </summary>
+        Size LabelSize {get; }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Interfaces/IILPanelConfigurator.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Interfaces/IILPanelConfigurator.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Interfaces/IILPanelConfigurator.cs	(revision 9102)
@@ -0,0 +1,52 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace ILNumerics.Drawing.Interfaces {
+    public interface IILPanelConfigurator {
+        /// <summary>
+        /// Implemented by custom graph objects, configures the hosting panel according to requirements of specific plot type
+        /// </summary>
+        /// <param name="panel">the panel to be configured</param>
+        void ConfigurePanel(ILPanel panel); 
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Interfaces/IILSupportsLight.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Interfaces/IILSupportsLight.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Interfaces/IILSupportsLight.cs	(revision 9102)
@@ -0,0 +1,50 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Drawing.Lighting; 
+
+namespace ILNumerics.Drawing.Interfaces {
+    interface IILSupportsLight {
+        ILMaterial Material { get; }
+        bool AutoNormals { get; set; } 
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Interfaces/IILTextInterpreter.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Interfaces/IILTextInterpreter.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Interfaces/IILTextInterpreter.cs	(revision 9102)
@@ -0,0 +1,68 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing; 
+using ILNumerics.Drawing.Labeling; 
+
+namespace ILNumerics.Drawing.Interfaces {
+    /// <summary>
+    /// interface for classes capable of transforming text 
+    /// expressions into visual output representation
+    /// </summary>
+    /// <seealso cref="ILNumerics.Drawing.Labeling.ILSimpleTexInterpreter"/>
+    public interface IILTextInterpreter {
+        /// <summary>
+        /// transform text element (text) into bitmap for rendering
+        /// </summary>
+        /// <param name="expression">item text expression, defines the visual output content</param>
+        /// <param name="font">font used for rendering the text</param>
+        /// <param name="color">initial color, unless overridden, used for items in expression</param>
+        /// <param name="renderer">IILTextRenderer implementation, used for caching the element(s)</param>
+        /// <returns>renderer queue, contains item keys and the size of transformed item expression</returns>
+        /// <remarks>The implementation should use the general caching capabilities 
+        /// of the renderer class. Therefore the item's elements must be cached subsequently
+        /// into the renderer before drawing. The render queue returned may be 
+        /// used for rendering in the same renderer than.</remarks>
+        ILRenderQueue Transform(
+                string expression, Font font, Color color, IILTextRenderer renderer);  
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Interfaces/IILTextRenderer.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Interfaces/IILTextRenderer.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Interfaces/IILTextRenderer.cs	(revision 9102)
@@ -0,0 +1,163 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing; 
+using ILNumerics.Drawing; 
+using ILNumerics.Drawing.Labeling; 
+
+namespace ILNumerics.Drawing.Interfaces {
+    /// <summary>
+    /// interface for all classes capable of renderung (device 
+    /// dependend) texts into plot panels 
+    /// </summary>
+    /// <remarks>class definitions should also implement the ILRendererAttribute. See <see cref="ILNumerics.Drawing.Platform.OpenGL.ILOGLRenderer"/> for an example.</remarks>
+    /// <seealso cref="ILNumerics.Drawing.Platform.OpenGL.ILOGLRenderer"/>
+    public interface IILTextRenderer {
+        /// <summary>
+        /// The name of the TextRenderer instance (implementation dependent)
+        /// </summary>
+        string Name { get; }
+        /// <summary>
+        /// A more descriptive name to be displayed into GUI's (implementation dependent)
+        /// </summary>
+        string NameLong { get; } 
+        /// <summary>
+        /// Get the graphics device type this TextRenderer instance 
+        /// is capable to use for drawing 
+        /// </summary>
+        GraphicDeviceType DeviceType { get; }
+        /// <summary>
+        /// Determine, if the text is to be drawn after the rendering 
+        /// backbuffer has been swapped and presented to the screen. (implementation dependent)
+        /// </summary>
+        bool DrawAfterBufferSwapped { get; } 
+        /// <summary>
+        /// Determine, if this renderer chaches the output (implementation dependent) 
+        /// </summary>
+        bool Cached { get; }
+        /// <summary>
+        /// Determine the coord system this renderer is specialized to draw in
+        /// </summary>
+        CoordSystem CoordSystem { get; }
+        /// <summary>
+        /// begins drawing, to be called before Draw()!
+        /// </summary>
+        /// <param name="p">extended render properties</param>
+        void Begin (ILRenderProperties p);
+        /// <summary>
+        /// begins drawing and queries current model view matrix also
+        /// </summary>
+        /// <param name="p">extended render properties</param>
+        /// <param name="modelview">current modelviewmatrix</param>
+        void Begin (ILRenderProperties p, ref double[] modelview);
+        /// <summary>
+        /// Draw the text (screen coords)
+        /// </summary>
+        /// <param name="renderQueue">contains items to be drawn</param>
+        /// <param name="position">position relative to surface, starting point for drawing</param>
+        /// <param name="orientation">orientation for item</param>
+        /// <param name="color">initial or default color</param>
+        /// <remarks>
+        /// 	<para>Before calling Draw(), the TextRenderer must have been initialized with Begin(g)!</para>
+        /// 	<para>use this function if drawing in screen coords, the size for render
+        /// output will be taken from the Size member of the render queue (pixels).</para>
+        /// </remarks>
+        /// <exception cref="InvalidOperationException">on attempt to draw any text without previous initialization</exception>
+        void Draw (ILRenderQueue renderQueue, System.Drawing.Point position, TextOrientation orientation, Color color); 
+        /// <summary>
+        /// Draws the text in world coords 
+        /// </summary>
+        /// <param name="renderQueue">contains items to be drawn</param>
+        /// <param name="x1">x1-position</param>
+        /// <param name="y1">y1-position</param>
+        /// <param name="z1">z1-position</param>
+        /// <param name="x2">x2-position</param>
+        /// <param name="y2">y2-position</param>
+        /// <param name="z2">z2-position</param>
+        /// <param name="color">base color for items not containing individual colors</param>
+        /// <remarks>
+        /// <para>Before calling Draw(), the TextRenderer must have been initialized with Begin(g)!</para>
+        /// <para>Use this function to draw the render queue in world coords. The position parameters mark the upper left 
+        /// and lower right corner of the quads to contain the render queue content.</para>
+        /// </remarks>
+        /// <exception cref="InvalidOperationException">on attempt to draw any text without previous initialization</exception>
+        void Draw (ILRenderQueue renderQueue, float x1, float y1, float z1, float x2, float y2, float z2, Color color); 
+        /// <summary>
+        /// finalizes the drawing (must prepare it again before drawing!)
+        /// </summary>
+        void End(ILRenderProperties p); 
+        /// <summary>
+        /// Cache single item into the renderer cache. 
+        /// </summary>
+        /// <param name="key">key used to uniquely identify the item in cache</param>
+        /// <param name="bmp">item bitmap data</param>
+        /// <param name="rect">section in bmp to be transfered into the cache</param>
+        void Cache(string key, Bitmap bmp, RectangleF rect); 
+        /// <summary>
+        /// test if an item for a specific key is already cached
+        /// </summary>
+        /// <param name="key"></param>
+        /// <returns></returns>
+        bool ExistsKey(string key); 
+        /// <summary>
+        /// test if the key exists and return the size of corresponding item on success
+        /// </summary>
+        /// <param name="key">key identifying the item</param>
+        /// <param name="size">if the key was found: the size of the corresponding item</param>
+        /// <returns>true, if the key exist, false otherwise</returns>
+        bool TryGetSize(string key, ref Size size);
+        /// <summary>
+        /// if set to a color (not Color.Empty), that color will be used for all renderings. 
+        /// The color contained in the rendering queue is ignored than.
+        /// </summary>
+        Color ColorOverride {
+            get;
+            set; 
+        }
+
+        /// <summary>
+        /// for cached renderers, fires if the internal cache was cleared
+        /// </summary>
+        event EventHandler CacheCleared; 
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Interfaces/IILVertexDefinition.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Interfaces/IILVertexDefinition.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Interfaces/IILVertexDefinition.cs	(revision 9102)
@@ -0,0 +1,97 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Drawing; 
+using System.Text;
+
+namespace ILNumerics.Drawing.Interfaces {
+
+    /// <summary>
+    /// definition of vertex data &amp; properties
+    /// </summary>
+    public interface IILVertexDefinition {
+        /// <summary>
+        /// determine, if the vertex is able to store individual alpha values
+        /// </summary>
+        bool StoresAlpha { get; }
+        /// <summary>
+        /// determine, if the vertex is able to store individual color values
+        /// </summary>
+        bool StoresColor { get; }
+        /// <summary>
+        /// determine, if the vertex is able to store normal data 
+        /// </summary>
+        bool StoresNormals { get; }
+        /// <summary>
+        /// Get/set the alpha value for the vertex
+        /// </summary>
+        byte Alpha { get; set; }
+        /// <summary>
+        /// Set the color for the vertex, alpha value is not modified!
+        /// </summary>
+        Color Color { get; set; }
+        /// <summary>
+        /// get/set position (X,Y,Z values) for the vertex 
+        /// </summary>
+        ILPoint3Df Position { get; set; }
+        /// <summary>
+        /// Get/set the normal vector for the value (see also: AutoCalculateNormals) 
+        /// </summary>
+        ILPoint3Df Normal { get; set; }
+        /// <summary>
+        /// get/set the X coordinate value for the vertex
+        /// </summary>
+        float XPosition { get; set; }
+        /// <summary>
+        /// get/set the Y coordinate value for the vertex
+        /// </summary>
+        float YPosition { get; set; }
+        /// <summary>
+        /// get/set the Z coordinate value for the vertex
+        /// </summary>
+        float ZPosition { get; set; }
+        /// <summary>
+        /// size of single vertex in bytes
+        /// </summary>
+        int VertexSize { get; }
+    }
+
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Labeling/ILHashCreator.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Labeling/ILHashCreator.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Labeling/ILHashCreator.cs	(revision 9102)
@@ -0,0 +1,75 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing; 
+
+namespace ILNumerics.Drawing.Labeling {
+    /// <summary>
+    /// Helper class used to create hashes for renderable items (currently text only)
+    /// </summary>
+    /// <remarks>This class should be used to retrieve an (unique) key for any 
+    /// renderable items used in ILNumerics.Drawing renderer classes. This way on can 
+    /// ensure not to create hash conflicts between different cached items.
+    ///  </remarks>
+    public class ILHashCreator {
+
+        /// <summary>
+        /// create hash for a text item, used to uniquely identify the item in a collection
+        /// </summary>
+        /// <param name="font">font used to draw the character</param>
+        /// <param name="text">text content</param>
+        /// <returns>string as key into collection. The key is: F:[(int)FontStyle][Size (3digits)]&[FontName]&text</returns>
+        public static string Hash (Font font, string text) {
+            return String.Format("F:{0}&{1:g3}&{2}&{3}",(int)font.Style,font.Size,font.Name,text); 
+        }
+
+        /// <summary>
+        /// create unique hash for bitmaps
+        /// </summary>
+        /// <param name="bitmap">bitmap</param>
+        /// <returns>unique key identifying the bitmap</returns>
+        public static string Hash (Bitmap bitmap) {
+            throw new NotImplementedException(); 
+        }
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Labeling/ILLabel.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Labeling/ILLabel.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Labeling/ILLabel.cs	(revision 9102)
@@ -0,0 +1,135 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Drawing;
+
+namespace ILNumerics.Drawing.Labeling {
+    /// <summary>
+    /// general label, mainly used for ILAxis
+    /// </summary>
+    public class ILLabel : ILLabelingElement {
+
+        #region attributes
+        private int m_padding; 
+        private LabelAlign m_align; 
+        internal Point m_position = new Point();
+        private bool m_visible; 
+        #endregion
+
+        #region properties 
+        /// <summary>
+        /// get/set visibility for the label
+        /// </summary>
+        public bool Visible {
+            get { return m_visible; }
+            set { m_visible = value; }
+        }
+        /// <summary>
+        /// get/ set the position for the label
+        /// </summary>
+        public Point Position {
+            get {
+                return m_position; 
+            }
+            set {
+                m_position = value; 
+            }
+        }
+        /// <summary>
+        /// Alignment along the axis value range. Possible values: lower, center, upper
+        /// </summary>
+        public LabelAlign Alignment {
+            get {
+                return m_align; 
+            }
+            set {
+                m_align = value; 
+                OnChanged(); 
+            }
+        }
+        /// <summary>
+        /// Get/ set the padding used to seperate the label from the elements around it
+        /// </summary>
+        public int Padding {
+            get {
+                return m_padding; 
+            }
+            set {
+                m_padding = value; 
+                OnChanged(); 
+            }
+        }
+        #endregion
+
+        #region constructor
+        /// <summary>
+        /// create a label for rendering
+        /// </summary>
+        public ILLabel (ILPanel panel) 
+            : base(panel,new Font(FontFamily.GenericSansSerif,10.0f),Color.DarkBlue) {
+            m_align = LabelAlign.Center; 
+            m_padding = 3;
+            m_visible = true; 
+        }
+        #endregion
+
+        #region abstract overrides
+
+        /// <summary>
+        /// draws the whole rendering queue
+        /// </summary>
+        public override void Draw(ILRenderProperties p) {
+            if (!m_visible || String.IsNullOrEmpty(m_expression)) return; 
+            if (m_expression != m_cachedExpression) 
+                interprete(m_expression); 
+            m_renderer.Begin(p);
+            Point renderPoint = offsetAlignment(m_size, m_position);
+            m_renderer.Draw(m_renderQueue, renderPoint ,m_orientation, m_color); 
+            m_renderer.End(p); 
+        }
+
+        #endregion
+
+        #region private helper
+
+
+        #endregion
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Labeling/ILLabelingElement.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Labeling/ILLabelingElement.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Labeling/ILLabelingElement.cs	(revision 9102)
@@ -0,0 +1,333 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Drawing; 
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Drawing.Interfaces; 
+using ILNumerics.Drawing; 
+
+namespace ILNumerics.Drawing.Labeling {
+    /// <summary>
+    /// Base class for text elements 
+    /// </summary>
+    public abstract class ILLabelingElement {
+
+#region event handler
+
+        /// <summary>
+        /// fires when an element's property has changed
+        /// </summary>
+        public event EventHandler Changed;
+        
+        protected virtual void OnChanged() {
+            if (Changed != null) 
+                Changed(this,null); 
+        }
+
+#endregion
+
+#region attributes
+
+        protected String m_expression; 
+        protected String m_cachedExpression; 
+        protected Color m_color; 
+        protected Font m_font; 
+        protected Size m_size; 
+        internal PointF m_anchor; 
+        protected TextOrientation m_orientation; 
+        protected IILTextInterpreter m_interpreter; 
+        protected IILTextRenderer m_renderer;
+        protected ILRenderQueue m_renderQueue; 
+
+#endregion
+
+#region properties 
+
+        /// <summary>
+        /// Size of the label for rendering, regardless of orientation
+        /// </summary>
+        public virtual Size Size {
+            get {
+                if (m_cachedExpression != m_expression) {
+                    interprete(m_expression); 
+                }
+                return m_size; 
+            }
+        }
+        /// <summary>
+        /// color used to display the element
+        /// </summary>
+        public virtual Color Color {
+            get { return m_color; }
+            set { 
+                m_color = value; 
+                OnChanged(); 
+            }
+        }
+        /// <summary>
+        /// Get/set system font used to draw the text
+        /// </summary>
+        public virtual Font Font { 
+            get { return m_font; }
+            set { 
+                if (m_font != null && 
+                    (m_font.Name != value.Name || 
+                    m_font.Style != value.Style ||
+                    m_font.Size != value.Size)) { 
+                    m_font = value;
+                    interprete(m_expression);  
+                    OnChanged();
+                }
+            }
+        }
+        /// <summary>
+        /// Get the orientation for the labeling element or sets it
+        /// </summary>
+        public virtual TextOrientation Orientation {
+            get { return m_orientation; }
+            set { 
+                m_orientation = value; 
+                OnChanged(); 
+            }
+        }
+        /// <summary>
+        /// Get/set the relative offset of the 'Position' point rel. to the overall label size, range 0..1 for X and Y 
+        /// </summary>
+        public PointF Anchor {
+            get {
+                return m_anchor; 
+            }
+            set {
+                m_anchor = value; 
+                OnChanged(); 
+            }
+        }
+        /// <summary>
+        /// Text interpreter used to transform labeling source into bitmap
+        /// </summary>
+        public IILTextInterpreter Interpreter {
+            get { return m_interpreter; }
+            set { 
+                if (value != null) {
+                    m_interpreter = value; 
+                    OnChanged(); 
+                }
+            }
+        }
+        /// <summary>
+        /// device dependent renderer, used to draw the labeling bitmap onto panel
+        /// </summary>
+        public IILTextRenderer Renderer {
+            get { return m_renderer; }
+            set { 
+                if (value != null) {
+                    m_renderer = value; 
+                    OnChanged(); 
+                }
+            }
+        }
+        /// <summary>
+        /// Get / set the text expression defining the content to be displayed 
+        /// </summary>
+        /// <remarks><para>The expression may contain markups according to 
+        /// the specific interpreter instance.</para></remarks>
+        public string Text {
+            get {
+                return m_expression; 
+            }
+            set {
+                if (value != m_expression) {
+                    m_expression = value; 
+                    // (clean up, interpret & cache: when drawing)
+                    OnChanged(); 
+                }
+            }
+        }
+
+#endregion
+
+#region constructor
+        /// <summary>
+        /// [abstract] Create a new labeling element 
+        /// </summary>
+        /// <param name="panel">panel hosting the element</param>
+        /// <param name="font">default font for the element</param>
+        /// <param name="color">default color for the element</param>
+        public ILLabelingElement(ILPanel panel, Font font, Color color) 
+            : this(panel,font,color,CoordSystem.Screen) {
+        }
+
+        /// <summary>
+        /// [abstract] Create a new labeling element 
+        /// </summary>
+        /// <param name="panel">panel hosting the element</param>
+        /// <param name="font">default font for the element</param>
+        /// <param name="color">default color for the element</param>
+        /// <param name="coordSystem">world / screen rendering method</param>
+        public ILLabelingElement (ILPanel panel, Font font, Color color, CoordSystem coordSystem) {
+            if (font != null) {
+                m_font = font; 
+            } else {
+                m_font = new System.Drawing.Font(
+                    System.Drawing.FontFamily.GenericSansSerif,10.0f);
+            }
+            m_color = color; 
+            m_orientation = TextOrientation.Horizontal; 
+            m_renderQueue = null; 
+            m_size = Size.Empty; 
+            m_expression = string.Empty; 
+            // init interpreter & renderer
+            m_renderer = panel.TextRendererManager.GetDefault(coordSystem);
+            m_renderer.CacheCleared += new EventHandler(m_renderer_CacheCleared);
+            m_interpreter = new ILSimpleTexInterpreter(); 
+        }
+
+#endregion
+
+#region public methods 
+
+        /// <summary>
+        /// Dispose off this element's ressources
+        /// </summary>
+        internal void Dispose() {
+            if (m_renderer != null) {
+                m_renderer.CacheCleared -= m_renderer_CacheCleared;
+                if (m_renderer is IDisposable) {
+                    (m_renderer as IDisposable).Dispose();
+                }
+                m_renderer = null; 
+            }
+        }
+        /// <summary>
+        /// draws the whole rendering queue
+        /// </summary>
+        public virtual void Draw(ILRenderProperties p) {
+            if (m_expression != m_cachedExpression) 
+                interprete(m_expression); 
+            m_renderer.Begin(p);
+            m_renderer.Draw(m_renderQueue,offsetAlignment(m_renderQueue.Size),m_orientation,m_color); 
+            m_renderer.End(p); 
+        }
+
+#endregion
+
+#region helper methods
+        
+        /// <summary>
+        /// if the renderer cleares its cache, the expression needs to be re-interpreted
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        protected void m_renderer_CacheCleared(object sender, EventArgs e) {
+            m_cachedExpression = ""; 
+        }
+        /// <summary>
+        /// add offset to an existing point according to internal alignment
+        /// </summary>
+        /// <param name="size">size of content to be aligned</param>
+        /// <param name="point">original point</param>
+        protected void offsetAlignment(Size size, ref Point point) {
+            if (m_orientation == TextOrientation.Vertical) {
+                point.X = point.X + (int)(m_anchor.Y * size.Height);
+                point.Y = point.Y - (int)(m_anchor.X * size.Width); 
+                //if (0 != (TickLabelAlign.right & m_alignment)) {
+                //    // point.X = point.X; 
+                //} else if (0 != (TickLabelAlign.center & m_alignment)) {
+                //    point.X = point.X - size.Height / 2; 
+                //} else 
+                //    point.X = point.X + size.Height; 
+                //if (0 != (TickLabelAlign.bottom & m_alignment)) {
+                //    point.Y = point.Y - size.Width;     
+                //} else if (0 != (TickLabelAlign.vertCenter & m_alignment)) {
+                //    point.Y = point.Y - size.Width / 2; 
+                //} //else point.Y = point.Y; 
+            } else {
+                point.X = point.X - (int)(m_anchor.X * size.Width);
+                point.Y = point.Y - (int)(m_anchor.Y * size.Height);
+                //if (0 != (TickLabelAlign.right & m_alignment)) { 
+                //    point.X = point.X - size.Width;     
+                //} else if (0 != (TickLabelAlign.center & m_alignment)) {
+                //    point.X = point.X - size.Width / 2; 
+                //} // else point.X = point.X; 
+                //if (0 != (TickLabelAlign.bottom & m_alignment)) {
+                //    point.Y = point.Y - size.Height;     
+                //} else if (0 != (TickLabelAlign.vertCenter & m_alignment)) {
+                //    point.Y = point.Y - size.Height / 2; 
+                //} // else point.Y = point.Y; 
+            }
+        }
+        /// <summary>
+        /// return offset according to current setting of m_alignment
+        /// </summary>
+        /// <param name="size">size of an element to align</param>
+        /// <returns>offset according to Alignment property</returns>
+        protected Point offsetAlignment(Size size) {
+            Point ret = new Point(); 
+            offsetAlignment(size, ref ret); 
+            return ret; 
+        }
+        /// <summary>
+        /// return offset according to current setting of m_alignment
+        /// </summary>
+        /// <param name="size">size of an element to align</param>
+        /// <param name="p">point inside rectangle of size 'size'</param>
+        /// <returns>offset according to Alignment property</returns>
+        protected Point offsetAlignment(Size size, Point p) {
+            offsetAlignment(size, ref p); 
+            return p; 
+        }
+        /// <summary>
+        /// interprete the expression and cache render queue
+        /// </summary>
+        /// <param name="expression"></param>
+        protected void interprete(string expression) {
+            if (m_renderQueue != null)
+                m_renderQueue.Clear(); 
+            m_renderQueue = 
+                m_interpreter.Transform(expression,m_font,m_color,m_renderer);
+            m_size = m_renderQueue.Size; 
+            m_cachedExpression = expression; 
+        }
+
+#endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Labeling/ILRenderQueue.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Labeling/ILRenderQueue.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Labeling/ILRenderQueue.cs	(revision 9102)
@@ -0,0 +1,170 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections; 
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing; 
+
+namespace ILNumerics.Drawing.Labeling {
+    /// <summary>
+    /// the class collects renderable items which define 
+    /// the graphical output for a render expression
+    /// </summary>
+    /// <remarks>ILRenderQueues are semi-immutable. Instances - once created - can only be cleared and 
+    /// re-created, but not altered. Therefore, they keep the size of the output cached over their livetime.</remarks>
+    public class ILRenderQueue : IEnumerable {
+
+        #region attributes 
+        Size m_size; 
+        List<ILRenderQueueItem> m_list; 
+        String m_expression;
+        #endregion
+
+        #region constructor
+        /// <summary>
+        ///  constructor, creates a new render queue with content
+        /// </summary>
+        /// <param name="expression">expression, which led to this queue</param>
+        /// <param name="queue">prepared queue</param>
+        /// <param name="size">size of content after rendering</param>
+        public ILRenderQueue(string expression, List<ILRenderQueueItem> queue, Size size) : base () {
+            m_size = size; 
+            m_list = queue; 
+            m_expression = expression;
+        }
+        #endregion 
+
+        #region properties 
+        /// <summary>
+        /// overall size of content of this render queue
+        /// </summary>
+        public Size Size {
+            get {
+                return m_size;     
+            }
+        }
+
+        /// <summary>
+        /// Expression which led to this queue
+        /// </summary>
+        public string Expression {
+            get { return m_expression; }
+        }
+        #endregion
+
+        #region IList<ILRenderQueueItem> Member
+
+        public int IndexOf(ILRenderQueueItem item) {
+            return m_list.IndexOf(item); 
+        }
+
+        //public void Insert(int index, ILRenderQueueItem item) {
+        //    m_list.Insert(index,item); 
+        //}
+
+        //public void RemoveAt(int index) {
+        //    m_list.RemoveAt(index); 
+        //}
+
+        public ILRenderQueueItem this[int index] {
+            get {
+                return m_list[index]; 
+            }
+            //set {
+            //    m_list[index] = value; 
+            //}
+        }
+
+        #endregion
+
+        #region ICollection<ILRenderQueueItem> Member
+
+        //public void Add(ILRenderQueueItem item) {
+        //    // todo: implement pooling of render queue item objects! 
+        //    m_list.Add(item); 
+        //}
+
+        public void Clear() {
+            // todo: implement pooling of render queue item objects! 
+            m_list.Clear(); 
+        }
+
+        public bool Contains(ILRenderQueueItem item) {
+            return m_list.Contains(item); 
+        }
+
+        public void CopyTo(ILRenderQueueItem[] array, int arrayIndex) {
+            m_list.CopyTo(array,arrayIndex); 
+        }
+
+        public int Count {
+            get { return m_list.Count;  }
+        }
+
+        public bool IsReadOnly {
+            get { return false; }
+        }
+
+        //public bool Remove(ILRenderQueueItem item) {
+        //    return m_list.Remove(item); 
+        //}
+
+        #endregion
+
+        #region IEnumerable<ILRenderQueueItem> Member
+
+        public IEnumerator<ILRenderQueueItem> GetEnumerator() {
+            foreach (ILRenderQueueItem item in m_list) 
+                yield return item; 
+        }
+
+        #endregion
+
+        #region IEnumerable Member
+
+        IEnumerator IEnumerable.GetEnumerator() {
+            return m_list.GetEnumerator(); 
+        }
+
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Labeling/ILRenderQueueItem.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Labeling/ILRenderQueueItem.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Labeling/ILRenderQueueItem.cs	(revision 9102)
@@ -0,0 +1,87 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Drawing; 
+
+namespace ILNumerics.Drawing.Labeling {
+    /// <summary>
+    /// Single item with rendering instructions, used in ILRenderQueues
+    /// </summary>
+    public class ILRenderQueueItem { 
+        /// <summary>
+        /// unique key, identifies the item in the render cache
+        /// </summary>
+        public string Key; 
+        /// <summary>
+        /// rendering offset for the item (used for sub-/superscripts etc.)
+        /// </summary>
+        public Point Offset; 
+        /// <summary>
+        /// individual color for the item 
+        /// </summary>
+        /// <remarks>If this property is set to Color.Empty, the item will 
+        /// be drawn with the color assigned to hosting element.</remarks>
+        public Color Color; 
+
+        /// <summary>
+        /// construct a new ILRenderQueueItem
+        /// </summary>
+        /// <param name="key">unique key</param>
+        /// <param name="xOffset">x coordinate for offset</param>
+        /// <param name="yOffset">y coordinate for offset</param>
+        /// <param name="color">individual color</param>
+        public ILRenderQueueItem (string key, int xOffset, int yOffset, Color color) {
+            Key = key; 
+            Offset = new Point(xOffset,yOffset); 
+            Color = color; 
+        }
+        /// <summary>
+        /// construct a new ILRenderQueueItem
+        /// </summary>
+        /// <param name="key">unique key</param>
+        /// <param name="offset">offset</param>
+        /// <param name="color">individual color</param>
+        public ILRenderQueueItem (string key, Point offset, Color color) {
+            Key = key; 
+            Offset = offset;
+            Color = color; 
+        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Labeling/ILRendererAttribute.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Labeling/ILRendererAttribute.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Labeling/ILRendererAttribute.cs	(revision 9102)
@@ -0,0 +1,100 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace ILNumerics.Drawing.Labeling {
+    /// <summary>
+    /// attribute used to identify IILTextRenderer types within assemblies 
+    /// </summary>
+    public class ILRendererAttribute : Attribute {
+        /// <summary>
+        /// the type of graphic device, the renderer is able to handle
+        /// </summary>
+        public readonly GraphicDeviceType GraphicDeviceType; 
+        /// <summary>
+        /// short name describing the renderer
+        /// </summary>
+        public readonly string Name; 
+        /// <summary>
+        /// long name describing the renderer
+        /// </summary>
+        public readonly string NameLong; 
+        /// <summary>
+        /// determine, if this renderer should be used as default 
+        /// renderer for the graphic device and the coord system
+        /// </summary>
+        public readonly bool IsDefault; 
+
+        /// <summary>
+        /// Detemine the coord system the renderer is based on
+        /// </summary>
+        public readonly CoordSystem Coords; 
+
+        /// <summary>
+        /// Constructor for a new attribute describing non-default renderer
+        /// </summary>
+        /// <param name="type">graphic device type </param>
+        /// <param name="Name">short name</param>
+        /// <param name="NameLong">long name</param>
+        public ILRendererAttribute(GraphicDeviceType type, string Name, string NameLong) {
+            this.GraphicDeviceType = type; 
+            this.Name = Name; 
+            this.NameLong = NameLong; 
+            this.IsDefault = false;
+            this.Coords = CoordSystem.Screen; 
+        }
+        /// <summary>
+        /// Constructor creating a new renderer attribute
+        /// </summary>
+        /// <param name="type">graphic device type </param>
+        /// <param name="Name">short name</param>
+        /// <param name="NameLong">long name</param>
+        /// <param name="Default">'default' flag</param>
+        public ILRendererAttribute(GraphicDeviceType type, string Name, string NameLong, bool Default, CoordSystem coords) {
+            this.GraphicDeviceType = type; 
+            this.Name = Name; 
+            this.NameLong = NameLong; 
+            this.IsDefault = Default;
+            this.Coords = coords;
+        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Labeling/ILShapeLabel.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Labeling/ILShapeLabel.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Labeling/ILShapeLabel.cs	(revision 9102)
@@ -0,0 +1,168 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing; 
+using ILNumerics.Drawing.Graphs; 
+using ILNumerics.Drawing; 
+using ILNumerics.Drawing.Interfaces; 
+
+
+namespace ILNumerics.Drawing.Labeling {
+    /// <summary>
+    /// a label used for labeling shapes (screen coords, defined via world coords)
+    /// </summary>
+    public class ILShapeLabel : ILLabelingElement {
+ 
+        #region attributes 
+        ILPanel m_panel;
+        CoordSystem m_coordSystem;
+        Color m_fringeColor = Color.LightGray;
+        ILArray<int> m_fringeOffsets = ILMath.returnType<int>();
+        #endregion
+
+        #region properties
+        /// <summary>
+        /// get/set the color used for drawing a fringe around glyphs, empty: no fringe
+        /// </summary>
+        public Color FringeColor {
+            get { return m_fringeColor; }
+            set { m_fringeColor = value; }
+        }
+        #endregion
+
+        #region constructors
+        public ILShapeLabel(ILPanel panel) : base(panel, null, Color.Black) {
+            m_panel = panel; 
+            m_coordSystem = CoordSystem.Screen;
+            m_anchor = new PointF(.5f,.5f);  // TickLabelAlign.center | TickLabelAlign.vertCenter;
+            m_fringeOffsets.a = new int[,]{ 
+                { -1, -1 },
+                { -1,  0 },
+                { -1,  1 },
+                {  0, -1 },
+                {  0,  1 },
+                {  1, -1 },
+                {  1,  0 },
+                {  1,  1 }};
+            m_fringeOffsets.a = m_fringeOffsets.T; 
+        }
+        public ILShapeLabel(ILPanel panel, CoordSystem coordSystem) 
+            : base(panel, null, Color.Black) {
+            m_panel = panel;
+            m_coordSystem = CoordSystem.Screen;
+            m_anchor = new PointF(.5f, .5f);  // TickLabelAlign.center | TickLabelAlign.vertCenter;
+            m_renderer.CacheCleared -= new EventHandler(m_renderer_CacheCleared);
+            m_renderer = panel.TextRendererManager.GetDefault(coordSystem);
+            m_renderer.CacheCleared += new EventHandler(m_renderer_CacheCleared);
+            m_fringeOffsets.a = new int[,]{ 
+                { -1, -1 },
+                { -1,  0 },
+                { -1,  1 },
+                {  0, -1 },
+                {  0,  1 },
+                {  1, -1 },
+                {  1,  0 },
+                {  1,  1 }};
+            m_fringeOffsets.a = m_fringeOffsets.T; 
+        }
+        #endregion
+
+        #region public interface
+        /// <summary>
+        /// (internal use)
+        /// </summary>
+        /// <param name="p">render properties</param>
+        /// <param name="center">center position for the label</param>
+        public void Draw(ILRenderProperties p, ILPoint3Df center ) {
+            if (!String.IsNullOrEmpty(Text)) {
+                if (m_expression != m_cachedExpression) 
+                    interprete(m_expression);
+                double[] modelview = null;
+                m_renderer.Begin(p, ref modelview);
+                Point dest = m_panel.World2Screen(center, modelview);
+                offsetAlignment(m_size, ref dest);
+                if (m_fringeColor.IsEmpty) {
+                    m_renderer.Draw(m_renderQueue, dest, TextOrientation.Horizontal, m_color);
+                } else {
+                    drawFringed(m_renderer, m_renderQueue, dest, TextOrientation.Horizontal, m_color); 
+                }
+                m_renderer.End(p); 
+            }
+        }
+
+        /// <summary>
+        /// draws a fringe around the render output in fringe color
+        /// </summary>
+        /// <param name="m_renderer"></param>
+        /// <param name="m_rendererQueue"></param>
+        /// <param name="dest"></param>
+        /// <param name="textOrientation"></param>
+        /// <param name="m_color"></param>
+        private void drawFringed(IILTextRenderer m_renderer, object m_rendererQueue, Point dest, TextOrientation textOrientation, Color m_color) {
+            m_renderer.ColorOverride = m_fringeColor; 
+            for (int i = 0; i < m_fringeOffsets.Size[0]; i++) {
+                m_renderer.Draw(m_renderQueue
+                                , new Point(dest.X + m_fringeOffsets.GetValue(i,0), dest.Y + m_fringeOffsets.GetValue(i,1))
+                                , TextOrientation.Horizontal, m_fringeColor);
+            }
+            m_renderer.ColorOverride = Color.Empty; 
+            m_renderer.Draw(m_renderQueue, dest, TextOrientation.Horizontal, m_color);
+
+        }
+        /// <summary>
+        /// (internal use)
+        /// </summary>
+        /// <param name="p">render properties</param>
+        /// <param name="min">minimum coord for label area</param>
+        /// <param name="max">maximum coord for label area</param>
+        public void Draw(ILRenderProperties p, ILPoint3Df min, ILPoint3Df max) {
+            if (!String.IsNullOrEmpty(Text)) {
+                if (m_expression != m_cachedExpression) 
+                    interprete(m_expression);
+                m_renderer.Begin(p);
+                m_renderer.Draw(m_renderQueue,min.X,min.Y,min.Z,max.X,max.Y,max.Z, m_color);
+                m_renderer.End(p);
+            }
+        }
+        #endregion
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Labeling/ILSimpleInterpreter.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Labeling/ILSimpleInterpreter.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Labeling/ILSimpleInterpreter.cs	(revision 9102)
@@ -0,0 +1,238 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Text;
+using System.Drawing; 
+using System.Collections.Generic;
+using ILNumerics.Drawing; 
+using ILNumerics.Drawing.Interfaces; 
+
+namespace ILNumerics.Drawing.Labeling {
+    /// <summary>
+    /// Transforms characters into bitmaps (1:1)
+    /// </summary>
+    /// <remarks>this is the base class for most IILTextInterpreter implementations</remarks>
+    public class ILSimpleInterpreter : IILTextInterpreter {
+
+#region attributes
+        static Graphics m_measGraphics; 
+        static Bitmap m_measBitmap; 
+        protected Font m_normalFont; 
+        protected Size m_size;
+#endregion
+
+#region constructor
+        
+        /// <summary>
+        /// create a new instance of this text interpreter
+        /// </summary>
+        public ILSimpleInterpreter () : base () {
+            resizeMeasureBMP(20,20);
+        }
+
+#endregion
+
+#region helper functions 
+
+        protected void resizeMeasureBMP(int width, int height) {
+            if (m_measBitmap != null) 
+                m_measBitmap.Dispose(); 
+            if (m_measGraphics != null)
+                m_measGraphics.Dispose(); 
+            m_measBitmap = new Bitmap(width+1,height+1); 
+            m_measGraphics = Graphics.FromImage(m_measBitmap); 
+        }
+
+        protected virtual void parseString (string expression, Font font, Point offset, Color color, 
+                                    IILTextRenderer renderer, ref Size size, 
+                                    ref List<ILRenderQueueItem> queue) {
+            int pos = 0;
+            string key, itemText; 
+            RectangleF bmpSize = new RectangleF(); 
+            int curHeigth = 0, curWidth = 0; 
+            Bitmap itemBMP = null; 
+            int lineHeight = 0, lineWidth = 0; 
+            Size itemSize = Size.Empty; 
+            while (pos < expression.Length) {
+                itemText = expression.Substring(pos++,1);
+                key = ILHashCreator.Hash(font,itemText); 
+                
+                if (renderer.TryGetSize(key, ref itemSize)) {
+                    queue.Add(new ILRenderQueueItem(key,offset,color));
+                    if (itemSize.Height > lineHeight) lineHeight = itemSize.Height; 
+                    lineWidth += (int)itemSize.Width;
+                } else {
+                    lock (this) {
+                        itemBMP = transformItem(itemText,font,out bmpSize); 
+                        renderer.Cache(key,itemBMP,bmpSize); 
+                        queue.Add(new ILRenderQueueItem(key,offset,color)); 
+                        // update size
+                        if (bmpSize.Height > lineHeight) 
+                            lineHeight = (int)bmpSize.Height; 
+                        lineWidth += (int)bmpSize.Width;
+                    }
+                }
+            }
+            size.Width += ((curWidth>lineWidth)?curWidth:lineWidth);
+            size.Height = curHeigth + lineHeight; 
+        }
+
+        /// <summary>
+        /// Render a string onto a bitmap and measure exact size
+        /// </summary>
+        /// <param name="item">item to be rendered</param>
+        /// <param name="font">font used for rendering</param>
+        /// <param name="size">[output] size of the rendered item</param>
+        /// <returns>bitmap containing the item</returns>
+        public Bitmap TransformItem (string item, Font font, out RectangleF size) {
+            Bitmap ret = transformItem(item,font,out size); 
+            return ret.Clone(Rectangle.Round(size),ret.PixelFormat); 
+        }
+
+        /// <summary>
+        /// Render a string onto a bitmap and measure exact size
+        /// </summary>
+        /// <param name="item">item to be rendered</param>
+        /// <param name="font">font used for rendering</param>
+        /// <param name="size">[output] size of the rendered item</param>
+        /// <returns>bitmap containing the item</returns>
+        protected Bitmap transformItem(string item, Font font, out RectangleF size) {
+            if (String.IsNullOrEmpty(item)) {
+                size = new RectangleF(0,0,1,1);    
+                return m_measBitmap; 
+            }
+            if (item == " ") {
+                size = new RectangleF (new PointF(0,0),m_measGraphics.MeasureString(item,font));
+                if (size.Right >= m_measBitmap.Width || size.Bottom >= m_measBitmap.Height) {
+                    resizeMeasureBMP((int)size.Right+15,(int)size.Bottom+15);     
+                    return transformItem(item,font,out size);
+                }
+                m_measGraphics.Clear(Color.Transparent); 
+                return m_measBitmap;
+            }
+            StringFormat sformat = StringFormat.GenericDefault; 
+            sformat.FormatFlags = StringFormatFlags.NoWrap 
+                                | StringFormatFlags.NoClip 
+                                | StringFormatFlags.MeasureTrailingSpaces; 
+            sformat.SetMeasurableCharacterRanges(new CharacterRange[]{new CharacterRange(0,item.Length)});
+
+            // draw the text
+            if (font.SizeInPoints < 16) {
+                m_measGraphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit;
+            } else {
+                m_measGraphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias; 
+            }
+            RectangleF layout = new RectangleF(0,0,m_measBitmap.Width,m_measBitmap.Height);
+            m_measGraphics.Clear(Color.Transparent); 
+            m_measGraphics.DrawString(item,font,Brushes.White,layout,sformat);
+            // measure bounds 
+            Region[] reg = m_measGraphics.MeasureCharacterRanges(item,font,layout,sformat); 
+            size = reg[0].GetBounds(m_measGraphics);
+            size.Width += 1; 
+            size.Height += 1; 
+            // compensate 
+            //size = new RectangleF((size.Left>0)?size.Left-1:size.Left,size.Top,size.Width,size.Height);
+#if EXPORTBMP   // debug support only 
+            if (true) {
+                Bitmap debBitmap = (Bitmap)m_measBitmap.Clone(); 
+                Graphics debGrap = Graphics.FromImage(debBitmap); 
+                //debGrap.Clear(Color.White); 
+                //debGrap.DrawString(item,font,Brushes.Black,layout,sformat);
+                debGrap.DrawRectangle(new Pen(Brushes.Red),Rectangle.Round(size));
+                debBitmap.Save("EXPORTBMP_transformItemResult.bmp",System.Drawing.Imaging.ImageFormat.Bmp); 
+            }
+#endif
+            if (size.Right >= m_measBitmap.Width || size.Bottom >= m_measBitmap.Height) {
+                resizeMeasureBMP((int)size.Right+15,(int)size.Bottom+15);     
+                return transformItem(item,font,out size);
+            }
+            return m_measBitmap; 
+        }
+
+#endregion
+
+#region IILTextInterpreter Member
+
+        /// <summary>
+        /// Transforms an expression into render queue definition
+        /// </summary>
+        /// <param name="expression">expression to be transformed</param>
+        /// <param name="font">font may used for transformation</param>
+        /// <param name="color">standard color used for transformation</param>
+        /// <param name="renderer">IILTextRenderer instance used for caching (and later rendering)</param>
+        /// <returns>render queue, later used to render the visual representation of the expression</returns>
+        /// <remarks>the expression may contain markups. See the online help at http://ilnumerics.net
+        /// for a detailed descriptioin of known symbols and their syntax.</remarks>
+        public ILRenderQueue Transform(string expression, Font font, Color color, 
+                                       IILTextRenderer renderer) {
+            List<ILRenderQueueItem> ret = new List<ILRenderQueueItem>(); 
+            Size size = Size.Empty; 
+            m_normalFont = font; 
+            parseString(expression,font,new Point(),color,renderer,ref size,ref ret); 
+            return new ILRenderQueue(expression, ret, size); 
+        }
+        /// <summary>
+        /// Render text expression into bitmap
+        /// </summary>
+        /// <param name="expression">text expression</param>
+        /// <param name="font">font used for rendering</param>
+        /// <returns>Bitmap with rendered expression</returns>
+        /// <remarks>The size of the bitmap returned will tightly fit around the rendered content.</remarks>
+        public virtual Bitmap Transform(string expression, Font font) {
+            RectangleF size; 
+            Bitmap ret = transformItem(expression, font, out size); 
+            return ret.Clone(size,ret.PixelFormat); 
+        }
+        /// <summary>
+        /// Render text expression into bitmap
+        /// </summary>
+        /// <param name="expression">text expression</param>
+        /// <returns>Bitmap with rendered expression</returns>
+        /// <remarks>The size of the bitmap returned will tightly fit around the rendered content. 
+        /// <para>A generic sans serif font of size 10em will be used. </para></remarks>
+        public virtual Bitmap Transform(string expression) {
+            Font font = new Font(FontFamily.GenericSansSerif,10f,FontStyle.Regular); 
+            RectangleF size; 
+            Bitmap ret = transformItem(expression, font, out size); 
+            return ret.Clone(size,ret.PixelFormat); 
+        }
+#endregion
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Labeling/ILSimpleTexInterpreter.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Labeling/ILSimpleTexInterpreter.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Labeling/ILSimpleTexInterpreter.cs	(revision 9102)
@@ -0,0 +1,675 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Text;
+using System.Drawing; 
+using System.Collections.Generic;
+using ILNumerics.Drawing; 
+using ILNumerics.Drawing.Interfaces; 
+
+namespace ILNumerics.Drawing.Labeling {
+    /// <summary>
+    /// Simple, (partial) tex symbol interpreter 
+    /// </summary>
+    /// <remarks>this is the default interpreter for all ILLabelingElements</remarks>
+    public class ILSimpleTexInterpreter : ILSimpleInterpreter {
+
+#region attributes
+        public static readonly ILKeywords Keywords = new ILKeywords(); 
+#endregion
+
+#region constructor
+        
+        /// <summary>
+        /// create a new instance of a simple text interpreter
+        /// </summary>
+        public ILSimpleTexInterpreter () : base () { }
+
+#endregion
+
+#region helper functions 
+
+        protected override void parseString (string expression, Font font, Point offset, Color color, 
+                                    IILTextRenderer renderer, ref Size size, 
+                                    ref List<ILRenderQueueItem> queue) {
+            int pos = 0;
+            string key, itemText; 
+            RectangleF bmpSize = new RectangleF(); 
+            int curHeigth = 0, curWidth = 0; 
+            Bitmap itemBMP = null; 
+            int lineHeight = 0, lineWidth = 0; 
+            Size itemSize = Size.Empty; 
+            while (pos < expression.Length) {
+                itemText = expression.Substring(pos++,1);
+                #region special position control sequences
+                if (itemText == "\r") {
+                    queue.Add(new ILRenderQueueItem(itemText,0,0, color)); 
+                    if (curWidth < lineWidth) 
+                        curWidth = lineWidth; 
+                    lineWidth = 0; 
+                    continue; 
+                } else if (itemText == "\n") {
+                    queue.Add(new ILRenderQueueItem(itemText,0,0, color));
+                    curHeigth += lineHeight; 
+                    lineHeight = 0;
+                    if (curWidth < lineWidth) 
+                        curWidth = lineWidth; 
+                    lineWidth = 0; 
+                    continue;
+                #endregion
+                } else if (itemText == "\\") {   
+                    #region font control
+                    if (pos < expression.Length - 2) {
+                        #region test for font control sequences: \it,\bf,\rm
+                        if (expression[pos] == 'i' && expression[pos+1] == 't') {
+                            font = new Font(font,font.Style | FontStyle.Italic); 
+                            pos += 2; continue; 
+                        } else if (expression[pos] == 'b' && expression[pos+1] == 'f') {
+                            font = new Font(font,font.Style | FontStyle.Bold); 
+                            pos += 2; continue; 
+                        } else if (expression[pos] == 'r' && expression[pos+1] == 'm') {
+                            font = new Font(font,FontStyle.Regular); 
+                            pos += 2; continue;
+                        }
+                        #endregion
+                        #region fontname,-size,-color
+                        if (parseKeyword(expression,ref pos,Keywords.Reset)) {
+                            color = Color.Empty; 
+                            font = m_normalFont; 
+                            offset = new Point(0,0);
+                            continue; 
+                        }
+                        string parameter = ""; 
+                        if (parseKeywordArgumented(expression,ref pos,Keywords.Fontname,ref parameter)) {
+                            font = new Font(parameter,font.Size,font.Style,font.Unit); 
+                            continue; 
+                        }
+                        if (parseKeywordArgumented(expression,ref pos,Keywords.Fontsize,ref parameter)) {
+                            int newSize;
+                            if (!int.TryParse(parameter,out newSize)) 
+                                continue; 
+                            if (parameter.StartsWith("+") && newSize > 0 ) {
+                                newSize += (int)font.Size; 
+                                if (newSize > 40) newSize = 40;    
+                            } else if (parameter.StartsWith("-") && -newSize < font.Size) {
+                                newSize = (int)font.Size + newSize; 
+                            } 
+                            if (newSize > 0 && newSize < 40) {
+                                offset.Y += (int)Math.Round(font.Size - newSize);  
+                                font = new Font(font.Name,newSize,font.Style,font.Unit); 
+                            }
+                            continue;
+                        }
+                        if (parseKeywordArgumented(expression,ref pos,Keywords.Color,ref parameter)) {
+                            parseColor(parameter, ref color);   
+                            continue; 
+                        }
+                        #endregion
+                    }
+                    #endregion
+                    //if (pos < expression.Length - "size".Length)
+                    #region handle predefined symbols 
+                    TextSymbols symbol = matchSymbol(expression,ref pos); 
+                    if (symbol != TextSymbols.nothing) {
+                        itemText = TranslateSymbol(symbol); 
+                        if (String.IsNullOrEmpty (itemText)) continue; 
+                    }
+                    #endregion
+                    #region lower- upper indices
+                } else if (pos < expression.Length && itemText == "_") {
+                    int end; 
+                    if (pos < expression.Length-1 && expression[pos] == '{') {
+                        pos ++; 
+                        // find end brace & remove
+                        end = expression.IndexOf('}',pos)-1;
+                        if (end > 0 && end < expression.Length) {
+                            parseString(
+                                expression.Substring(pos,end-pos+1),
+                                new Font(font.Name,font.Size * 0.7f,font.Style,font.Unit),
+                                new Point(offset.X,offset.Y + (int)(0.3f * font.Height)),
+                                color, renderer, ref size, ref queue);
+                            pos = end+2;
+                            continue; 
+                        }
+                    } 
+                    // cache next char only
+                    parseString(
+                        expression.Substring(pos++,1),
+                        new Font(font.Name,font.Size * 0.7f,font.Style,font.Unit),
+                        new Point(offset.X,offset.Y + (int)(0.3f * font.Height)),
+                        color, renderer, ref size, ref queue);
+                    continue; 
+                } else if (pos < expression.Length && itemText == "^") {
+                    int end; 
+                    //offset.Y += 0.8f * font.Height; 
+                    if (pos < expression.Length-1 && expression[pos] == '{') {
+                        pos ++; 
+                        // find end brace & remove
+                        end = expression.IndexOf('}',pos)-1;
+                        if (end > 0 && end < expression.Length) { 
+                            parseString(
+                                expression.Substring(pos,end-pos+1),
+                                new Font(font.Name,font.Size * 0.7f,font.Style,font.Unit),
+                                new Point(offset.X,offset.Y - (int)(0.2f * font.Height)),
+                                color, renderer, ref size, ref queue);
+                            pos = end+2;
+                            continue; 
+                        }
+                    } 
+                    // cache next char only
+                    parseString(
+                        expression.Substring(pos++,1),
+                        new Font(font.Name,font.Size * 0.7f,font.Style,font.Unit),
+                        new Point(offset.X,offset.Y - (int)(0.2f * font.Height))
+                        ,color, renderer, ref size, ref queue);
+                    continue; 
+                    #endregion
+                }
+                key = ILHashCreator.Hash(font,itemText); 
+                
+                if (renderer.TryGetSize(key, ref itemSize)) {
+                    queue.Add(new ILRenderQueueItem(key,offset,color));
+                    if (itemSize.Height > lineHeight) lineHeight = itemSize.Height; 
+                    lineWidth += (int)itemSize.Width;
+                } else {
+                    lock (this) {
+                        itemBMP = transformItem(itemText,font,out bmpSize); 
+                        renderer.Cache(key,itemBMP,bmpSize); 
+                        queue.Add(new ILRenderQueueItem(key,offset,color)); 
+                        // update size
+                        if (bmpSize.Height > lineHeight) 
+                            lineHeight = (int)bmpSize.Height; 
+                        lineWidth += (int)bmpSize.Width;
+                    }
+                }
+            }
+            size.Width += ((curWidth>lineWidth)?curWidth:lineWidth);
+            size.Height = curHeigth + lineHeight; 
+        }
+
+        private bool parseKeyword(string text, ref int pos, string keyword) {
+            if (pos < text.Length - keyword.Length                 
+                && text.Substring(pos,keyword.Length) == keyword) {
+                pos += keyword.Length; 
+                return true; 
+            }
+            return false; 
+        }
+
+        private void parseColor(string parameter, ref Color color) {
+            if (!String.IsNullOrEmpty(parameter) && parameter[0] == '#') {
+                // try to parse for rgb value. Format: #D2E540
+                if (parameter.Length == 7) {
+                    IFormatProvider format = System.Threading.Thread.CurrentThread.CurrentCulture; 
+                    byte r,g,b; 
+                    // R - value
+                    if (!byte.TryParse(parameter.Substring(1,2),
+                                      System.Globalization.NumberStyles.HexNumber,
+                                      format,out r)) return; 
+                    // G - value
+                    if (!byte.TryParse(parameter.Substring(3,2),
+                                      System.Globalization.NumberStyles.HexNumber,
+                                      format,out g)) return;
+                    // B - value
+                    if (!byte.TryParse(parameter.Substring(5,2),
+                                      System.Globalization.NumberStyles.HexNumber,
+                                      format,out b)) return;
+                    color = Color.FromArgb(r,g,b); 
+                } 
+            } else {
+                // try to parse for known color name
+                try {
+                    color = Color.FromName(parameter); 
+                } catch {}
+            }
+        }
+        private bool parseKeywordArgumented(string text, ref int pos, string keyword, ref string parameter) {
+            int tmpPos = pos; 
+            if (pos < text.Length - keyword.Length                 
+                && text.Substring(pos,keyword.Length) == keyword) {
+                tmpPos = pos+keyword.Length; 
+                if (text[tmpPos] != '{' 
+                    || tmpPos == text.Length-1) return false; 
+                int end = text.IndexOf('}',++tmpPos); 
+                if (end < tmpPos) return false; 
+                parameter = text.Substring(tmpPos,end-tmpPos).Trim(); 
+                pos = end + 1;
+                return true; 
+            }
+            return false; 
+        }
+        /// <summary>
+        /// extract TextSymbol from text 
+        /// </summary>
+        /// <param name="text">text to extract symbol from</param>
+        /// <param name="pos">current text character position</param>
+        /// <returns>one of TextSymbol enumeration values</returns>
+        /// <remarks>if one symbol was found, its enum representation is 
+        /// returned and pos is increased by the corresponding number of 
+        /// characters. If no matching symbol was found, pos is not altered 
+        /// and TextSymbols.nothing will be returned.</remarks>
+        internal static TextSymbols matchSymbol (string text, ref int pos) {
+            foreach (string sym in Enum.GetNames(typeof(TextSymbols))) {
+                if (pos <= text.Length - sym.Length) {
+                    if (text.Substring(pos,sym.Length) != sym) {
+                        continue; 
+                    }
+                    if (sym == "nothing") continue; 
+                    pos += sym.Length; 
+                    return (TextSymbols)Enum.Parse(typeof(TextSymbols),sym); 
+                }
+            }
+            return TextSymbols.nothing; 
+        }
+        /// <summary>
+        ///  translates TextSymbol enum value to unicode character
+        /// </summary>
+        /// <param name="symbol">enum representation</param>
+        /// <returns>unicode character</returns>
+        /// <remarks>refers to: http://www.decodeunicode.org/ (e.g.)</remarks>
+        public static string TranslateSymbol (TextSymbols symbol) {
+            #region symbol matching
+            switch (symbol) {
+                case TextSymbols.alpha:
+                    return "Î±";
+                case TextSymbols.beta:
+                    return "Î²";
+                case TextSymbols.gamma:
+                    return "Î³";
+                case TextSymbols.delta:
+                    return "ÎŽ";
+                case TextSymbols.epsilon:
+                    return "Îµ";
+                case TextSymbols.zeta:
+                    return "Î¶";
+                case TextSymbols.eta:
+                    return "Î·";
+                case TextSymbols.theta:
+                    return "Îž";
+                case TextSymbols.vartheta:
+                    return "\u03d1";
+                case TextSymbols.iota:
+                    return "Î¹";
+                case TextSymbols.kappa:
+                    return "Îº";
+                case TextSymbols.lambda:
+                    return "Î»";
+                case TextSymbols.mu:
+                    return "ÎŒ";
+                case TextSymbols.nu:
+                    return "Îœ";
+                case TextSymbols.xi:
+                    return "ÎŸ";
+                case TextSymbols.pi:
+                    return "Ï";
+                case TextSymbols.rho:
+                    return "Ï";
+                case TextSymbols.sigma:
+                    return "Ï";
+                case TextSymbols.varsigma:
+                    return "Ï";
+                case TextSymbols.tau:
+                    return "Ï";
+                case TextSymbols.upsilon:
+                    return "Ï
+";
+                case TextSymbols.phi:
+                    return "Ï";
+                case TextSymbols.chi:
+                    return "Ï";
+                case TextSymbols.psi:
+                    return "Ï";
+                case TextSymbols.omega:
+                    return "Ï";
+                case TextSymbols.Gamma: 
+                    return "Î"; 
+                case TextSymbols.Delta:
+                    return "Î";
+                case TextSymbols.Theta:
+                    return "Î";
+                case TextSymbols.Lambda:
+                    return "Î";
+                case TextSymbols.Xi: 
+                    return "Î";
+                case TextSymbols.Pi:
+                    return "\u03a0"; //"Î "; 
+                case TextSymbols.Sigma:
+                    return "Î£";
+                case TextSymbols.Upsilon:
+                    return "Î¥";
+                case TextSymbols.Phi:
+                    return "ÎŠ";
+                case TextSymbols.Psi:
+                    return "Îš";
+                case TextSymbols.Omega:
+                    return "Î©"; 
+                case TextSymbols.forall:
+                    return "\u2200";
+                case TextSymbols.exists:
+                    return "\u2203";  
+                case TextSymbols.ni:
+                    return "\u220b"; 
+                case TextSymbols.cong:
+                    return "\u2205"; 
+                case TextSymbols.neq:
+                    return "\u2260"; 
+                case TextSymbols.equiv:
+                    return "\u2261"; 
+                case TextSymbols.approx:
+                    return "\u2240"; 
+                case TextSymbols.aleph:
+                    return "\u2235"; 
+                case TextSymbols.Im:
+                    return "\u2111"; 
+                case TextSymbols.Re:
+                    return "\u211b"; 
+                case TextSymbols.wp:
+                    return "\u2118"; 
+                case TextSymbols.otimes:
+                    return "\u2297"; 
+                case TextSymbols.oplus:
+                    return "\u2295"; 
+                case TextSymbols.oslash:
+                    return "\u2205"; 
+                case TextSymbols.cap:
+                    return "\u22c2"; 
+                case TextSymbols.cup:
+                    return "\u22c3"; 
+                case TextSymbols.supseteq:
+                    return "\u2287"; 
+                case TextSymbols.supset:
+                    return "\u2283"; 
+                case TextSymbols.subseteq:
+                    return "\u2286"; 
+                case TextSymbols.subset:
+                    return "\u2282"; 
+                case TextSymbols.int_:
+                    return "\u222b"; 
+                case TextSymbols.in_:
+                    return "\u2208"; 
+                case TextSymbols.o:
+                    return "\u25cb"; 
+                case TextSymbols.rfloor:
+                    return "\u230b"; 
+                case TextSymbols.lceil:
+                    return "\u2308"; 
+                case TextSymbols.nabla:
+                    return "\u2207"; 
+                case TextSymbols.lfloor:
+                    return "\u230a"; 
+                case TextSymbols.cdot:
+                    return "\u2219"; 
+                case TextSymbols.ldots:
+                    return "\u2026"; 
+                case TextSymbols.cdots:
+                    return "\u220f"; 
+                case TextSymbols.perp:
+                    return "\u22a5"; 
+                case TextSymbols.neg:
+                    return "\u2511"; 
+                case TextSymbols.prime:
+                    return "\u2032"; 
+                case TextSymbols.wedge:
+                    return "\u22c0"; 
+                case TextSymbols.times:
+                    return "\u2a09"; 
+                case TextSymbols.Null:
+                    return "\u2205"; 
+                case TextSymbols.rceil:
+                    return "\u2309"; 
+                case TextSymbols.surd:
+                    return "\u221a"; 
+                case TextSymbols.mid:
+                    return "|"; 
+                case TextSymbols.vee:
+                    return "\u22c1"; 
+                case TextSymbols.varpi:
+                    return "\u03d6"; 
+                case TextSymbols.copyright:
+                    return "\u00a9"; 
+                case TextSymbols.langle:
+                    return "\u2329"; 
+                case TextSymbols.rangle:
+                    return "\u232a"; 
+                case TextSymbols.sim: 
+                    return "\u223c"; 
+                case TextSymbols.leq: 
+                    return "\u2264"; 
+                case TextSymbols.infty: 
+                    return "\u221e"; 
+                case TextSymbols.leftrightarrow: 
+                    return "\u21d4"; 
+                case TextSymbols.leftarrow: 
+                    return "\u21d0"; 
+                case TextSymbols.uparrow: 
+                    return "\u21d1"; 
+                case TextSymbols.rightarrow: 
+                    return "\u21d2"; 
+                case TextSymbols.downarrow:         
+                    return "\u21d3"; 
+                case TextSymbols.circ: 
+                    return "\u25cc"; 
+                case TextSymbols.pm: 
+                    return "\u00b1"; 
+                case TextSymbols.geq: 
+                    return "\u2265"; 
+                case TextSymbols.propto: 
+                    return "\u221d"; 
+                case TextSymbols.partial: 
+                    return "\u2202"; 
+                case TextSymbols.div: 
+                    return "\u00f7"; 
+                default:
+                    break;
+            }
+            return ""; 
+            #endregion
+        }
+
+#endregion
+
+#region symbol definitions
+
+        /// <summary>
+        /// available keywords, interpretable by this IILInterpreter
+        /// </summary>
+        /// <remarks><para>The static instance ILSimpleTexInterpreter.Keywords can be 
+        /// used to alter the keywords used to switch to different font styles etc.</para></remarks>
+        public class ILKeywords {
+            private string m_fontname = "fontname";
+            /// <summary>
+            /// placeholder for font name control sequence
+            /// </summary>
+            public string Fontname {
+                get { return m_fontname; }
+                set { if (!string.IsNullOrEmpty(value)) m_fontname = value; }
+            }     
+            private string m_fontsize = "fontsize";
+            /// <summary>
+            /// placeholder for font size control sequence
+            /// </summary>
+            public string Fontsize {
+                get { return m_fontsize; }
+                set { if (!string.IsNullOrEmpty(value)) m_fontsize = value; }
+            }     
+            private string m_italic = "it";
+            /// <summary>
+            /// placeholder for italic font control sequence
+            /// </summary>
+            public string Italic {
+                get { return m_italic; }
+                set { if (!string.IsNullOrEmpty(value)) m_italic = value; }
+            }     
+            private string m_bold = "bf";
+            /// <summary>
+            /// placeholder for bold font control sequence
+            /// </summary>
+            public string Bold {
+                get { return m_bold; }
+                set { if (!string.IsNullOrEmpty(value)) m_bold = value; }
+            }     
+            private string m_color = "color";
+            /// <summary>
+            /// placeholder for font color control sequence
+            /// </summary>
+            public string Color {
+                get { return m_color; }
+                set { if (!string.IsNullOrEmpty(value)) m_color = value; }
+            }     
+            private string m_reset = "reset";
+            /// <summary>
+            /// placeholder for text control sequence 'reset to initial value' 
+            /// </summary>
+            public string Reset {
+                get { return m_reset; }
+                set { if (!string.IsNullOrEmpty(value)) m_reset = value; }
+            }     
+        }
+#pragma warning disable 1591
+        /// <summary>
+        /// all available TextSymbols (like \\Alpha etc.) this IILTextInterpreter understands
+        /// </summary>
+        public enum TextSymbols {
+            alpha,
+            beta,
+            gamma,
+            delta,
+            epsilon,
+            zeta,
+            eta,
+            theta,
+            vartheta,
+            iota,
+            kappa,
+            lambda,
+            mu,
+            nu,
+            xi,
+            pi,
+            rho,
+            sigma,
+            varsigma,
+            tau, 
+            upsilon,
+            phi,
+            chi,
+            psi,
+            omega,
+            Gamma,
+            Delta,
+            Theta,
+            Lambda,
+            Xi,
+            Pi,
+            Sigma,
+            Upsilon,
+            Phi,
+            Psi,
+            Omega,
+            forall,
+            exists,
+            ni,
+            cong,
+            neq,
+            equiv,
+            approx,
+            aleph,
+            Im,
+            Re,
+            wp,
+            otimes,
+            oplus,
+            oslash,
+            cap,
+            cup,
+            supseteq,
+            supset,
+            subseteq,
+            subset,
+            int_,
+            in_,
+            o,
+            rfloor,
+            lceil,
+            nabla,
+            lfloor,
+            cdot,
+            ldots,
+            perp,
+            neg,
+            prime,
+            wedge,
+            times,
+            Null,
+            rceil,
+            surd,
+            mid,
+            vee,
+            varpi,
+            copyright,
+            langle,
+            rangle,
+            nothing,
+            sim,
+            leq,
+            infty,
+            clubsuit,
+            diamondsuit,
+            heartsuit,
+            spadesuit,
+            leftrightarrow,
+            leftarrow,
+            uparrow,
+            rightarrow,
+            downarrow,
+            circ,
+            pm,
+            geq,
+            propto,
+            partial,
+            div,
+            cdots
+        }
+#pragma warning restore 1591
+
+#endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Labeling/ILTextRendererManager.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Labeling/ILTextRendererManager.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Labeling/ILTextRendererManager.cs	(revision 9102)
@@ -0,0 +1,225 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Reflection; 
+using ILNumerics.Drawing.Interfaces; 
+using ILNumerics.Exceptions; 
+using ILNumerics.Drawing; 
+
+
+namespace ILNumerics.Drawing.Labeling {
+    /// <summary>
+    /// Provides access to all (device dependent) ILRenderer available 
+    /// </summary>
+    public class ILRendererManager {
+
+        #region members / properties 
+        
+        Dictionary<string,string> m_rendererCollection; 
+        Dictionary<string,IILTextRenderer> m_rendererCache; 
+        GraphicDeviceType m_graphicsDevice;
+        string m_defaultRendererScreen; 
+        string m_defaultRendererWorld; 
+        ILPanel m_panel; 
+        #endregion 
+        
+        #region constructor
+        /// <summary>
+        /// create manager instance, device dependent
+        /// </summary>
+        /// <param name="panel">the hosting panel, will give access to this manager instance</param>
+        /// <remarks>While creating ILTextRendereManager instances, the executing assembly will be queried for 
+        /// available classes matching the device. Corresponding types are than provided by calling the GetRenderer() method.</remarks>
+        public ILRendererManager (ILPanel panel) 
+            : this(panel,new Assembly[] { Assembly.GetExecutingAssembly()} ) {
+        }
+        /// <summary>
+        /// create manager instance, device dependent
+        /// </summary>
+        /// <param name="panel">The hosting panel, giving access to his manager instance</param>
+        /// <param name="assemblies">assemblies to query for matching ILRenderer types</param>
+        /// <remarks>While creating ILRendererManager instances, the given assemblies will be queried for 
+        /// available classes matching the device. Corresponding types are than provided by calling the 
+        /// GetRenderer() method.</remarks>
+        public ILRendererManager (ILPanel panel, Assembly[] assemblies) {
+            m_graphicsDevice = panel.GraphicDeviceType; 
+            m_panel = panel; 
+            m_rendererCollection = new Dictionary<string,string>();
+            m_rendererCache = new Dictionary<string,IILTextRenderer>(); 
+            foreach (Assembly ass in assemblies) {
+                AddAssemblyTypes(ass); 
+            }
+            if (m_rendererCollection.Count == 0) 
+                throw new InvalidOperationException("No valid ILRenderer found!"); 
+        }
+        #endregion
+
+        #region public interface 
+
+        /// <summary>
+        /// Create a new ILRenderer instance, matching the current graphics device
+        /// </summary>
+        /// <param name="typeName">full class name of the new text renderer</param>
+        /// <param name="assembly">assembly hosting the textrenderer, null for executing assembly</param>
+        /// <returns>newly created ILRenderer instance from assembly</returns>
+        public IILTextRenderer CreateInstance (string typeName, Assembly assembly) {
+            if (typeName == null) 
+                throw new ILArgumentException ("The type must be a valid ILTextRenderer!"); 
+            string key = (assembly==null) 
+                ? typeName : assembly.FullName +  "|" + typeName; 
+            if (m_rendererCache.ContainsKey(key))
+                return m_rendererCache[key]; 
+            if (assembly == null) 
+                assembly = Assembly.GetExecutingAssembly(); 
+            Type type = assembly.GetType(typeName);
+            if (type == null  || type.GetInterface("IILTextRenderer") == null)
+                throw new ILArgumentException (String.Format(
+                            "The type '{0}' was not found in assembly {1} or is not a valid IILTextRenderer!"
+                            ,typeName,assembly)); 
+            queryAddRenderer(type); 
+            if (!m_rendererCollection.ContainsKey(key)) 
+                throw new ILArgumentException("The renderer could not be loaded. Make sure, to specify the correct assembly and the type is properly decorated by the ILRendererAttribute!");
+            IILTextRenderer ret = (IILTextRenderer)type.InvokeMember(
+                          typeName, BindingFlags.DeclaredOnly | 
+                          BindingFlags.Public | BindingFlags.NonPublic | 
+                          BindingFlags.Instance | BindingFlags.CreateInstance, null, null, 
+                          new object[] {m_panel});
+            if (!m_rendererCache.ContainsKey(typeName)) {
+                m_rendererCache[typeName] = ret;  
+            }
+            return ret; 
+        }
+        /// <summary>
+        /// Create the default instance of IILTextRenderer for 
+        /// the current graphics device and a coord system
+        /// </summary>
+        /// <param name="coords">coord system, the renderer is 
+        /// specialized and the default renderer for</param>
+        /// <returns>default IILTextRenderer object</returns>
+        public IILTextRenderer GetDefault(CoordSystem coords) {
+            string key = (coords == CoordSystem.World3D)  
+                 ? m_defaultRendererWorld : m_defaultRendererScreen; 
+            if (m_rendererCache.ContainsKey(key) && m_rendererCache[key] != null) 
+                return m_rendererCache[key]; 
+            // must create a new instance 
+            IILTextRenderer ret; 
+            switch (coords) {
+                case CoordSystem.World3D:
+                    ret = CreateInstance(m_defaultRendererWorld,null);
+                    break; 
+                default:
+                    ret = CreateInstance(m_defaultRendererScreen,null);
+                    break; 
+            }
+            m_rendererCache[key] = ret; 
+            return ret; 
+        }
+        /// <summary>
+        /// Get a collection of all IILTextRenderer types and corresponding displayNames available
+        /// </summary>
+        public IDictionary<string,string> RendererNames {
+            get {
+                IDictionary<string,string> ret = new Dictionary<string,string>(); 
+                foreach (KeyValuePair<string,string> v in m_rendererCollection) {
+                    ret.Add(v); 
+                }
+                return ret; 
+            }
+        }
+        #endregion
+
+        #region private helper
+        /// <summary>
+        /// iterate over types attribute, select IILTextRenderer attribute, 
+        /// register for later reference, add/overwrite default renderers
+        /// </summary>
+        /// <param name="t">IILTextRenderer type</param>
+        private void queryAddRenderer(Type t)
+        {
+            foreach (object att in t.GetCustomAttributes(false)) {
+                if (att is ILRendererAttribute) {
+                    ILRendererAttribute trAttr = (ILRendererAttribute)att; 
+                    if (trAttr.GraphicDeviceType == m_graphicsDevice ||
+                        trAttr.GraphicDeviceType == GraphicDeviceType.GDI) {
+                        if (t.GetInterface("IILTextRenderer") == null)
+                            continue; 
+                        if (m_rendererCollection.ContainsKey(t.FullName)) 
+                            m_rendererCollection[t.FullName] = trAttr.Name; 
+                        else 
+                            m_rendererCollection.Add(t.FullName,trAttr.Name); 
+                        if (trAttr.IsDefault) {
+                            if (trAttr.Coords == CoordSystem.Screen) 
+                                m_defaultRendererScreen = t.FullName; 
+                            else if (trAttr.Coords == CoordSystem.World3D)
+                                m_defaultRendererWorld = t.FullName; 
+                        }
+                        break; 
+                    }
+                }
+            }
+        }
+
+        private void AddAssemblyTypes (Assembly assembly) {
+            System.Diagnostics.Trace.Write("Entering ILTextRendererManager.AddAssemblyTypes...");
+            m_rendererCollection.Add("ILNumerics.Drawing.Platform.OpenGL.ILOGLRenderer", "OpenGL Renderer");
+            m_defaultRendererScreen = "ILNumerics.Drawing.Platform.OpenGL.ILOGLRenderer";
+            m_defaultRendererWorld = "ILNumerics.Drawing.Platform.OpenGL.ILOGLRenderer";
+            try {
+                Type[] types = assembly.GetTypes(); 
+                foreach (Type t in types) {
+                    queryAddRenderer(t);
+                }
+                System.Diagnostics.Trace.WriteLine("success. " + m_rendererCollection.Count.ToString() + " renderer found.");
+                System.Diagnostics.Trace.Indent(); 
+                foreach (var i in m_rendererCollection) {
+                    System.Diagnostics.Trace.WriteLine(i.Key.ToString() + " -- " + i.Value);
+                }
+                System.Diagnostics.Trace.Unindent();
+            } catch (Exception exc) {
+                System.Diagnostics.Trace.WriteLine("failure. Exception information:");
+                System.Diagnostics.Trace.WriteLine(exc.ToString()); 
+            }
+        }
+
+        #endregion
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Labeling/ILTextureData.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Labeling/ILTextureData.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Labeling/ILTextureData.cs	(revision 9102)
@@ -0,0 +1,100 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing; 
+
+namespace ILNumerics.Drawing.Labeling {
+    /// <summary>
+    /// class encapsulating texture item definitions
+    /// </summary>
+    public class ILTextureData {
+
+        #region attributes 
+        private RectangleF m_textureRectangle;
+        private int m_width = -1; 
+        private int m_height = -1; 
+        #endregion 
+
+        #region Properties
+        /// <summary>
+        /// the item's rectangle area in the texture sheet (texture coordinates) 
+        /// </summary>
+        public RectangleF TextureRectangle {
+            get {
+                return m_textureRectangle; 
+            }
+            set {
+                m_textureRectangle = value; 
+            }
+        }
+        /// <summary>
+        /// Width of the (rendered) item
+        /// </summary>
+        public int Width {
+            get {
+                return m_width;
+            }
+            set {
+                m_width = value; 
+            }
+        }
+        /// <summary>
+        /// Height of the (rendered) item
+        /// </summary>
+        public int Height {
+            get {
+                return m_height; 
+            }
+            set {
+                m_height = value; 
+            }
+        }
+        #endregion
+
+        #region constructor
+        internal ILTextureData (int height, int width) {
+            m_height = height; 
+            m_width = width;
+        }
+        #endregion
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Labeling/ILTextureManager.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Labeling/ILTextureManager.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Labeling/ILTextureManager.cs	(revision 9102)
@@ -0,0 +1,274 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing; 
+using ILNumerics.Drawing.Platform.OpenGL; 
+
+namespace ILNumerics.Drawing.Labeling {
+    /// <summary>
+    ///  manages multiple texture sheets for storage and rendering
+    /// </summary>
+    public class ILTextureManager {
+
+        #region events
+        /// <summary>
+        /// Fires, when the managed texture sheets are cleared. Registrars must rebuild needed items afterwards
+        /// </summary>
+        public event EventHandler TextureCacheCleared; 
+        #endregion
+
+        #region attributes / properties
+        protected int m_lastTextureSheet = -1; 
+        private List<ILTextureStorage> m_textureSheets; 
+        /// <summary>
+        /// All texture sheets must conform to this graphics device
+        /// </summary>
+        /// <remarks>the graphics device type must be the same as 
+        /// the one used by the panel!</remarks>
+        public GraphicDeviceType DeviceType {
+            get { return m_deviceType; }
+            set { m_deviceType = value; }
+        }
+        private GraphicDeviceType m_deviceType;
+        /// <summary>
+        /// Default height for new texture sheets
+        /// </summary>
+        public int DefaultHeight {
+            get { return m_defaultHeight; }
+            set { m_defaultHeight = value; }
+        } 
+        private int m_defaultHeight;
+        /// <summary>
+        /// Default width for new texture sheets
+        /// </summary>
+        public int DefaultWidth {
+            get { return m_defaultWidth; }
+            set { m_defaultWidth = value; }
+        } 
+        private int m_defaultWidth;
+        private static object m_lock = new object(); 
+        #endregion 
+
+        #region constructor
+        internal ILTextureManager(GraphicDeviceType deviceType) {
+            m_textureSheets = new List<ILTextureStorage>(); 
+            m_deviceType = deviceType;
+            if (m_deviceType != GraphicDeviceType.OpenGL) {
+                throw new NotImplementedException("Only OpenGL contexts can be handled so far!"); 
+            }
+            m_defaultHeight = 500; 
+            m_defaultWidth = 500; 
+        }
+        #endregion
+
+        #region public interface
+        /// <summary>
+        /// Clear all texture sheets and free their memory (cache) from GL. 
+        /// </summary>
+        /// <remarks> This will also fire the TextureCacheCleared event.</remarks>
+        public void Clear() {
+            lock (m_lock) {
+                foreach(ILTextureStorage storage in m_textureSheets) {
+                    storage.Dispose(true);
+                }
+                m_textureSheets.Clear(); 
+                if (TextureCacheCleared != null) {
+                    TextureCacheCleared(this, new EventArgs()); 
+                }
+            }
+        }
+        
+        /// <summary>
+        /// Reset any caching may beeing active for this texture manager. Call this once to begin rendering.
+        /// </summary>
+        public void Reset() {
+            m_lastTextureSheet = -1; 
+        }
+        /// <summary>
+        /// retrieve rendering information for texture item
+        /// </summary>
+        /// <param name="key">key used to identify the texture item</param>
+        /// <returns>texture item data</returns>
+        /// <remarks>If the key has been found in one of the texture sheets, the
+        /// corresponding texture sheet will be set as current</remarks>
+        public ILTextureData GetTextureItem(string key) {
+            return GetTextureItem(key,true); 
+        }
+        /// <summary>
+        /// retrieve rendering information for texture item
+        /// </summary>
+        /// <param name="key">key used to identify the texture item</param>
+        /// <param name="makeCurrent">if true: sets the corresponding texture sheet 
+        /// as 'current' for subsequent rendering</param>
+        /// <returns>texture item data</returns>
+        public ILTextureData GetTextureItem(string key, bool makeCurrent) {
+            ILTextureData ret; 
+            lock (m_lock) {
+                foreach (ILTextureStorage storage in m_textureSheets) {
+                    ret = storage.Get(key); 
+                    if (ret != null) {
+                        if (makeCurrent && m_lastTextureSheet != storage.TextureID) {
+#if PRINTTEXTURESHEETSWITCH
+            Console.Out.WriteLine(String.Format("TSheet switching from {0} to {1}",m_lastTextureSheet,storage.TextureID)); 
+#endif
+                            storage.MakeCurrent();
+                            m_lastTextureSheet = storage.TextureID; 
+                        }
+                        return ret; 
+                    }
+                }
+            }
+            throw new ArgumentException("The key was not found in any texture sheet");
+        }
+        /// <summary>
+        /// retrieve rendering information for texture item
+        /// </summary>
+        /// <param name="key">key used to identify the texture item</param>
+        /// <param name="makeCurrent">if true: sets the corresponding texture sheet 
+        /// as 'current' for subsequent rendering</param>
+        /// <param name="textureID">returns the texture sheet key of the item, 
+        /// used to identify the texture in the graphic system</param>
+        /// <returns>texture item data</returns>
+        public ILTextureData GetTextureItem(string key, bool makeCurrent, out int textureID) {
+            ILTextureData ret; 
+            lock (m_lock) {
+                foreach (ILTextureStorage storage in m_textureSheets) {
+                    ret = storage.Get(key); 
+                    if (ret != null) {
+                        if (makeCurrent) {
+                            storage.MakeCurrent(); 
+                        }
+                        textureID = storage.TextureID; 
+                        return ret; 
+                    }
+                }
+            }
+            throw new ArgumentException("The key was not found in any texture sheet");
+        }
+        /// <summary>
+        /// Store item into texture cache, use full bitmap
+        /// </summary>
+        /// <param name="key">key used to identify the texture in cache</param>
+        /// <param name="item">bitmap holding the texture content</param>
+        /// <returns>true if the texture was successfully stored, false otherwise</returns>
+        public bool StoreTextureItem(string key, Bitmap item) { 
+            return StoreTextureItem(key,item, new Rectangle(new Point(), item.Size)); 
+        }
+        /// <summary>
+        /// Store item into texture cache, use full bitmap
+        /// </summary>
+        /// <param name="key">key used to identify the texture in cache</param>
+        /// <param name="item">bitmap holding the texture content</param>
+        /// <param name="rect">rectangle defining the area in item used for content</param>
+        /// <returns>true if the texture was successfully stored, false otherwise</returns>
+        public bool StoreTextureItem(string key, Bitmap item, Rectangle rect) {
+            lock (m_lock) {
+                foreach (ILTextureStorage storage in m_textureSheets) {
+                    if (storage.Store(key,item,rect)) {
+                        return true; 
+                    }
+                }
+                ILTextureStorage stor = CreateStorage(); 
+                m_textureSheets.Add(stor); 
+                return stor.Store(key,item,rect); 
+            }
+        }
+        public bool StoreTextureItem(string key, Bitmap item, RectangleF usedArea) {
+            lock (m_lock) {
+                foreach (ILTextureStorage storage in m_textureSheets) {
+                    if (storage.Store(key,item,usedArea)) {
+                        return true; 
+                    }
+                }
+                ILTextureStorage stor = CreateStorage(); 
+                m_textureSheets.Add(stor); 
+                return stor.Store(key,item,usedArea);
+            }
+        }
+        /// <summary>
+        /// test, if a texture item for the given key exists 
+        /// in any texture storage sheets
+        /// </summary>
+        /// <param name="key">unique key to be tested for</param>
+        /// <returns>true, if a corresponding texture item exists, otherwise false</returns>
+        public bool Exists (string key) {
+            lock (m_lock) { 
+                foreach (ILTextureStorage storage in m_textureSheets) {
+                    if (storage.Exists(key)) {
+                        return true; 
+                    }
+                }
+                return false;
+            }
+        }
+        public bool TryGetTextureItem (string key, out ILTextureData item) {
+            lock (m_lock) {
+                foreach (ILTextureStorage storage in m_textureSheets) {
+                    if (storage.TryGetTextureItem(key, out item)) {
+                        return true; 
+                    }
+                }
+                item = null; 
+                return false; 
+            }
+        }
+
+        internal void Dispose() {                                                   
+            Clear(); 
+        }
+
+        #endregion
+
+        #region helper functions
+
+        private ILTextureStorage CreateStorage () {
+            switch (m_deviceType) {
+                case GraphicDeviceType.OpenGL:
+                    return new ILOGLTextureStorage(m_defaultWidth,m_defaultHeight); 
+                default:
+                    throw new NotImplementedException(); 
+            }
+        }
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Labeling/ILTextureStorage.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Labeling/ILTextureStorage.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Labeling/ILTextureStorage.cs	(revision 9102)
@@ -0,0 +1,371 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing;
+using System.Drawing.Imaging; 
+
+namespace ILNumerics.Drawing.Labeling {
+    /// <summary>
+    /// The class provides texture storage for a single class of texures (e.g. one font)
+    /// </summary>
+    /// <remarks>The texture items are stored in a single texture sheet 
+    /// and organized via a simple binary tree.</remarks>
+    public abstract class ILTextureStorage {
+
+        #region attributes / properties
+        protected Dictionary<string,ILTextureData> m_items;
+        protected int m_height;
+        protected int m_width;
+        protected int m_textureId; 
+        /// <summary>
+        ///  cache, which texture has been bound at last
+        /// </summary>
+        protected bool m_disposed = true; 
+        protected static int[] m_tmpData; 
+        protected Node m_root; 
+
+        /// <summary>
+        /// overall height of the internal texture sheet
+        /// </summary>
+        public int Height {
+            get { return m_height; }
+        }
+
+        /// <summary>
+        /// current width of the internal texture sheet
+        /// </summary>
+        public int Width {
+            get { return m_width; }
+        } 
+        /// <summary>
+        /// Key used to identify the texure in the graphic system 
+        /// </summary>
+        public int TextureID {
+            get {
+                return m_textureId; 
+            }
+        }
+        #endregion
+
+        #region constructor
+        /// <summary>
+        /// construct new storage
+        /// </summary>
+        /// <param name="height">absolute height (permanent)</param>
+        /// <param name="width">absolute width (permanent)</param>
+        /// <remarks>Suggested size parameter will be increased to the next power of two.</remarks>
+        public ILTextureStorage(int height, int width) {
+            m_items = new Dictionary<string,ILTextureData>();
+            if (width <= 0 || height <= 0)
+                throw new ArgumentOutOfRangeException("width & height ", width, "Must be greater than zero.");
+            // make size a power of 2
+            m_height = (int)Math.Pow(2,Math.Ceiling(Math.Log(height,2)));
+            m_width = (int)Math.Pow(2,Math.Ceiling(Math.Log(width,2)));
+            if (m_height > 1024) m_height = 1024; // limit to 1024 for compatibility reasons 
+            if (m_width > 1024) m_width = 1024; 
+            m_root = new Node();
+            m_root.Rect = new Rectangle(0,0,m_width,m_height); 
+            InitTexture(); 
+            m_disposed = false; 
+            //System.Diagnostics.Debug.WriteLine("ILTextureStorage (constr) ThreadID:" 
+            //    + System.Threading.Thread.CurrentThread.ManagedThreadId);
+        }
+        #endregion
+
+        #region public / abstract interface
+        /// <summary>
+        /// fetch texture item from storage
+        /// </summary>
+        /// <param name="key"></param>
+        /// <returns></returns>
+        public virtual ILTextureData Get (string key) {
+            ILTextureData ret = null; 
+            if (!m_items.TryGetValue(key,out ret)) {
+                return null; //throw new ArgumentException("no texture item has been found for key: " + key); 
+            }
+            return ret;
+        }
+        /// <summary>
+        /// try to fetch item by key
+        /// </summary>
+        /// <param name="key">unique key</param>
+        /// <param name="item">[output] item found</param>
+        /// <returns>true: item was found, false otherwise</returns>
+        public virtual bool TryGetTextureItem(string key, out ILTextureData item) {
+            if (m_items.ContainsKey(key)) {
+                item = m_items[key]; 
+                return true; 
+            }
+            item = null; 
+            return false; 
+        }
+        /// <summary>
+        /// test, if a key exists in the texture storage
+        /// </summary>
+        /// <param name="key">unique key to be tested for</param>
+        /// <returns>true if a texture item associated with that key exists, false otherwise</returns>
+        public bool Exists (string key) {
+            return m_items.ContainsKey(key); 
+        }
+        /// <summary>
+        /// store bitmap into texture sheet
+        /// </summary>
+        /// <param name="key">unique key for item</param>
+        /// <param name="data">item bitmap data</param>
+        /// <param name="rect">rectangle used in data bitmap</param>
+        /// <returns>true on success</returns>
+        public virtual bool Store (string key, Bitmap data, Rectangle rect) {
+            if (data.Height > m_height || data.Width > m_width) 
+                throw new ArgumentException("texture size is too large for this packer!");
+            // add to packer  
+            ILTextureData item; 
+            if (m_items.TryGetValue(key,out item)) {
+                item.Height = data.Height; 
+                item.Width = data.Width; 
+                // todo: remove item from packer & from texture sheet (somehow...[?])
+            } else {
+                item = new ILTextureData(rect.Height,rect.Width); 
+                m_items.Add(key, item);
+            }
+            Node node = m_root.Insert(item); 
+            if (node == null) 
+                return false; 
+            item.TextureRectangle = RectangleF.FromLTRB( (0.5f + node.Rect.Left) / m_width,
+                                                    (0.5f + node.Rect.Top) / m_height,
+                                                    (node.Rect.Right - 0.5f) / m_width,
+                                                    (node.Rect.Bottom - 0.5f) /m_height);
+            Store(data,rect, node.Rect); 
+            return true; 
+        }
+        /// <summary>
+        /// store bitmap into texture sheet
+        /// </summary>
+        /// <param name="key">unique key for item</param>
+        /// <param name="data">item bitmap data</param>
+        /// <param name="bmpRect">used rectangle in data bitmap</param>
+        public virtual bool Store (string key, Bitmap data, RectangleF bmpRect) {
+            if (bmpRect.Height > m_height || bmpRect.Width > m_width) 
+                throw new ArgumentException("texture size is too large for this packer!");
+            // add to packer  
+            ILTextureData item; Node node;
+            Rectangle itemRect = Rectangle.Ceiling(bmpRect); 
+            if (m_items.TryGetValue(key,out item)) {
+                item.Height = itemRect.Height;
+                item.Width = itemRect.Width; 
+                // todo: remove item from packer & from texture sheet (somehow...[?])
+                node = m_root.Insert(item);
+                if (node == null) 
+                    return false; 
+            } else {
+                item = new ILTextureData(itemRect.Height, itemRect.Width); 
+                node = m_root.Insert(item); 
+                if (node == null) 
+                    return false; 
+                m_items.Add(key, item);
+            }
+            item.TextureRectangle = RectangleF.FromLTRB( (0.5f + node.Rect.Left) / m_width,
+                                                    (0.5f + node.Rect.Top) / m_height,
+                                                    (node.Rect.Right - 0.5f) / m_width,
+                                                    (node.Rect.Bottom - 0.5f) /m_height);
+            //item.TextureRectangle = RectangleF.FromLTRB( (0f + node.Rect.Left) / m_width,
+            //                                        (0f + node.Rect.Top) / m_height,
+            //                                        (node.Rect.Right - 0f) / m_width,
+            //                                        (node.Rect.Bottom - 0f) /m_height);            
+            Store(data,bmpRect,node.Rect); 
+            return true; 
+        }
+        /// <summary>
+        /// initialize texture sheet 
+        /// </summary>
+        protected abstract void InitTexture();
+        /// <summary>
+        /// store item in texture sheet in GL
+        /// </summary>
+        /// <param name="data">new item bitmap data</param>
+        /// <param name="location">area in bitmap data to be stored</param>
+        /// <param name="rect">rectangle specifying area to store the data into,
+        /// texture coords: range from 0...1.0</param>
+        protected abstract void Store(Bitmap data, RectangleF location, RectangleF rect);
+        /// <summary>
+        /// select the texture storage as current in the GL
+        /// </summary>
+        /// <remarks>Calling this function before an storage / render operation is 
+        /// obligatory in specific rendering machines (e.g. OpenGL). For GL's, where 
+        /// it is not neccessary, the implementation must ignore any calls to this function.</remarks>
+        public abstract void MakeCurrent(); 
+        /// <summary>
+        /// Dispose off any texture storage's ressources
+        /// </summary>
+        public void Dispose() {
+            GC.SuppressFinalize(this);
+            Dispose(true); 
+        }
+        /// <summary>
+        /// Dispose off manually
+        /// </summary>
+        /// <param name="manual"></param>
+        /// <remarks>The true disposing is done in the concrete implementation.</remarks>
+        public virtual void Dispose(bool manual) {
+            if (!m_disposed) {
+                if (manual) {
+                    // free texture from GL 
+                }
+                m_disposed = true; 
+            }
+        }
+        /// <summary>
+        /// Finalizer, disposing ressources
+        /// </summary>
+        ~ILTextureStorage() {
+            Dispose(false); 
+        }
+
+        #endregion
+
+        #region helper functions
+
+        #endregion 
+
+        #region Node - binary tree
+        /// <summary>
+        /// class representing a binary tree, used to manage the items on the texture sheet
+        /// </summary>
+        /// <remarks>This code is a slightly modified version of the OpenTK.Utilities framework
+        /// TextPrinter/TextureStorage classes. See http://opentk.com for details.</remarks>
+        protected class Node
+        {
+            public Node()
+            {
+            }
+
+            Node left, right;
+            Rectangle rect;
+            int use_count;
+
+            public Rectangle Rect { get { return rect; } set { rect = value; } }
+            public Node Left { get { return left; } set { left = value; } }
+            public Node Right { get { return right; } set { right = value; } }
+
+            #region --- Constructor ---
+
+            public bool Leaf
+            {
+                get { return left == null && right == null; }
+            }
+
+            #endregion
+
+            #region public Node Insert(ILTextureData item)
+
+            public Node Insert(ILTextureData item)
+            {
+                if (!this.Leaf)
+                {
+                    // Recurse towards left child, and if that fails, towards the right.
+                    Node new_node = left.Insert(item);
+                    return new_node ?? right.Insert(item);
+                }
+                else
+                {
+                    // We have recursed to a leaf.
+
+                    // If it is not empty go back.
+                    if (use_count != 0)
+                        return null;
+
+                    // If this leaf is too small go back.
+                    if (rect.Width < item.Width || rect.Height < item.Height)
+                        return null;
+
+                    // If this leaf is the right size, insert here.
+                    if (rect.Width == item.Width && rect.Height == item.Height)
+                    {
+                        use_count = 1;
+                        return this;
+                    }
+
+                    // This leaf is too large, split it up. We'll decide which way to split
+                    // by checking the width and height difference between this rectangle and
+                    // out item's bounding box. If the width difference is larger, we'll split
+                    // horizontaly, else verticaly.
+                    left = new Node();
+                    right = new Node();
+
+                    int dw = this.rect.Width - item.Width + 1;
+                    int dh = this.rect.Height - item.Height + 1;
+
+                    if (dw > dh)
+                    {
+                        left.rect = new Rectangle(rect.Left, rect.Top, item.Width, rect.Height);
+                        right.rect = new Rectangle(rect.Left + item.Width, rect.Top, rect.Width - item.Width, rect.Height);
+                    }
+                    else
+                    {
+                        left.rect = new Rectangle(rect.Left, rect.Top, rect.Width, item.Height);
+                        right.rect = new Rectangle(rect.Left, rect.Top + item.Height, rect.Width, rect.Height - item.Height);
+                    }
+
+                    return left.Insert(item);
+                }
+            }
+
+            #endregion
+
+            #region public void Clear()
+            
+            public void Clear()
+            {
+                if (left != null)
+                    left.Clear();
+                if (right != null)
+                    right.Clear();
+
+                left = right = null;
+            }
+
+            #endregion
+        }
+
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Labeling/ILWorldLabel.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Labeling/ILWorldLabel.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Labeling/ILWorldLabel.cs	(revision 9102)
@@ -0,0 +1,147 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing; 
+using ILNumerics.Drawing.Interfaces; 
+using ILNumerics.Drawing; 
+
+namespace ILNumerics.Drawing.Labeling {
+    /// <summary>
+    /// general label, drawn in world coords
+    /// </summary>
+    public class ILWorldLabel : ILLabelingElement {
+
+        #region attributes
+        private int m_padding; 
+        private LabelAlign m_align; 
+        private ILPoint3Df m_minPosition;
+        private ILPoint3Df m_maxPosition; 
+        #endregion
+
+        #region properties 
+        
+        /// <summary>
+        /// get/ set the minimum position for the label
+        /// </summary>
+        public ILPoint3Df PositionMin {
+            get {
+                return m_minPosition; 
+            }
+            set {
+                m_minPosition = value; 
+            }
+        }
+        /// <summary>
+        /// get/ set the maximium position for the label
+        /// </summary>
+        public ILPoint3Df PositionMax {
+            get {
+                return m_maxPosition; 
+            }
+            set {
+                m_maxPosition = value; 
+            }
+        }
+        /// <summary>
+        /// Alignment along the axis value range. Possible values: lower, center, upper
+        /// </summary>
+        public LabelAlign Alignment {
+            get {
+                return m_align; 
+            }
+            set {
+                m_align = value; 
+                OnChanged(); 
+            }
+        }
+
+        /// <summary>
+        /// Get/ set the padding used to seperate the label from the elements around it
+        /// </summary>
+        public int Padding {
+            get {
+                return m_padding; 
+            }
+            set {
+                m_padding = value; 
+                OnChanged(); 
+            }
+        }
+        #endregion
+
+        #region constructor
+        /// <summary>
+        /// create a label for rendering
+        /// </summary>
+        public ILWorldLabel (ILPanel panel) 
+            : base(panel,new Font(FontFamily.GenericSansSerif,10.0f)
+                    ,Color.DarkBlue,CoordSystem.World3D) {
+            m_align = LabelAlign.Center; 
+            m_padding = 3; 
+        }
+        #endregion
+
+        #region abstract overrides
+
+        /// <summary>
+        /// draws the whole rendering queue
+        /// </summary>
+        public override void Draw(ILRenderProperties p) {
+            if (m_expression != m_cachedExpression) 
+                interprete(m_expression); 
+            m_renderer.Begin(p);
+            //offsetAlignment(m_size,ref m_position);
+            m_renderer.Draw(m_renderQueue
+                ,m_minPosition.X,m_minPosition.Y,m_minPosition.Z
+                ,m_maxPosition.X,m_maxPosition.Y,m_maxPosition.Z
+                ,m_color); 
+            m_renderer.End(p); 
+        }
+
+        #endregion
+
+        #region private helper
+
+
+        #endregion
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Lighting/ILLight.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Lighting/ILLight.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Lighting/ILLight.cs	(revision 9102)
@@ -0,0 +1,135 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing; 
+using ILNumerics.Drawing.Collections; 
+
+namespace ILNumerics.Drawing.Lighting {
+    public class ILLight {
+
+        #region eventing
+        public EventHandler Changed; 
+        protected void OnChanged() {
+            if (Changed != null) {
+                Changed(this, new EventArgs()); 
+            }
+        }
+        #endregion
+
+        #region attributes
+        private bool m_enabled;
+        private int m_index;
+        private ILPoint3Df m_position;
+        private Color m_specular;
+        private Color m_emission;
+        private Color m_ambient;
+        private Color m_diffuse;
+        #endregion
+
+        #region properties
+        public bool Enabled {
+            get { return m_enabled; }
+            set { 
+                m_enabled = value; 
+                OnChanged(); 
+            }
+        }
+        public int Index {
+            get { return m_index; }
+        }
+        public ILPoint3Df Position {
+            get { return m_position; }
+            set { 
+                m_position = value;  
+                OnChanged(); 
+            }
+        }
+        public Color Specular {
+            get { return m_specular; }
+            set { 
+                m_specular = value;  
+                OnChanged(); 
+            }
+        }
+        public Color Ambient {
+            get {
+                return m_ambient; 
+            } 
+            set {
+                m_ambient = value; 
+                OnChanged(); 
+            }
+        }
+        public Color Diffuse {
+            get {
+                return m_diffuse; 
+            } 
+            set {
+                m_diffuse = value; 
+                OnChanged(); 
+            }
+        }
+        #endregion
+
+        #region constructors
+        public ILLight (int index) {
+            m_enabled = index == 0; 
+            m_index = index; 
+            Position = new ILPoint3Df(100f,100f,100);
+            Specular = Color.FromArgb(255,255,255);
+            Ambient = Color.FromArgb(90,90,90); 
+            Diffuse = Color.FromArgb(160,160,160);  
+        }
+        #endregion
+
+        #region public interface
+
+        #endregion
+
+        #region private helpers
+
+        #endregion
+
+
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Lighting/ILMaterial.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Lighting/ILMaterial.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Lighting/ILMaterial.cs	(revision 9102)
@@ -0,0 +1,97 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing; 
+
+namespace ILNumerics.Drawing.Lighting {
+    public class ILMaterial : ICloneable {
+
+        #region attributes
+        byte m_shininess;
+        Color m_specular;
+        Color m_emission; 
+        #endregion
+
+        #region properties
+        /// <summary>
+        /// shape/intensity for specular reflection, range: 1...128
+        /// </summary>
+        public byte Shininess {
+            get { return m_shininess; }
+            set { m_shininess = value; }
+        }
+        /// <summary>
+        /// color for specular reflection
+        /// </summary>
+        public Color Specular {
+            get { return m_specular; }
+            set { m_specular = value; }
+        }
+        /// <summary>
+        /// color for emissive reflection
+        /// </summary>
+        public Color Emission {
+            get { return m_emission; }
+            set { m_emission = value; }
+        }
+        #endregion
+
+        #region public interface
+        /// <summary>
+        /// construct new material object, initialize default values
+        /// </summary>
+        public ILMaterial() {
+            m_shininess = (byte)96;
+            m_specular = Color.FromArgb(255, Color.Gray);
+            m_emission = Color.FromArgb(255, Color.Black); 
+        }
+
+        public object Clone() {
+            return MemberwiseClone(); 
+        }
+        #endregion
+
+        #region private helpers
+
+        #endregion
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Marker/ILBitmapMarkerShape.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Marker/ILBitmapMarkerShape.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Marker/ILBitmapMarkerShape.cs	(revision 9102)
@@ -0,0 +1,93 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing; 
+using ILNumerics.Drawing.Labeling; 
+
+namespace ILNumerics.Drawing.Marker {
+    public abstract class ILBitmapMarkerShape : ILMarkerShape {
+
+        #region attributes
+        protected Bitmap m_bitmap; 
+        #endregion
+
+        #region constructors
+        internal ILBitmapMarkerShape (ILPanel panel, Bitmap bitmap) : base(panel) {
+            m_bitmap = bitmap;     
+        }
+        #endregion
+
+        #region properties
+        public Bitmap Bitmap {
+            get {
+                return m_bitmap; 
+            }
+            set {
+                m_bitmap = value; 
+                storeBitmap(m_bitmap); 
+            }
+        }
+        #endregion
+
+        #region public interface
+        public string Hash() {
+            // create hash based on the width, height & middle scanline of bitmap
+            StringBuilder sb = new StringBuilder(
+                        String.Format("M:{0}W{1}H{2}:","BMP",m_bitmap.Width,m_bitmap.Height)); 
+            int h = m_bitmap.Height / 2; 
+            for (int x = 0; x < Math.Min(m_bitmap.Width,30);x++) {
+                sb.Append(m_bitmap.GetPixel(x,h).ToArgb().ToString());
+            }
+            return sb.ToString(); 
+        }
+
+        #endregion
+
+        #region private helper
+        protected virtual void storeBitmap(Bitmap bitmap) {
+            string key = Hash(); 
+            ILTextureManager mana = m_panel.TextureManager; 
+            mana.StoreTextureItem(key,m_bitmap); 
+        }
+        #endregion
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Marker/ILMarker.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Marker/ILMarker.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Marker/ILMarker.cs	(revision 9102)
@@ -0,0 +1,188 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing;
+using ILNumerics.Drawing; 
+using ILNumerics.Drawing.Platform.OpenGL;  
+using ILNumerics.Exceptions; 
+
+namespace ILNumerics.Drawing.Marker {
+    /// <summary>
+    /// Properties for marker (e.g. used for line plots)
+    /// </summary>
+    public class ILMarker {
+        
+        #region eventing 
+        /// <summary>
+        /// Fires when the properties have changed
+        /// </summary>
+        public event EventHandler Changed; 
+        protected void OnChanged() {
+            if (Changed != null) {
+                Changed(this,new EventArgs()); 
+            }
+        }
+        #endregion
+
+        #region attributes 
+        private ILPanel m_panel; 
+        private int m_markerSize; 
+        private ILMarkerShape m_shape; 
+        private Color m_color; 
+        protected bool m_visible; 
+        #endregion
+
+        #region properties 
+        /// <summary>
+        /// Switch on or off the visibility of all markers 
+        /// </summary>
+        public bool Visible {
+            get {
+                return m_visible; 
+            }
+            set {
+                m_visible = value; 
+                OnChanged(); 
+            }
+        }
+        /// <summary>
+        /// Marker color
+        /// </summary>
+        public Color Color {
+            get {
+                return m_color; 
+            }
+            set {
+                m_color = value;
+                if (!value.IsEmpty) 
+                    m_visible = true; 
+                else 
+                    m_visible = false; 
+                OnChanged(); 
+            }
+        }
+        /// <summary>
+        /// Shape of markers, compatible with string, markerStyle or bitmap arguments
+        /// </summary>
+        public ILMarkerShape Shape {
+            get {
+                return m_shape; 
+            }
+            set {
+                //implement abstract factory pattern
+                if (value is ILMarkerShapeProxy) {
+                    m_shape = Create(value as ILMarkerShapeProxy);  
+                    if ((m_shape is ILStyledMarkerShape) && (m_shape as ILStyledMarkerShape).Style == MarkerStyle.None )
+                        m_visible = false; 
+                    else 
+                        m_visible = true; 
+                    //m_markerSize = 8; 
+                } 
+                OnChanged(); 
+            }
+        }
+        /// <summary>
+        /// Size of markers in pixels (default: 10)
+        /// </summary>
+        public int Size {            
+            get {
+                return m_markerSize; 
+            }
+            set {
+                m_markerSize = value; 
+                if (m_markerSize > 0) 
+                    m_visible = true; 
+                else 
+                    m_visible = false; 
+                OnChanged(); 
+            }
+        }
+        #endregion
+
+        #region constructor
+        /// <summary>
+        /// create a new marker property instance
+        /// </summary>
+        public ILMarker (ILPanel panel) {
+            m_panel = panel; 
+            m_shape = MarkerStyle.None; 
+            m_markerSize = 5;
+            m_visible = false; 
+            m_color = Color.DarkBlue; 
+        }
+        #endregion
+
+        #region public interface
+        internal static ILTexMarkerShape Create(ILPanel panel, string expression) {
+            return new ILTexMarkerShape(panel,expression);    
+        }
+        internal static ILStyledMarkerShape Create(ILPanel panel, MarkerStyle style) {
+            switch (panel.GraphicDeviceType) {
+                case GraphicDeviceType.OpenGL:
+                    return new ILOGLStyledMarkerShape(panel,style);    
+                default:
+                    throw new NotImplementedException("styled markers are not implemented yet for this graphics device type!");
+            }
+        }
+        internal static ILBitmapMarkerShape Create(ILPanel panel, Bitmap bitmap) {
+            switch (panel.GraphicDeviceType) {
+                case GraphicDeviceType.OpenGL:
+                    return new ILOGLBitmapMarkerShape(panel,bitmap);    
+                default:
+                    throw new NotImplementedException("Bitmap markers are not implemented yet for this graphics device type!");
+            }
+        }
+        internal ILMarkerShape Create(ILMarkerShapeProxy proxy) {
+
+            if (proxy.Source is string) {
+                return Create(m_panel,proxy.Source as string); 
+            } else if (proxy.Source is MarkerStyle) {
+                return Create(m_panel,(MarkerStyle)proxy.Source); 
+            } else if (proxy.Source is Bitmap) {
+                return Create(m_panel,proxy.Source as Bitmap); 
+            }
+            throw new ILArgumentException(String.Format("Unable to create marker shape based on proxy source given: {0}",proxy.Source.ToString())); 
+        }
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Marker/ILMarkerShape.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Marker/ILMarkerShape.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Marker/ILMarkerShape.cs	(revision 9102)
@@ -0,0 +1,80 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing; 
+using ILNumerics.Drawing.Interfaces; 
+using ILNumerics.Drawing.Labeling; 
+using ILNumerics.Drawing; 
+using ILNumerics.Drawing.Shapes; 
+
+
+namespace ILNumerics.Drawing.Marker {
+    public abstract class ILMarkerShape {
+
+        #region attributes
+        protected ILPanel m_panel;  
+        #endregion
+
+        #region constructors 
+        internal ILMarkerShape (ILPanel panel) { 
+            m_panel = panel; 
+        }
+        #endregion
+
+        #region cast operators
+        public static implicit operator ILMarkerShape(string content) {
+            return new ILMarkerShapeProxy(content);
+        }
+        public static implicit operator ILMarkerShape(MarkerStyle style) {
+            return new ILMarkerShapeProxy(style);
+        }
+        public static implicit operator ILMarkerShape(Bitmap bitmap) {
+            return new ILMarkerShapeProxy(bitmap);
+        }
+        #endregion 
+
+
+        #region public interface 
+        internal abstract void Draw(ILRenderProperties p, ILMarker marker, C4bV3f[] vertices, int startID, int vertCount);
+        #endregion
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Marker/ILMarkerShapeProxy.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Marker/ILMarkerShapeProxy.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Marker/ILMarkerShapeProxy.cs	(revision 9102)
@@ -0,0 +1,84 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing; 
+using ILNumerics.Drawing.Interfaces;
+using ILNumerics.Drawing.Shapes;
+
+namespace ILNumerics.Drawing.Marker {
+    
+    /// <summary>
+    /// Class used to enable flexible settings for marker shapes in ILMarker
+    /// </summary>
+    class ILMarkerShapeProxy : ILMarkerShape {
+
+        #region attributes
+        private object m_source; 
+        #endregion 
+
+        #region constructors
+        public ILMarkerShapeProxy (string expression) : base (null) {
+            m_source = expression; 
+        }
+        public ILMarkerShapeProxy (Bitmap bitmap) : base (null) {
+            m_source = bitmap; 
+        }
+        public ILMarkerShapeProxy (MarkerStyle style) : base (null) {
+            m_source = style; 
+        }
+        #endregion
+
+        #region properties
+        internal Object Source {
+            get {
+                return m_source; 
+            }
+        }
+        #endregion
+
+        #region public interface 
+        internal override void Draw(ILRenderProperties p, ILMarker marker, C4bV3f[] vertices, int startID, int vertCount) {
+            // dummy. Nothing to do! 
+        }
+        #endregion
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Marker/ILStyledMarkerShape.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Marker/ILStyledMarkerShape.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Marker/ILStyledMarkerShape.cs	(revision 9102)
@@ -0,0 +1,132 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing; 
+using ILNumerics.Drawing; 
+using ILNumerics.Drawing.Labeling; 
+
+namespace ILNumerics.Drawing.Marker {
+    public abstract class ILStyledMarkerShape : ILMarkerShape {
+
+        #region attributes 
+        protected MarkerStyle m_style; 
+        #endregion
+
+        #region properties
+        /// <summary>
+        /// The style of markers 
+        /// </summary>
+        public MarkerStyle Style {
+            get {
+                return m_style; 
+            }
+            set {
+                m_style = value; 
+                CacheMarkerBitmap(); 
+            }
+        }
+        #endregion
+
+        #region constructor
+        /// <summary>
+        /// create new styled marker
+        /// </summary>
+        internal ILStyledMarkerShape (ILPanel panel, MarkerStyle style) : base(panel) {
+            m_style = style; 
+        }
+        #endregion
+
+        #region public interface
+        public override string ToString() {
+            return String.Format(""); 
+        }
+        public string Hash() {
+            string key = Enum.GetName(typeof(MarkerStyle),m_style);
+            key = key.Substring(0, 3) + key.Substring(key.Length - 3); 
+            return String.Format("M:{0}",key); 
+        }
+        /// <summary>
+        /// convert marker style into bitmap
+        /// </summary>
+        /// <param name="marker">marker with style property</param>
+        /// <returns>bitmap according to style</returns>
+        /// <remarks>the bitmap will be loaded from ILNumerics.Drawing ressources. For marker style 'bitmap'
+        /// the bitmap referenced in the marker will be returned.</remarks>
+        public static Bitmap BitmapFromStyle(MarkerStyle style) {
+            switch (style) {
+                case MarkerStyle.Circle:
+                    return Resources.Markers.Circle25x25;
+                case MarkerStyle.Diamond:
+                    return Resources.Markers.Diamond25x25;
+                case MarkerStyle.TriangleUp:
+                    return Resources.Markers.TriangleUp25x25;
+                case MarkerStyle.TriangleDown:
+                    return Resources.Markers.TriangleDown25x25;
+                case MarkerStyle.TriangleLeft:
+                    return Resources.Markers.TriangleLeft25x25;
+                case MarkerStyle.TriangleRight:
+                    return Resources.Markers.TriangleRight25x25;
+                case MarkerStyle.Plus:
+                    return Resources.Markers.Plus25x25;
+                case MarkerStyle.Cross:
+                    return Resources.Markers.Cross25x25;
+                default:
+                    throw new NotImplementedException("ILStyledMarker: marker style not supported!");
+            }
+        }
+
+
+        #endregion
+
+        #region private helper
+
+        protected void CacheMarkerBitmap() {
+            ILTextureManager mana = m_panel.TextureManager;
+            string key = Hash();
+            Bitmap markerbmp = BitmapFromStyle(m_style);
+            // we need it in format Argb!
+            mana.StoreTextureItem(key, markerbmp);
+        }
+        
+        #endregion
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Marker/ILTexMarkerShape.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Marker/ILTexMarkerShape.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Marker/ILTexMarkerShape.cs	(revision 9102)
@@ -0,0 +1,196 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing; 
+using ILNumerics.Drawing; 
+using ILNumerics.Drawing.Interfaces; 
+using ILNumerics.Drawing.Labeling; 
+using ILNumerics.Drawing.Shapes; 
+
+namespace ILNumerics.Drawing.Marker {
+    public class ILTexMarkerShape : ILMarkerShape {
+
+        #region attributes 
+        protected string m_expression; 
+        protected IILTextInterpreter m_interpreter; 
+        protected Font m_font; 
+        protected int m_maxLabelsDrawn; 
+        protected string m_valueFormat;
+        protected IILTextRenderer m_renderer; 
+        #endregion
+
+        #region constructors 
+        internal ILTexMarkerShape (ILPanel panel, string expression) 
+            :base (panel) {
+            m_expression = expression; 
+            m_interpreter = new ILSimpleTexInterpreter(); 
+            m_font = new Font(FontFamily.GenericSansSerif,10.0f); 
+            m_maxLabelsDrawn = 50; 
+            m_valueFormat = "f"; 
+            m_renderer = panel.TextRendererManager.GetDefault(CoordSystem.World3D); 
+        }
+        #endregion
+
+        #region properties
+        /// <summary>
+        /// Interpreter instance usedt to convert expression into visual output
+        /// </summary>
+        public IILTextInterpreter Interpreter {
+            get {
+                return m_interpreter; 
+            }
+            set {
+                m_interpreter = value; 
+            }
+        }
+        /// <summary>
+        /// maximum number of labels to be drawn
+        /// </summary>
+        /// <remarks>If the graph contains more datapoints, only <i>MaxLabelsDrawn</i> markers 
+        /// will be shown. This is for performance reasons only. Default is 50.</remarks>
+        public int MaxLabelsDrawn {
+            get { return m_maxLabelsDrawn; }
+            set { 
+                if (value >= 0) 
+                    m_maxLabelsDrawn = value; 
+            }
+        }
+        /// <summary>
+        /// Format string used to convert value numbers into string 
+        /// </summary>
+        /// <remarks>Default: 'f'</remarks>
+        public string ValueFormat {
+            get { return m_valueFormat; }
+            set {
+                if (!String.IsNullOrEmpty(value)) {
+                    m_valueFormat = value; 
+                }
+            }
+        }
+        /// <summary>
+        /// Expression defining the marker tex shape
+        /// </summary>
+        /// <remarks>The expression may uses markups interpretable by the current interpreter. This is - by default - an simple Tex interpreter. 
+        /// In addition to all partial tex commands, one may uses placeholders '\\index', '\\xvalue' and/or '\\yvalue'. Those placeholders will be 
+        /// replaces for every marker individually with its real values at runtime.
+        /// <para>This property is readonly. In order to change the expression, assign the new expression string to the Shape property of the 
+        /// containing ILMarker class.</para></remarks>
+        public string Expression {
+            get {
+                return m_expression; 
+            }
+        }
+        #endregion
+
+        #region public interface 
+        public string Hash() {
+            return String.Format("M:{0}",m_expression); 
+        }
+
+        /// <summary>
+        /// draw all markers (graph / legend)
+        /// </summary>
+        /// <param name="marker">the marker object (for properties)</param>
+        /// <param name="vertices">coords, interleaved</param>
+        /// <param name="vertcount">number of coords, special: -1 for legend rendering</param>
+        /// <remarks>This function is reused for both: drawing in world coords (graph) and drawing in
+        /// screen coords (legend). Latter case requires vertcount to be -1, vertices must contain
+        /// at least 2 float values than!</remarks>
+        internal override void Draw(ILRenderProperties p, ILMarker marker, C4bV3f[] vertices, int startID, int vertcount) {
+            if (vertcount > 0) {
+                int inc = Math.Max(1,(vertcount/m_maxLabelsDrawn)); 
+                m_renderer.Begin(p); 
+                for (int i = 0; i < vertcount; i += inc) {
+                    #region draw textured points (slow version: textured quads)
+                    string expr = m_expression.Replace("\\index",i.ToString());
+                    expr = expr.Replace("\\xvalue",vertices[i].XPosition.ToString(m_valueFormat)); 
+                    expr = expr.Replace("\\yvalue",vertices[i].YPosition.ToString(m_valueFormat)); 
+                    ILRenderQueue queue = m_interpreter.Transform(expr,m_font,marker.Color,m_renderer); 
+                    #region determine size for markers in world coords (graph limits)
+                        float w,h;
+                        ILClippingData clip = m_panel.Limits; 
+                        float s05x; 
+                        float s05y; 
+                        s05x = Math.Abs(queue.Size.Width * clip.WidthF / 2 / (m_panel.ClientSize.Width)); 
+                        s05y = Math.Abs(queue.Size.Height * clip.HeightF / 2 / (m_panel.ClientSize.Height)); 
+                    #endregion
+                    // this is slow! Todo: replace by point sprites! 
+                    w = vertices[i].XPosition; 
+                    h = vertices[i].YPosition;           
+                    if (m_panel.ClipViewData && (w < clip.XMin || w > clip.XMax || h < clip.YMin || h > clip.YMax)) {
+                        continue; 
+                    }
+                    m_renderer.Draw(queue,w-s05x,h+s05y,vertices[i].ZPosition,
+                                    w + s05x,h-s05y,vertices[i].ZPosition,marker.Color); 
+                    #endregion
+                }
+                m_renderer.End(p);
+            } else if (vertcount == -1) {
+                #region render for legend
+                m_renderer.Begin(p); 
+                string expr = m_expression.Replace("\\index","0");
+                expr = expr.Replace("\\xvalue","0.2"); 
+                expr = expr.Replace("\\yvalue","0.4"); 
+                ILRenderQueue queue = m_interpreter.Transform(expr,m_font,marker.Color,m_renderer); 
+                #region determine size for markers in SCREEN COORDS
+                float w,h;
+                ILClippingData clip = m_panel.Limits; 
+                float s05x; 
+                float s05y; 
+                s05x = Math.Abs(queue.Size.Width / 2 ); 
+                s05y = Math.Abs(queue.Size.Height / 2); 
+
+                #endregion
+                // this is slow! Todo: replace by point sprites! 
+                w = vertices[0].XPosition; 
+                h = vertices[0].YPosition;
+                
+                m_renderer.Draw(queue,w-s05x,h-s05y,0,w + s05x,h+s05y,0,marker.Color); 
+                m_renderer.End(p);
+                #endregion
+            }
+
+        }
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/Definitions.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/Definitions.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/Definitions.cs	(revision 9102)
@@ -0,0 +1,857 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+#pragma warning disable 1591
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing;
+using System.Runtime.InteropServices;
+using ILNumerics.Drawing.Graphs; 
+
+
+namespace ILNumerics.Drawing {
+
+
+    /// <summary>
+    /// Options for adapting ILPanel view limits 
+    /// </summary>
+    public enum AutoZoomOptions {
+        /// <summary>
+        /// never adapt automatically, the view limits are handled by the user
+        /// </summary>
+        Never,
+        /// <summary>
+        /// Only adapt view limits once at startup, later changes of the data limits will not affect the view limits
+        /// </summary>
+        OnStartup,
+        /// <summary>
+        /// View limits will automatically adapt changes of data limits. (Default)
+        /// </summary>
+        OnDataChanges
+    }
+    /// <summary>
+    /// modes for projecting the rendering output to the available client area
+    /// </summary>
+    public enum AspectRatioMode {
+        /// <summary>
+        /// plots fill available rendering area of the PlotCubeScreenRectF rectangle
+        /// </summary>
+        StretchToFill, 
+        /// <summary>
+        /// plots will be shrinked to fit inside PlotCubeScreeRectF but maintain data aspect ratio
+        /// </summary>
+        MaintainRatios
+    }
+    /// <summary>
+    /// defines the movement from current to new zoom setting
+    /// </summary>
+    public enum ZoomModes {
+        /// <summary>
+        /// No ramp, jump to new zoom setting
+        /// </summary>
+        Jump,
+        /// <summary>
+        /// morph softly to new zoom setting
+        /// </summary>
+        RollSoft,
+        /// <summary>
+        /// morph faster to new setting
+        /// </summary>
+        RollHard,
+        /// <summary>
+        /// morph to new setting by 'going over the limit'
+        /// </summary>
+        RollOverride
+    }
+    /// <summary>
+    /// predefined colormaps
+    /// </summary>
+    public enum Colormaps {
+        Autumn,
+        Bone,
+        //Colorcube,
+        Cool,
+        Copper,
+        Flag,
+        Gray,
+        Hot,
+        Hsv,
+        ILNumerics,
+        Jet,
+        Lines, 
+        Pink,
+        Prism,
+        Spring,
+        Summer,
+        White,
+        Winter
+    }
+    /// <summary>
+    /// Orientation for labels and other purposes
+    /// </summary>
+    public enum TextOrientation {
+        Horizontal,
+        Vertical
+    }
+    /// <summary>
+    /// Alignment for 
+    /// </summary>
+    public enum VerticalAlignment {
+        Lower,
+        Middle,
+        Upper
+    }
+ 
+    /// <summary>
+    /// Suggest, how label positions for axis ticks are to be choosen
+    /// </summary>
+    public enum TickLabelRenderingHint {
+        /// <summary>
+        /// tick labels will optimally fill the whole axis length
+        /// </summary>
+        Filled, 
+        /// <summary>
+        /// multiples of 10^n will be prefered for label steps
+        /// </summary>
+        Multiple1,
+        /// <summary>
+        /// multiples of 2*10^n will be prefered for label steps
+        /// </summary>
+        Multiple2,
+        /// <summary>
+        /// multiples of 5*10^n will be prefered for label steps
+        /// </summary>
+        Multiple5,
+        /// <summary>
+        /// Try to find the optimal division for tick label steps [default]
+        /// </summary>
+        /// <remarks>This method is the most computational intensive one.</remarks>
+        Auto
+    }
+    
+    /// <summary>
+    /// Names for all 3 axes 
+    /// </summary>
+    public enum AxisNames {
+        XAxis = 0,
+        YAxis = 1,
+        ZAxis = 2
+    }
+
+    /// <summary>
+    /// simple single unlabled tick
+    /// </summary>
+    public struct UnlabeledTick {
+        /// <summary>
+        /// Position of tick
+        /// </summary>
+        public float Position; 
+    }
+    /// <summary>
+    /// Axis ticks spacing type: linear, logarithmic
+    /// </summary>
+    public enum AxisType {
+        /// <summary>
+        /// linear axis tick spacing
+        /// </summary>
+        Linear,
+        /// <summary>
+        /// logarithmic axis tick spacing
+        /// </summary>
+        Logarithmic
+    }
+    /// <summary>
+    /// On which sides ticks will be displayed
+    /// </summary>
+    public enum TickDisplay {
+        /// <summary>
+        /// ticks for axis will be displayed on label side only
+        /// </summary>
+        LabelSide, 
+        /// <summary>
+        /// ticks for axis will be displayed on label - and the opposite site 
+        /// </summary>
+        BothSides
+    }
+    /// <summary>
+    /// how ticks are displayed (inside/outside)
+    /// </summary>
+    public enum TickDirection {
+        /// <summary>
+        /// Ticks will lay inside the rendering cube
+        /// </summary>
+        Inside, 
+        /// <summary>
+        /// Ticks will lay outside the rendering cube
+        /// </summary>
+        Outside
+    }
+
+    /// <summary>
+    /// orientation for axis labels (not implemented)
+    /// </summary>
+    public enum ILAxisLabelOrientation {
+        Normal, 
+        Rotate90,
+        Rotate180,
+        Rotate270,
+        Arbitrary
+    }
+    /// <summary>
+    /// TickModes - automatic or manual axis tick positioning
+    /// </summary>
+    public enum TickMode {
+        /// <summary>
+        /// find tick positions automatically 
+        /// </summary>
+        Auto,
+        /// <summary>
+        /// manually create ticks 
+        /// </summary>
+        Manual
+    }
+    /// <summary>
+    /// options for the sizing of the projection of the plot cube onto the 2D screen client area of the control
+    /// </summary>
+    public enum PlotBoxScreenSizeMode {
+        /// <summary>
+        /// the projection of the plot cube drawing area fills the whole controls space (labels may be hidden) 
+        /// </summary>
+        Maximum, 
+        /// <summary>
+        /// the size of plot cube projection rectangle is automatically determined, taking labels size into account
+        /// </summary>
+        Optimal,
+        /// <summary>
+        /// more pixel exact positioning, strictly only the place really needed for labels is used (slower)
+        /// </summary>
+        StrictOptimal,
+        /// <summary>
+        /// No automatic resizing for the cube projection size, values from PlotCubeScreenRect are taken
+        /// </summary>
+        Manual
+    }
+    /// <summary>
+    /// possible states/reasons/sources for rendering the scene
+    /// </summary>
+    internal enum RenderReason {
+        /// <summary>
+        /// normal source, the scene is to be rendered the common way
+        /// </summary>
+        PaintEvent, 
+        /// <summary>
+        /// the rendering was re-initialized because the matrices need to be recalculated for laying out labels correctly 
+        /// </summary>
+        RecalcLabels
+    }
+    /// <summary>
+    /// Alignments for labels 
+    /// </summary>
+    public enum LabelAlign {
+        /// <summary>
+        /// align the label near the lower range limit
+        /// </summary>
+        Lower, 
+        /// <summary>
+        /// align the label in the center 
+        /// </summary>
+        Center,
+        /// <summary>
+        /// align the label near the upper range limit
+        /// </summary>
+        Upper
+    }
+    /// <summary>
+    /// Possible alignments for tick labels
+    /// </summary>
+    /// <remarks>member of this enum can get bitwise combined. Default is: Top,Left</remarks>
+    [FlagsAttribute]
+    public enum TickLabelAlign {
+        /// <summary>
+        /// align the label to the left side
+        /// </summary>
+        left = 0,
+        /// <summary>
+        /// align the labels to the center
+        /// </summary>
+        center = 1,
+        /// <summary>
+        /// align the label to the right side
+        /// </summary>
+        right = 2, 
+        /// <summary>
+        /// align the label to top
+        /// </summary>
+        top = 0,
+        /// <summary>
+        /// align the label to center vertically 
+        /// </summary>
+        vertCenter = 4,
+        /// <summary>
+        /// align the label to bottom
+        /// </summary>
+        bottom = 16
+    }
+
+    /// <summary>
+    /// projection types
+    /// </summary>
+    public enum Projection {
+        /// <summary>
+        /// 3D graphs will be distorted for opotimized 3D impression
+        /// </summary>
+        Perspective,
+        /// <summary>
+        /// graphs will not be distorted. objects in the front will get the same size as objects in the back
+        /// </summary>
+        Orthographic
+    }
+
+    /// <summary>
+    /// valid marker styles (partially supported)
+    /// </summary>
+    public enum MarkerStyle {
+        /// <summary>
+        /// draw markers as dots
+        /// </summary>
+        Dot,
+        /// <summary>
+        /// draw markers as circle
+        /// </summary>
+        Circle, 
+        /// <summary>
+        /// draw markers as diamonds
+        /// </summary>
+        Diamond,
+        /// <summary>
+        /// draw markers as square
+        /// </summary>
+        Square,
+        /// <summary>
+        /// draw markers as up pointing triangles
+        /// </summary>
+        TriangleUp,
+        /// <summary>
+        /// draw markers as up pointing triangles
+        /// </summary>
+        TriangleDown,
+        /// <summary>
+        /// draw markers as up pointing triangles
+        /// </summary>
+        TriangleLeft,
+        /// <summary>
+        /// draw markers as up pointing triangles
+        /// </summary>
+        TriangleRight,
+        /// <summary>
+        /// draw markers as plus
+        /// </summary>
+        Plus,
+        /// <summary>
+        /// draw markers as cross
+        /// </summary>
+        Cross,
+        /// <summary>
+        /// do not draw markers
+        /// </summary>
+        None,
+    }
+    /// <summary>
+    /// Possible positions of the camera
+    /// </summary>
+    public enum CameraQuadrant {
+        TopLeftFront,
+        TopLeftBack,
+        TopRightBack,
+        TopRightFront,
+        BottomLeftFront,
+        BottomLeftBack,
+        BottomRightBack,
+        BottomRightFront
+    }
+    /// <summary>
+    /// Shading styles for surface graphs
+    /// </summary>
+    public enum ShadingStyles {
+        /// <summary>
+        /// color will be interpolated between all corners 
+        /// </summary>
+        Interpolate, 
+        /// <summary>
+        /// same color for whole tile area
+        /// </summary>
+        /// <remarks>The resulting color will 
+        /// reflect the average over all corner values for a rectangle</remarks>
+        Flat   
+    }
+
+    /// <summary>
+    /// line style
+    /// </summary>
+    public enum LineStyle {
+        /// <summary>
+        /// solid line
+        /// </summary>
+        Solid = Int32.MaxValue, 
+        /// <summary>
+        /// dashed line
+        /// </summary>
+        Dashed = Int16.MaxValue,
+        /// <summary>
+        /// point dashed line
+        /// </summary>
+        PointDash = unchecked((int)4294837760),
+        /// <summary>
+        /// dotted line
+        /// </summary>
+        Dotted = unchecked((int)3435973836),
+        /// <summary>
+        /// use user stipple pattern 
+        /// </summary>
+        UserPattern = -1,
+        /// <summary>
+        /// no line at all
+        /// </summary>
+        None = 0
+    }
+    /// <summary>
+    /// modes of mouse interaction with ILPanel
+    /// </summary>
+    public enum InteractiveModes {
+        ZoomRectangle, 
+        Rotating,
+        Selecting,
+        Translating,
+        None
+    }
+    /// <summary>
+    /// single precision 3D point structure
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential)]
+    public struct ILPoint3Df {
+        /// <summary>
+        /// X coordinate
+        /// </summary>
+        public float X;
+        /// <summary>
+        /// Y coordinate
+        /// </summary>
+        public float Y;
+        /// <summary>
+        /// Z coordinate
+        /// </summary>
+        public float Z;
+        /// <summary>
+        /// create point in single precision
+        /// </summary>
+        /// <param name="x">X coord</param>
+        /// <param name="y">Y coord</param>
+        /// <param name="z">Z coord</param>
+        public ILPoint3Df (float x, float y, float z) {
+            X = x; 
+            Y = y; 
+            Z = z; 
+        }
+        /// <summary>
+        /// create new ILPoint3Df by double values (for convenience, internally casted to float)
+        /// </summary>
+        /// <param name="x">X coord</param>
+        /// <param name="y">Y coord</param>
+        /// <param name="z">Z coors</param>
+        public ILPoint3Df (double x, double y, double z) {
+            X = (float)x; 
+            Y = (float)y; 
+            Z = (float)z; 
+        }
+        /// <summary>
+        /// convert this point to string representation
+        /// </summary>
+        /// <returns></returns>
+        public override string ToString() {
+            return "X:" + X.ToString() + " Y:" + Y.ToString() + " Z:" + Z.ToString(); 
+        }
+        /// <summary>
+        /// Access to coords by index
+        /// </summary>
+        /// <param name="index">index number: 0=x, 1=y, 2=z</param>
+        /// <returns>float value of coord specified</returns>
+        public float this[int index] {
+            get {
+                switch (index) {
+                    case 0:
+                        return X;
+                    case 1: 
+                        return Y;
+                    default: 
+                        return Z;
+                }
+            }
+        }
+        public static bool operator == (ILPoint3Df p1, ILPoint3Df p2) {
+            return (p1.X == p2.X && 
+                    p1.Y == p2.Y && 
+                    p1.Z == p2.Z); 
+        }
+        public static bool operator != (ILPoint3Df p1, ILPoint3Df p2) {
+            return (p1.X != p2.X || 
+                    p1.Y != p2.Y ||
+                    p1.Z != p2.Z);  
+        }
+        public static ILPoint3Df operator + (ILPoint3Df p1, ILPoint3Df p2) {
+            ILPoint3Df ret = new ILPoint3Df(); 
+            ret.X = p1.X + p2.X; 
+            ret.Y = p1.Y + p2.Y; 
+            ret.Z = p1.Z + p2.Z; 
+            return ret; 
+        }
+        public static ILPoint3Df operator - (ILPoint3Df p1, ILPoint3Df p2) {
+            ILPoint3Df ret = new ILPoint3Df(); 
+            ret.X = p1.X - p2.X; 
+            ret.Y = p1.Y - p2.Y; 
+            ret.Z = p1.Z - p2.Z; 
+            return ret; 
+        }
+        public static ILPoint3Df operator * (ILPoint3Df p1, float factor) {
+            ILPoint3Df ret = new ILPoint3Df(); 
+            ret.X = p1.X * factor; 
+            ret.Y = p1.Y * factor; 
+            ret.Z = p1.Z * factor; 
+            return ret; 
+        }
+        public static ILPoint3Df operator *(OpenTK.Math.Matrix4 mat, ILPoint3Df vec) {
+            return new ILPoint3Df(
+                mat.Row0.X * vec.X + mat.Row0.Y * vec.Y + mat.Row0.Z * vec.Z + mat.Row0.W,
+                mat.Row1.X * vec.X + mat.Row1.Y * vec.Y + mat.Row1.Z * vec.Z + mat.Row1.W,
+                mat.Row2.X * vec.X + mat.Row2.Y * vec.Y + mat.Row2.Z * vec.Z + mat.Row2.W); 
+        }
+        public static ILPoint3Df operator / (ILPoint3Df p1, float factor) {
+            ILPoint3Df ret = new ILPoint3Df(); 
+            ret.X = p1.X / factor; 
+            ret.Y = p1.Y / factor; 
+            ret.Z = p1.Z / factor; 
+            return ret; 
+        }
+        public static readonly ILPoint3Df Empty = new ILPoint3Df(float.NaN,float.NaN,float.NaN); 
+        public bool IsEmtpy () {
+            return float.IsNaN(X) || float.IsNaN(Y) || float.IsNaN(Z); 
+        }
+
+        /// <summary>
+        /// cross product
+        /// </summary>
+        /// <param name="a">vector 1</param>
+        /// <param name="b">vector 2</param>
+        /// <returns>normalized cross product between a x b</returns>
+        public static ILPoint3Df cross(ILPoint3Df a, ILPoint3Df b) {
+            return new ILPoint3Df(
+                a.Y * b.Z - a.Z * b.Y,
+                a.Z * b.X - a.X * b.Z,
+                a.X * b.Y - a.Y * b.X);     
+        }
+        /// <summary>
+        /// normalized cross product
+        /// </summary>
+        /// <param name="a">vector 1</param>
+        /// <param name="b">vector 2</param>
+        /// <returns>normalized cross product: a x b</returns>
+        public static ILPoint3Df crossN(ILPoint3Df a, ILPoint3Df b) {
+            ILPoint3Df ret = new ILPoint3Df(
+                a.Y * b.Z - a.Z * b.Y,
+                a.Z * b.X - a.X * b.Z,
+                a.X * b.Y - a.Y * b.X); 
+            float len = (float)Math.Sqrt(ret.X * ret.X + ret.Z * ret.Z + ret.Y * ret.Y); 
+            if (len != 0)
+                return (ret / len); 
+            return ret; 
+        }
+        public float GetLength() {
+            return (float)Math.Sqrt(X * X + Y * Y + Z * Z); 
+        }
+        public static ILPoint3Df MaxValue {
+            get { return new ILPoint3Df(float.MaxValue,float.MaxValue,float.MaxValue); }
+        }
+        public static ILPoint3Df MinValue {
+            get { return new ILPoint3Df(float.MinValue,float.MinValue,float.MinValue); }
+        }
+        public static ILPoint3Df Min(ILPoint3Df val1, ILPoint3Df val2) {
+            ILPoint3Df ret = val1; 
+            if (val2.X < val1.X) ret.X = val2.X; 
+            if (val2.Y < val1.Y) ret.Y = val2.Y; 
+            if (val2.Z < val1.Z) ret.Z = val2.Z; 
+            return ret; 
+        }
+        public static ILPoint3Df Min(ILPoint3Df val1, ILPoint3Df val2, ref bool changed) {
+            ILPoint3Df ret = val1; 
+            if (val2.X < val1.X) { 
+                ret.X = val2.X; 
+                changed = true; 
+            }
+            if (val2.Y < val1.Y) { 
+                ret.Y = val2.Y; 
+                changed = true; 
+            } 
+            if (val2.Z < val1.Z) { 
+                ret.Z = val2.Z; 
+                changed = true; 
+            }
+            return ret; 
+        }
+        public static ILPoint3Df Max(ILPoint3Df val1, ILPoint3Df val2) {
+            ILPoint3Df ret = val1; 
+            if (val2.X > val1.X) ret.X = val2.X; 
+            if (val2.Y > val1.Y) ret.Y = val2.Y; 
+            if (val2.Z > val1.Z) ret.Z = val2.Z; 
+            return ret; 
+        }
+        public static ILPoint3Df Max(ILPoint3Df val1, ILPoint3Df val2, ref bool changed) {
+            ILPoint3Df ret = val1;  
+            if (val2.X > val1.X) { 
+                ret.X = val2.X; 
+                changed = true; 
+            }
+            if (val2.Y > val1.Y) {
+                ret.Y = val2.Y; 
+                changed = true; 
+            }
+            if (val2.Z > val1.Z) {
+                ret.Z = val2.Z; 
+                changed = true; 
+            }
+            return ret; 
+        }
+
+
+        public static ILPoint3Df normalize(ILPoint3Df p) {
+            float length = (float)Math.Sqrt(p.X * p.X + p.Y * p.Y + p.Z * p.Z);
+            return p / length;                 
+        }
+
+        public static ILPoint3Df normalize(float x, float y, float z) {
+            float length = (float)Math.Sqrt(x * x + y * y + z * z);
+            return new ILPoint3Df(x,y,z) / length;                 
+        }
+
+        public void ToPolar(out float len, out float phi, out float rho) {
+            len = (float)Math.Sqrt(X * X + Y * Y + Z * Z);
+            phi = (float)Math.Atan2(Y, X);
+            rho = (float)Math.Atan2(Math.Sqrt(X * X + Y * Y), Z);
+        }
+
+        /// <summary>
+        /// rotate the vector, keep length
+        /// </summary>
+        /// <param name="normal">axis as rotation normal</param>
+        /// <param name="angleDeg">angle to move (radian)</param>
+        /// <returns>rotated version of this vector, does not change original vector</returns>
+        public ILPoint3Df Spin(ILPoint3Df normal, float angleDeg) {
+            float a = angleDeg * (float)Math.PI / 180f;
+            float cosa = (float)Math.Cos(a);
+            float sina = (float)Math.Sin(a);
+            normal = ILPoint3Df.normalize(normal);
+            float omincosa = 1 - cosa;
+            ILPoint3Df ret = new ILPoint3Df(
+                (cosa + X * X * omincosa) * normal.X
+                + (X * Y * omincosa - Z * sina) * normal.Y
+                + (X * Z * omincosa + Y * sina) * normal.Z,
+
+                (Y * X * omincosa + Z * sina) * normal.X
+                + (cosa + Y * Y * omincosa) * normal.Y
+                + (Y * Z * omincosa - X * sina) * normal.Z,
+
+                (Z * X * omincosa - Y * sina) * normal.X
+                + (Z * Y * omincosa + X * sina) * normal.Y
+                + (cosa + Z * Z * omincosa) * normal.Z);
+            return ret; 
+        }
+        /// <summary>
+        /// Compares obj's coordinate values to those of this class instance
+        /// </summary>
+        /// <param name="obj">ILPoint3Df to compare</param>
+        /// <returns>true, if X,Y and Z coordinates are equal</returns>
+        public override bool Equals(object obj) {
+            return ((ILPoint3Df)obj) == this;
+        }
+        /// <summary>
+        /// get a hash code for this ILPoint3Df object
+        /// </summary>
+        /// <returns>hash code</returns>
+        public override int GetHashCode() {
+            return base.GetHashCode();
+        }
+    }
+    /// <summary>
+    /// double precision 3D point definition
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential)]
+    public struct ILPoint3Dd {
+        /// <summary>
+        /// X coord
+        /// </summary>
+        public double X;
+        /// <summary>
+        /// Y coord
+        /// </summary>
+        public double Y;
+        /// <summary>
+        /// Z coord
+        /// </summary>
+        public double Z;
+    }
+    /// <summary>
+    /// supported graphics devices
+    /// </summary>
+    public enum GraphicDeviceType {
+        /// <summary>
+        /// DirectX based 
+        /// </summary>
+        Direct3D,
+        /// <summary>
+        /// OpenGL based (not supported yet)
+        /// </summary>
+        OpenGL,
+        /// <summary>
+        /// Windows native graphics device (not implemented)
+        /// </summary>
+        GDI,
+        /// <summary>
+        /// unknown graphics device (not used, errror)
+        /// </summary>
+        Unknown
+    }
+    /// <summary>
+    /// valid types for plotting graphs
+    /// </summary>
+    public enum GraphType {
+        Axis,
+        Plot2D,
+        Plot3D,
+        Surf,
+        Mesh,
+        Waterfall,
+        Ribbon,
+        Image,
+        Imagesc,
+        PColor,
+        Contour,
+        CountourFilled,
+        ContourSlice,
+        Scatter,
+        Scatter3,
+        SceneGraph,
+        Errorbar,
+        Stem,
+        Stairs,
+        Stem3,
+        Bar,
+        BarHorizontal,
+        Auto
+    }
+    /// <summary>
+    /// Coordinate systems for TextRenderer
+    /// </summary>
+    public enum CoordSystem {
+        /// <summary>
+        /// the location is expected to be specified into screen coords
+        /// </summary>
+        Screen, 
+        /// <summary>
+        /// the location is expected to be specified into world (3D) coords
+        /// </summary>
+        World3D
+    }
+    /// <summary>
+    /// possible types of renderable items 
+    /// </summary>
+    public enum RenderItemType {
+        /// <summary>
+        /// the item defines a character 
+        /// </summary>
+        Character,
+        /// <summary>
+        /// the item defines a bitmap
+        /// </summary>
+        Bitmap
+    }
+    /// <summary>
+    /// possible reason for an ILGraphCollectionChangedEvent to occur
+    /// </summary>
+    public enum GraphCollectionChangeReason {
+        Added,
+        Deleted,
+        Changed
+    }
+    public class ILLayoutData {
+        public ILLayoutData(ILCamera camera) {
+            CameraPosition = camera; 
+        }
+        public ILCamera CameraPosition; 
+        public ILLayoutData() {
+        }
+    }
+}
+
+namespace ILNumerics.Drawing.Labeling {
+    /// <summary>
+    /// simple single labeled tick
+    /// </summary>
+    public struct LabeledTick {
+        /// <summary>
+        /// tick label
+        /// </summary>
+        public readonly ILRenderQueue Queue; 
+        /// <summary>
+        /// tick position
+        /// </summary>
+        public readonly float Position; 
+        /// <summary>
+        /// create single labeled tick
+        /// </summary>
+        /// <param name="position">position</param>
+        /// <param name="queue">render queue used to render the item</param>
+        public LabeledTick(float position, ILRenderQueue queue) { 
+            Position = position; 
+            Queue    = queue; 
+        }
+    }
+    
+
+}
+    
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/Events.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/Events.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/Events.cs	(revision 9102)
@@ -0,0 +1,219 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+#pragma warning disable 1591
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing; 
+using ILNumerics.Drawing.Graphs;
+using ILNumerics.Drawing.Interfaces;
+
+namespace ILNumerics.Drawing {
+
+    /// <summary>
+    /// tick provider function delegate definition
+    /// </summary>
+    /// <param name="min">minimum axis limit</param>
+    /// <param name="max">maximum axis limit</param>
+    /// <param name="maxCount">maximum number of ticks to create</param>
+    /// <returns>list of tick position to be drawn</returns>
+    /// <remarks>User defined tick providers must fulfill this delegates signature. 
+    /// </remarks>
+    public delegate List<float> ILLabeledTickProvider (float min, float max, int maxCount);  
+
+    /// <summary>
+    /// occours if the clipping data for an subfigure have changed
+    /// </summary>
+    /// <param name="sender">object which changed the data</param>
+    /// <param name="e">arguments containing the new clipping data</param>
+    public delegate void ILClippingDataChangedEvent (object sender, ClippingChangedEventArgs e); 
+    
+    /// <summary>
+    /// delegate used to measure text, device dependent
+    /// </summary>
+    /// <param name="text">text to be measured</param>
+    /// <param name="font">Font used for rendering</param>
+    /// <returns>Size in screen coords</returns>
+    public delegate Size MeasureTextDelegate(string text, Font font); 
+
+    /// <summary>
+    /// arguments on ClippinChangedEvents
+    /// </summary>
+    public class ClippingChangedEventArgs : EventArgs {
+        /// <summary>
+        /// creates a new ClippingChangedEventArgs object
+        /// </summary>
+        /// <param name="clippingData"></param>
+        public ClippingChangedEventArgs(ILClippingData clippingData) {
+            ClippingData = clippingData; 
+        }
+        /// <summary>
+        /// the current (new) clipping data
+        /// </summary>
+        public ILClippingData ClippingData;
+    }
+    /// <summary>
+    /// occours if a graphics device has been reset by the underlying graphics framework
+    /// </summary>
+    /// <param name="sender">objects who hosts the graphics device</param>
+    /// <param name="eventArgs"></param>
+    public delegate void ILGraphicsDeviceResetEvent(object sender, EventArgs eventArgs); 
+    /// <summary>
+    /// occours if a graphics device has been (re)created by an output panel
+    /// </summary>
+    /// <param name="sender">objects who hosts the graphics device</param>
+    /// <param name="eventArgs"></param>
+    public delegate void ILGraphicsDeviceCreatedEvent(object sender, EventArgs eventArgs); 
+    /// <summary>
+    /// arguments to communicate changes on graphs 
+    /// </summary>
+    public class ILGraphChangedEventArgs : EventArgs {
+        /// <summary>
+        /// string description of the changed parameter
+        /// </summary>
+        public readonly string Source; 
+        public ILGraphChangedEventArgs (string source) {
+            this.Source = source; 
+        }
+    }
+    /// <summary>
+    /// fires, if properties of a graph were /have changed
+    /// </summary>
+    /// <param name="sender"></param>
+    /// <param name="args"></param>
+    public delegate void ILGraphChangedEvent (object sender, ILGraphChangedEventArgs args); 
+    
+    /// <summary>
+    /// arguments for ILGraphCollectionChanged events
+    /// </summary>
+    public class ILGraphCollectionChangedEventArgs: EventArgs {
+        public readonly GraphCollectionChangeReason Reason; 
+        public readonly ILGraph Graph; 
+        /// <summary>
+        /// description of element changed (in some cases)
+        /// </summary>
+        public readonly IILPanelConfigurator Configurator;
+        /// <summary>
+        /// arguments for GraphCollectionChanged events
+        /// </summary>
+        /// <param name="graph">the graph who was changed, for ILPlot: the scene graph</param>
+        /// <param name="reason">reason</param>
+        /// <param name="configurator"> instance of IILPanelConfigurator or null</param>
+        public ILGraphCollectionChangedEventArgs(ILGraph graph, GraphCollectionChangeReason reason, IILPanelConfigurator configurator) {
+            this.Graph = graph; 
+            this.Reason = reason; 
+            this.Configurator = configurator; 
+        }
+    }
+    /// <summary>
+    /// occurs on changes to the graph collection: add, delete
+    /// </summary>
+    /// <param name="sender">graph collection</param>
+    /// <param name="args"></param>
+    public delegate void ILGraphCollectionChangedEvent(object sender, ILGraphCollectionChangedEventArgs args);  
+
+    /// <summary>
+    /// Event handler handling LabeledTickAdding events 
+    /// </summary>
+    public class ILLabeledTickAddingArgs : EventArgs {
+        public bool Cancel; 
+        public float Value; 
+        public string Expression; 
+        public int Index; 
+
+        public ILLabeledTickAddingArgs (float value, string expression, int index) {
+            Value = value; 
+            Expression = expression; 
+            Cancel = false; 
+            Index = index; 
+        }
+    }
+    /// <summary>
+    /// Delegate definition for function handling LabeledTickAdding events
+    /// </summary>
+    /// <param name="sender">the sender of the event (e.g. ILTickCollection)</param>
+    /// <param name="args">arguments </param>
+    public delegate void LabeledTickAddingHandler (object sender, ILLabeledTickAddingArgs args); 
+
+    /// <summary>
+    /// Event arguments for axis changed events
+    /// </summary>
+    public class ILAxisChangedEventArgs : EventArgs {
+        /// <summary>
+        /// Name of changed axis (X-,Y-,ZAxis)
+        /// </summary>
+        public AxisNames AxisName;
+        /// <summary>
+        /// construct a new instance 
+        /// </summary>
+        /// <param name="name"></param>
+        public ILAxisChangedEventArgs (AxisNames name) {
+            AxisName = name; 
+        }
+    }
+    /// <summary>
+    /// delegate for functions handling AxisChanged events
+    /// </summary>
+    /// <param name="sender"></param>
+    /// <param name="args"></param>
+    public delegate void AxisChangedEventHandler (object sender, ILAxisChangedEventArgs args); 
+
+    /// <summary>
+    /// event argument for SceneGraphNodeAdded events
+    /// </summary>
+    public class ILSceneGraphNodeEventArgs : EventArgs {
+        /// <summary>
+        /// Node which was added to the scene graph
+        /// </summary>
+        public ILSceneGraphNode Node;
+
+        public ILSceneGraphNodeEventArgs(ILSceneGraphNode node) {
+            Node = node; 
+        }
+    }
+    /// <summary>
+    /// used for events fired once a SceneGraphNode was added
+    /// </summary>
+    /// <param name="sender">the object</param>
+    /// <param name="args">the arguments</param>
+    public delegate void SceneGraphNodeHandler (object sender, ILSceneGraphNodeEventArgs args);  
+
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/ILAction.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/ILAction.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/ILAction.cs	(revision 9102)
@@ -0,0 +1,86 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+#pragma warning disable 1591
+
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading; 
+
+namespace ILNumerics.Drawing.Misc {
+    public abstract class ILAction {
+
+        #region attributes
+        Thread m_workerThread; 
+        protected bool m_canceled; 
+        #endregion
+
+        #region properties
+        #endregion
+
+        #region constructor
+        public ILAction() {
+            m_canceled = false; 
+            m_workerThread = new Thread(new ParameterizedThreadStart(RunInternal)); 
+        }
+        #endregion
+
+        #region public interface 
+        // Run
+        public void Run() {
+            if (m_workerThread.ThreadState != ThreadState.Running) {
+                m_canceled = false; 
+                m_workerThread.Start();
+            }
+        }
+        // Cancel
+        public void Cancel() {
+            m_canceled = true; 
+        }
+
+        protected abstract void RunInternal(object parameter); 
+        #endregion 
+
+        #region private helper
+
+        #endregion
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/ILActionRamp.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/ILActionRamp.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/ILActionRamp.cs	(revision 9102)
@@ -0,0 +1,127 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+#pragma warning disable 1591
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics; 
+
+namespace ILNumerics.Drawing.Misc {
+    
+    public class ILActionRamp : List<ILActionRampElement> {
+
+        public static ILActionRamp s_OverrideRamp;
+        public static ILActionRamp Override {
+            get {
+                if (s_OverrideRamp == null) {
+                    using (ILScope.Enter()) {
+                        s_OverrideRamp = new ILActionRamp();
+                        ILArray<float> tmp = ILMath.sin(ILMath.linspace<float>(-ILMath.pi / 1.7, ILMath.pi / 1.7, 20));
+                        tmp -= tmp[0];
+                        tmp /= tmp["end"];
+                        foreach (float val in tmp) {
+                            s_OverrideRamp.Add(new ILActionRampElement(val, .02f));
+                        }
+                    }
+                }
+                return s_OverrideRamp;
+            }
+        }
+        public static ILActionRamp s_softRamp;
+        public static ILActionRamp Soft {
+            get {
+                if (s_softRamp == null) {
+                    using (ILScope.Enter()) {
+                        s_softRamp = new ILActionRamp();
+                        ILArray<float> tmp = ILMath.sin(ILMath.linspace<float>(-ILMath.pif / 2f, ILMath.pif / 2f, 10f));
+                        tmp += 1;
+                        tmp /= 2;
+                        foreach (float val in tmp) {
+                            s_softRamp.Add(new ILActionRampElement(val, .02f));
+                        }
+                    }
+                }
+                return s_softRamp;
+            }
+        }
+        public static ILActionRamp s_hardRamp;
+        public static ILActionRamp Hard {
+            get {
+                if (s_hardRamp == null) {
+                    using (ILScope.Enter()) {
+                        s_hardRamp = new ILActionRamp();
+                        ILArray<float> tmp = ILMath.sin(ILMath.linspace<float>(0.0, 1.0, 10.0));
+                        foreach (float val in tmp) {
+                            s_hardRamp.Add(new ILActionRampElement(val, .02f));
+                        }
+                    }
+                }
+                return s_hardRamp;
+            }
+        }
+        public static ILActionRamp s_linearRamp;
+        public static ILActionRamp Linear {
+            get {
+                if (s_linearRamp == null) {
+                    using (ILScope.Enter()) {
+                        s_linearRamp = new ILActionRamp();
+                        for (int i = 0; i < 10; i++) {
+                            s_linearRamp.Add(new ILActionRampElement(i / 9.0f, 0.02f));
+                        }
+                    }
+                }
+                return s_linearRamp;
+            }
+        }
+        public static ILActionRamp s_noRamp;
+        public static ILActionRamp NoRamp {
+            get {
+                if (s_noRamp == null) {
+                    s_noRamp = new ILActionRamp();
+                    s_noRamp.Add(new ILActionRampElement(1, 0));
+                }
+                return s_noRamp;
+            }
+        }
+
+        public ILActionRamp() {}
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/ILActionRampElement.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/ILActionRampElement.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/ILActionRampElement.cs	(revision 9102)
@@ -0,0 +1,54 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace ILNumerics.Drawing.Misc {
+    public class ILActionRampElement {
+        public float Value; 
+        public float Duration;
+
+        public ILActionRampElement(float value, float duration) {
+            Value = value; 
+            Duration = duration; 
+        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/ILAxis.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/ILAxis.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/ILAxis.cs	(revision 9102)
@@ -0,0 +1,430 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+#pragma warning disable 1591
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing; 
+using ILNumerics.Drawing.Interfaces; 
+using ILNumerics.Exceptions; 
+using ILNumerics.Drawing.Collections; 
+using ILNumerics.Drawing.Labeling; 
+using ILNumerics.Drawing; 
+
+namespace ILNumerics.Drawing {
+    /// <summary>
+    /// Axis object for ILPanel
+    /// </summary>
+    public abstract class ILAxis : IDisposable {
+
+        #region attributes
+        
+        public event EventHandler Changed; 
+        protected ILTickCollection m_labeledTicks; 
+        protected ICollection<UnlabeledTick> m_unLabeledTicks; 
+        protected ILLineProperties m_grid; 
+        protected ILLineProperties m_nearLines; 
+        protected ILLineProperties m_farLines; 
+        protected ILClippingData m_clipping; 
+        protected ILLabel m_label; 
+        protected AxisType m_axisType;
+        protected AxisNames m_axisName; 
+        protected bool m_visible = true; 
+        protected bool m_invalidated = true; 
+        protected ILLayoutData m_layoutData; 
+        private ILLabeledTickProvider m_labelProvider;
+        protected ILPanel m_panel; 
+        #endregion 
+
+        #region properties
+
+        /// <summary>
+        /// Panel hosting the axis (readonly)
+        /// </summary>
+        ILPanel Panel {
+            get { return m_panel; }
+        }
+
+        /// <summary>
+        /// Used to retrieve/specify the delegate computing nice labels for axis
+        /// </summary>
+        /// <remarks>One can replace the default tick provider by a user 
+        /// defined labeled tick computation function. Therefore simply set this property to
+        /// your own ILLabeledTickProvider function.
+        /// </remarks>
+        public ILLabeledTickProvider LabeledTickProvider {
+            get {
+                return m_labelProvider; 
+            }
+            set {
+                if (value == null) return; 
+                m_labelProvider = value; 
+            }
+        }
+        /// <summary>
+        /// get properties for far axis lines (opposite label side) or sets it
+        /// </summary>
+        public ILLineProperties FarLines {
+            get {
+                return m_farLines; 
+            }
+            set {
+                m_farLines = value; 
+                OnChange();
+            }
+        }
+        /// <summary>
+        /// get properties for near axis lines (opposite label side) or sets it
+        /// </summary>
+        public ILLineProperties NearLines {
+            get {
+                return m_nearLines; 
+            }
+            set {
+                m_nearLines = value; 
+                OnChange(); 
+            }
+        }
+        /// <summary>
+        /// label to be displayed next to this axis
+        /// </summary>
+        public ILLabel Label {
+            get {
+                return m_label; 
+            }
+            set {
+                m_label = value; 
+                OnChange(); 
+            }
+        }
+        /// <summary>
+        /// Switch visibility on/ off
+        /// </summary>
+        public bool Visible { 
+            get {
+                return m_visible;
+            }
+            set {
+                m_visible = value; 
+                OnChange(); 
+            }
+        }
+        /// <summary>
+        /// axis type
+        /// </summary>
+        public AxisType AxisType {
+            get {
+                return m_axisType; 
+            }
+            set {
+                m_axisType = value; 
+                OnChange(); 
+            }
+        }
+        /// <summary>
+        /// Gives access to the collection of labeled ticks
+        /// </summary>
+        public ILTickCollection LabeledTicks {
+           get { 
+               return m_labeledTicks; 
+           }
+        }
+        /// <summary>
+        /// access to the collection of unlabeled ticks (not used)
+        /// </summary>
+        public ICollection<UnlabeledTick> UnlabeledTicks {
+            get {
+                return m_unLabeledTicks; 
+            }
+        }
+        /// <summary>
+        /// access to a specific axis by number 
+        /// </summary>
+        public int Index {
+            get {
+                return (int)m_axisName;
+            }
+        }
+        /// <summary>
+        /// access grid lines properties 
+        /// </summary>
+        public ILLineProperties Grid {
+            get {
+                return m_grid;
+            }
+        }
+        /// <summary>
+        /// access axis limits 
+        /// </summary>
+        public ILClippingData Limits {
+            get {
+                return m_clipping; 
+            }
+        }
+
+        #endregion
+
+        #region Event handling
+        /// <summary>
+        /// fires a changed event
+        /// </summary>
+        protected void OnChange() {
+            Invalidate();
+            if (Changed != null) {
+                Changed(this,null); 
+            }
+        }
+        /// <summary>
+        /// occures if the registered clipping data have changed
+        /// </summary>
+        /// <param name="sender">ILClipping data</param>
+        /// <param name="e">clipping changed event args</param>
+        void m_clipping_Changed(object sender, ClippingChangedEventArgs e) {
+            Invalidate(); 
+        }
+        void m_labeledTicks_Changed(object sender, ILAxisChangedEventArgs args) {
+            Invalidate();
+        }
+        void m_grid_Changed(object sender, EventArgs e) {
+            Invalidate(); 
+        }
+        void m_label_Changed(object sender, EventArgs e) {
+            Invalidate(); 
+        }
+        #endregion
+
+        #region constructor
+        /// <summary>
+        /// construct ILAxis object. This contructor is not to be called directly.
+        /// </summary>
+        /// <param name="name">type of the axis: XAxis,YAxis,ZAxis</param>
+        /// <param name="clippingView">Clipping data to be registered into the axis.</param>
+        /// <param name="layoutData">additional layout data, does currently only contain the camera [depricated]</param>
+        /// <param name="panel">panel hosting the scene</param>
+        /// <remarks>ILAxis objects are created GL-device dependend by use of a device dependend ILPanel instance's
+        /// member ILPanel.CreateAxis(). This acts like a factory pattern. The specific axis derivate will be
+        /// created by the derived ILPanel object (ILDXPanel or ILOGLPanel).</remarks>
+        public ILAxis (AxisNames name, ILClippingData clippingView,
+                       ILLayoutData layoutData,ILPanel panel) {
+            m_panel = panel; 
+            m_axisName = name; 
+            m_labeledTicks = new ILTickCollection(panel,m_axisName);
+            m_layoutData = layoutData; 
+            m_labelProvider = null; 
+            m_labeledTicks.Changed += new AxisChangedEventHandler(m_labeledTicks_Changed);
+            m_unLabeledTicks = new List<UnlabeledTick>(10); 
+            m_grid = new ILLineProperties();
+            m_grid.Style = LineStyle.Dashed;
+            m_grid.Color = Color.FromArgb(220, 220, 225);
+            m_grid.Width = 1; 
+
+            m_grid.Changed += new EventHandler(m_grid_Changed);
+            m_clipping = clippingView; 
+            m_axisType = AxisType.Linear;
+            m_nearLines = new ILLineProperties(); 
+            m_nearLines.Color = Color.DarkBlue; 
+            m_nearLines.Width = 1; 
+            m_nearLines.Antialiasing = true; 
+            m_nearLines.Changed +=new EventHandler(m_grid_Changed);
+            m_farLines = new ILLineProperties(); 
+            m_farLines.Color = Color.DarkBlue; 
+            m_farLines.Width = 1; 
+            m_farLines.Antialiasing = true; 
+            m_farLines.Changed +=new EventHandler(m_grid_Changed);
+            m_label = new ILLabel(panel);
+            m_label.Changed += new EventHandler(m_label_Changed);
+            m_clipping.Changed += new ILClippingDataChangedEvent(m_clipping_Changed);
+            m_invalidated = true; 
+        }
+        #endregion
+
+        #region abstract interface 
+        /// <summary>
+        /// this function does the drawing of the axis lines 
+        /// </summary>
+        /// <param name="p">render properties</param>
+        /// <param name="background">true: draw background only, false: draw foreground only</param>
+        /// <remarks>This function is called in the general rendering algorithm. I.e. <b>before</b> the surface buffers has been swapped.</remarks>
+        protected abstract void iDrawAxis(ILRenderProperties p, bool background); 
+        /// <summary>
+        /// (internal use) do the drawing of axis' label 
+        /// </summary>
+        /// <param name="p">render properties</param>
+        /// <remarks>When this function is called, depends on the DrawAfterBufferSwaped setting 
+        /// of the current TextRenderer.</remarks>
+        protected virtual void iDrawLabel(ILRenderProperties p) {
+            if (m_visible)
+                m_label.Draw(p);
+        }
+
+        /// <summary>
+        /// (internal use) draw tick labels
+        /// </summary>
+        /// <param name="p">render properties</param>
+        protected virtual void iDrawTickLabels(ILRenderProperties p) {
+            if (m_visible)
+                m_labeledTicks.Draw(p,m_clipping.Min[Index],m_clipping.Max[Index]); 
+        }
+        /// <summary>
+        /// Do all rendering for the grid of the axis
+        /// </summary>
+        protected abstract void drawGrid();
+
+        /// <summary>
+        /// draw this axis in the back (behind the graphs)
+        /// </summary>
+        /// <param name="p">render properties</param>
+        /// <remarks>This method is used internally. There should be no need to call it directly.</remarks>
+        internal virtual void RenderState1(ILRenderProperties p) {
+            if (m_invalidated) {
+                Configure(p);
+                p.Canceled = true;
+            }
+            if (!m_labeledTicks.Renderer.DrawAfterBufferSwapped)
+                iDrawTickLabels(p); 
+            if (!m_label.Renderer.DrawAfterBufferSwapped) 
+                iDrawLabel(p); 
+            iDrawAxis(p,true); 
+        } 
+        /// <summary>
+        /// Do rendering of foreground (before the graphs)
+        /// </summary>
+        /// <param name="p">render properties</param>
+        public virtual void RenderState2(ILRenderProperties p) {
+            //if (m_invalidated) 
+            //    Configure(p); 
+            iDrawAxis(p,false); 
+        }
+        /// <summary>
+        /// do rendering after the buffers have been swapped
+        /// </summary>
+        /// <param name="p">render properties</param>
+        public virtual void RenderState3(ILRenderProperties p) {
+            if (m_labeledTicks.Renderer.DrawAfterBufferSwapped)
+                iDrawTickLabels(p); 
+            if (m_label.Renderer.DrawAfterBufferSwapped) 
+                iDrawLabel(p); 
+        }
+
+        /// <summary>
+        /// update axis (recalculate number &amp; position of labels in auto mode, recreate vertices)
+        /// </summary>
+        /// <param name="p">render properties</param>
+        /// <remarks>This method is used internally. There should be no need to call it directly.</remarks>
+        internal virtual void Configure(ILRenderProperties p) {
+            if (m_clipping.Min.IsEmtpy() || m_clipping.Max.IsEmtpy()) return; 
+            if (p.PassCount > 0) return;
+            if (m_labeledTicks.Mode == TickMode.Auto) {
+                int tickCount = GetMaxTickCount(p); 
+                if (m_labelProvider != null) {
+                    string format = String.Format("g{0}",m_labeledTicks.Precision); 
+                    m_labeledTicks.Replace(
+                        m_labelProvider(m_clipping.Min[Index],m_clipping.Max[Index],tickCount));
+                } else {
+                    m_labeledTicks.CreateAuto(m_clipping.Min[Index],m_clipping.Max[Index],tickCount);
+                }
+            }
+            PrepareMeshes(p); 
+            PrepareLabels(p); 
+            m_invalidated = false; 
+        }
+        /// <summary>
+        /// recreate vertices
+        /// </summary>
+        /// <param name="p">render properties</param>
+        public abstract void PrepareMeshes(ILRenderProperties p);
+        /// <summary>
+        /// recreate labels
+        /// </summary>
+        /// <param name="p">render properties</param>
+        public virtual void PrepareLabels(ILRenderProperties p) {
+            // prepare textrenderer
+        }
+
+        /// <summary>
+        /// number of ticks optimally fitting on screen
+        /// </summary>
+        /// <param name="p">render properties</param>
+        /// <returns>optimal number of ticks for this axis</returns>
+        internal int GetMaxTickCount(ILRenderProperties p) {
+            //System.Diagnostics.Debug.Assert(m_labeledTicks.Mode == TickMode.Auto); 
+            SizeF rect = m_labeledTicks.Size; 
+            Point s = new Point(),e = new Point();
+            s = m_labeledTicks.m_lineStart; 
+            e = m_labeledTicks.m_lineEnd; 
+            s.X = (int)(Math.Floor((float)Math.Abs(e.X - s.X) / (float)(rect.Width + m_labeledTicks.Padding))); 
+            s.Y = (int)(Math.Floor((float) Math.Abs(e.Y - s.Y) / (float)(rect.Height + m_labeledTicks.Padding))); 
+            return (int)Math.Floor(Math.Max((double)s.X,s.Y) + 1); 
+        }
+        
+        /// <summary>
+        /// determine number of primitives (lines) to be drawn for this axis
+        /// </summary>
+        /// <returns>number of primitives</returns>
+        internal int countPrimitves() {
+            return (m_visible)? 
+                (m_labeledTicks.Count + 1 + m_unLabeledTicks.Count) * 4 : 4; 
+        }
+
+        /// <summary>
+        /// Invalidate this axis, causes recreation on next render
+        /// </summary>
+        public virtual void Invalidate() {
+            m_invalidated = true; 
+        }
+
+        /// <summary>
+        /// (internal use) dispose off this axis' elements
+        /// </summary>
+        public virtual void Dispose() {
+            if (m_labeledTicks != null) 
+                m_labeledTicks.Dispose(); 
+            if (m_label != null) {
+                m_label.Dispose(); 
+            }
+        }
+
+        #endregion
+
+        #region private helper 
+        #endregion
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/ILCamera.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/ILCamera.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/ILCamera.cs	(revision 9102)
@@ -0,0 +1,451 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Diagnostics; 
+
+namespace ILNumerics.Drawing {
+    /// <summary>
+    /// This class represents the camera's positioning and aiming direction.
+    /// </summary>
+    [DebuggerDisplay("r:{m_distance} Ï:{m_phiDebugDisp}Â° Ï:{m_rhoDebugDisp}Â° - P:{Position} - L:{LookAt}")]
+    public class ILCamera {
+
+        #region event handling 
+        /// <summary>
+        /// fires, if the position of the camera has changed
+        /// </summary>
+        public event EventHandler Changed;
+        /// <summary>
+        /// Fires a Changed event
+        /// </summary>
+        public virtual void OnChange() {
+            if (Changed != null && !m_suspended)
+                Changed(this,new EventArgs()); 
+        }
+        #endregion
+
+        #region attributes 
+        // input attributes (writable)
+        private bool m_suspended = false;
+        protected float m_posX;
+        protected float m_posY;
+        protected float m_posZ; 
+        protected float m_topX;
+        protected float m_topY;
+        protected float m_topZ; 
+        protected float m_lookAtX;
+        protected float m_lookAtY;
+        protected float m_lookAtZ;
+        // output/cached attributes (readonly) 
+        // polar coordinates 
+        private float m_distance = 1.0f; 
+        private float m_phi = 0; 
+        private float m_rho = 0.0f;
+        /// <summary>
+        /// Offset angle for 2nd cached triangular phi value (needed for surface plots)
+        /// </summary>
+        internal float Offset = (float)(Math.PI / 4); 
+        /// <summary>
+        /// cachced triangular phi value with offset (needed for surface plots)
+        /// </summary>
+        internal float CosPhiShift;                
+        /// <summary>
+        /// cachced triangular phi value with offset (needed for surface plots)
+        /// </summary>
+        internal float SinPhiShift; 
+        /// <summary>
+        /// cached value for cosine of phi - this is readonly and for performance only.
+        /// </summary>
+        internal float CosPhi; 
+        /// <summary>
+        /// cached value for sine of phi - this is readonly and for performance only.
+        /// </summary>
+        internal float SinPhi; 
+        /// <summary>
+        /// cached value for cosine of rho - this is readonly and for performance only.
+        /// </summary>
+        internal float CosRho; 
+        /// <summary>
+        /// cached value for sine of rho - this is readonly and for performance only.
+        /// </summary>
+        internal float SinRho; 
+        private CameraQuadrant m_quadrant;
+        #endregion
+
+        #region properties 
+
+        /// <summary>
+        /// point, the camera is aiming at (world coords)
+        /// </summary>
+        public ILPoint3Df LookAt {
+            get { return new ILPoint3Df(m_lookAtX,m_lookAtY,m_lookAtZ); }
+            set {
+                //m_posX += (value.X - m_lookAtX);
+                //m_posY += (value.Y - m_lookAtY);
+                //m_posZ += (value.Z - m_lookAtZ); 
+                m_lookAtX = value.X;
+                m_lookAtY = value.Y;
+                m_lookAtZ = value.Z;
+                 
+                updatePosition();
+                OnChange();
+            }
+        }
+
+        /// <summary>
+        /// distance from the scene (readonly)
+        /// </summary>
+        public float Distance {
+            get {
+                return m_distance; 
+            }
+            set {
+                m_distance = Math.Abs(value);
+                updateCachedVars();
+                updatePosition();
+                OnChange(); 
+            }
+        }
+        /// <summary>
+        /// debugger helper: display phi in degrees (readonly)
+        /// </summary>
+        private int m_phiDebugDisp {
+            get {
+                return (int)Math.Round(m_phi * 180 / Math.PI); 
+            }
+        }
+        /// <summary>
+        /// debugger helper: display rho in degrees
+        /// </summary>
+        private int m_rhoDebugDisp {
+            get {
+                return (int)Math.Round(m_rho * 180 / Math.PI); 
+            }
+        }
+        /// <summary>
+        /// rotation of the scene (seen from above) [radians, readlony, rel. to lookat]
+        /// </summary>
+        public float Phi {
+            get {
+                return m_phi; 
+            }
+            set {
+                m_phi = (float)((value + (Math.PI * 2)) % (Math.PI * 2));
+                updateCachedVars();
+                updatePosition();
+                OnChange();
+            }
+        }
+        /// <summary>
+        /// pitch of the scene [radians], setting moves camera around lookat point
+        /// </summary>
+        public float Rho {
+            get {
+                return m_rho; 
+            }
+            set {
+                if (value < 0.0f)
+                    m_rho = 0.0f;
+                else if (value > Math.PI)
+                    m_rho = (float)Math.PI; 
+                else 
+                    m_rho = value; 
+                updateCachedVars();
+                updatePosition();
+                OnChange(); 
+            }
+        }
+
+        /// <summary>
+        /// Quadrant the camera is currently watching the scene from
+        /// </summary>
+        public CameraQuadrant Quadrant {
+            get{
+                return m_quadrant; 
+            }
+        }
+        /// <summary>
+        /// Determine, if camera is placed in an upper quadrant of the scene
+        /// </summary>
+        public bool LooksFromTop {
+            get {
+                return m_rho < Math.PI/2; 
+            }
+        }
+        /// <summary>
+        /// Determine, if camera is located in an left quadrant of the scene
+        /// </summary>
+        public bool LooksFromLeft {
+            get {
+                return Math.Sin(m_phi) < 0; 
+            }
+        }
+        /// <summary>
+        /// Determine, if camera is located in an front quadrant of the scene
+        /// </summary>
+        public bool LooksFromFront {
+            get {
+                return Math.Cos(m_phi) >= 0; 
+            }
+        }
+        /// <summary>
+        /// true, when looking from top on the un-rotated scene (common for 2D plots)
+        /// </summary>
+        public bool Is2DView {
+            get {
+                return Math.Abs(SinPhi) < 1e-5 && Math.Abs(SinRho) < 1e-5; 
+            }
+        }
+        /// <summary>
+        /// get/set camera position, absolute cartesian coordinates
+        /// </summary>
+        /// <remarks>Keep in mind, the angle for phi points towards negative Y axis! The cartesian property 
+        /// <paramref name="Position"/> handles the camera position in absolute world coordinates, while the 
+        /// polar coordinates (Rho, Phi, Distance) supress the camera position by means of coordinates 
+        /// relative to the LookAt point (i.e. usually the center of the viewing cube)!</remarks>
+        public ILPoint3Df Position {
+            get {
+                ILPoint3Df ret = new ILPoint3Df(m_posX, m_posY, m_posZ);
+                return ret; 
+            }
+            set {
+                m_posX = value.X;
+                m_posY = value.Y;
+                m_posZ = value.Z; 
+                cart2Pol(value - new ILPoint3Df(m_lookAtX, m_lookAtY, m_lookAtZ)); 
+                updateCachedVars();
+                OnChange(); 
+            }
+        }
+        /// <summary>
+        /// orientation of the camera, normalized, readonly
+        /// </summary>
+        /// <remarks>This vector is readonly always points 'upwards'.</remarks>
+        public ILPoint3Df Top
+        {
+            get
+            {
+                ILPoint3Df ret = new ILPoint3Df(m_topX, m_topY, m_topZ);
+                return ret;
+            }
+        }
+        #endregion 
+
+        #region constructors
+        public ILCamera (ILCamera vport) {
+            m_rho = vport.m_rho; 
+            m_phi = vport.m_phi; 
+            m_distance = vport.m_distance;
+            m_lookAtX = vport.m_lookAtX;
+            m_lookAtY = vport.m_lookAtY;
+            m_lookAtZ = vport.m_lookAtZ;
+            m_posX = vport.m_posX;
+            m_posY = vport.m_posY;
+            m_posZ = vport.m_posZ; 
+            updateCachedVars();
+            computeQuadrant();
+        }
+        /// <summary>
+        /// Create a viewport: view at scene from top, no rotation
+        /// </summary>
+        public ILCamera () {
+            m_posX = 0;
+            m_posY = 0;
+            m_posZ = 10; 
+            m_quadrant = CameraQuadrant.TopLeftFront; 
+            updateCachedVars(); 
+        }
+        public ILCamera (float Phi, float Rho, float Distance) {
+            m_rho = Rho; 
+            m_phi = Phi; 
+            m_distance = Distance; 
+            updateCachedVars();
+            updatePosition(); 
+            computeQuadrant();
+        }
+        #endregion
+
+        #region public interface 
+        /// <summary>
+        /// suspend the firing of events until EventingResume() was called
+        /// </summary>
+        public void EventingSuspend() {
+            m_suspended = true; 
+        }
+        /// <summary>
+        /// Resume firing 'Change' events after it has been suspended
+        /// </summary>
+        public void EventingResume() {
+            EventingResume(true); 
+        }
+        /// <summary>
+        /// Resume firing 'Change' events, optionally skip pending events
+        /// </summary>
+        internal void EventingResume(bool fireEvents) {
+            m_suspended = false;
+            if (fireEvents) 
+                OnChange(); 
+        }
+        /// <summary>
+        /// Set both angles and distance at once  
+        /// </summary>
+        /// <param name="phi">Rotation, radians</param>
+        /// <param name="rho">Pitch, radians</param>
+        /// <param name="distance">Distance from scene</param>
+        public void Set(float phi, float rho, float distance) {
+            if (distance < 0) 
+                throw new Exceptions.ILArgumentException("Camera distance must be positive!"); 
+            m_phi = (float)(phi % (Math.PI * 2)); 
+            m_rho = (float)(rho % (Math.PI)); 
+            m_distance = distance;
+            updateCachedVars();
+            OnChange(); 
+        }
+        /// <summary>
+        /// Set complete camera position (angles and distance) at once
+        /// </summary>
+        /// <param name="phi">Rotation (degrees)</param>
+        /// <param name="rho">Pitch (degrees)</param>
+        /// <param name="distance">Distance from scene</param>
+        public void SetDeg(float phi,float rho, float distance) { 
+            Set ((float)(phi/180.0 * Math.PI),(float)(rho / 180.0f * Math.PI),distance); 
+        }
+        /// <summary>
+        /// Convert camera position to string
+        /// </summary>
+        /// <returns>string display with distance,roatation and pitch</returns>
+        public override string ToString() {
+            return String.Format("r:{0} Ï:{1}Â° Ï:{2}Â° - P:{3} - L:{4}",
+                m_distance,m_phiDebugDisp,m_rhoDebugDisp,Position,LookAt);
+        }
+        #endregion
+
+        #region private helper 
+        /// <summary>
+        /// update internal cartesian (absolut) coordinates of position relative 
+        /// to lookAt point. To be called after any polar coordinates were changed.
+        /// </summary>
+        private void updatePosition() {
+            m_posX = m_lookAtX + (m_distance * SinRho * SinPhi);
+            m_posY = m_lookAtY + (m_distance * SinRho * -CosPhi);
+            m_posZ = m_lookAtZ + (m_distance * CosRho);
+        }
+        private void cart2Pol(ILPoint3Df cartVec) {
+            cartVec.ToPolar(out m_distance, out m_phi, out m_rho);
+        }
+        ///// <summary>
+        /////  update position, cons. polar coord and lookat as new
+        ///// </summary>
+        //private void pol2Cart() {
+                
+        //}
+
+        private void computeQuadrant() {
+            //if (m_phi == 0.0 && m_rho == 0.0) {
+            //    m_quadrant = CameraQuadrant.TopLeftFront; 
+            //    return; 
+            //}
+            if (m_rho < System.Math.PI / 2) {
+                // top 
+                if (m_phi < Math.PI) {
+                    // right
+                    if (m_phi < Math.PI / 2) {
+                        // front
+                        m_quadrant = CameraQuadrant.TopRightFront; 
+                    } else {
+                        // back
+                        m_quadrant = CameraQuadrant.TopRightBack; 
+                    }
+                } else {
+                    // left
+                    if (m_phi > Math.PI / 2 * 3) {
+                        // front
+                        m_quadrant = CameraQuadrant.TopLeftFront;
+                    } else {
+                        // back
+                        m_quadrant = CameraQuadrant.TopLeftBack;
+                    }
+                }
+            } else {
+                // bottom
+                if (m_phi < Math.PI) {
+                    // right
+                    if (m_phi < Math.PI / 2) {
+                        // front
+                        m_quadrant = CameraQuadrant.BottomRightFront; 
+                    } else {
+                        // back
+                        m_quadrant = CameraQuadrant.BottomRightBack; 
+                    }
+                } else {
+                    // left
+                    if (m_phi > Math.PI / 2 * 3) {
+                        // front
+                        m_quadrant = CameraQuadrant.BottomLeftFront; 
+                    } else {
+                        // back
+                        m_quadrant = CameraQuadrant.BottomLeftBack; 
+                    }
+                }
+            }
+        }
+        private void updateCachedVars () {
+            CosPhi = (float)Math.Cos(m_phi); 
+            SinPhi = (float)Math.Sin(m_phi);
+            SinPhiShift = (float)Math.Sin(m_phi + Offset); 
+            CosPhiShift = (float)Math.Cos(m_phi + Offset); 
+            CosRho = (float)Math.Cos(m_rho); 
+            SinRho = (float)Math.Sin(m_rho);
+            // update top
+            ILPoint3Df top = ILPoint3Df.normalize(-SinPhi * CosRho, CosPhi * CosRho, SinRho); 
+            m_topX = top.X; 
+            m_topY = top.Y;
+            m_topZ = top.Z; 
+
+            computeQuadrant();
+        }
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/ILClippingData.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/ILClippingData.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/ILClippingData.cs	(revision 9102)
@@ -0,0 +1,668 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Drawing.Misc; 
+
+namespace ILNumerics.Drawing {
+    /// <summary>
+    /// Class holding and managing limits for a 3 dimensional cube
+    /// </summary>
+    public sealed class ILClippingData {
+
+        #region eventing 
+        /// <summary>
+        /// fires if the data range have changed
+        /// </summary>
+        public event ILClippingDataChangedEvent Changed; 
+        /// <summary>
+        /// called if the limits have changed
+        /// </summary>
+        private void OnChange() {
+            if (m_eventingActive && Changed != null) {
+                Changed ( this, new ClippingChangedEventArgs(this)); 
+            }
+            m_isDirty = false; 
+        }
+        #endregion
+
+        #region attributes 
+        private bool m_eventingActive = true;
+        private float m_xMin = float.MaxValue;
+        private float m_yMin = float.MaxValue;
+        private float m_zMin = float.MaxValue;
+        private float m_xMax = float.MinValue;
+        private float m_yMax = float.MinValue;
+        private float m_zMax = float.MinValue;
+        private float m_sphereRadius; 
+        private bool m_isDirty = false;
+        private bool m_allowZeroVolume = true;
+        #endregion
+
+        #region properties 
+
+        /// <summary>
+        /// the radius of a sphere tightly enclosing the box determined by this clipping data limits (readonly)
+        /// </summary>
+        public float SphereRadius {
+            get {
+                return m_sphereRadius;  
+            }
+        }
+        /// <summary>
+        /// minimum value for x axis
+        /// </summary>
+        public float XMin {
+            get {
+                return m_xMin; 
+            }
+            set {
+                if (m_xMin != value) {
+                    m_isDirty = true; 
+                    m_xMin = value;
+                    if (!m_allowZeroVolume) ensureVolumeNotZero();
+                    m_sphereRadius = getSphereRadius(); 
+                    if (m_eventingActive && Changed != null)
+                        OnChange();
+                }
+            }
+        }
+        /// <summary>
+        /// minimum value for y axis
+        /// </summary>
+        public float YMin {
+            get {
+                return m_yMin; 
+            }
+            set {
+                if (m_yMin != value) {
+                    m_isDirty = true; 
+                    m_yMin = value;
+                    if (!m_allowZeroVolume) ensureVolumeNotZero();
+                    m_sphereRadius = getSphereRadius();
+                    if (m_eventingActive && Changed != null)
+                        OnChange();
+                }
+            }
+        }
+        /// <summary>
+        /// minimum value for z axis
+        /// </summary>
+        public float ZMin {
+            get {
+                return m_zMin; 
+            }
+            set {
+                if (m_zMin != value) {
+                    m_isDirty = true;
+                    m_zMin = value;
+                    if (!m_allowZeroVolume) ensureVolumeNotZero();
+                    m_sphereRadius = getSphereRadius();
+                    if (m_eventingActive && Changed != null)
+                        OnChange(); 
+                }
+            }
+        }
+        /// <summary>
+        /// maximum value for x axis
+        /// </summary>
+        public float XMax {
+            get {
+                return m_xMax; 
+            }
+            set {
+                if (m_xMax != value) {
+                    m_isDirty = true; 
+                    m_xMax = value;
+                    if (!m_allowZeroVolume) ensureVolumeNotZero();
+                    m_sphereRadius = getSphereRadius();
+                    if (m_eventingActive && Changed != null)
+                        OnChange(); 
+                }
+            }
+        }
+        /// <summary>
+        /// maximum value for y axis
+        /// </summary>
+        public float YMax {
+            get {
+                return m_yMax; 
+            }
+            set {
+                if (m_yMax != value) {
+                    m_isDirty = true; 
+                    m_yMax = value;
+                    if (!m_allowZeroVolume) ensureVolumeNotZero();
+                    m_sphereRadius = getSphereRadius();
+                    if (m_eventingActive && Changed != null)
+                        OnChange(); 
+                }
+            }
+        }
+        /// <summary>
+        /// maximum value for z axis
+        /// </summary>
+        public float ZMax {
+            get {
+                return m_zMax; 
+            }
+            set {
+                if (m_zMax != value) {
+                    m_isDirty = true; 
+                    m_zMax = value;
+                    if (!m_allowZeroVolume) ensureVolumeNotZero();
+                    m_sphereRadius = getSphereRadius();
+                    if (m_eventingActive && Changed != null)
+                        OnChange(); 
+                }
+            }
+        }
+        /// <summary>
+        /// minimum (coordinate)
+        /// </summary>
+        public ILPoint3Df Min {
+            get {
+                return new ILPoint3Df(XMin,YMin,ZMin);
+            }
+        }
+        /// <summary>
+        /// maximum (coordinate)
+        /// </summary>
+        public ILPoint3Df Max {
+            get {
+                return new ILPoint3Df(XMax,YMax,ZMax); 
+            }
+        }
+        /// <summary>
+        /// get center of this clipping range
+        /// </summary>
+        public ILPoint3Df CenterF {
+            get { 
+                ILPoint3Df ret; 
+                ret.X = (XMax + XMin) / 2.0f; 
+                ret.Y = (YMax + YMin) / 2.0f; 
+                ret.Z = (ZMax + ZMin) / 2.0f; 
+                return ret; 
+            }
+        }
+        /// <summary>
+        /// get width (x-direction) of this clipping range
+        /// </summary>
+        public float WidthF {
+            get {
+                return (XMax - XMin);
+            }
+        }
+        /// <summary>
+        /// get height (y-direction) of this clipping range
+        /// </summary>
+        public float HeightF {
+            get {
+                return (YMax - YMin);
+            }
+        }
+        /// <summary>
+        /// get depth (z-direction) of this clipping range
+        /// </summary>
+        public float DepthF {
+            get {
+                return (ZMax - ZMin);
+            }
+        }
+        /// <summary>
+        /// marks the limits as altered, without having fired a changed event yet
+        /// </summary>
+        public bool IsDirty {
+            get {
+                return m_isDirty; 
+            }
+        }
+        /// <summary>
+        /// true: this clipping data always ensures a non-zero volume
+        /// </summary>
+        /// <remarks>'NonZeroVolumne' means, non of Depth,Width nor Heigth are allowed to be zero. If some edge of the cube is set to zero, the class expands this edge by 1 in each direction.</remarks>
+        public bool AllowZeroVolume {
+            get {
+                return m_allowZeroVolume;
+            }
+            set {
+                m_allowZeroVolume = value;
+            }
+        }
+        #endregion
+
+        #region public interface
+        /// <summary>
+        /// suspend the firing of events until EventingResume has been called
+        /// </summary>
+        public void EventingSuspend() {
+            m_eventingActive = false;
+            m_isDirty = false; 
+        }
+        /// <summary>
+        /// Resume previously suspended eventing. Start sending events again.
+        /// </summary>
+        public void EventingResume() {
+            m_eventingActive = true;
+            if (m_isDirty && Changed != null) {
+                OnChange();
+            }
+        }
+        /// <summary>
+        /// enable eventing without sending pending events
+        /// </summary>
+        public void EventingStart() {
+            m_eventingActive = true;
+            m_isDirty = false; 
+        }
+        /// <summary>
+        /// update ranges for this object with union of both ranges. 
+        /// </summary>
+        /// <param name="clipData">clipping ranges to create union with</param>
+        public void Update (ILClippingData clipData) {
+            if (clipData.XMin < XMin) { m_isDirty = true; m_xMin = clipData.XMin; }
+            if (clipData.YMin < YMin) { m_isDirty = true; m_yMin = clipData.YMin; }
+            if (clipData.ZMin < ZMin) { m_isDirty = true; m_zMin = clipData.ZMin; }
+            if (clipData.XMax > XMax) { m_isDirty = true; m_xMax = clipData.XMax; }
+            if (clipData.YMax > YMax) { m_isDirty = true; m_yMax = clipData.YMax; }
+            if (clipData.ZMax > ZMax) { m_isDirty = true; m_zMax = clipData.ZMax; }
+            if (!m_allowZeroVolume) ensureVolumeNotZero();
+            m_sphereRadius = getSphereRadius();
+            if (m_isDirty && m_eventingActive && Changed != null) 
+                OnChange(); 
+            }
+        /// <summary>
+        /// update ranges for this object with point coords for specific axes
+        /// </summary>
+        /// <param name="point">point with coords to update ranges with</param>
+        /// <param name="updateBitFlags">bitflag combination to specify axis to be recognized: 1,2,4 -> x,y,z</param>
+        public void Update (ILPoint3Df point, int updateBitFlags) {
+            if ((updateBitFlags & 1) != 0) {
+                if (point.X < XMin) { m_isDirty = true; m_xMin = point.X; }
+                if (point.X > XMax) { m_isDirty = true; m_xMax = point.X; }
+            }
+            if ((updateBitFlags & 2) != 0) {
+                if (point.Y < YMin) { m_isDirty = true; m_yMin = point.Y; }
+                if (point.Y > YMax) { m_isDirty = true; m_yMax = point.Y; }
+            }
+            if ((updateBitFlags & 4) != 0) {
+                if (point.Z < ZMin) { m_isDirty = true; m_zMin = point.Z; }
+                if (point.Z > ZMax) { m_isDirty = true; m_zMax = point.Z; }
+            }
+            if (!m_allowZeroVolume) ensureVolumeNotZero();
+            m_sphereRadius = getSphereRadius();
+            if (m_isDirty && m_eventingActive && Changed != null) 
+                OnChange(); 
+        }
+        /// <summary>
+        /// update clipping data for this object with union of this and rectangle specified
+        /// </summary>
+        /// <param name="luCorner">left upper corner</param>
+        /// <param name="rbCorner">right lower corner</param>
+        public void Update (ILPoint3Df luCorner, ILPoint3Df rbCorner) {
+            bool oldeventState = m_eventingActive; 
+            m_eventingActive = false; 
+            Update(luCorner,7);
+            m_eventingActive = oldeventState; 
+            Update(rbCorner,7);
+        }
+        public void Update (ILPoint3Df center, float zoomFactor) {
+            if (zoomFactor == 1.0f && center == CenterF) return; 
+            m_isDirty = true; 
+            float s = WidthF * zoomFactor / 2; 
+            m_xMin = center.X - s; 
+            m_xMax = center.X + s; 
+            s = HeightF * zoomFactor / 2; 
+            m_yMin = center.Y - s; 
+            m_yMax = center.Y + s; 
+            s = DepthF * zoomFactor / 2; 
+            m_zMin = center.Z - s; 
+            m_zMax = center.Z + s;
+            if (!m_allowZeroVolume) ensureVolumeNotZero();
+            m_sphereRadius = getSphereRadius();
+            if (m_eventingActive && Changed != null) 
+                OnChange();  
+        }
+        /// <summary>
+        /// Set clipping limits to volume inside the box specified 
+        /// </summary>
+        /// <param name="lunCorner">left-upper-near corner of the volume box</param>
+        /// <param name="rbfCorner">right-bottom-far corner of the volume box</param>
+        public void Set(ILPoint3Df lunCorner, ILPoint3Df rbfCorner) {
+            m_isDirty = true; 
+            m_xMin = Math.Min(lunCorner.X,rbfCorner.X); 
+            m_xMax = Math.Max(lunCorner.X,rbfCorner.X); 
+            m_yMin = Math.Min(lunCorner.Y,rbfCorner.Y); 
+            m_yMax = Math.Max(lunCorner.Y,rbfCorner.Y); 
+            m_zMin = Math.Min(lunCorner.Z,rbfCorner.Z); 
+            m_zMax = Math.Max(lunCorner.Z,rbfCorner.Z);
+            if (!m_allowZeroVolume) ensureVolumeNotZero();
+            m_sphereRadius = getSphereRadius();
+            if (m_eventingActive && Changed != null) 
+                OnChange(); 
+        }
+        /// <summary>
+        /// reset this clipping range to initial (all empty)
+        /// </summary>
+        public void Reset() {
+            m_xMin = float.MaxValue; 
+            m_yMin = float.MaxValue; 
+            m_zMin = float.MaxValue; 
+            m_xMax = float.MinValue; 
+            m_yMax = float.MinValue;  
+            m_zMax = float.MinValue; 
+            m_isDirty = true; 
+            if (m_eventingActive && Changed != null) 
+                OnChange();  
+        }
+        /// <summary>
+        /// copy this from other clipping data
+        /// </summary>
+        /// <param name="m_clippingData"></param>
+        internal void CopyFrom(ILClippingData m_clippingData) {
+            m_xMin = m_clippingData.XMin;
+            m_yMin = m_clippingData.YMin;
+            m_zMin = m_clippingData.ZMin;
+            m_xMax = m_clippingData.XMax;
+            m_yMax = m_clippingData.YMax;
+            m_zMax = m_clippingData.ZMax;
+            if (!m_allowZeroVolume) ensureVolumeNotZero();
+            m_sphereRadius = getSphereRadius();
+            m_isDirty = true; 
+            if (m_eventingActive && Changed != null) 
+                OnChange();  
+        }
+        /// <summary>
+        /// stretch clipping region to unit cube [0 1][0 1][0 1] 
+        /// </summary>
+        /// <returns></returns>
+        public ILPoint3Df ScaleToUnitCube () {
+            ILPoint3Df ret = new ILPoint3Df(); 
+            float a = WidthF; 
+            if (a != 0.0f)  ret.X = 1 / a;
+            else            ret.X = 0.0f; 
+
+            a = HeightF; 
+            if (a != 0.0f)  ret.Y = 1 / a;
+            else            ret.Y = 0.0f; 
+
+            a = DepthF; 
+            if (a != 0.0f)  ret.Z = 1 / a;
+            else            ret.Z = 0.0f; 
+            return ret; 
+        }
+        /// <summary>
+        /// offset centering scaled unit cube to zero: [-0.5 0.5][-0.5 0.5][-0.5 0.5]
+        /// </summary>
+        /// <returns></returns>
+        public ILPoint3Df CenterToUnitCube() {
+            ILPoint3Df a = ScaleToUnitCube(); 
+            ILPoint3Df b = new ILPoint3Df(); 
+            b.X = -0.5f - a.X * XMin; 
+            b.Y = -0.5f - a.Y * YMin; 
+            if (ZMin < ZMax)
+                b.Z = (-0.5f - a.Z * ZMin); 
+            else b.Z = 0.0f; 
+            return b; 
+        }
+        /// <summary>
+        /// creates clone of this clipping data
+        /// </summary>
+        /// <returns>clone</returns>
+        public ILClippingData Clone() {
+            ILClippingData ret = new ILClippingData(); 
+            ret.Update(this); 
+            return ret;
+        }
+        /// <summary>
+        /// Map coordinat from unit cube space [-0.5..0.5] into the space limited by this clipping data
+        /// </summary>
+        /// <param name="x">x coordinate (unit cube space: -0.5 ... 0.5)</param>
+        /// <param name="y">y coordinate (unit cube space: -0.5 ... 0.5)</param>
+        /// <param name="z">z coordinate (unit cube space: -0.5 ... 0.5)</param>
+        /// <returns></returns>
+        public ILPoint3Df Map(float x, float y, float z) {
+            ILPoint3Df ret; 
+            ret.X = (x + 0.5f) * (m_xMax-m_xMin) + m_xMin; 
+            ret.Y = (y + 0.5f) * (m_yMax-m_yMin) + m_yMin; 
+            ret.Z = (z + 0.5f) * (m_zMax-m_zMin) + m_zMin;
+            //if (!m_allowZeroVolume) ensureVolumeNotZero();
+            return ret;
+        }
+
+        public override string ToString() {
+            return String.Format("Min:{0} Max:{1}",Min,Max); 
+        }
+        /// <summary>
+        /// Expand/shrink all those edges, not touched by the given line
+        /// </summary>
+        /// <param name="nearLineEnd">near line point</param>
+        /// <param name="farLineEnd">far line point</param>
+        /// <param name="offset">multiplicator, shrink-/expand value</param>
+        public void GetZoomParameter(ILPoint3Df nearLineEnd, ILPoint3Df farLineEnd, float offset, 
+                        out ILPoint3Df minCorner, out ILPoint3Df maxCorner) {
+            // we determine, if the side is touched by the line. 
+            // if 'yes': the side is skipped (its limit/position are kept)
+            // if 'no': the side is moved towards/away from center
+            minCorner = this.Min;
+            maxCorner = this.Max; 
+            float sX, sY, sZ; 
+            float lamb; 
+            float aX = nearLineEnd.X - farLineEnd.X;
+            float aY = nearLineEnd.Y - farLineEnd.Y;
+            float aZ = nearLineEnd.Z - farLineEnd.Z;
+            float offX = WidthF * (offset/2.0f);
+            float offY = HeightF * (offset/2.0f);
+            float offZ = DepthF * (offset/2.0f); 
+            #region front side
+            lamb = (m_yMin - nearLineEnd.Y) / aY; 
+            sX = nearLineEnd.X + lamb * aX;
+            sZ = nearLineEnd.Z + lamb * aZ;
+            if (sX > m_xMax || sX < m_xMin || sZ > m_zMax || sZ < m_zMin) {
+                minCorner.Y += offY; 
+            }
+            #endregion
+            #region right side
+            lamb = (m_xMax - nearLineEnd.X) / aX;
+            sY = nearLineEnd.Y + lamb * aY;
+            sZ = nearLineEnd.Z + lamb * aZ;
+            if (sY > m_yMax || sY < m_yMin || sZ > m_zMax || sZ < m_zMin) {
+                maxCorner.X -= offX;
+            }
+            #endregion
+            #region back side
+            lamb = (m_yMax - nearLineEnd.Y) / aY;
+            sX = nearLineEnd.X + lamb * aX;
+            sZ = nearLineEnd.Z + lamb * aZ;
+            if (sX > m_xMax || sX < m_xMin || sZ > m_zMax || sZ < m_zMin) {
+                maxCorner.Y -= offY;
+            }
+            #endregion
+            #region left side
+            lamb = (m_xMin - nearLineEnd.X) / aX;
+            sY = nearLineEnd.Y + lamb * aY;
+            sZ = nearLineEnd.Z + lamb * aZ;
+            if (sY > m_yMax || sY < m_yMin || sZ > m_zMax || sZ < m_zMin) {
+                minCorner.X += offX;
+            }
+            #endregion
+            #region top side
+            lamb = (m_zMax - nearLineEnd.Z) / aZ;
+            sX = nearLineEnd.X + lamb * aX;
+            sY = nearLineEnd.Y + lamb * aY;
+            if (sY > m_yMax || sY < m_yMin || sX > m_xMax || sX < m_xMin) {
+                maxCorner.Z -= offZ;
+            }
+            #endregion
+            #region bottom side
+            lamb = (m_zMin - nearLineEnd.Z) / aZ;
+            sX = nearLineEnd.X + lamb * aX;
+            sY = nearLineEnd.Y + lamb * aY;
+            if (sY > m_yMax || sY < m_yMin || sX > m_xMax || sX < m_xMin) {
+                minCorner.Z += offZ;
+            }
+            #endregion
+            #region translate: move line to cross middle of view cube
+            ILPoint3Df rQ =  CenterF; 
+            sX = rQ.X - nearLineEnd.X; 
+            sY = rQ.Y - nearLineEnd.Y; 
+            sZ = rQ.Z - nearLineEnd.Z; 
+            lamb = (aX * sX + aY * sY + aZ * sZ) / (aX * aX + aY * aY + aZ * aZ);
+            offX = rQ.X - (nearLineEnd.X + lamb * aX);
+            offY = rQ.Y - (nearLineEnd.Y + lamb * aY);
+            offZ = rQ.Z - (nearLineEnd.Z + lamb * aZ);
+            minCorner.X -= offX;
+            minCorner.Y -= offY;
+            minCorner.Z -= offZ;
+            maxCorner.X -= offX;
+            maxCorner.Y -= offY;
+            maxCorner.Z -= offZ;
+            #endregion
+        }
+
+        #endregion
+
+        #region private helper
+
+        private float getSphereRadius() {
+            return ((Max - Min) / 2f).GetLength(); 
+        }
+
+        /// <summary>
+        /// Ensure that this clipping data has valid length for all dimensions  [deprecated]
+        /// </summary>
+        /// <remarks>If the length of the clipping cube is infinity for any dimension, 
+        /// that dimension is set to a range of -0.5...0.5.
+        /// <para>This function is to be called by custom graphs which create their 
+        /// size <b>relative</b> to the size of the clipping container. Those 
+        /// graphs will need a valid container size and may call this function in the 
+        /// constructor.</para></remarks>
+        /// <returns>true if the length in any dimension had to be corrected (set to 1.0), false otherwise.</returns>
+        private bool EnsureValidSize() {
+            bool change = false; 
+            if (float.IsInfinity(WidthF)) {
+                change = true;
+                m_xMin = -0.5f;
+                m_xMax = 0.5f;
+            }
+            if (float.IsInfinity(HeightF)) {
+                change = true;
+                m_yMin = -0.5f;
+                m_yMax = 0.5f; 
+            }
+            if (float.IsInfinity(DepthF)) {
+                change = true;
+                m_zMin = -0.5f;
+                m_zMax = 0.5f;
+            }
+            if (change && m_eventingActive && Changed != null) {
+                OnChange(); 
+            }
+            return change; 
+        }
+
+        private void ensureVolumeNotZero() {
+            if (HeightF == 0) {
+                m_isDirty = true;
+                m_yMin = m_yMin - 1f;
+                m_yMax = m_yMin + 2f;
+            }
+            if (WidthF == 0) {
+                m_isDirty = true;
+                m_xMin = m_xMin - 1f;
+                m_xMax = m_xMin + 2f;
+            }
+            if (DepthF == 0) {
+                m_isDirty = true;
+                m_zMin = m_zMin - 1f;
+                m_zMax = m_zMin + 2f;
+            }
+        }
+        #endregion
+
+        #region operator overloads 
+        /// <summary>
+        /// Equalty operator overload, true if both cubes span the same region in 3D space 
+        /// </summary>
+        /// <param name="limit1">cube 1</param>
+        /// <param name="limit2">cube 2</param>
+        /// <returns>true if both cubes span the same 3D space, false otherwise</returns>
+        public static bool operator == (ILClippingData limit1, ILClippingData limit2) {
+            return (limit1.m_xMax == limit2.m_xMax && 
+                    limit1.m_yMax == limit2.m_yMax && 
+                    limit1.m_zMax == limit2.m_zMax && 
+                    limit1.m_xMin == limit2.m_xMin && 
+                    limit1.m_yMin == limit2.m_yMin && 
+                    limit1.m_zMin == limit2.m_zMin); 
+        }
+        /// <summary>
+        /// unequalty operator
+        /// </summary>
+        /// <param name="limit1">cube 1</param>
+        /// <param name="limit2">cube 2</param>
+        /// <returns>false if both cubes span the same 3D space, true otherwise</returns>
+        public static bool operator !=(ILClippingData limit1, ILClippingData limit2) {
+            return (limit1.m_xMax != limit2.m_xMax || 
+                    limit1.m_yMax != limit2.m_yMax ||
+                    limit1.m_zMax != limit2.m_zMax || 
+                    limit1.m_xMin != limit2.m_xMin || 
+                    limit1.m_yMin != limit2.m_yMin || 
+                    limit1.m_zMin != limit2.m_zMin); 
+        }
+        /// <summary>
+        /// Returns hash code for this ILClippingData
+        /// </summary>
+        /// <returns>hash code</returns>
+        public override int GetHashCode() {
+            return base.GetHashCode();
+        }
+        /// <summary>
+        /// Compares to cube objects
+        /// </summary>
+        /// <param name="obj"></param>
+        /// <returns>true if obj references this class instance, false otherwise</returns>
+        public override bool Equals(object obj) {
+            return base.Equals(obj);
+        }
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/ILColorEnumerator.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/ILColorEnumerator.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/ILColorEnumerator.cs	(revision 9102)
@@ -0,0 +1,84 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing;
+using ILNumerics.Drawing.Misc;  
+
+namespace ILNumerics.Drawing.Misc {
+    /// <summary>
+    /// enumerate colors 
+    /// </summary>
+    public class ILColorEnumerator {
+
+        List<Color> m_colors;
+        int m_curPos; 
+
+        /// <summary>
+        /// create new color enumeration based on a specific colormap
+        /// </summary>
+        /// <param name="basemap"></param>
+        public ILColorEnumerator(Colormaps basemap) {
+            ILColormap cm = new ILColormap(basemap);
+            m_colors = new List<Color>(); 
+            for (int i = 0; i < cm.Length; i++) {
+                m_colors.Add(cm.Map(i)); 
+            }
+            m_curPos = 0; 
+        }
+        /// <summary>
+        /// create new color enumerator based on Colormap.Lines
+        /// </summary>
+        public ILColorEnumerator () : this (Colormaps.Lines) { }
+
+        /// <summary>
+        /// return next color and increase internal pointer
+        /// </summary>
+        /// <returns></returns>
+        public Color NextColor() {
+            Color ret = m_colors[m_curPos++]; 
+            if (m_curPos == m_colors.Count) 
+                m_curPos = 0;
+            return ret; 
+        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/ILColorProvider.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/ILColorProvider.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/ILColorProvider.cs	(revision 9102)
@@ -0,0 +1,458 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+#pragma warning disable 1591
+
+using System;
+using System.Drawing;
+using System.Collections.Generic; 
+using ILNumerics.Drawing.Graphs; 
+
+namespace ILNumerics.Drawing.Misc
+{
+   /// <summary>
+   /// Color helper - change RGB to/ from HLS model
+   /// </summary>
+   public class ILColorProvider
+   {
+       
+        public static readonly float MAXHUEVALUE = 200;     
+        private byte red = 0;
+        private byte green = 0;
+        private byte blue = 0;
+
+        private float hue = 0;
+        private float luminance = 0;
+        private float saturation = 0;
+
+        public byte Red
+        {
+         get
+         {
+            return red;
+         }
+         set
+         {
+            red = value;
+            ToHLS();
+         }      
+      }
+      public byte Green
+      {
+         get
+         {
+            return green;
+         }
+         set
+         {
+            green = value;
+            ToHLS();
+         }
+      }
+      public byte Blue
+      {
+         get
+         {
+            return blue;
+         }
+         set
+         {
+            blue = value;
+            ToHLS();
+         }
+      }
+      public float Luminance
+      {
+         get
+         {
+            return luminance;
+         }
+         set
+         {
+            if ((luminance < 0.0f) || (luminance > 1.0f))
+            {
+               throw new ArgumentOutOfRangeException("Luminance", "Luminance must be between 0.0 and 1.0");
+            }
+            luminance = value;
+            ToRGB();
+         }
+      }
+      public float Hue
+      {
+         get
+         {
+            return hue;
+         }
+         set
+         {
+            if ((hue < 0.0f) || (hue > 360.0f))
+            {
+               throw new ArgumentOutOfRangeException("Hue", "Hue must be between 0.0 and 360.0");
+            }
+            hue = value;
+            ToRGB();
+         }
+      }
+      public float Saturation
+      {
+         get
+         {
+            return saturation;
+         }
+         set
+         {
+            if ((saturation < 0.0f) || (saturation > 1.0f))
+            {
+               throw new ArgumentOutOfRangeException("Saturation", "Saturation must be between 0.0 and 1.0");
+            }
+            saturation = value;
+            ToRGB();
+         }
+      }
+
+      public Color Color
+      {
+         get
+         {
+            Color c = Color.FromArgb(red, green, blue);
+            return c;
+         }
+         set
+         {
+            red = value.R;
+            green = value.G;
+            blue = value.B;
+            ToHLS();
+         }
+      }
+
+      public void LightenColor(float lightenBy)
+      {
+         luminance *= (1.0f + lightenBy);
+         if (luminance > 1.0f)
+         {
+            luminance = 1.0f;
+         }
+         ToRGB();
+      }
+
+      public void DarkenColor(float darkenBy)
+      {
+         luminance *= darkenBy;
+         ToRGB();
+      }
+      
+
+      public ILColorProvider(Color c)
+      {
+         red = c.R;
+         green = c.G;
+         blue = c.B;
+         ToHLS();
+         
+      }
+
+      public ILColorProvider(float hue, float luminance, float saturation)
+      {
+         this.hue = hue;
+         this.luminance = luminance;
+         this.saturation = saturation;
+         ToRGB();
+      }
+
+      public ILColorProvider(byte red, byte green, byte blue)
+      {
+         this.red = red;
+         this.green = green;
+         this.blue = blue;
+      }
+
+      public ILColorProvider(ILColorProvider hlsrgb)
+      {
+         this.red = hlsrgb.Red;
+         this.blue = hlsrgb.Blue;
+         this.green = hlsrgb.Green;
+         this.luminance = hlsrgb.Luminance;
+         this.hue = hlsrgb.Hue;
+         this.saturation = hlsrgb.Saturation;
+      }
+
+      public ILColorProvider()
+      {
+      }
+
+      private void ToHLS() 
+      {         
+         byte minval = Math.Min(red, Math.Min(green, blue));
+         byte maxval = Math.Max(red, Math.Max(green, blue));
+
+         float mdiff  = (float)(maxval - minval);
+         float msum   = (float)(maxval + minval);
+   
+         luminance = msum / 510.0f;
+
+         if (maxval == minval) 
+         {
+            saturation = 0.0f;
+            hue = 0.0f; 
+         }   
+         else 
+         { 
+            float rnorm = (maxval - red) / mdiff;      
+            float gnorm = (maxval - green) / mdiff;
+            float bnorm = (maxval - blue) / mdiff;   
+
+            saturation = (luminance <= 0.5f) ? (mdiff / msum) : (mdiff /
+             (510.0f - msum));
+
+            if (red == maxval) 
+            {
+               hue = 60.0f * (6.0f + bnorm - gnorm);
+            }
+            if (green == maxval) 
+            {
+               hue = 60.0f * (2.0f + rnorm - bnorm);
+            }
+            if (blue  == maxval) 
+            {
+               hue = 60.0f * (4.0f + gnorm - rnorm);
+            }
+            if (hue > 360.0f) 
+            {
+               hue = hue - 360.0f;
+            }
+         }
+      }
+      /// <summary>
+      /// convert hue value to RGB value, based on predefined values  
+      /// </summary>
+      /// <param name="hue">hue: in range 0...MAXHUEVALUE</param>
+      /// <returns>int value as RGB color, A=255</returns>
+      /// <remarks>the internal values (rgb / luminance,saturation) will not be altered</remarks>
+      public int H2RGB(float hueVal)  
+      {
+          if (saturation == 0.0) // gray, simple case
+          {
+              byte bval = (byte)(luminance * 255.0F); 
+              return (unchecked((byte)255) << 24) + (bval << 16) + (bval << 8) + bval; 
+
+          } else {
+              float rm1;
+              float rm2;
+             
+              if (luminance <= 0.5f) 
+              {
+                 rm2 = luminance + luminance * saturation;
+              } else {
+                 rm2 = luminance + saturation - luminance * saturation;
+              }
+              rm1 = 2.0f * luminance - rm2;
+              return (unchecked((byte)255) << 24) 
+                        + (ToRGB1(rm1, rm2, hueVal + 120.0f) << 16)
+                        + (ToRGB1(rm1, rm2, hueVal) << 8)
+                        + ToRGB1(rm1, rm2, hueVal - 120.0f);
+
+          }
+      }
+      /// <summary>
+      /// convert hue value to seperate RGB values, based on predefined values  
+      /// </summary>
+      /// <param name="hue">hue: in range 0...MAXHUEVALUE</param>
+      /// <returns>int value as RGB color, A=255</returns>
+      /// <remarks>the internal values (rgb / luminance,saturation) will not be altered. 
+      /// rgb returned as seperate float values, normalized to 0.0f...1.0f</remarks>
+      public void H2RGB(float hueVal, out float r, out float g, out float b)   
+      {
+          if (saturation == 0.0) // gray, simple case
+          {
+              byte bval = (byte)(luminance * 255.0F); 
+              r = bval/256f; 
+              g = bval/256f; 
+              b = bval/256f; 
+              return; 
+          } else {
+              float rm1;
+              float rm2;
+             
+              if (luminance <= 0.5f) 
+              {
+                 rm2 = luminance + luminance * saturation;
+              } else {
+                 rm2 = luminance + saturation - luminance * saturation;
+              }
+              rm1 = 2.0f * luminance - rm2;
+              r = ToRGB1(rm1, rm2, hueVal + 120.0f)/256f; 
+              g = ToRGB1(rm1, rm2, hueVal)/256f; 
+              b = ToRGB1(rm1, rm2, hueVal - 120.0f)/256f; 
+              return;  
+          }
+      }
+      /// <summary>
+      /// convert hue value to seperate RGB values, based on predefined values  
+      /// </summary>
+      /// <param name="hue">hue: in range 0...MAXHUEVALUE</param>
+      /// <param name="offset">offset into vertex array</param>
+      /// <param name="va">vertex array, target for the color</param>
+      /// <remarks>the internal values (rgb / luminance,saturation) will not be altered. 
+      /// rgb returned as seperate float values, normalized to 0.0f...1.0f</remarks>
+      public void H2RGB(float hue, float[] va, ref int offset)   
+      {
+          if (saturation == 0.0) // gray, simple case
+          {
+              byte bval = (byte)(luminance * 255.0F); 
+              va[offset++] = bval/256f; 
+              va[offset++] = bval/256f; 
+              va[offset++] = bval/256f; 
+              return; 
+          } else {
+              float rm1;
+              float rm2;
+             
+              if (luminance <= 0.5f) 
+              {
+                 rm2 = luminance + luminance * saturation;
+              } else {
+                 rm2 = luminance + saturation - luminance * saturation;
+              }
+              rm1 = 2.0f * luminance - rm2;
+              va[offset++] = ToRGB1(rm1, rm2, hue + 120.0f)/256f; 
+              va[offset++] = ToRGB1(rm1, rm2, hue)/256f; 
+              va[offset++] = ToRGB1(rm1, rm2, hue - 120.0f)/256f; 
+              return;  
+          }
+      }
+      
+       /// <summary>
+      /// convert hue value to seperate RGB values, based on predefined values  
+      /// </summary>
+      /// <param name="hue">hue: in range 0...MAXHUEVALUE</param>
+      /// <returns>int value as RGB color, A=255</returns>
+      /// <remarks>the internal values (rgb / luminance,saturation) will not be altered. 
+      /// rgb returned as seperate float values, normalized to 0.0f...1.0f</remarks>
+      public void H2RGB(float hueVal, out byte r, out byte g, out byte b)   
+      {
+          if (saturation == 0.0) // gray, simple case
+          {
+              byte bval = (byte)(luminance * 255.0F); 
+              r = bval; 
+              g = bval; 
+              b = bval; 
+              return; 
+          } else {
+              float rm1;
+              float rm2;
+             
+              if (luminance <= 0.5f) 
+              {
+                 rm2 = luminance + luminance * saturation;
+              } else {
+                 rm2 = luminance + saturation - luminance * saturation;
+              }
+              rm1 = 2.0f * luminance - rm2;
+              r = ToRGB1(rm1, rm2, hueVal + 120.0f); 
+              g = ToRGB1(rm1, rm2, hueVal); 
+              b = ToRGB1(rm1, rm2, hueVal - 120.0f); 
+              return;  
+          }
+      }
+
+      private void ToRGB() 
+      {
+         if (saturation == 0.0) // Grauton, einfacher Fall
+         {
+            red = (byte)(luminance * 255.0F);
+            green = red;
+            blue = red;
+         }
+         else
+         {
+            float rm1;
+            float rm2;
+         
+            if (luminance <= 0.5f) 
+            {
+               rm2 = luminance + luminance * saturation;
+            }
+            else
+            {
+               rm2 = luminance + saturation - luminance * saturation;
+            }
+            rm1 = 2.0f * luminance - rm2;
+            red   = ToRGB1(rm1, rm2, hue + 120.0f);   
+            green = ToRGB1(rm1, rm2, hue);
+            blue  = ToRGB1(rm1, rm2, hue - 120.0f);
+         }
+      }
+
+      private static byte ToRGB1(float rm1, float rm2, float rh)
+      {
+         if (rh > 360.0f) 
+         {
+            rh -= 360.0f;
+         }
+         else if (rh <   0.0f) 
+         {
+            rh += 360.0f;
+         }
+ 
+         if (rh <  60.0f) 
+         {
+            rm1 = rm1 + (rm2 - rm1) * rh / 60.0f;   
+         }
+         else if (rh < 180.0f) 
+         {
+            rm1 = rm2;
+         }
+         else if (rh < 240.0f) 
+         {
+            rm1 = rm1 + (rm2 - rm1) * (240.0f - rh) / 60.0f; 
+         }
+                   
+         return (byte)(rm1 * 255);
+      }
+      
+      public static void Colorize (List<ILPlot2DGraph> graphs) {
+          KnownColor[] colors = (KnownColor[])Enum.GetValues(typeof(KnownColor)); 
+          int curColIdx = 0; 
+          foreach (ILPlot2DGraph graph in graphs) {
+                graph.Line.Color = Color.FromKnownColor(colors[curColIdx++ % colors.Length]); 
+          }
+      }
+   }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/ILColormap.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/ILColormap.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/ILColormap.cs	(revision 9102)
@@ -0,0 +1,423 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing; 
+using ILNumerics; 
+
+namespace ILNumerics.Drawing.Misc {
+    public sealed class ILColormap {
+
+        #region events 
+        public event EventHandler Changed; 
+        protected void OnChanged() {
+            if (Changed != null) {
+                Changed(this,null); 
+            }
+        }
+        #endregion
+
+        #region attributes
+        ILArray<float> m_map = ILMath.returnType<float>(); 
+        Colormaps m_type; 
+        #endregion
+
+        #region properties
+        /// <summary>
+        /// number of colors in the colormap
+        /// </summary>
+        public int Length {
+            get {
+                return m_map.Size[0]; 
+            }
+        }
+        /// <summary>
+        /// The colormap type this colormap is based on (readonly)
+        /// </summary>
+        public Colormaps Type {
+            get {
+                return m_type; 
+            }
+        }
+        /// <summary>
+        /// retrieve / set internal data for color indices
+        /// </summary>
+        /// <remarks>colors will be a matrix of exactly 3 columns. Each element will range between 0.0 ... 1.0. 
+        /// If in set access the matrix provided contains elements outside the range, the matrix will be normalized to fit into 0.0 ... 1.0.
+        /// <para>The array returned will be a reference of the internal data only. It cannot be used to alter internal color table! In order to alter the color table, one can query the table, alter it outside and store it back than.</para></remarks>
+        public ILRetArray<float> Data {
+            get {
+                return m_map;
+            }
+            set {
+                if (! object.Equals (value,null) && !value.IsEmpty && value.IsMatrix && value.Size[0] > 1 && value.Size[1] == 3) {
+                    ILArray<float> max = ILMath.maxall(value); 
+                    ILArray<float> min = ILMath.minall(value); 
+                    m_map.a = ((value - min) / (max-min)).C; 
+                    OnChanged(); 
+                }
+            }
+        }
+        #endregion
+
+        #region constructor
+        /// <summary>
+        /// construct new colormap, based on HLS model
+        /// </summary>
+        internal ILColormap () {
+            m_map.a = MapCreator.CreateMap(Colormaps.Hsv);   
+            m_type = Colormaps.Hsv; 
+        }
+        /// <summary>
+        ///  create specific colormap
+        /// </summary>
+        /// <param name="map"></param>
+        public ILColormap (Colormaps map) {
+            m_map.a = MapCreator.CreateMap(map,128);
+            m_type = map; 
+        }
+        /// <summary>
+        /// create colormap based on predefined colors
+        /// </summary>
+        /// <param name="colors"></param>
+        public ILColormap(ILInArray<float> colors) {
+            using (ILScope.Enter(colors)) {
+                if (ILMath.isnull(colors)) 
+                    throw new Exceptions.ILArgumentException("colors argument may not be null"); 
+                m_map.a = colors.C;
+                m_type = Colormaps.ILNumerics;
+            }
+        }
+        #endregion
+
+        #region public interface
+        public Color this[double index] {
+            get {
+                return Map(index); 
+            }
+        }
+        public Color Map(int index) {
+            return Color.FromArgb(255,
+                                (int)(m_map.GetValue(index,0)*255),
+                                (int)(m_map.GetValue(index,1)*255),
+                                (int)(m_map.GetValue(index,2)*255));
+        }
+        public Color Map(double index) {
+            if (index >= m_map.Size[0]-1) 
+                return Map(m_map.Size[0]-1); 
+            if (index < 0) return Map(0); 
+            int find = (int)Math.Floor(index); 
+            if (find == index) 
+                return Map(find); 
+            // interpolate
+            index = index - find; 
+            float r1 = m_map.GetValue(find,0);
+            float g1 = m_map.GetValue(find,1); 
+            float b1 = m_map.GetValue(find,2); 
+            r1 = (float)(index*(m_map.GetValue(find+1,0)-r1)+r1); 
+            g1 = (float)(index*(m_map.GetValue(find+1,1)-g1)+g1); 
+            b1 = (float)(index*(m_map.GetValue(find+1,2)-b1)+b1); 
+            return Color.FromArgb(255,(int)(r1*255),(int)(g1*255),(int)(b1*255)); 
+        }
+        /// <summary>
+        /// map all elements in A into final colors
+        /// </summary>
+        /// <param name="A">array with elements to map</param>
+        /// <returns>colors as ILArray, the i-th row represents the color for the i-th element of A as RGB tripel.</returns>
+        public ILRetArray<float> Map (ILDenseArray<float> A) {
+            using (ILScope.Enter(A)) {
+                ILArray<float> ret = ILMath.returnType<float>();
+                ret.a = ILMath.zeros<float>(A.Size.NumberOfElements, 3);
+                float min, max;
+                if (!A.GetLimits(out min, out max) || min == max) {
+                    // special case: all constant: return middle of colormap
+                    return ILMath.repmat<float>(m_map[m_map.Length / 2, ILMath.full], ret.Size[0], 1);
+                }
+
+                float dist = (m_map.Size[0] - 1) / (A.MaxValue - min);
+                for (int i = 0; i < ret.Size[0]; i++) {
+                    double index = (double)(A.GetValue(i) - min) * dist;
+                    if (index >= m_map.Size[0] - 1) {
+                        ret[i, ILMath.full] = m_map["end;:"];
+                        continue;
+                    } else if (index < 0) {
+                        ret[i, ILMath.full] = m_map["0;:"];
+                        continue;
+                    }
+                    int find = (int)Math.Floor(index);
+                    if (find == index) {
+                        ret[i, ILMath.full] = m_map[find, ILMath.full];
+                        continue;
+                    }
+                    // interpolate
+                    index = index - find;
+                    float r1 = m_map.GetValue(find, 0);
+                    float g1 = m_map.GetValue(find, 1);
+                    float b1 = m_map.GetValue(find, 2);
+                    r1 = (float)(index * (m_map.GetValue(find + 1, 0) - r1) + r1);
+                    g1 = (float)(index * (m_map.GetValue(find + 1, 1) - g1) + g1);
+                    b1 = (float)(index * (m_map.GetValue(find + 1, 2) - b1) + b1);
+                    ret.SetValue(r1, i, 0);
+                    ret.SetValue(g1, i, 1);
+                    ret.SetValue(b1, i, 2);
+                }
+                return ret;
+            }
+        }
+        public void Map(double value, float[] vertices,ref int offset) {
+            if (value >= m_map.Size[0]-1) {
+                vertices[offset++] = m_map.GetValue(m_map.Size[0]-1,0); 
+                vertices[offset++] = m_map.GetValue(m_map.Size[0]-1,1); 
+                vertices[offset++] = m_map.GetValue(m_map.Size[0]-1,2); 
+                return; 
+            }
+            if (value < 0) {
+                vertices[offset++] = m_map.GetValue(0,0); 
+                vertices[offset++] = m_map.GetValue(0,1); 
+                vertices[offset++] = m_map.GetValue(0,2);
+                return; 
+            }
+            int find = (int)Math.Floor(value); 
+            if (find == value) {
+                vertices[offset++] = m_map.GetValue(find,0); 
+                vertices[offset++] = m_map.GetValue(find,1); 
+                vertices[offset++] = m_map.GetValue(find,2); 
+                return; 
+            }
+            // interpolate
+            value = value - find; 
+            float r1 = m_map.GetValue(find,0);
+            float g1 = m_map.GetValue(find,1); 
+            float b1 = m_map.GetValue(find,2); 
+            r1 = (float)(value*(m_map.GetValue(find+1,0)-r1)+r1); 
+            g1 = (float)(value*(m_map.GetValue(find+1,1)-g1)+g1); 
+            b1 = (float)(value*(m_map.GetValue(find+1,2)-b1)+b1); 
+            vertices[offset++] = r1; 
+            vertices[offset++] = g1; 
+            vertices[offset++] = b1; 
+        }
+        /// <summary>
+        /// convert index value to color, interpolating
+        /// </summary>
+        /// <param name="value">index, position into color table, range 0...(Length-1). Values outer limits will be truncated.</param>
+        /// <param name="r">out value: red component</param>
+        /// <param name="g">out value: green component</param>
+        /// <param name="b">out value: blue component</param>
+        public void Map(double value, out byte r, out byte g, out byte b) {
+            if (value >= m_map.Size[0]-1) {
+                r = (byte)(m_map.GetValue(m_map.Size[0]-1,0)*255); 
+                g = (byte)(m_map.GetValue(m_map.Size[0]-1,1)*255); 
+                b = (byte)(m_map.GetValue(m_map.Size[0]-1,2)*255); 
+                return; 
+            }
+            if (value < 0) {
+                r = (byte)(m_map.GetValue(0,0)*255); 
+                g = (byte)(m_map.GetValue(0,1)*255); 
+                b = (byte)(m_map.GetValue(0,2)*255); 
+                return; 
+            }
+            int find = (int)Math.Floor(value); 
+            if (find == value) {
+                r = (byte)(m_map.GetValue(find,0)*255); 
+                g = (byte)(m_map.GetValue(find,1)*255); 
+                b = (byte)(m_map.GetValue(find,2)*255); 
+                return; 
+            }
+            // interpolate
+            value = value - find; 
+            float r1 = m_map.GetValue(find,0);
+            float g1 = m_map.GetValue(find,1); 
+            float b1 = m_map.GetValue(find,2); 
+            r = (byte)((value*(m_map.GetValue(find+1,0)-r1)+r1)*255); 
+            g = (byte)((value*(m_map.GetValue(find+1,1)-g1)+g1)*255); 
+            b = (byte)((value*(m_map.GetValue(find+1,2)-b1)+b1)*255); 
+            return; 
+        }
+        #endregion
+
+        #region create maps
+        internal class MapCreator : ILNumerics.ILMath {
+            /// <summary>
+            /// create colorpam of length 128
+            /// </summary>
+            /// <param name="map">map specification</param>
+            /// <returns>colormap (matrix with size [len,3])</returns>
+            internal static ILRetArray<float> CreateMap(Colormaps map) {
+                return CreateMap(map,128); 
+            }
+            /// <summary>
+            /// create colormap
+            /// </summary>
+            /// <param name="map">map specification</param>
+            /// <param name="len">len of colormap</param>
+            /// <returns>colormap (matrix with size [len,3])</returns>
+            internal static ILRetArray<float> CreateMap(Colormaps map, int len) {
+                using (ILScope.Enter()) {
+                    ILArray<float> ret = empty<float>(); 
+                    ILArray<double> retd; // helper var 
+                    int n;
+                    switch (map) {
+                        case Colormaps.Autumn:
+                            ret.a = tosingle(horzcat(ones(len, 1), linspace(0, 1.0, len).T, zeros(len, 1)));
+                            break;
+                        case Colormaps.Bone:
+                            ret.a = CreateMap(Colormaps.Hot)[":;end:-1:0"];
+                            ret.a = (tosingle(repmat(linspace(0, 1.0, len).T, 1, 3) * 7.0) + ret) / 8.0f;
+                            break;
+                        //case Colormaps.Colorcube:
+                        //    throw new NotImplementedException("ILColormap: sorry, colorcube must be implemented!");
+                            //break;
+                        case Colormaps.Cool:
+                            retd = horzcat(linspace(0, 1.0, len).T, linspace(1.0, 0.0, len).T, ones(len, 1));
+                            ret.a = tosingle(retd);
+                            break;
+                        case Colormaps.Copper:
+                            retd = linspace(0, 1.0, len).T;
+                            ret.a = empty<float>();
+                            ret.a = tosingle(min(1.0, retd * 1.25));
+                            ret[":;1"] = tosingle(retd * 0.782);
+                            ret[":;2"] = tosingle(retd * 0.4975);
+                            break;
+                        case Colormaps.Flag:
+                            retd = new double[,] { { 1, 0, 0 }, { 1, 1, 1 }, { 0, 0, 1 }, { 0, 0, 0 } };
+                            retd = repmat(retd.T, (int)ceil((double)len / retd.Size[1]), 1);
+                            ret.a = tosingle(retd[vec(0, len - 1), full]);
+                            break;
+                        case Colormaps.Gray:
+                            ret.a = tosingle(repmat(linspace(0, 1.0, len).T, 1, 3));
+                            break;
+                        case Colormaps.Hot:
+                            n = (int)fix(len / 8.0 * 3);
+                            retd = zeros(len, 3);
+                            ILArray<double> rng = vec(0, n - 1);
+                            retd[rng, 0] = linspace(0, 1.0, n);
+                            retd[vec(n, len - 1), 0] = 1.0;
+                            retd[rng + n, 1] = linspace(0, 1.0, n);
+                            retd[vec(2 * n, len - 1), 1] = 1.0;
+                            rng = vec(len - 2 * n, len - 1);
+                            retd[rng, 2] = linspace(0, 1.0, rng.Length);
+                            ret.a = tosingle(retd);
+                            break;
+                        case Colormaps.Hsv:
+                            n = len / 6;
+                            // red 
+                            ILArray<double> peak = 2.0 - abs(linspace(2, -2, 4 * n));
+                            retd = zeros(len, 3);
+                            retd[vec(len - peak.Length, len - 1), 0] = peak;
+                            retd[vec(0, 4 * n - 1), 1] = peak;
+                            retd[vec(0, 2 * n - 1), 2] = peak[vec(2 * n, 4 * n - 1)];
+                            retd[vec(len - 2 * n, len - 1), 2] = peak[vec(0, 2 * n - 1)];
+                            retd[retd > 1] = 1;
+                            ret.a = tosingle(retd);
+                            break;
+                        case Colormaps.ILNumerics:
+                            ret.a = zeros<float>(len, 3);
+                            int tmp;
+                            ILColorProvider cprov = new ILColorProvider(0.0f, 0.5f, 1.0f);
+                            rng = linspace(ILColorProvider.MAXHUEVALUE, 0.0, len);
+                            for (int i = 0; i < len; i++) {
+                                tmp = cprov.H2RGB((float)rng[i]);
+                                ret.SetValue((float)(tmp >> 16 & 255), i, 0);
+                                ret.SetValue((float)(tmp >> 8 & 255), i, 1);
+                                ret.SetValue((float)(tmp & 255), i, 2);
+                            }
+                            ret.a /= 255.0f;
+                            break;
+                        case Colormaps.Jet:
+                            n = len / 8;
+                            // red 
+                            peak = 1.5 - abs(linspace(1.5, -1.5, 6 * n));
+                            retd = zeros(len, 3);
+                            retd[vec(0, 5 * n - 1), 0] = peak[vec(n, 6 * n - 1)];
+                            retd[vec(n, 7 * n - 1), 1] = peak;
+                            retd[vec(3 * n, 8 * n - 1), 2] = peak[vec(0, 5 * n - 1)];
+                            retd[retd > 1] = 1;
+                            ret.a = tosingle(retd);
+                            break;
+                        case Colormaps.Lines:
+                            ret = zeros<float>(30,3); 
+                            ret = new float[,] {
+                            {1,0,145},{210,16,6},{0,168,65},{255,210,7}, {0,0,0},
+                            {177,6,210},{255,147,3},{0,131,145},{151,168,0},
+                            {35,93,131},{249,3,255},{120,169,90},{234,168,107},
+                            {2,229,32},{97,5,29},{180,180,180},{87,65,4},
+                            {140,140,140},{97,5,75},{112,46,4},{90,90,90}
+                            };
+                            ret.a = ret.T / 255f;
+                            break;
+                        case Colormaps.Pink:
+                            ret.a = CreateMap(Colormaps.Hot, len);
+                            ret.a = sqrt((repmat(tosingle(linspace(0, 1.0, len).T), 1, 3) * 2.0f + ret) / 3.0f);
+                            break;
+                        case Colormaps.Prism:
+                            retd = new double[,] { { 1, 0, 0 }, { 1, 0.5, 0 }, { 1, 1, 0 }, { 0, 1, 0 }, { 0, 0, 1 }, { 2 / 3.0, 0, 1 } };
+                            retd = repmat(retd.T, (int)ceil((double)len / retd.Size[1]), 1);
+                            ret.a = tosingle(retd[vec(0, len - 1), full]);
+                            break;
+                        case Colormaps.Spring:
+                            retd = ones(len, 1);
+                            retd[":;1"] = linspace(0.0, 1.0, len);
+                            retd[":;2"] = linspace(1.0, 0.0, len);
+                            ret.a = tosingle(retd);
+                            break;
+                        case Colormaps.Summer:
+                            retd = linspace(0.0, 1.0, len).T;
+                            retd[":;1"] = 0.5 + retd / 2.0; ;
+                            retd[":;2"] = ones(len, 1) * 0.4;
+                            ret.a = tosingle(retd);
+                            break;
+                        case Colormaps.White:
+                            ret.a = tosingle(ones(len, 3));
+                            break;
+                        case Colormaps.Winter:
+                            retd = zeros(len, 1);
+                            retd[":;2"] = 0.5 + (1.0 - linspace(0.0, 1.0, len)) / 2.0;
+                            retd[":;1"] = linspace(0.0, 1.0, len);
+                            ret.a = tosingle(retd);
+                            break;
+                    }
+                    return ret;
+                }
+            }
+        }
+        #endregion
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/ILDrawingException.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/ILDrawingException.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/ILDrawingException.cs	(revision 9102)
@@ -0,0 +1,61 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace ILNumerics.Drawing {
+    /// <summary>
+    /// Drawing exception
+    /// </summary>
+    public class ILDrawingException : Exception {
+        /// <summary>
+        /// create new drawing exception
+        /// </summary>
+        /// <param name="message">message</param>
+        public ILDrawingException(string message) : base(message) { }
+        /// <summary>
+        /// create new drawing exception
+        /// </summary>
+        /// <param name="message">message</param>
+        /// <param name="innerException">inner (nested) exception</param>
+        public ILDrawingException(string message, Exception innerException) : base(message,innerException) { }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/ILGraphComparer.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/ILGraphComparer.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/ILGraphComparer.cs	(revision 9102)
@@ -0,0 +1,92 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Drawing.Graphs; 
+
+namespace ILNumerics.Drawing.Misc {
+    public class ILGraphComparer : IComparer<ILGraph> {
+
+        ILCamera m_camera;
+
+        public ILCamera Camera {
+            get { return m_camera; }
+            set { m_camera = value; }
+        } 
+
+        public ILGraphComparer () {}
+
+
+
+        #region IComparer<ILGraph> Member
+
+        /// <summary>
+        /// sort graphs regarding their Z order 
+        /// </summary>
+        /// <param name="x">first graph</param>
+        /// <param name="y">second graph</param>
+        /// <returns></returns>
+        public int Compare(ILGraph x, ILGraph y) {
+            if (m_camera.LooksFromTop)
+                return Comparer<float>.Default.Compare(x.Limits.CenterF.Z,y.Limits.CenterF.Z); 
+            else     
+                return Comparer<float>.Default.Compare(y.Limits.CenterF.Z,x.Limits.CenterF.Z); 
+            // if finer control over sorting is needed, try the following code instead! 
+            //ILPoint3Df cent1 = x.Limits.CenterF; 
+            //ILPoint3Df cent2 = y.Limits.CenterF; 
+            //float distX = cent1.X - m_camera.X; 
+            //float distY = cent1.Y - m_camera.Y; 
+            //float distZ = cent1.Z - m_camera.Z; 
+            //float dist1 = distX * distX + distY * distY + distZ * distZ; 
+            //distX = cent2.X - m_camera.X;
+            //distY = cent2.Y - m_camera.Y;
+            //distZ = cent2.Z - m_camera.Z;
+            //float dist2 = distX * distX + distY * distY + distZ * distZ; 
+            //if (dist2 > dist1) {
+            //    return 1; 
+            //} else if (dist2 == dist1) {
+            //    return 0; 
+            //} else 
+            //    return -1; 
+        }
+        #endregion
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/ILLegend.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/ILLegend.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/ILLegend.cs	(revision 9102)
@@ -0,0 +1,244 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing;
+using System.Windows.Forms;  
+using ILNumerics.Drawing; 
+using ILNumerics.Exceptions;  
+using ILNumerics.Drawing.Graphs; 
+using ILNumerics.Drawing.Interfaces; 
+using ILNumerics.Drawing.Labeling; 
+using ILNumerics.Drawing.Platform.OpenGL; 
+
+namespace ILNumerics.Drawing.Misc {
+    public abstract class ILLegend {
+
+        #region events 
+        public event EventHandler Changed; 
+        protected void OnChanged() {
+            if (Changed != null) {
+                Changed(this,null); 
+            }
+        }
+        void m_border_Changed(object sender, EventArgs e) {
+            OnChanged(); 
+        }
+        #endregion
+
+        #region attributes
+        protected ILPanel m_panel;
+        protected Size m_size;
+        protected PointF m_location; 
+        protected Color m_bgColor; 
+        protected ILLineProperties m_border; 
+        protected float m_opacity; 
+        protected Padding m_padding; 
+        protected bool m_visible; 
+        #endregion
+
+        #region properties
+        /// <summary>
+        /// get / set visibility for legend
+        /// </summary>
+        public bool Visible {
+            get {
+                return m_visible; 
+            }
+            set {
+                m_visible = value; 
+                OnChanged(); 
+            }
+        }
+        /// <summary>
+        /// Get/ set opacity for filled area, values: 0...1.0
+        /// </summary>
+        public float Opacity {
+            get {
+                return m_opacity; 
+            }
+            set {
+                m_opacity = value; 
+                OnChanged(); 
+            }
+        }
+
+        /// <summary>
+        /// Get / set background color
+        /// </summary>
+        public Color BackgroundColor {
+            get {
+                return m_bgColor; 
+            } 
+            set {
+                m_bgColor = value; 
+                OnChanged(); 
+            }
+        }
+        /// <summary>
+        /// get/ set location of legend box (upper/left corner, fraction of ClientSize [(0,0)...(1f,1F)]), empty for auto mode
+        /// </summary>
+        public PointF Location {
+            get {
+                return m_location; 
+            }
+            set {
+                m_location = value; 
+                OnChanged(); 
+            }
+        }
+        /// <summary>
+        /// get/ set size of legend box, empty for auto mode
+        /// </summary>
+        public Size Size {
+            get { return m_size; }
+            set { 
+                m_size = value; 
+                OnChanged(); 
+            }
+        }
+        /// <summary>
+        /// set properties of legend's border 
+        /// </summary>
+        public ILLineProperties Border {
+            get {
+                return m_border; 
+            } 
+        }
+        #endregion
+
+        #region constructor
+        /// <summary>
+        /// construct new legend object
+        /// </summary>
+        internal ILLegend (ILPanel panel) {
+            m_panel = panel; 
+            m_size = Size.Empty; 
+            m_border = new ILLineProperties();
+            m_border.Antialiasing = false;
+            m_border.Color = Color.LightGray;  
+            m_border.Style = LineStyle.Solid; 
+            m_border.Width = 2; 
+            m_border.Changed += new EventHandler(m_border_Changed);
+            m_location = Point.Empty;
+            m_bgColor = Color.FromArgb(250,250,250); 
+            m_opacity = 0.9f; 
+            m_padding = new Padding(5);
+            m_visible = false; 
+        }
+        /// <summary>
+        /// Create new instance of ILLegend, depending on graphics device type
+        /// </summary>
+        /// <param name="panel">panel hosting this legend</param>
+        /// <returns>newly created ILLegend object</returns>
+        public static ILLegend Create(ILPanel panel) {
+            if (panel is ILOGLPanel) {
+                return new ILOGLLegend(panel); 
+            } else 
+                throw new NotImplementedException("Currently only legends for OpenGL are supported"); 
+        }
+        #endregion
+
+        #region public interface
+        /// <summary>
+        /// Draw the legend onto a predefined bitmap or into GL context
+        /// </summary>
+        /// <param name="p">render properties</param>
+        /// <param name="area">rectangle area defines region to draw legend contents into.</param>
+        /// <remarks>This function does only render to a predefined bitmap, which must be given in p. Rendering to 
+        /// (dvice dependent) graphic contexts is done in derived implementations.</remarks>
+        public virtual void Draw(ILRenderProperties p, Rectangle area) {
+            if (m_panel == null || m_panel.Graphs == null) return; 
+            if (p.Graphics == null) {
+                throw new ILArgumentException("ILLegend:Draw: unexpected parameter (bitmap) is null. This should be handled in derived classes!"); 
+            }
+            // draw bg + border 
+            PointF p1,p2; 
+            float offsX = Math.Max(m_border.Width / 2.0f,1.0f), offsY; 
+            p1 = new PointF(offsX,offsX); 
+            p2 = new PointF(m_size.Width-offsX,offsX); 
+            Pen pen = new Pen(m_border.Color,m_border.Width); 
+            // todo: implement dash styles 
+            p.Graphics.Clear(m_bgColor); 
+            p.Graphics.DrawLine(pen,p1,p2); 
+            p1.X = p2.X; p1.Y = m_size.Height - offsX; 
+            p.Graphics.DrawLine(pen,p2,p1); 
+            p2.X = offsX; p2.Y = p1.Y; 
+            p.Graphics.DrawLine(pen,p1,p2);
+            p1.X = offsX; p1.Y = offsX; 
+            p.Graphics.DrawLine(pen,p2,p1); 
+            List<IILLegendRenderer> providers = new List<IILLegendRenderer>(10); 
+            foreach (ILGraph graph in m_panel.Graphs) {
+                if (graph is IILLegendRenderer) {
+                    providers.Add(graph as IILLegendRenderer); 
+                } 
+            }
+            // compute final example sizes to fit into my size
+            offsX = m_size.Width * 0.1f; offsY = m_size.Height * 0.1f;
+            area.Height = (int)(m_size.Height - 2 * offsY) / providers.Count; 
+            area.Width  = (int)(m_size.Width - 2 * offsX) / providers.Count; 
+            area.X = (int)offsX; 
+            for (int i = 0; i < providers.Count; i++) {
+                area.Y = (int)(offsY + i * area.Height); 
+                // todo: not implemented! 
+                providers[i].DrawToLegend(p,area,area);
+            }
+        }
+
+        #endregion
+
+        #region helper functions
+        protected List<IILLegendRenderer> getRenderers(ref Size labelSize) {
+            List<IILLegendRenderer> ret = new List<IILLegendRenderer>(); 
+            foreach(ILGraph graph in m_panel.Graphs) {
+                IILLegendRenderer rend = graph as IILLegendRenderer; 
+                if (rend != null) {
+                    ret.Add(rend); 
+                    if (rend.LabelSize.Width > labelSize.Width) 
+                        labelSize.Width = rend.LabelSize.Width; 
+                    labelSize.Height += rend.LabelSize.Height; 
+                }
+            }
+            return ret; 
+        }
+        #endregion
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/ILLineProperties.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/ILLineProperties.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/ILLineProperties.cs	(revision 9102)
@@ -0,0 +1,232 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing; 
+
+namespace ILNumerics.Drawing {
+    /// <summary>
+    /// properties for line graphs
+    /// </summary>
+    public class ILLineProperties {
+
+        #region event handling 
+        /// <summary>
+        /// fires if the properties were changed
+        /// </summary>
+        public event EventHandler Changed; 
+        protected void OnChanged() {
+            if (Changed != null) {
+                Changed(this,new EventArgs()); 
+            }
+        }
+        #endregion
+
+        #region attributes
+        private int m_lineWidth; 
+        private LineStyle m_lineStyle; 
+        private short m_linePattern; 
+        private float m_linePatternScale; 
+        private Color m_foreColor; 
+        private bool m_visible; 
+        private bool m_setAntialiasing = false;
+        private bool m_antialiasing;
+        #endregion
+
+        #region Properties 
+        /// <summary>
+        /// line width (default: 1)
+        /// </summary>
+        /// <remarks>if antialiasing is active, it will be disabled 
+        /// as long as the width is less than 2 and automatically 
+        /// reenabled if the width gets larger than 1 again.</remarks>
+        public int Width {
+            get {
+                return m_lineWidth; 
+            }
+            set {
+                // for width = 1, antialiasing will not work and 
+                // must get disabled temporarily here 
+                if (value <= 1) {
+                    if (m_antialiasing) {
+                        m_antialiasing = false; 
+                        m_setAntialiasing = true; 
+                    }
+                } else {
+                    if (m_setAntialiasing) {
+                        m_setAntialiasing = false; 
+                        m_antialiasing = true; 
+                    }
+                }
+                m_lineWidth = value; 
+                OnChanged(); 
+            }
+        }
+        /// <summary>
+        /// line style (default: solid)
+        /// </summary>
+        public LineStyle Style {
+            get {
+                return m_lineStyle; 
+            }
+            set {
+                m_lineStyle = value; 
+                OnChanged(); 
+            }
+        }
+        /// <summary>
+        /// user defined line stipple pattern for line style 'UserPattern'
+        /// </summary>
+        /// <remarks>the pattern is defined by corresponding bits 
+        /// set in the short value. It may be stretched via the 
+        /// LinePatternScale parameter. Default: 15</remarks>
+        public short Pattern {
+            get {
+                return m_linePattern; 
+            }
+            set {
+                m_linePattern = value;
+                m_lineStyle = LineStyle.UserPattern; 
+                OnChanged(); 
+            }
+        }
+        /// <summary>
+        /// scaling for line stipple patterns (default: 2.0f)
+        /// </summary>
+        public float PatternScale {
+            get {
+                return m_linePatternScale; 
+            }
+            set {
+                m_linePatternScale = value;
+                OnChanged(); 
+            }
+        }
+        /// <summary>
+        /// Line color (default: DarkOliveGreen)
+        /// </summary>
+        public Color Color {
+            get {
+                return m_foreColor; 
+            }
+            set {
+                m_foreColor = value; 
+                OnChanged(); 
+            }
+        }
+        /// <summary>
+        /// get / set if lines are visible (default: true)
+        /// </summary>
+        public bool Visible {
+            get {
+                return m_visible; 
+            }
+            set {
+                m_visible = value; 
+                OnChanged(); 
+            }
+        }
+        /// <summary>
+        /// draw lines with smooth antialiasing (if possible and supported)
+        /// </summary>
+        /// <remarks>If the object supports antialiased lines, edges will be drawn 
+        /// smoothly. This sometimes comes with the drawback of the lines beeing 
+        /// more thick. Not all objects support antialiasing. Default value is 'false'.</remarks>
+        public bool Antialiasing {
+            get {
+                return m_antialiasing; 
+            }
+            set {
+                if (m_setAntialiasing && !value) {
+                    m_setAntialiasing = false; 
+                }
+                m_antialiasing = value; 
+                OnChanged(); 
+            }
+        }
+        #endregion 
+
+        #region public properties 
+        public ILLineProperties Clone() {
+            return (ILLineProperties) this.MemberwiseClone(); 
+        }
+        public void CopyFrom(ILLineProperties props) {
+            if (props != null) {
+                this.Antialiasing = props.Antialiasing;
+                this.Color = props.Color;
+                this.Pattern = props.Pattern;
+                this.PatternScale = props.PatternScale;
+                this.Style = props.Style;
+                this.Visible = props.Visible;
+                this.Width = props.Width; 
+            }
+        }
+        #endregion 
+
+        #region constructors
+        /// <summary>
+        /// create default properties for graphs
+        /// </summary>
+        public ILLineProperties() {
+            m_lineStyle = LineStyle.Solid; 
+            m_foreColor = Color.AntiqueWhite;
+            m_lineWidth = 1; 
+            m_linePattern = 15; 
+            m_linePatternScale = 2.0f;
+            m_visible = true; 
+            m_antialiasing = false; 
+        }
+        /// <summary>
+        /// create a new instance of this class based on another instance
+        /// </summary>
+        /// <param name="props">properties to be copied</param>
+        public ILLineProperties(ILLineProperties props) {
+            m_lineStyle = props.Style; 
+            m_foreColor = props.Color;
+            m_lineWidth = props.Width; 
+            m_linePattern = props.Pattern; 
+            m_linePatternScale = props.PatternScale; 
+            m_visible = true; 
+            m_antialiasing = props.m_antialiasing;
+        }
+        #endregion
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/ILRenderProperties.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/ILRenderProperties.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/ILRenderProperties.cs	(revision 9102)
@@ -0,0 +1,107 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace ILNumerics.Drawing {
+    /// <summary>
+    /// extended drawing properties
+    /// </summary>
+    /// <remarks>the class collects flags for special
+    /// rendering states (vector exports, picking).
+    /// </remarks>
+    public class ILRenderProperties {
+        /// <summary>
+        /// current camera 
+        /// </summary>
+        public ILCamera Camera;
+        /// <summary>
+        /// current clipping (view limits) data
+        /// </summary>
+        public bool Clipping;
+        /// <summary>
+        /// if not null, the rendering should be done offscreen via this graphics object
+        /// </summary>
+        public System.Drawing.Graphics Graphics;
+        /// <summary>
+        /// if set to true while rendering, the render process will be cancelled 
+        /// </summary>
+        public bool Canceled = false;
+        /// <summary>
+        /// inform content object of the reason for rendering, see the <see cref="ILNumerics.Drawing.RenderReason">enumeration</see> for possible values.
+        /// </summary>
+        internal RenderReason Reason;
+        /// <summary>
+        /// measures the absolute used up region while rendering, initiallized to int.MaxValue
+        /// </summary>
+        public int MinX;
+        /// <summary>
+        /// measures the absolute used up region while rendering, initiallized to int.MinValue
+        /// </summary>
+        public int MaxX;
+        /// <summary>
+        /// measures the absolute used up region while rendering, initiallized to int.MaxValue
+        /// </summary>
+        public int MinY;
+        /// <summary>
+        /// measures the absolute used up region while rendering, initiallized to int.MinValue
+        /// </summary>
+        public int MaxY;
+        /// <summary>
+        /// Some rendering settings require multiple rendering passes. Those are counted here.
+        /// </summary>
+        public int PassCount = 0;
+
+        /// <summary>
+        /// Resets this instance.
+        /// </summary>
+        /// <returns>Instance reset to default values.</returns>
+        public ILRenderProperties Reset() {
+            PassCount = 0;
+            Reason = RenderReason.PaintEvent;
+            MinX = int.MaxValue;
+            MinY = int.MaxValue;
+            MaxX = int.MinValue;
+            MaxY = int.MinValue;
+            return this; 
+        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/ILZoomAction.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/ILZoomAction.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/ILZoomAction.cs	(revision 9102)
@@ -0,0 +1,103 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading;
+
+namespace ILNumerics.Drawing.Misc {
+    public class ILZoomAction : ILAction {
+        
+        ILPoint3Df m_MinCornerStart;
+        ILPoint3Df m_MinCornerEnd; 
+        ILPoint3Df m_MaxCornerStart; 
+        ILPoint3Df m_MaxCornerEnd; 
+        ILActionRamp m_ramp; 
+        int m_currentStep; 
+        ILPanel m_panel; 
+
+        public ILZoomAction(ILPoint3Df MinCornerStart,
+                            ILPoint3Df MinCornerEnd,
+                            ILPoint3Df MaxCornerStart,
+                            ILPoint3Df MaxCornerEnd, 
+                            ILActionRamp ramp,
+                            ILPanel panel) 
+        : base () {
+            m_MaxCornerEnd = ILPoint3Df.Max(MinCornerEnd,MaxCornerEnd);
+            m_MaxCornerStart = ILPoint3Df.Max(MinCornerStart,MaxCornerStart); 
+            m_MinCornerEnd = ILPoint3Df.Min(MinCornerEnd,MaxCornerEnd);
+            m_MinCornerStart = ILPoint3Df.Min(MinCornerStart,MaxCornerStart);
+            m_ramp = ramp; 
+            m_panel = panel; 
+        }
+
+        protected override void RunInternal(object parameter) {
+            float x1 = m_MinCornerStart.X;
+            float y1 = m_MinCornerStart.Y;
+            float z1 = m_MinCornerStart.Z;
+            float x2 = m_MaxCornerStart.X;
+            float y2 = m_MaxCornerStart.Y;
+            float z2 = m_MaxCornerStart.Z;
+            float aMinX = m_MinCornerEnd.X - x1;
+            float aMinY = m_MinCornerEnd.Y - y1;
+            float aMinZ = m_MinCornerEnd.Z - z1;
+            float aMaxX = m_MaxCornerEnd.X - x2;
+            float aMaxY = m_MaxCornerEnd.Y - y2;
+            float aMaxZ = m_MaxCornerEnd.Z - z2;
+            foreach (ILActionRampElement elem in m_ramp) {
+                if (m_canceled) return; 
+                ILPoint3Df min = new ILPoint3Df(
+                            x1 + aMinX * elem.Value,
+                            y1 + aMinY * elem.Value,
+                            z1 + aMinZ * elem.Value);
+                ILPoint3Df max = new ILPoint3Df(
+                            x2 + aMaxX * elem.Value,
+                            y2 + aMaxY * elem.Value,
+                            z2 + aMaxZ * elem.Value); 
+                m_panel.Limits.Set(min,max);
+                m_panel.Refresh(); 
+                if (m_canceled) return; 
+                Thread.Sleep((int)(elem.Duration * 1000)); 
+            }
+
+
+        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILGLU.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILGLU.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILGLU.cs	(revision 9102)
@@ -0,0 +1,168 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System; 
+using OpenTK; 
+using OpenTK.Graphics; 
+using OpenTK.Math; 
+using ILNumerics;
+using ILNumerics.Drawing; 
+
+/// <summary>
+/// This is a managed replacement for the OpenGL utilities library
+/// </summary>
+public partial class ILGLU {
+	
+	/// <summary>
+	/// Looks at eye, target, top and moveOffset.
+	/// </summary>
+	/// <param name='eye'>
+	/// Position of camera
+	/// </param>
+	/// <param name='target'>
+	/// Point the camera aims at
+	/// </param>
+	/// <param name='top'>
+	/// 'up' vector of the camera
+	/// </param>
+	/// <param name='moveOffset'>
+	/// offset for moving the whole scene slightly out of center
+	/// </param>
+	/// <remarks>Reference: http://www.opengl.org/sdk/docs/man/xhtml/gluLookAt.xml </remarks>
+	public static void LookAt (ILPoint3Df eye, ILPoint3Df target, ILPoint3Df top, ILPoint3Df moveOffset)
+	{
+		ILPoint3Df f = ILPoint3Df.normalize(target - eye);
+    	ILPoint3Df s = ILPoint3Df.cross(f, top);
+    	ILPoint3Df u = ILPoint3Df.cross(s, f);
+		// todo: cache this temp matrix! 
+    	double[] tmpMat = new double[16]; 
+    	tmpMat[0] = s.X; 	tmpMat[4] = s.Y; 	tmpMat[8] = s.Z; 	tmpMat[12] = 0;
+    	tmpMat[1] = u.X; 	tmpMat[5] = u.Y; 	tmpMat[9] = u.Z; 	tmpMat[13] = 0;
+    	tmpMat[2] = -f.X; 	tmpMat[6] = -f.Y; 	tmpMat[10] = -f.Z; 	tmpMat[14] = 0;
+    	tmpMat[3] = 0;   	tmpMat[7] = 0;   	tmpMat[11] = 0;   	tmpMat[15] = 1;
+    	GL.MultMatrix(tmpMat); 
+    	s = moveOffset - eye; 
+    	GL.Translate( s.X,s.Y,s.Z);
+	}
+	
+	/// <summary>
+	/// Get the screen coords of a point from world space coords
+	/// </summary>
+	/// <param name='worldCoords'>
+	/// World coords.
+	/// </param>
+	/// <param name='mm'>
+	/// Modelview matrix (as 1d double vector) 
+	/// </param>
+	/// <param name='pm'>
+	/// Projection matrix (as 1d double vector)
+	/// </param>
+	/// <param name='vm'>
+	/// View matrix (as 1d double vector) 
+	/// </param>
+	/// <param name='screen'>
+	/// [Output] point with screen coords (and a z value, see OpenGL man pages)
+	/// </param>
+	/// <remarks>Reference:	http://www.opengl.org/sdk/docs/man/xhtml/gluProject.xml </remarks>
+	public static void Project(ILPoint3Df worldCoords, double[] mm, double[] pm, int[] vm, out ILPoint3Df screen) {
+		screen = new ILPoint3Df(); 
+		screen.X = (float)((pm[0] * mm[00] + pm[4] * mm[01] + pm[8] * mm[02] + pm[12] * mm[03]) * worldCoords.X 
+				  +(pm[0] * mm[04] + pm[4] * mm[05] + pm[8] * mm[06] + pm[12] * mm[07]) * worldCoords.Y 
+				  +(pm[0] * mm[08] + pm[4] * mm[09] + pm[8] * mm[10] + pm[12] * mm[11]) * worldCoords.Z 
+				  +(pm[0] * mm[12] + pm[4] * mm[13] + pm[8] * mm[14] + pm[12] * mm[15]));  
+		
+		screen.Y = (float)((pm[1] * mm[00] + pm[5] * mm[01] + pm[9] * mm[02] + pm[13] * mm[03]) * worldCoords.X 
+				  +(pm[1] * mm[04] + pm[5] * mm[05] + pm[9] * mm[06] + pm[13] * mm[07]) * worldCoords.Y 
+				  +(pm[1] * mm[08] + pm[5] * mm[09] + pm[9] * mm[10] + pm[13] * mm[11]) * worldCoords.Z 
+				  +(pm[1] * mm[12] + pm[5] * mm[13] + pm[9] * mm[14] + pm[13] * mm[15]));  
+
+		screen.Z = (float)((pm[2] * mm[00] + pm[6] * mm[01] + pm[10] * mm[02] + pm[14] * mm[03]) * worldCoords.X 
+				  +(pm[2] * mm[04] + pm[6] * mm[05] + pm[10] * mm[06] + pm[14] * mm[07]) * worldCoords.Y 
+				  +(pm[2] * mm[08] + pm[6] * mm[09] + pm[10] * mm[10] + pm[14] * mm[11]) * worldCoords.Z 
+				  +(pm[2] * mm[12] + pm[6] * mm[13] + pm[10] * mm[14] + pm[14] * mm[15]));  
+		
+		screen.X = vm[0] + (vm[2] * (screen.X + 1f)) / 2f; 
+		screen.Y = vm[1] + (vm[3] * (screen.Y + 1f)) / 2f; 
+		screen.Z = (screen.Z + 1) / 2; 
+	}
+	
+	/// <summary>
+	/// Convert screen coordinates into world coordinates
+	/// </summary>
+	/// <param name='screen'>
+	/// Screen coordinates X,Y (and Z: see the OpenGL manual)
+	/// </param>
+	/// <param name='mm'>
+	/// Modelview matrix
+	/// </param>
+	/// <param name='pm'>
+	/// Projection matrix
+	/// </param>
+	/// <param name='vm'>
+	/// View matrix
+	/// </param>
+	/// <param name='world'>
+	/// [Output] World coordinates
+	/// </param>
+	/// <remarks>Reference: http://www.opengl.org/sdk/docs/man/xhtml/gluUnProject.xml </remarks>
+	public static void UnProject(ILPoint3Df screen, double[] mm, double[] pm, int[] vm, out ILPoint3Df world) {
+		Matrix4 p = new Matrix4 (new Vector4((float)pm[0],(float)pm[4],(float)pm[8],(float)pm[12]),
+								 new Vector4((float)pm[1],(float)pm[5],(float)pm[9],(float)pm[13]),
+								 new Vector4((float)pm[2],(float)pm[6],(float)pm[10],(float)pm[14]),
+								 new Vector4((float)pm[3],(float)pm[7],(float)pm[11],(float)pm[15])); 
+		
+		Matrix4 m = new Matrix4 (new Vector4((float)mm[0],(float)mm[4],(float)mm[8],(float)mm[12]),
+								 new Vector4((float)mm[1],(float)mm[5],(float)mm[9],(float)mm[13]),
+								 new Vector4((float)mm[2],(float)mm[6],(float)mm[10],(float)mm[14]),
+								 new Vector4((float)mm[3],(float)mm[7],(float)mm[11],(float)mm[15])); 
+		
+		Vector4 normScreen = new Vector4(
+				2f * ( screen.X - vm[0]) / vm[2] - 1f,
+				2f * ( screen.Y - vm[1]) / vm[3] - 1f,
+			 	2f * screen.Z - 1f,
+				1); 
+		Matrix4 p_m = Matrix4.Mult(p, m); 
+		Matrix4 inv_mp = Matrix4.Invert( p_m ); 
+		
+		world.X = inv_mp.Row0.X*normScreen.X+inv_mp.Row0.Y*normScreen.Y+inv_mp.Row0.Z*normScreen.Z+inv_mp.Row0.W;
+		world.Y = inv_mp.Row1.X*normScreen.X+inv_mp.Row1.Y*normScreen.Y+inv_mp.Row1.Z*normScreen.Z+inv_mp.Row1.W; 
+		world.Z = inv_mp.Row2.X*normScreen.X+inv_mp.Row2.Y*normScreen.Y+inv_mp.Row2.Z*normScreen.Z+inv_mp.Row2.W;
+		
+	}
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLAxis.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLAxis.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLAxis.cs	(revision 9102)
@@ -0,0 +1,129 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using OpenTK;
+using OpenTK.Platform;
+using OpenTK.Graphics; 
+using OpenTK.Graphics.OpenGL; 
+using OpenTK.Graphics.OpenGL.Enums; 
+using System.Drawing;
+using ILNumerics.Drawing.Interfaces; 
+using ILNumerics.Drawing.Labeling; 
+using ILNumerics.Drawing; 
+
+namespace ILNumerics.Drawing.Platform.OpenGL {
+    /// <summary>
+    /// OpenGL implementation for ILAxis 
+    /// </summary>
+    public abstract class ILOGLAxis : ILAxis, IDisposable {
+
+        #region attributes
+        private int m_primitivCount;
+        #endregion
+
+        #region constructor
+        internal ILOGLAxis (AxisNames name, ILClippingData clippingView,
+                            ILLayoutData layoutData,
+                            ILOGLPanel panel)
+            : base (name,clippingView,layoutData,panel) {
+            m_invalidated = true;
+            panel.GraphicsDeviceCreated += new ILGraphicsDeviceCreatedEvent(initialize);
+            panel.GraphicsDeviceReset += new ILGraphicsDeviceResetEvent(configure);
+        }
+        #endregion
+
+        #region helper functions
+        private void initialize(object sender, EventArgs eventArgs) {
+            if (m_panel == null || m_panel.GetDeviceContext() == null)
+                return; 
+            Invalidate(); 
+            // todo: setup font + sprite objects for OpenGL ?
+            m_primitivCount = countPrimitves(); 
+            //m_labeledTicks.TextRenderer = m_panel.TextRendererManager.CreateInstance(
+            //            "ILNumerics.Drawing.TextRenderer.ILGDIRenderer" ,null); 
+            //m_label.TextRenderer = m_panel.TextRendererManager.CreateInstance(
+            //            "ILNumerics.Drawing.TextRenderer.ILGDIRenderer" ,null); 
+        }
+
+        void configure(object sender, EventArgs eventArgs) {
+        }
+
+#if DEBUG
+        private void debub_write_mat(string prefix) {
+            double[] modmat = new double[16]; 
+            GL.GetDouble(GetPName.ProjectionMatrix,modmat); 
+            System.Diagnostics.Debug.Write(prefix + new ILArray<double>(modmat,4,4).ToString()); 
+        }
+#endif
+
+        protected void ConfigureOGLLineProperties(LineStyle style, int width) { 
+            int stipFact = 0; 
+            short stipple = ILPanel.StippleFromLineStyle(style,ref stipFact); 
+            GL.LineWidth(width); 
+            if (style == LineStyle.Solid || style == LineStyle.None) {
+                GL.Disable(EnableCap.LineStipple); 
+            } else {
+                GL.Enable(EnableCap.LineStipple); 
+                GL.LineStipple (stipFact,stipple); 
+            }
+        }
+        #endregion 
+
+        #region ILAxis abstract overrides
+        public override void Dispose()
+        {
+            m_invalidated = true;
+            base.Dispose();
+        }
+
+        public override void PrepareMeshes(ILRenderProperties p) {
+            return; 
+        }
+
+        public override void PrepareLabels(ILRenderProperties p) {
+            return; 
+        }
+
+        #endregion
+         
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLBitmapMarkerShape.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLBitmapMarkerShape.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLBitmapMarkerShape.cs	(revision 9102)
@@ -0,0 +1,136 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing; 
+using ILNumerics.Drawing.Marker; 
+using ILNumerics.Drawing; 
+using OpenTK.Graphics; 
+using ILNumerics.Drawing.Labeling; 
+using ILNumerics.Drawing.Shapes; 
+
+
+namespace ILNumerics.Drawing.Platform.OpenGL {
+    public class ILOGLBitmapMarkerShape : ILBitmapMarkerShape {
+
+        #region constructors
+        internal ILOGLBitmapMarkerShape(ILPanel panel, Bitmap bitmap) 
+            : base(panel,bitmap) {}
+        #endregion
+
+        #region public interface
+        internal override void Draw(ILRenderProperties p, ILMarker marker, C4bV3f[] vertices, int startID, int vertCount) {
+            if (vertCount == 0 && vertCount != -1) return; 
+            string texKey = Hash();                
+            ILTextureData texData; 
+            if (!m_panel.TextureManager.Exists(texKey)) {
+                storeBitmap(m_bitmap);
+            }
+            texData = m_panel.TextureManager.GetTextureItem(texKey,true); 
+    System.Diagnostics.Debug.Assert(texData != null,"The texture key for the bitmap was expected to exist in texture storage, but it was not found!"); 
+            // prepare for plotting
+            GL.Color3(marker.Color); 
+            GL.PushAttrib(AttribMask.AllAttribBits);
+
+            GL.Enable(EnableCap.Texture2D);
+            GL.Enable(EnableCap.Blend);
+            GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
+            GL.Disable(EnableCap.DepthTest);
+            RectangleF rectF = texData.TextureRectangle; 
+            float w,h;
+            if (vertCount > 0) {
+                #region draw textured points (slow version: textured quads)
+                #region determine size for markers in world coords (graph limits)
+                ILClippingData clip = m_panel.Limits; 
+                float s05x; 
+                float s05y; 
+                //if (m_marker.)
+                s05x = Math.Abs(marker.Size * clip.WidthF / (m_panel.ClientSize.Width)); 
+                s05y = Math.Abs(marker.Size * clip.HeightF / (m_panel.ClientSize.Height)); 
+
+                #endregion
+                // draw all markers using quads. 
+                // this is slow! Todo: replace by point sprites! 
+                GL.Begin(BeginMode.Quads); 
+                for (int i = 0; i < vertCount; i++) {
+                    w = vertices[i].Position.X; 
+                    h = vertices[i].Position.Y;           
+                    if (m_panel.ClipViewData && (w < clip.XMin || w > clip.XMax || h < clip.YMin || h > clip.YMax)) 
+                        continue; 
+                    w -= s05x;             
+                    h -= s05y; 
+                    GL.TexCoord2(rectF.Left,rectF.Bottom);              
+                    GL.Vertex2(w,h);                                        // ul
+                    GL.TexCoord2(rectF.Left,rectF.Top);                 
+                    GL.Vertex2(w,h + 2 * s05y);                             // bl
+                    w += 2 * s05x;                                
+                    GL.TexCoord2(rectF.Right,rectF.Top);                
+                    GL.Vertex2(w,h + 2 * s05y);                             // br
+                    GL.TexCoord2(rectF.Right,rectF.Bottom);             
+                    GL.Vertex2(w,h);                                        // tr
+                }
+                GL.End(); 
+                #endregion
+            } else if (vertCount == -1) {
+                #region render to legend 
+                // draw all markers using quads. 
+                // this is slow! Todo: replace by point sprites! 
+                GL.Begin(BeginMode.Quads); 
+                    w = vertices[0].XPosition - m_bitmap.Width / 2; 
+                    h = vertices[0].YPosition - m_bitmap.Height / 2;           
+                    GL.TexCoord2(rectF.Left,rectF.Top);              
+                    GL.Vertex2(w,h);                                        // ul
+                    GL.TexCoord2(rectF.Left,rectF.Bottom);                 
+                    GL.Vertex2(w,h + m_bitmap.Height);                      // bl
+                    w += m_bitmap.Width;                                
+                    GL.TexCoord2(rectF.Right,rectF.Bottom);                
+                    GL.Vertex2(w,h + m_bitmap.Height);                      // br
+                    GL.TexCoord2(rectF.Right,rectF.Top);             
+                    GL.Vertex2(w,h);                                        // tr
+                GL.End(); 
+                #endregion
+            }
+            GL.PopAttrib();
+        }
+
+        #endregion
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLImageSCGraph.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLImageSCGraph.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLImageSCGraph.cs	(revision 9102)
@@ -0,0 +1,279 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Drawing; 
+using ILNumerics.Exceptions; 
+using OpenTK; 
+using OpenTK.Graphics; 
+using OpenTK.Graphics.OpenGL;
+using OpenTK.Graphics.OpenGL.Enums; 
+using ILNumerics.Drawing.Graphs;
+using ILNumerics.Drawing.Misc;
+using ILNumerics.Misc;   
+using VERTEXTYPEDEF = ILNumerics.Drawing.Platform.OpenGL.ILOGLImageSCGraph.VertexC4V2; 
+
+namespace ILNumerics.Drawing.Platform.OpenGL {
+    /// <summary>
+    /// OpenGL implementation for ILImageSCGraph
+    /// </summary>
+    public class ILOGLImageSCGraph : ILImageSCGraph {
+
+        #region attributes
+        protected VERTEXTYPEDEF[] m_vertices;
+        #endregion
+
+        #region vertex definition
+        /// <summary>
+        /// Vertex definition: 4Color (uint), 2 Vertex (float)
+        /// </summary>
+        [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
+        [System.Diagnostics.DebuggerDisplay("RGBA:{CR},{CG},{CB},{CA} (X,Y)=({Vx},{Vy})", Name="Vertex")]
+        public struct VertexC4V2 {
+            public byte CR;
+            public byte CG;
+            public byte CB; 
+            public byte CA; 
+            public float Vx; 
+            public float Vy; 
+        }
+        #endregion
+
+        #region constructors 
+        internal ILOGLImageSCGraph(ILOGLPanel panel, ILArray<float> X,
+                                  ILArray<float> Y, ILArray<float> Z, ILArray<float> C,
+                                 ILClippingData clippingContainer)
+            : base(panel, X, Y, Z, C, clippingContainer) {
+            using (ILScope.Enter(X, Y, Z, C)) {
+                m_panel = panel;
+                m_localClipping.ZMax = 0;
+                m_localClipping.ZMin = 0;
+                m_localClipping.XMax = (float)m_cols + 0.5f;
+                m_localClipping.XMin = -0.5f;
+                m_localClipping.YMax = (float)m_rows + 0.5f;
+                m_localClipping.YMin = -0.5f;
+            }
+        }
+        #endregion 
+
+        #region helper functions
+        protected override void CreateVertices() {
+            ILColormap colormap = m_panel.Colormap;  
+            if (m_vertices == null) {
+                m_vertices = ILMemoryPool.Pool.New<VERTEXTYPEDEF>(m_Vertcount); 
+            }
+            float val = 0.0f; 
+            float minZ = m_sourceArray.MinValue; 
+            float maxZ = m_sourceArray.MaxValue; 
+            float a = colormap.Length / (maxZ - minZ);
+            byte ca = (byte)(m_opacity * 255); 
+            VERTEXTYPEDEF curVertex; int i = 0; 
+            // first row is special (no color, just for grid)
+            for (int c = 0; c < m_cols-1; c++) {
+                curVertex = new VERTEXTYPEDEF(); 
+                curVertex.Vx = c-0.5f; 
+                curVertex.Vy = -0.5f; 
+                curVertex.CA = ca; 
+                val = m_sourceArray.GetValue(0,c); 
+                colormap.Map((val - minZ) * a,
+                    out curVertex.CR, out curVertex.CG,out curVertex.CB); 
+                m_vertices[i++] = curVertex;  
+            }
+            // right corner
+            curVertex = new VERTEXTYPEDEF(); 
+            curVertex.Vx = m_cols-1.5f; 
+            curVertex.Vy = -0.5f; 
+            curVertex.CA = ca; 
+            colormap.Map((val - minZ) * a,
+                out curVertex.CR, out curVertex.CG,out curVertex.CB); 
+            m_vertices[i++] = curVertex;  
+            for (int r = 0; r < m_rows-1; r++) {
+                // first col part is special (no color)
+                curVertex = new VERTEXTYPEDEF(); 
+                curVertex.Vx = -0.5f; 
+                curVertex.Vy = r+0.5f; 
+                curVertex.CA = ca; 
+                colormap.Map((m_sourceArray.GetValue(r,0) - minZ) * a,
+                    out curVertex.CR, out curVertex.CG,out curVertex.CB); 
+                m_vertices[i++] = curVertex;  
+                for (int c = 0; c < m_cols-1; c++) {
+                    curVertex = new VERTEXTYPEDEF(); 
+                    val = m_sourceArray.GetValue(r,c);
+                    // set color values 
+                    colormap.Map((val- minZ) * a,
+                        out curVertex.CR, out curVertex.CG,out curVertex.CB); 
+                    curVertex.CA = ca; 
+                    curVertex.Vx = c+0.5f; 
+                    curVertex.Vy = r+0.5f; 
+                    m_vertices[i++] = curVertex; 
+                }
+            }
+            m_vertexReady = true;
+        }
+        protected override void m_globalClipping_Changed(object sender, ClippingChangedEventArgs e) {
+            base.m_globalClipping_Changed(sender, e);
+            //m_vertexReady = false; 
+            //m_indexReady = false; 
+        }
+        #endregion
+
+        #region public interface 
+        /// <summary>
+        /// Draws the graph into existing context
+        /// </summary>
+        public override void Draw(ILRenderProperties p) {
+            if (m_panel.Camera.Rho > Math.PI/2) return; 
+            if (!m_isReady)
+                Configure(); 
+            float zPos = m_zPosition; 
+            if (zPos == float.PositiveInfinity) {
+                zPos = m_panel.Limits.ZMax;
+            } else if (zPos == float.NegativeInfinity) {
+                zPos = m_panel.Limits.ZMin;
+            }
+            GL.Translate(0.0f, 0.0f, zPos); 
+            GL.Enable(EnableCap.Blend); 
+            GL.Disable(EnableCap.DepthTest); 
+            GL.BlendFunc (BlendingFactorSrc.SrcAlpha,
+                          BlendingFactorDest.OneMinusSrcAlpha);            
+            GL.ShadeModel(ShadingModel.Flat); 
+            unsafe {
+                fixed (VERTEXTYPEDEF* pVertices = m_vertices) {
+                    GL.InterleavedArrays(
+                           InterleavedArrayFormat.C4ubV2f,0,(IntPtr)pVertices); 
+                    if (m_filled) {
+                        fixed (UInt32* pIndices = m_indices) {
+                            for (int i = 0; i < m_stripesCount; i++) {
+                                GL.DrawElements(BeginMode.Triangles,m_stripesLen,
+                                    DrawElementsType.UnsignedInt,
+                                    (IntPtr)(pIndices+i*m_stripesLen));
+                            }
+                            GL.Finish();
+                        }
+                    }
+                    #region draw grid
+                    if (m_wireLines.Visible) {
+                        if (m_wireLines.Style == LineStyle.Solid) {
+                            GL.Disable(EnableCap.LineStipple);
+                        } else {
+                            int stipFactr = 1;  
+                            short stipple; 
+                            if (m_wireLines.Style != LineStyle.UserPattern) 
+                                stipple = ILPanel.StippleFromLineStyle(
+                                          m_wireLines.Style, ref stipFactr);
+                            else 
+                                stipple = m_wireLines.Pattern; 
+                            GL.Enable(EnableCap.LineStipple);
+                            GL.LineStipple((int)m_wireLines.PatternScale,stipple);
+                        }
+                        if (m_wireLines.Antialiasing)
+                            GL.Enable(EnableCap.LineSmooth);
+                        else
+                            GL.Disable(EnableCap.LineSmooth);
+                        GL.Disable(EnableCap.Blend); 
+                        GL.LineWidth(m_wireLines.Width); 
+                        if (m_wireLines.Color != System.Drawing.Color.Empty) {
+                            GL.DisableClientState(EnableCap.ColorArray);
+                            GL.Color3(m_wireLines.Color); 
+                        } 
+                        fixed (UInt32* pIndices = m_gridIndices) { 
+                            GL.DrawElements(BeginMode.Lines,
+                                        m_gridIndicesCount,
+                                        DrawElementsType.UnsignedInt,
+                                        (IntPtr)pIndices);
+                            GL.Finish();
+                        }
+                    }
+                    #endregion
+                }
+            }
+            GL.Translate(0.0f, 0.0f, -zPos); 
+        }
+        /// <summary>
+        /// Dispose off this graph's vertices
+        /// </summary>
+        public override void Dispose() {
+            base.Dispose(); 
+            if (m_vertices != null) {
+                ILMemoryPool.Pool.Free<VERTEXTYPEDEF>(m_vertices); 
+            }
+        }
+        /// <summary>
+        /// Ensures the recalculation of vertices if neccessary
+        /// </summary>
+        public override void Invalidate() {
+            if (Math.Floor(m_panel.Camera.Phi / (Math.PI / 4.0)) != m_oldSubQuadrant) {    
+                //must only recalculate indices, and only if the camera subquadrant has changed
+                m_indexReady = false; 
+                m_isReady = false; 
+            }
+        }
+        public override void DrawToLegend(ILRenderProperties p, Rectangle sampleRect, Rectangle labelRect) {
+            if (m_filled) {
+                // draw inner filled area
+                GL.ShadeModel(ShadingModel.Smooth); 
+                GL.Begin(BeginMode.TriangleStrip); 
+                    GL.Color3(m_panel.Colormap[m_panel.Colormap.Length-1]); 
+                    GL.Vertex2(sampleRect.X,sampleRect.Y + sampleRect.Height); 
+                    GL.Color3(m_panel.Colormap[(int)(m_panel.Colormap.Length/2)]); 
+                    GL.Vertex2(sampleRect.X,sampleRect.Y); 
+                    GL.Vertex2(sampleRect.X+sampleRect.Width,sampleRect.Y + sampleRect.Height); 
+                    GL.Color3(m_panel.Colormap[0]); 
+                    GL.Vertex2(sampleRect.X+sampleRect.Width,sampleRect.Y); 
+                GL.End(); 
+            } 
+            if (m_wireLines.Visible) {
+                ILNumerics.Drawing.Platform.OpenGL.ILOGLPanel.SetupLineStyle(m_wireLines); 
+                GL.Begin(BeginMode.LineStrip); 
+                    GL.Vertex2(sampleRect.X,sampleRect.Y); 
+                    GL.Vertex2(sampleRect.X+sampleRect.Width,sampleRect.Y); 
+                    GL.Vertex2(sampleRect.X+sampleRect.Width,sampleRect.Y + sampleRect.Height); 
+                    GL.Vertex2(sampleRect.X,sampleRect.Y + sampleRect.Height); 
+                    GL.Vertex2(sampleRect.X,sampleRect.Y); 
+                GL.End(); 
+            }
+            m_label.m_position.X = labelRect.X + labelRect.Width / 2;
+            m_label.m_position.Y = labelRect.Y + labelRect.Height / 2; 
+            m_label.Anchor = new PointF(.5f,.5f);  //  TickLabelAlign.center | TickLabelAlign.vertCenter; 
+            m_label.Draw(p); 
+        }
+        #endregion 
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLLegend.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLLegend.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLLegend.cs	(revision 9102)
@@ -0,0 +1,178 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing; 
+using ILNumerics.Drawing.Labeling; 
+using ILNumerics.Drawing; 
+using ILNumerics.Drawing.Interfaces; 
+using ILNumerics.Drawing.Misc; 
+using ILNumerics.Drawing.Graphs; 
+using OpenTK.Graphics; 
+
+namespace ILNumerics.Drawing.Platform.OpenGL {
+    public class ILOGLLegend : ILLegend {
+
+        #region attributes 
+
+        #endregion
+
+        #region constructor
+        internal ILOGLLegend (ILPanel panel) : base (panel) {}
+        #endregion
+
+        #region abstract overloads 
+        /// <summary>
+        /// draw legend into opengl context
+        /// </summary>
+        /// <param name="p">rendering properties</param>
+        /// <param name="area">area to draw the content into, if g is null, this will be ignored also</param>
+        public override void Draw(ILRenderProperties p, System.Drawing.Rectangle area) {
+            if (!m_visible) return; 
+            // handle drawing to bitmap 
+            if (p.Graphics != null) {
+                base.Draw(p, area);
+                return; 
+            }
+            // draw to OpenGL context
+            if (GraphicsContext.CurrentContext == null)
+                throw new GraphicsContextException("No OpenGL GraphicsContext current is selected for the calling thread.");
+
+            #region set 2D projection   
+            float[] viewport = new float[4]; 
+            GL.GetFloat(GetPName.Viewport, viewport);
+            GL.MatrixMode(MatrixMode.Projection);
+            GL.PushMatrix();     
+            GL.LoadIdentity();
+            GL.Ortho(viewport[0], viewport[2], viewport[3], viewport[1], -1.0, 1.0);
+
+            GL.MatrixMode(MatrixMode.Modelview);
+            GL.PushMatrix();
+            GL.LoadIdentity();
+
+            //GL.PushAttrib(AttribMask.TextureBit | AttribMask.EnableBit | AttribMask.ColorBufferBit);
+
+            //GL.Enable(EnableCap.Texture2D);
+            GL.Enable(EnableCap.Blend);
+            GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
+            
+            GL.Disable(EnableCap.DepthTest);
+            #endregion
+
+            #region draw bounding box + bg
+            Size labelSize = Size.Empty, boxSize = Size.Empty; 
+            Rectangle sampleRect = Rectangle.Empty, labelRect = Rectangle.Empty; 
+            List<IILLegendRenderer> renderer = getRenderers(ref labelSize); 
+            // automatically size the box 
+            boxSize.Width = m_padding.Horizontal+labelSize.Width + 30; // <- default width for sample
+            boxSize.Height = m_padding.Bottom+labelSize.Height+m_padding.Top*renderer.Count; 
+            if (!m_size.IsEmpty) {
+                // prefer given size, with limitations
+                boxSize.Width = Math.Max(boxSize.Width,m_size.Width); 
+                boxSize.Height = Math.Max(boxSize.Height,m_size.Height); 
+            }
+            Point location = Point.Empty; 
+            if (m_location.IsEmpty) {
+                int minx = m_panel.ClientSize.Width - boxSize.Width - m_border.Width * 2;
+                int miny = m_panel.ClientSize.Height - boxSize.Height - m_border.Width * 2; 
+                // by default: place legend at upper right corner
+                location.X = m_panel.ClientSize.Width - boxSize.Width - m_panel.Padding.Right - m_border.Width * 2;
+                if (location.X < 0) location.X = 0;
+                if (location.X > minx) location.X = minx; 
+                location.Y = m_panel.Padding.Top;
+                if (location.Y < 0) location.Y = 0; 
+                if (location.Y > miny) location.Y = miny; 
+            } else 
+                location = new Point((int)(m_location.X * (float)m_panel.ClientSize.Width)
+                            ,(int)(m_location.Y * (float)m_panel.ClientSize.Height)); 
+
+            float offsX = Math.Max(m_border.Width / 2.0f,1.0f); 
+            m_bgColor = Color.FromArgb((int)(m_opacity * 255),m_bgColor); 
+            GL.Color4(m_bgColor);
+            GL.ShadeModel(ShadingModel.Flat); 
+            GL.Begin(BeginMode.Quads); 
+                GL.Vertex2(location.X + offsX,              location.Y + offsX);
+                GL.Vertex2(location.X + boxSize.Width-offsX,location.Y + offsX); 
+                GL.Vertex2(location.X + boxSize.Width-offsX,location.Y + boxSize.Height - offsX); 
+                GL.Vertex2(location.X + offsX,              location.Y + boxSize.Height - offsX);
+                GL.Vertex2(location.X + offsX,              location.Y + offsX); 
+            GL.End(); 
+            
+            ILNumerics.Drawing.Platform.OpenGL.ILOGLPanel.SetupLineStyle(m_border); 
+            GL.Begin(BeginMode.LineStrip); 
+                GL.Vertex2(location.X + offsX,              location.Y + offsX);
+                GL.Vertex2(location.X + boxSize.Width-offsX,location.Y + offsX); 
+                GL.Vertex2(location.X + boxSize.Width-offsX,location.Y + boxSize.Height - offsX); 
+                GL.Vertex2(location.X + offsX,              location.Y + boxSize.Height - offsX);
+                GL.Vertex2(location.X + offsX,              location.Y + offsX); 
+            GL.End(); 
+            #endregion
+            
+            sampleRect.Y = location.Y+m_padding.Top; 
+            sampleRect.Width = boxSize.Width - 2 * m_padding.Right - labelSize.Width; 
+            sampleRect.X = location.X + m_padding.Left; 
+            
+            labelRect.Y = location.Y+m_padding.Top; 
+            labelRect.Width = labelSize.Width; 
+            labelRect.X = sampleRect.Right + m_padding.Right;
+            
+            for (int i = 0; i < renderer.Count; i++) {
+                IILLegendRenderer rend = renderer[i]; 
+                sampleRect.Height = rend.LabelSize.Height; 
+                labelRect.Height = sampleRect.Height; 
+                try {
+                    rend.DrawToLegend(p,sampleRect,labelRect); 
+                } catch (Exception) {}
+                sampleRect.Y = sampleRect.Bottom + m_padding.Top; 
+                labelRect.Y = sampleRect.Y;
+            }
+
+            #region restore previous projection
+            //GL.PopAttrib();
+            GL.MatrixMode(MatrixMode.Modelview);
+            GL.PopMatrix();
+            GL.MatrixMode(MatrixMode.Projection);
+            GL.PopMatrix();
+            #endregion
+        }
+        #endregion
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLLineRendererC4bV3f.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLLineRendererC4bV3f.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLLineRendererC4bV3f.cs	(revision 9102)
@@ -0,0 +1,152 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using ILNumerics.Drawing.Shapes; 
+using OpenTK.Graphics;
+using OpenTK.Graphics.OpenGL; 
+
+namespace ILNumerics.Drawing.Platform.OpenGL {
+    /// <summary>
+    /// An OpenGL vertex renderer, capable of rendering
+    /// vertex arrays of type C4bV3f (simple /-primitive shapes).
+    /// </summary>
+    public unsafe class ILOGLLineRendererC4bV3f : ILVertexRenderer {
+
+        #region attributes
+        uint[] m_closeLoopIndices; 
+        #endregion
+
+        #region properties
+        #endregion
+
+        public ILOGLLineRendererC4bV3f (int numVertices) {
+            CloseLines = false; 
+            m_closeLoopIndices = new uint[2] {(uint)numVertices-1,0}; 
+        }
+        public override void Draw(ILRenderProperties props, ILShape shape) {
+            GL.Enable(EnableCap.Blend);
+            GL.BlendFunc (BlendingFactorSrc.SrcAlpha,
+                          BlendingFactorDest.OneMinusSrcAlpha); 
+            GL.Enable(EnableCap.DepthTest);
+            ILLine line = (shape as ILLine);
+            if (line != null && line.Border.Visible) {
+                fixed (C4bV3f* pVertices = line.Vertices) {
+                    ILOGLPanel.SetupLineStyle(line.Border);
+                    GL.InterleavedArrays(InterleavedArrayFormat.C4ubV3f, 0, (IntPtr)pVertices);
+                    GL.DisableClientState(EnableCap.ColorArray);
+                    if (line.OldestVertexID == 0) {
+                        GL.DrawArrays(BeginMode.LineStrip, 0, line.VertexCount);
+                    } else {
+                        GL.DrawArrays(BeginMode.LineStrip, line.OldestVertexID, line.VertexCount - line.OldestVertexID);
+                        GL.DrawElements(BeginMode.Lines,2,DrawElementsType.UnsignedInt, m_closeLoopIndices);
+                        GL.DrawArrays(BeginMode.LineStrip, 0, line.OldestVertexID);
+                    }
+                }
+            }
+            GL.Disable(EnableCap.DepthTest);
+            ILOGLPanel.SetupLineStyle(line.Properties);
+            fixed (C4bV3f* pVertices = line.Vertices) {
+                GL.InterleavedArrays(InterleavedArrayFormat.C4ubV3f, 0, (IntPtr)pVertices);
+                if (line.Shading == ShadingStyles.Interpolate)
+                    GL.ShadeModel(ShadingModel.Smooth);
+                else {
+                    GL.ShadeModel(ShadingModel.Flat);
+                    GL.DisableClientState(EnableCap.ColorArray);
+                    GL.Color4(line.FillColor);  
+                }
+                if (line.OldestVertexID == 0) {
+                    GL.DrawArrays(BeginMode.LineStrip, 0, line.VertexCount);
+                } else {
+                    GL.DrawArrays(BeginMode.LineStrip, line.OldestVertexID, line.VertexCount - line.OldestVertexID);
+                    GL.DrawElements(BeginMode.Lines, 2, DrawElementsType.UnsignedInt, m_closeLoopIndices);
+                    GL.DrawArrays(BeginMode.LineStrip, 0, line.OldestVertexID);
+                }
+            }
+
+        }
+        public override void Draw(ILRenderProperties props, ILShape shape, int[] indices) {
+            System.Diagnostics.Debug.Assert(indices != null && indices != null); 
+            GL.Enable(EnableCap.DepthTest);
+            GL.Disable(EnableCap.Blend); 
+            ILBorderedShape<C4bV3f> bShape = (shape as ILBorderedShape<C4bV3f>); 
+            if (bShape != null && bShape.Border.Visible) {
+                fixed (int* pIndices = indices) 
+                fixed (C4bV3f* pVertices = bShape.Vertices) {
+                    ILOGLPanel.SetupLineStyle(bShape.Border);
+                    GL.InterleavedArrays(
+                                    InterleavedArrayFormat.C4ubV3f, 0, (IntPtr)pVertices);
+                    GL.DisableClientState(EnableCap.ColorArray);
+                    if (CloseLines)
+                        GL.DrawElements(BeginMode.LineLoop, indices.Length, 
+                                    DrawElementsType.UnsignedInt, (IntPtr)pIndices);
+                    else 
+                        GL.DrawElements(BeginMode.LineStrip, indices.Length, 
+                                    DrawElementsType.UnsignedInt, (IntPtr)pIndices);
+                }
+            }
+            
+            GL.Enable(EnableCap.Blend);
+            GL.BlendFunc (BlendingFactorSrc.SrcAlpha,
+                          BlendingFactorDest.OneMinusSrcAlpha); 
+            ILShape<C4bV3f> cShape = (shape as ILShape<C4bV3f>);
+            if (cShape is ILLine) {
+                ILOGLPanel.SetupLineStyle((cShape as ILLine).Properties);
+                GL.Disable(EnableCap.DepthTest); 
+            } else {
+                GL.Disable(EnableCap.LineSmooth);
+            }
+            fixed (int* pIndices = indices) 
+            fixed (C4bV3f* pVertices = cShape.Vertices) {
+                GL.InterleavedArrays(InterleavedArrayFormat.C4ubV3f, 0, (IntPtr)pVertices);
+                if (cShape.Shading == ShadingStyles.Interpolate)
+                    GL.ShadeModel(ShadingModel.Smooth);
+                else {
+                    GL.ShadeModel(ShadingModel.Flat);
+                    GL.DisableClientState(EnableCap.ColorArray);
+                    GL.Color4(shape.FillColor); 
+                }
+                GL.DrawElements(BeginMode.LineStrip, indices.Length,
+                                DrawElementsType.UnsignedInt, (IntPtr)pIndices);
+            }
+
+        }
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLLinesRendererC4bV3f.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLLinesRendererC4bV3f.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLLinesRendererC4bV3f.cs	(revision 9102)
@@ -0,0 +1,108 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using ILNumerics.Drawing.Shapes; 
+using OpenTK.Graphics;
+using OpenTK.Graphics.OpenGL; 
+
+namespace ILNumerics.Drawing.Platform.OpenGL {
+    /// <summary>
+    /// An OpenGL vertex renderer, capable of rendering
+    /// vertex arrays of type C4bV3f (simple /-primitive shapes).
+    /// </summary>
+    public unsafe class ILOGLLinesRendererC4bV3f : ILVertexRenderer {
+
+        #region attributes
+        #endregion
+
+        #region properties
+        #endregion
+
+        public ILOGLLinesRendererC4bV3f () {
+            CloseLines = false; 
+        }
+        public override void Draw(ILRenderProperties props, ILShape shape) {
+            GL.Enable(EnableCap.Blend);
+            GL.BlendFunc (BlendingFactorSrc.SrcAlpha,
+                          BlendingFactorDest.OneMinusSrcAlpha); 
+            GL.Enable(EnableCap.DepthTest);
+            ILLines lines = (shape as ILLines);
+            ILOGLPanel.SetupLineStyle(lines.Properties);
+            fixed (C4bV3f* pVertices = lines.Vertices) {
+                GL.InterleavedArrays(InterleavedArrayFormat.C4ubV3f, 0, (IntPtr)pVertices);
+                if (lines.Shading == ShadingStyles.Interpolate)
+                    GL.ShadeModel(ShadingModel.Smooth);
+                else {
+                    GL.ShadeModel(ShadingModel.Flat);
+                    GL.DisableClientState(EnableCap.ColorArray);
+                    GL.Color4(lines.FillColor);  
+                }
+                GL.DrawArrays(BeginMode.LineStrip, 0, lines.VertexCount);
+            }
+
+        }
+        public override void Draw(ILRenderProperties props, ILShape shape, int[] indices) {
+            System.Diagnostics.Debug.Assert(indices != null); 
+            GL.Enable(EnableCap.DepthTest);
+            GL.Enable(EnableCap.Blend);
+            GL.BlendFunc (BlendingFactorSrc.SrcAlpha,
+                          BlendingFactorDest.OneMinusSrcAlpha); 
+            ILShape<C4bV3f> cShape = (shape as ILShape<C4bV3f>);
+            if (cShape is ILLines) {
+                ILOGLPanel.SetupLineStyle((cShape as ILLines).Properties);
+                GL.Disable(EnableCap.DepthTest); 
+            } 
+            fixed (int* pIndices = indices) 
+            fixed (C4bV3f* pVertices = cShape.Vertices) {
+                GL.InterleavedArrays(InterleavedArrayFormat.C4ubV3f, 0, (IntPtr)pVertices);
+                if (cShape.Shading == ShadingStyles.Interpolate)
+                    GL.ShadeModel(ShadingModel.Smooth);
+                else {
+                    GL.ShadeModel(ShadingModel.Flat);
+                    GL.DisableClientState(EnableCap.ColorArray);
+                }
+                GL.DrawElements(BeginMode.Lines, indices.Length,
+                                DrawElementsType.UnsignedInt, (IntPtr)pIndices);
+            }
+
+        }
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLPanel.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLPanel.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLPanel.cs	(revision 9102)
@@ -0,0 +1,879 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.Windows.Forms;
+using System.Diagnostics; 
+using ILNumerics.Exceptions;
+using ILNumerics.Drawing; 
+using ILNumerics.Drawing.Graphs;
+using ILNumerics.Drawing.Lighting; 
+using ILNumerics.Drawing.Interfaces;
+using OpenTK.Graphics;
+using OpenTK.Platform; 
+using OpenTK;
+using OpenTK.Math; 
+using ILNumerics.Drawing.Shapes; 
+using System.Linq; 
+ 
+namespace ILNumerics.Drawing.Platform.OpenGL {
+    /// <summary>
+    /// OpenGL implementation for ILPanel
+    /// </summary>
+    internal partial class ILOGLPanel : ILPanel, IILCreationFactory{
+
+        #region members / properties 
+        bool m_mustReconfigureLight = true; 
+        GraphicsMode m_format;
+        IWindowInfo m_window_info;
+        IGraphicsContext m_context;
+        IGLControl m_implementation; 
+        private const float Sqrt2 = 1.4142135623730950488016887242097f;
+        double[] m_projMatrix = new double[16]; 
+        double[] m_modelViewMatrix = new double[16];
+        int[] m_viewMatrix = new int[16]; 
+        float[] m_selectionVertices = new float[32];  // V2F format, interleaved
+        int m_errorCount = 0; 
+        private readonly int MAXERRORLOGCOUNT = 100; 
+        protected bool m_polyOffsetEnable = true;
+        /// <summary>
+        /// Gets an interface to the underlying GraphicsContext used by this GLControl.
+        /// </summary>
+        public override object GetDeviceContext() {
+            return m_context; 
+        }
+
+        internal double[] ProjectionMatrix {
+            get {
+                return m_projMatrix; 
+            }
+        }
+        internal double[] ModelviewMatrix {
+            get {
+                return m_modelViewMatrix; 
+            }
+        }
+        internal int[] ViewMatrix {
+            get {
+                return m_viewMatrix; 
+            }
+        }
+
+        /// <summary>
+        /// Control polygon offset ([on]/off)
+        /// </summary>
+        public bool PolyOffsetEnable {
+            get {
+                return m_polyOffsetEnable;
+            }
+            set {
+                m_polyOffsetEnable = value; 
+            }
+        }
+
+        #endregion private members
+
+        #region constructors 
+ 
+        internal ILOGLPanel() : base( GraphicDeviceType.OpenGL ) {
+#if TRACE 
+            Trace.TraceInformation("{0},{1} ILOGLPanel.ctor(mode) start",DateTime.Now, Environment.TickCount); 
+            Trace.Indent(); 
+#endif
+
+            this.SetStyle(ControlStyles.Opaque, true);
+            this.SetStyle(ControlStyles.UserPaint, true);
+            this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
+            m_format = GraphicsMode.Default;
+
+            if (Configuration.RunningOnWindows)
+                m_implementation = new OpenTK.Platform.Windows.WinGLControl(m_format, this);
+            else if (Configuration.RunningOnX11)
+                m_implementation = new OpenTK.Platform.X11.X11GLControl(m_format, this);
+            else if (Configuration.RunningOnOSX)
+                throw new PlatformNotSupportedException("Refer to http://www.opentk.com for more information.");
+
+            this.CreateControl();
+
+#if TRACE 
+            Trace.Unindent(); 
+            Trace.TraceInformation("{0},{1} ILPanel.ctor(mode) end",DateTime.Now, Environment.TickCount); 
+#endif
+        }
+
+        #endregion
+
+        #region panel setup / destroy 
+
+        /// <summary>
+        /// will get called after the handle has been created
+        /// </summary>
+        /// <param name="e"></param>
+        protected override void OnHandleCreated(EventArgs e) {
+            base.OnHandleCreated(e);
+            if (DesignMode)
+                m_context = new DummyGLContext(null);
+            else
+                m_context = m_implementation.CreateContext();
+
+            m_window_info = m_implementation.WindowInfo;
+            this.MakeCurrent();
+            ((IGraphicsContextInternal)m_context).LoadAll();
+            OnGraphicsDeviceCreated(); 
+        }
+        /// <summary>
+        /// gets called, after the handle has been destroyed
+        /// </summary>
+        /// <param name="e"></param>
+        protected override void OnHandleDestroyed(EventArgs e)
+        {
+            base.OnHandleDestroyed(e);
+            if (m_context != null)
+            {
+                m_context.Dispose();
+                m_context = null;
+            }
+            m_window_info = null;
+        }
+        /// <summary>
+        /// Dispose off the panels resources
+        /// </summary>
+        /// <param name="disposing"></param>
+        protected override void Dispose(bool disposing) {
+            m_active = false;
+            base.Dispose(disposing);
+            if (disposing) {
+                // he ? 
+            }
+            if (m_context != null && disposing) {
+                m_context.Dispose();
+                m_context = null;
+            }
+        }
+
+        #endregion
+
+        #region rendering related        
+
+        /// <summary>
+        /// set up viewport, projection and modelview matrices
+        /// </summary>
+        protected override void UpdateMatrices(float width2D, float height2D, float zDepth) {
+            if (ClientSize.IsEmpty) return;
+            if (m_plotBoxScreenRectF.Size.IsEmpty) return;
+
+            float worldSceneWidth;
+            float worldSceneHeight;
+//            ILPoint3Df camPos = m_camera.Position;
+            ILPoint3Df top;
+            ILPoint3Df moveOffset;
+            helperUpdateMatrices(width2D, height2D, out worldSceneWidth, out worldSceneHeight, out top, out moveOffset);
+            
+            #region projection 
+            GL.MatrixMode(MatrixMode.Projection); 
+            GL.LoadIdentity();
+
+            float nearPlane = 0f; // Math.Max(0.0f, m_camera.Distance - m_clippingView.SphereRadius);
+            float farPlane = m_camera.Distance + m_clippingView.SphereRadius * 100;
+            if (m_projection == Projection.Perspective) {
+                float angle = (float)Math.Atan2(worldSceneHeight / 2.0f, m_camera.Distance - (zDepth / 2)) * 2.0f;
+                Glu.Perspective(angle / Math.PI * 180, (double)worldSceneWidth / worldSceneHeight,
+                    nearPlane, farPlane);
+            } else {
+                GL.Ortho(
+                      -worldSceneWidth / 2.0, worldSceneWidth / 2.0
+                    , -worldSceneHeight / 2.0, worldSceneHeight / 2.0
+                    , nearPlane, farPlane);
+            }
+            GL.GetDouble(GetPName.ProjectionMatrix,m_projMatrix);
+            // set viewport 
+            GL.Viewport(0,0,ClientSize.Width,ClientSize.Height);
+            GL.GetInteger(GetPName.Viewport,m_viewMatrix);
+            #endregion
+
+            #region modelview
+            GL.MatrixMode(MatrixMode.Modelview);
+            GL.LoadIdentity();
+			ILGLU.LookAt (m_camera.Position, m_camera.LookAt, m_camera.Top, moveOffset); 
+			
+//            Glu.LookAt(camPos.X, camPos.Y, camPos.Z
+//                      , m_camera.LookAt.X, m_camera.LookAt.Y, m_camera.LookAt.Z
+//                      , m_camera.Top.X, m_camera.Top.Y, m_camera.Top.Z);
+//            GL.Translate(moveOffset.X,moveOffset.Y,moveOffset.Z); 
+            
+			GL.GetDouble(GetPName.ModelviewMatrix, m_modelViewMatrix);
+			//Console.Out.WriteLine("Camera: {0} || Top: {1} \n m_modelViewMatr:{2}",m_camera.ToString(), m_camera.Top.ToString(), String.Join(", ", m_modelViewMatrix)); 
+			//Console.Out.WriteLine("Camera: {0} || Top: {1} \n m_modelViewMatr:{2}",m_camera.ToString(), m_camera.Top.ToString(), String.Join(", ", m_modelViewMatrix)); 
+            #endregion
+
+        }
+
+        protected override void iRenderingState1(ILRenderProperties p) {
+            MakeCurrent();
+        }
+        /// <summary>
+        /// Render the OpenGL scene
+        /// </summary>
+        /// <param name="g"></param>
+        protected override void iRenderingState2(ILRenderProperties p) {
+
+            if (m_context == null || (!m_active && !m_drawHidden))
+                return;
+            try {
+                //System.Diagnostics.Debug.WriteLine(String.Format("ILOGLPanel{0}: RenderScene, Thread={1}"
+                //        ,this.GetHashCode(), System.Threading.Thread.CurrentThread.GetHashCode())); 
+                // draw background
+                GL.ClearColor(m_backColor);
+                GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
+                // draw back axis
+                GL.Enable(EnableCap.DepthTest); 
+                if (m_fillBackground)
+                    renderBackground(); 
+                GL.Enable(EnableCap.Blend);
+                //GL.MatrixMode(MatrixMode.Modelview);
+                //GL.PushMatrix();
+                if (m_polyOffsetEnable) {
+                    GL.Enable(EnableCap.PolygonOffsetFill); 
+                } else {
+                    GL.Disable(EnableCap.PolygonOffsetFill); 
+                }
+                GL.PolygonOffset(1.0f,1.0f);
+                GL.Disable(EnableCap.Blend); 
+                m_axes.XAxis.RenderState1(p);
+                m_axes.YAxis.RenderState1(p);
+                if (m_camera.SinRho > 1e-5)
+                    m_axes.ZAxis.RenderState1(p);
+
+                if ((m_plotBoxScreenSizeMode != PlotBoxScreenSizeMode.StrictOptimal)
+                    || (p.PassCount > 0)) {
+
+                    #region enable clipping planes
+                    if (m_renderProperties.Clipping) {
+                        unsafe {
+                            fixed (double* pClip = m_clipplanes) {
+                                if (m_clippingView.WidthF > 0) {
+                                    GL.ClipPlane(ClipPlaneName.ClipPlane0, pClip);
+                                    GL.ClipPlane(ClipPlaneName.ClipPlane1, pClip + 4);
+                                    GL.Enable(EnableCap.ClipPlane0);
+                                    GL.Enable(EnableCap.ClipPlane1);
+                                }
+                                if (m_clippingView.HeightF > 0) {
+                                    GL.ClipPlane(ClipPlaneName.ClipPlane2, pClip + 8);
+                                    GL.ClipPlane(ClipPlaneName.ClipPlane3, pClip + 12);
+                                    GL.Enable(EnableCap.ClipPlane2);
+                                    GL.Enable(EnableCap.ClipPlane3);
+                                }
+                                if (m_clippingView.DepthF > 0) {
+                                    GL.ClipPlane(ClipPlaneName.ClipPlane4, pClip + 16);
+                                    GL.ClipPlane(ClipPlaneName.ClipPlane5, pClip + 20);
+                                    GL.Enable(EnableCap.ClipPlane4);
+                                    GL.Enable(EnableCap.ClipPlane5);
+                                }
+                            }
+                        }
+                    }
+                    #endregion
+                    // draw all graphs
+                    //GL.MatrixMode(MatrixMode.Modelview);
+                    //ILPoint3Df ab = m_clippingView.CenterToUnitCube();
+                    //GL.Translate(ab.X, ab.Y, ab.Z);
+                    //ab = m_clippingView.ScaleToUnitCube();
+                    //GL.Scale(ab.X, ab.Y, ab.Z); //Identity; //RotationZ(m_cameraPhi); 
+
+                    #region lighting
+                    if (m_mustReconfigureLight) {
+                        m_mustReconfigureLight = false;
+                        if (m_lights.Enabled) {
+                            float[] tmpF = new float[4]; tmpF[3] = 1.0f;
+                            foreach (ILLight light in m_lights) {
+                                EnableCap lightID = EnableCap.Light0 + light.Index;
+                                if (!light.Enabled) {
+                                    GL.Disable(lightID);
+                                    continue;
+                                }
+                                GL.Enable(lightID);
+                                tmpF[0] = light.Position.X;
+                                tmpF[1] = light.Position.Y;
+                                tmpF[2] = light.Position.Z;
+                                GL.Lightv((LightName)lightID, LightParameter.Position, tmpF);
+                                tmpF[0] = (float)light.Ambient.R / 255;
+                                tmpF[1] = (float)light.Ambient.G / 255;
+                                tmpF[2] = (float)light.Ambient.B / 255;
+                                GL.Lightv((LightName)lightID, LightParameter.Ambient, tmpF);
+                                tmpF[0] = (float)light.Specular.R / 255;
+                                tmpF[1] = (float)light.Specular.G / 255;
+                                tmpF[2] = (float)light.Specular.B / 255;
+                                GL.Lightv((LightName)lightID, LightParameter.Specular, tmpF);
+                                tmpF[0] = (float)light.Diffuse.R / 255;
+                                tmpF[1] = (float)light.Diffuse.G / 255;
+                                tmpF[2] = (float)light.Diffuse.B / 255;
+                                GL.Lightv((LightName)lightID, LightParameter.Diffuse, tmpF);
+                            }
+                        }
+                    }
+                    #endregion
+
+                    #region graph rendering
+                    // Easy sorting - this expects a few graphs in the collection only.
+                    // For situations, where a large number of graphs need to be sorted here, 
+                    // one may implement sorting in the way it is done in ILSceneGraph 
+                    // (via ILNumerics.ILArray and ILMath.sort). 
+                    
+                    //m_graphs.Sort(new ILNumerics.Drawing.Misc.ILGraphComparer());
+                    m_sortingCacheList.Clear(); 
+                    m_graphs.GetSortedList4Render(m_camera, m_sortingCacheList);
+                    foreach (ILGraph graph in m_sortingCacheList) {
+                        try {
+                            graph.Draw(p);
+                        } catch (Exception e) {
+#if TRACE
+                        m_errorCount++;
+ 
+                        if (m_errorCount < MAXERRORLOGCOUNT) {
+                            System.Diagnostics.Trace.TraceError(String.Format("[{0}].Draw() failed: {1}",graph.GetType().Name,e.ToString()));       
+                        } else if (m_errorCount == MAXERRORLOGCOUNT) {
+                            System.Diagnostics.Trace.TraceError(String.Format("(more than {0} errors. Further reporting disabled.)",m_errorCount)); 
+                        }
+#endif
+                        if (m_errorCount < 3) {
+                            MessageBox.Show(e.Message, "ILNumerics.Drawing");
+                        }
+
+                        }
+                    }
+                    #endregion
+
+                    #region world label test, please delete me
+                    //ILNumerics.Drawing.Labeling.ILLabel label = new ILNumerics.Drawing.Labeling.ILLabel(this); 
+                    //label.Position = new Point(0,0); 
+                    //label.Text = "World"; 
+                    //label.Renderer = TextRendererManager.GetDefault(CoordSystem.World3D); 
+                    //label.Draw(g); 
+                    #endregion
+
+                    #region disable clipping planes
+                    GL.Disable(EnableCap.ClipPlane0);
+                    GL.Disable(EnableCap.ClipPlane1);
+                    GL.Disable(EnableCap.ClipPlane2);
+                    GL.Disable(EnableCap.ClipPlane3);
+                    GL.Disable(EnableCap.ClipPlane4);
+                    GL.Disable(EnableCap.ClipPlane5);
+                    #endregion disable clipping planes
+
+                }
+                // render front axis 
+                //GL.MatrixMode(MatrixMode.Modelview); 
+                //GL.PopMatrix(); 
+                GL.Enable(EnableCap.Blend);
+                GL.Enable(EnableCap.LineSmooth);
+                m_axes.XAxis.RenderState2(p);
+                m_axes.YAxis.RenderState2(p);
+                if (m_camera.SinRho > 1e-5)
+                    m_axes.ZAxis.RenderState2(p);
+
+            } catch (ILArgumentException e) { 
+                throw new ILArgumentException("rendering failed at state 2",e);  
+            } 
+        }
+        /// <summary>
+        /// swap buffers and finalize rendering
+        /// </summary>
+        /// <param name="p"></param>
+        protected override void iRenderingState3(ILRenderProperties p) {
+
+            try {
+                p.Graphics = null;
+                m_legend.Draw(p, Rectangle.Empty);
+
+                #region screen label test, please delete me
+                //label = new ILNumerics.Drawing.Labeling.ILLabel(this); 
+                //label.Position = new Point(30,40); 
+                //label.Text = "Screen"; 
+                //label.Renderer = TextRendererManager.GetDefault(CoordSystem.Screen); 
+                //label.Draw(g); 
+                #endregion
+
+                //GL.MatrixMode(MatrixMode.Modelview);
+                if (m_selectingMode == InteractiveModes.ZoomRectangle && m_isDragging)
+                    drawSelectionRect(PointToClient(MousePosition));
+
+#if DRAWPLOTCUBESCREENRECT
+                #region
+                float[] viewport = new float[4];
+                GL.GetFloat(GetPName.Viewport, viewport);
+                GL.MatrixMode(MatrixMode.Projection);
+                GL.PushMatrix();
+                GL.LoadIdentity();
+                GL.Ortho(viewport[0], viewport[2], viewport[3], viewport[1], -1.0, 1.0);
+                GL.MatrixMode(MatrixMode.Modelview);
+                GL.PushMatrix();
+                GL.LoadIdentity();
+                GL.Color3(Color.LightGray);
+                GL.LineWidth(1f);
+                GL.Begin(BeginMode.LineLoop);
+                GL.Vertex2(m_plotBoxScreenRectF.Left * ClientSize.Width, m_plotBoxScreenRectF.Top * ClientSize.Height);
+                GL.Vertex2(m_plotBoxScreenRectF.Right * ClientSize.Width, m_plotBoxScreenRectF.Top * ClientSize.Height);
+                GL.Vertex2(m_plotBoxScreenRectF.Right * ClientSize.Width, m_plotBoxScreenRectF.Bottom * ClientSize.Height);
+                GL.Vertex2(m_plotBoxScreenRectF.Left * ClientSize.Width, m_plotBoxScreenRectF.Bottom * ClientSize.Height);
+                GL.End();
+                GL.PopMatrix();
+                GL.MatrixMode(MatrixMode.Projection);
+                GL.PopMatrix();
+                #endregion
+
+#endif
+                //GL.Finish();
+                // update model matrix (to be avilable for zooming etc.)
+                //GL.GetDouble(GetPName.ModelviewMatrix,m_modelViewMatrix);
+
+
+#if DRAWTEXTURESHEET
+                #region
+                // prepare GL
+                float[] deb_viewport = new float[4]; 
+                GL.GetFloat(GetPName.Viewport, deb_viewport);
+                GL.MatrixMode(MatrixMode.Projection);
+                GL.PushMatrix();     
+                GL.LoadIdentity();
+                GL.Ortho(deb_viewport[0], deb_viewport[2], deb_viewport[3], deb_viewport[1], -1.0, 1.0);
+                GL.MatrixMode(MatrixMode.Modelview);
+                GL.PushMatrix();
+                GL.LoadIdentity();
+                GL.PushAttrib(AttribMask.TextureBit | AttribMask.EnableBit | AttribMask.ColorBufferBit);
+                GL.Enable(EnableCap.Texture2D);
+                GL.Enable(EnableCap.Blend);
+                GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
+                GL.Disable(EnableCap.DepthTest);
+                // draw one large quad with whole texture sheet
+                GL.Begin(BeginMode.Quads); 
+                GL.TexCoord2(0,1);   
+                GL.Vertex2(0,ClientSize.Height/2);      // ul
+                GL.TexCoord2(0,0); 
+                GL.Vertex2(0,0);                    // bl
+                GL.TexCoord2(1,0); 
+                GL.Vertex2(ClientSize.Width,0);                    // br
+                GL.TexCoord2(1,1); 
+                GL.Vertex2(ClientSize.Width,ClientSize.Height/2);      // tr
+                GL.End();
+                #endregion
+#endif
+
+                SwapBuffers();
+                m_axes.XAxis.RenderState3(p);
+                m_axes.YAxis.RenderState3(p);
+                if (m_camera.SinRho > 1e-5)
+                    m_axes.ZAxis.RenderState3(p);
+
+                //if (false) {
+                //    p.Graphics.DrawLine(new Pen(new SolidBrush(Color.Red)), m_axes[0].Label.m_position, m_axes[0].Label.m_position);
+                //    p.Graphics.DrawLine(new Pen(new SolidBrush(Color.Green)), m_axes[1].Label.m_position, m_axes[0].Label.m_position);
+                //    p.Graphics.DrawLine(new Pen(new SolidBrush(Color.Blue)), m_axes[2].Label.m_position, m_axes[0].Label.m_position);
+                //}
+            } catch (ILArgumentException exc) {
+                throw new ILArgumentException("rendering failed aat state 3",exc);
+                // todo: exception handling
+            }
+        }
+        /// <summary>
+        /// draws the selection rectangle va OpenGL (rather than GDI in base class)
+        /// </summary>
+        /// <param name="endPoint"></param>
+        protected override void drawSelectionRect(Point endPoint) {
+            float [] viewport = new float[4]; 
+            GL.GetFloat(GetPName.Viewport, viewport);
+            GL.MatrixMode(MatrixMode.Projection);
+            GL.PushMatrix();     
+            GL.LoadIdentity();
+            GL.Ortho(viewport[0], viewport[2], viewport[3], viewport[1], -1.0, 1.0);
+
+            GL.MatrixMode(MatrixMode.Modelview);
+            GL.PushMatrix();
+            GL.LoadIdentity();
+
+            //GL.Enable(EnableCap.Texture2D);
+            //GL.Enable(EnableCap.Blend);
+            //GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
+
+            GL.Disable(EnableCap.DepthTest);
+            SetupLineStyle(m_selectionRectangle); 
+            //// upper left corner
+            m_selectionVertices[0] = m_mouseStart.X;
+            m_selectionVertices[1] = m_mouseStart.Y + (endPoint.Y - m_mouseStart.Y) / 4;
+            m_selectionVertices[2] = m_mouseStart.X;
+            m_selectionVertices[3] = m_mouseStart.Y;
+            m_selectionVertices[4] = m_mouseStart.X;
+            m_selectionVertices[5] = m_mouseStart.Y;
+            m_selectionVertices[6] = m_mouseStart.X + (endPoint.X - m_mouseStart.X) / 4;
+            m_selectionVertices[7] = m_mouseStart.Y;
+            // lower left corner 
+            m_selectionVertices[8] = m_mouseStart.X;
+            m_selectionVertices[9] = endPoint.Y - (endPoint.Y - m_mouseStart.Y) / 4;
+            m_selectionVertices[10] = m_mouseStart.X;
+            m_selectionVertices[11] = endPoint.Y;
+            m_selectionVertices[12] = m_mouseStart.X;
+            m_selectionVertices[13] = endPoint.Y;
+            m_selectionVertices[14] = m_mouseStart.X + (endPoint.X - m_mouseStart.X) / 4;
+            m_selectionVertices[15] = endPoint.Y;
+            // lower right corner 
+            m_selectionVertices[16] = endPoint.X;
+            m_selectionVertices[17] = endPoint.Y - (endPoint.Y - m_mouseStart.Y) / 4;
+            m_selectionVertices[18] = endPoint.X;
+            m_selectionVertices[19] = endPoint.Y;
+            m_selectionVertices[20] = endPoint.X;
+            m_selectionVertices[21] = endPoint.Y;
+            m_selectionVertices[22] = endPoint.X - (endPoint.X - m_mouseStart.X) / 4;
+            m_selectionVertices[23] = endPoint.Y;
+            // upper right corner 
+            m_selectionVertices[24] = endPoint.X;
+            m_selectionVertices[25] = m_mouseStart.Y + (endPoint.Y - m_mouseStart.Y) / 4;
+            m_selectionVertices[26] = endPoint.X;
+            m_selectionVertices[27] = m_mouseStart.Y;
+            m_selectionVertices[28] = endPoint.X;
+            m_selectionVertices[29] = m_mouseStart.Y;
+            m_selectionVertices[30] = endPoint.X - (endPoint.X - m_mouseStart.X) / 4;
+            m_selectionVertices[31] = m_mouseStart.Y;
+            // draw them
+            unsafe {
+                fixed (float* verticesP = m_selectionVertices) {
+                    GL.InterleavedArrays(InterleavedArrayFormat.V2f,8,(IntPtr)verticesP);
+                    GL.DrawArrays(BeginMode.Lines,0,16);
+                }
+            }
+            GL.MatrixMode(MatrixMode.Modelview);
+            GL.PopMatrix();
+            GL.MatrixMode(MatrixMode.Projection);
+            GL.PopMatrix();
+        }
+        /// <summary>
+        /// Swaps the front and back buffers, presenting the rendered scene to the screen.
+        /// </summary>
+        protected void SwapBuffers() {
+            if (m_context != null)
+                m_context.SwapBuffers();
+        }
+        /// <summary>
+        /// Makes the underlying this GLControl current in the calling thread.
+        /// All OpenGL commands issued are hereafter interpreted by this GLControl.
+        /// </summary>
+        protected void MakeCurrent() {
+            if (m_context != null)
+                m_context.MakeCurrent(m_implementation.WindowInfo);
+        }
+
+        public override void DrawToBitmap(Bitmap bitmap, Rectangle bounds) {   
+            RenderScene(m_renderProperties);
+            BitmapData bmpData = bitmap.LockBits(bounds,ImageLockMode.ReadWrite,
+                                 System.Drawing.Imaging.PixelFormat.Format24bppRgb); 
+            // reset any changes to pixel store
+            GL.PixelStore(PixelStoreParameter.UnpackAlignment,4.0f); 
+            GL.PixelStore(PixelStoreParameter.UnpackRowLength,bmpData.Width); 
+            GL.PixelStore(PixelStoreParameter.UnpackSkipRows,bounds.Y); 
+            GL.PixelStore(PixelStoreParameter.UnpackSkipPixels,bounds.X); 
+            GL.ReadPixels(0,0,bounds.Width,bounds.Height,OpenTK.Graphics.PixelFormat.Bgr,
+                          PixelType.UnsignedByte,(IntPtr)bmpData.Scan0); 
+            bitmap.UnlockBits(bmpData); 
+            bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY); 
+        }
+        #endregion
+
+        #region IILGraphFactory member
+        /// <summary>
+        /// Create specific graph (device dependent)
+        /// </summary>
+        /// <param name="data">numeric data to be visualized, any numeric type is accepted</param>
+        /// <param name="type">type of graph to be created</param>
+        /// <param name="additionalParams">user defined parameter, depend on concrete device type</param>
+        /// <returns>Concrete ILGraph object</returns>
+        public ILGraph CreateGraph(ILInArray<float> data, GraphType graphType, params ILArray<float>[] parameter) {
+            using (ILScope.Enter(data)) {
+                switch (graphType) {
+                    case GraphType.Plot2D:
+                        if (parameter != null && parameter.Length == 1
+                            && parameter[0] != null && parameter[0] is ILArray<float>) {
+                                return new ILOGLPlot2DGraph(this, parameter[0] as ILArray<float>,
+                                                        data, m_graphs.Limits);
+                        } else {
+                            return new ILOGLPlot2DGraph(this, data, m_graphs.Limits);
+                        }
+                    case GraphType.Surf:
+                        if (parameter == null || parameter.Length == 0)
+                            return new ILOGLSurfaceGraph(this, null, null, data, null, m_graphs.Limits);
+                        if (parameter.Length == 2) {
+                            return new ILOGLSurfaceGraph(this, data, parameter[0] as ILArray<float>,
+                                                         parameter[1] as ILArray<float>, null, m_graphs.Limits);
+                        } else if (parameter.Length == 1) {
+                            return new ILOGLSurfaceGraph(this, null, null, data,
+                                                         parameter[0] as ILArray<float>, m_graphs.Limits);
+                        } else if (parameter.Length == 3) {
+                            return new ILOGLSurfaceGraph(this, parameter[0] as ILArray<float>, parameter[1] as ILArray<float>,
+                                                         data, parameter[2] as ILArray<float>, m_graphs.Limits);
+                        } else
+                            throw new ILArgumentException("graph creation: invalid number of arguments! (surface)");
+                    case GraphType.Imagesc:
+                        return new ILOGLImageSCGraph(this, null, null, data, null, m_graphs.Limits);
+                    default:
+                        throw new ILInvalidOperationException("Graph type not supported: " + graphType.ToString());
+                }
+            }
+        }
+        /// <summary>
+        /// Create Axis (device dependent)
+        /// </summary>
+        /// <param name="name">specfies axis name (X,Y,ZAxis)</param>
+        /// <param name="clippingView">the global clipping view object for the axis</param>
+        /// <param name="parameters">user defined parameters (implementation dependent)</param>
+        /// <returns>ILAXis object</returns>
+        public ILAxis CreateAxis(AxisNames name, ILClippingData clippingView, params object[] parameters) {
+            switch (name) {
+                case AxisNames.XAxis:
+                    return new ILOGLXAxis(clippingView, m_layoutData, this);
+                case AxisNames.YAxis:
+                    return new ILOGLYAxis(clippingView, m_layoutData, this);
+                default:
+                    return new ILOGLZAxis(clippingView, m_layoutData, this);
+            } 
+        }
+        /// <summary>
+        /// create a new device dependent scene graph for hosting shapes, internally used
+        /// </summary>
+        /// <returns>scene graph</returns>
+        public ILSceneGraph CreateSceneGraph() {
+            return new ILSceneGraph(this,m_graphs.Limits);     
+        }
+        public ILVertexRenderer CreateVertexRenderer(Type vertexType, ILShape shape) {
+            if (vertexType == typeof(C4bV3f)) {
+                ILVertexRenderer ret;  
+                if (shape is ILQuads) {
+                    ret = new ILOGLVertexRendererC4bV3f(BeginMode.Quads); 
+                } else if (shape is ILPolygon) {
+                    ret = new ILOGLVertexRendererC4bV3f(BeginMode.Polygon); 
+                } else if (shape is ILLine) {
+                    ret = new ILOGLLineRendererC4bV3f(shape.VertexCount); 
+                    ret.CloseLines = false; 
+                } else if (shape is ILTriangle) {
+                    ret = new ILOGLVertexRendererC4bV3f(BeginMode.Triangles); 
+                } else if (shape is ILQuad) {
+                    ret = new ILOGLVertexRendererC4bV3f(BeginMode.Quads); 
+                } else if (shape is ILLines) {
+                    ret = new ILOGLLinesRendererC4bV3f(); 
+                } else if (shape is ILTriangles) {
+                    ret = new ILOGLVertexRendererC4bV3f(BeginMode.Triangles); 
+                } else if (shape is ILPoints) {
+                    ret = new ILOGLPointsRendererC4bV3f(); 
+                } else 
+                    throw new NotSupportedException ("Shape of type " + shape.GetType().Name + " is not supported!"); 
+                return ret; 
+            } else if (vertexType == typeof(C4fN3fV3f)) {
+                ILOGLVertexRendererC4fN3fV3f ret; 
+                if (shape is ILLitQuads) {
+                    ret = new ILOGLVertexRendererC4fN3fV3f(BeginMode.Quads); 
+                    ret.UseLight = true;
+                } else if (shape is ILLitPolygon) {
+                    ret = new ILOGLVertexRendererC4fN3fV3f(BeginMode.Polygon);
+                    ret.UseLight = true;
+                } else if (shape is ILLitQuad) {
+                    ret = new ILOGLVertexRendererC4fN3fV3f(BeginMode.Quads);
+                    ret.UseLight = true;
+                } else if (shape is ILLitTriangle) {
+                    ret = new ILOGLVertexRendererC4fN3fV3f(BeginMode.Triangles);
+                    ret.UseLight = true;
+                } else if (shape is ILLitSphere) {
+                    ret = new ILOGLVertexRendererC4fN3fV3f(BeginMode.Triangles);
+                    ret.UseLight = true;
+                } else if (shape is ILLitTriangles) {
+                    ret = new ILOGLVertexRendererC4fN3fV3f(BeginMode.Triangles);
+                    ret.UseLight = true;
+                } else {
+                    throw new NotSupportedException("Shape of type " + shape.GetType().Name + " is not supported for vertex type " + vertexType.Name + "!"); 
+                }
+                return ret; 
+            } else {
+                throw new NotSupportedException("VertexType is not supported!"); 
+            }
+        } 
+        internal override IILCreationFactory GetCreationFactory() {
+            return this;
+        }
+
+        #endregion
+
+        #region public methods
+
+        public override Point World2Screen(ILPoint3Df world) {
+            //Vector3 w = new Vector3(world.X, world.Y, world.Z);
+            ILPoint3Df screen;
+            ILGLU.Project(world,m_modelViewMatrix, m_projMatrix, m_viewMatrix, out screen);
+            return new Point((int)screen.X,(int)(ClientSize.Height - screen.Y));
+        }
+        public override Point World2Screen(ILPoint3Df world, double[] modelview) {
+            //Vector3 w = new Vector3(world.X, world.Y, world.Z);
+            ILPoint3Df screen;
+            ILGLU.Project(world,modelview, m_projMatrix, m_viewMatrix, out screen);
+            return new Point((int)screen.X,(int)(ClientSize.Height - screen.Y));
+        }
+
+        public static void SetupLineStyle(ILLineProperties wireprops) {
+            if (wireprops.Style == LineStyle.Solid) {
+                GL.Disable(EnableCap.LineStipple);
+            } else {
+                int stipFactr = 1;
+                short stipple;
+                if (wireprops.Style != LineStyle.UserPattern)
+                    stipple = ILPanel.StippleFromLineStyle(
+                                    wireprops.Style, ref stipFactr);
+                else {
+                    stipple = wireprops.Pattern;
+                    stipFactr = (int)wireprops.PatternScale; 
+                }
+                GL.Enable(EnableCap.LineStipple);
+                GL.LineStipple(stipFactr, stipple);
+            }
+            if (wireprops.Antialiasing && wireprops.Width > 1)
+                GL.Enable(EnableCap.LineSmooth);
+            else
+                GL.Disable(EnableCap.LineSmooth);
+            GL.LineWidth(wireprops.Width);
+            GL.Color3(wireprops.Color);
+        }
+		
+		private string DebugJoin(string seperator, double[] list) {
+			System.Text.StringBuilder ret = new System.Text.StringBuilder(); 
+			foreach (object o in list) {
+				ret.Append(seperator + String.Format("{0:f2}",o)); 
+			}
+			return ret.ToString(); 
+		}
+
+        /// <summary>
+        /// Transform 2 world coordinates into screen coords under current matrices
+        /// </summary>
+        /// <param name="p1_3D">world coord point 1</param>
+        /// <param name="p2_3D">world coord point 2</param>
+        /// <param name="p1_2D">(output) screen coord point 1</param>
+        /// <param name="p2_2D">(output) screen coord point 2</param>
+        public override void World2Screen(ILPoint3Df p1_3D, ILPoint3Df p2_3D, out Point p1_2D, out Point p2_2D) {
+			ILPoint3Df s, e; 
+            ILGLU.Project(p1_3D, m_modelViewMatrix, m_projMatrix, m_viewMatrix, out s);
+            ILGLU.Project(p2_3D, m_modelViewMatrix, m_projMatrix, m_viewMatrix, out e);
+            p1_2D = new Point((int)s.X,(int)(ClientSize.Height - s.Y));
+            p2_2D = new Point((int)e.X,(int)(ClientSize.Height - e.Y));
+       }
+        /// <summary>
+        /// transform from screen space into world space using OpenGL
+        /// </summary>
+        /// <param name="x">screen X</param>
+        /// <param name="y">screen Y</param>
+        /// <returns>world coord</returns>
+        public override void Screen2World(int x, int y, out ILPoint3Df nearClip, out ILPoint3Df farClip) {
+            // TODO: check the Z coord values. 0.68 here was result of trial only! 
+            ILGLU.UnProject(new ILPoint3Df(x, y, 0.0f), m_modelViewMatrix, m_projMatrix, m_viewMatrix, out nearClip);
+            ILGLU.UnProject(new ILPoint3Df(x, y, 1.0f), m_modelViewMatrix, m_projMatrix, m_viewMatrix, out farClip);
+
+        }
+        public override ILPoint3Df Screen2World2D(int x, int y) {
+            ILPoint3Df ret;
+            ILGLU.UnProject(new ILPoint3Df(x, y, 0), m_modelViewMatrix, m_projMatrix, m_viewMatrix, out ret);
+            ret.Z = m_clippingView.CenterF.Z; 
+			return ret;  
+        }
+        
+        #endregion
+
+        #region private helper 
+        private void renderBackground () {
+            //determine, which edges are in the back, fill with cube background color
+            GL.Begin(BeginMode.TriangleStrip);
+            GL.Color3(m_cubeBGColor);
+            float xmin = m_clippingView.XMin;
+            float xmax = m_clippingView.XMax;
+            float ymin = m_clippingView.YMin;
+            float ymax = m_clippingView.YMax;
+            float zmin = m_clippingView.ZMin;
+            float zmax = m_clippingView.ZMax;
+            if (!m_camera.LooksFromLeft) {
+                if (m_camera.LooksFromFront) {
+                    // left & back border
+                    GL.Vertex3(xmin,ymin,zmin);       
+                    GL.Vertex3(xmin,ymin,zmax);       
+                    GL.Vertex3(xmin,ymax,zmin);       
+                    GL.Vertex3(xmin,ymax,zmax);       
+                    GL.Vertex3(xmax,ymax,zmin);       
+                    GL.Vertex3(xmax,ymax,zmax);       
+                } else {
+                    GL.Vertex3(xmin,ymax,zmin);    //   
+                    GL.Vertex3(xmin,ymax,zmax);       
+                    GL.Vertex3(xmin,ymin,zmin);       
+                    GL.Vertex3(xmin,ymin,zmax);       
+                    GL.Vertex3(xmax,ymin,zmin);       
+                    GL.Vertex3(xmax,ymin,zmax);       
+                }
+            } else {
+                if (!m_camera.LooksFromFront) {
+                    GL.Vertex3(xmin,ymin,zmin);       
+                    GL.Vertex3(xmin,ymin,zmax);       
+                    GL.Vertex3(xmax,ymin,zmin);       
+                    GL.Vertex3(xmax,ymin,zmax);       
+                    GL.Vertex3(xmax,ymax,zmin);       
+                    GL.Vertex3(xmax,ymax,zmax);       
+                } else {
+                    GL.Vertex3(xmin,ymax,zmin);       
+                    GL.Vertex3(xmin,ymax,zmax);       
+                    GL.Vertex3(xmax,ymax,zmin);       
+                    GL.Vertex3(xmax,ymax,zmax);       
+                    GL.Vertex3(xmax,ymin,zmin);       
+                    GL.Vertex3(xmax,ymin,zmax);       
+                }
+            }
+            GL.End();
+            // draw bottom 
+            if (m_camera.LooksFromTop) {
+                GL.Begin(BeginMode.TriangleStrip); 
+                GL.Vertex3(xmin,ymin,zmin); 
+                GL.Vertex3(xmax,ymin,zmin); 
+                GL.Vertex3(xmin,ymax,zmin); 
+                GL.Vertex3(xmax,ymax,zmin); 
+                GL.End(); 
+            }
+        }
+        #endregion 
+    
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLPlot2DGraph.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLPlot2DGraph.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLPlot2DGraph.cs	(revision 9102)
@@ -0,0 +1,165 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing;
+using System.Drawing.Imaging; 
+using System.Data;
+using System.Windows.Forms;
+using ILNumerics.Exceptions; 
+using System.Resources; 
+using OpenTK.Graphics; 
+using OpenTK.Graphics.OpenGL;
+using OpenTK.Platform;
+using OpenTK.Graphics.OpenGL.Enums;
+using ILNumerics.Drawing.Graphs; 
+using ILNumerics.Drawing; 
+using ILNumerics.Drawing.Labeling; 
+using ILNumerics.Drawing.Interfaces; 
+using ILNumerics.Drawing.Shapes; 
+
+namespace ILNumerics.Drawing.Platform.OpenGL
+{
+    /// <summary>
+    /// OpenGL implementation for ILPlot2DGraph
+    /// </summary>
+    public class ILOGLPlot2DGraph : ILPlot2DGraph {
+
+        #region attributes 
+
+        protected int m_textureName = 0; 
+        protected float[] m_markerQuads; 
+
+        #endregion
+
+        #region constructors 
+
+        internal ILOGLPlot2DGraph(ILPanel panel, ILArray<float> sourceArray,
+                                  ILClippingData clippingContainer) 
+                                : base(panel, sourceArray,clippingContainer) {
+        }
+        internal ILOGLPlot2DGraph(ILPanel panel, ILArray<float> xData, ILArray<float> yData,
+                                  ILClippingData clippingContainer) 
+                                : base(panel, xData, yData, clippingContainer) {
+        }
+
+        #endregion
+
+        #region public (& abstract) interface 
+
+        public override void Draw(ILRenderProperties p) {
+            //System.Diagnostics.Debug.WriteLine("ILOGLGraphPlot2D_Draw"); 
+            #region draw line
+            // draw linestrip - simple case - fast vertex rendering 
+            if (m_properties.Visible) {
+                GL.Disable(EnableCap.Blend); 
+                GL.Disable(EnableCap.Texture2D);
+                ILOGLPanel.SetupLineStyle(m_properties); 
+                unsafe { 
+                    fixed(C4bV3f* pVertArr = m_vertices) {  
+                        GL.InterleavedArrays(InterleavedArrayFormat.C4ubV3f,0,(IntPtr)pVertArr); 
+                        if (m_properties.Color.IsEmpty) {
+                            GL.ShadeModel(ShadingModel.Smooth); 
+                        } else {
+                            GL.ShadeModel(ShadingModel.Flat); 
+                            GL.DisableClientState(EnableCap.ColorArray); 
+                        }
+
+                        if (m_startID < 2) {
+                            GL.DrawArrays(BeginMode.LineStrip, m_startID, m_vertexCount-1);
+                        } else {
+                            GL.DrawArrays(BeginMode.LineStrip, m_startID, m_vertexCount-m_startID);
+                            GL.DrawArrays(BeginMode.LineStrip, 0, m_startID);
+                        }
+                    }
+                }
+            }
+            #endregion
+            #region draw markers
+            if (m_marker.Visible) { 
+                m_marker.Shape.Draw(p, m_marker, m_vertices,0, m_vertexCount-1);
+            }
+            #endregion
+        }
+        public override void Dispose() {
+            m_vertices = null;
+        }
+        /// <summary>
+        /// (re)create vertex buffer, line-, texture objects
+        /// </summary>
+        internal override void Configure() {
+        }
+
+        public override void DrawToLegend(ILRenderProperties p, Rectangle sampleArea, Rectangle labelArea) {
+            if (p.Graphics != null) {
+                // bitmap output is handled by base class
+                base.DrawToLegend(p, sampleArea, labelArea);
+                return; 
+            }
+            int sampY = (int)(sampleArea.Top + sampleArea.Height / 2.0f);
+            #region draw line
+            if (m_properties.Visible) {
+                ILNumerics.Drawing.Platform.OpenGL.ILOGLPanel.SetupLineStyle(m_properties); 
+                GL.Begin(BeginMode.Lines); 
+                GL.Vertex2(sampleArea.Left,sampY); 
+                GL.Vertex2(sampleArea.Right,sampY); 
+                GL.End();
+            }
+            #endregion
+
+            #region draw marker 
+            if (m_marker.Visible) {
+                C4bV3f pos = new C4bV3f();
+                pos.XPosition = sampleArea.Left + sampleArea.Width / 2.0f; 
+                pos.YPosition = sampY; 
+                m_marker.Shape.Draw(p, m_marker,new C4bV3f[] {pos},0,-1);
+            }
+            #endregion
+            //GL.Vertex2(sampleArea.Right,sampleArea.Bottom); 
+            //GL.Vertex2(sampleArea.Left,sampleArea.Bottom); 
+            m_label.m_position.X = labelArea.X + labelArea.Width / 2;
+            m_label.m_position.Y = labelArea.Y + labelArea.Height / 2;
+            m_label.Anchor = new PointF(.5f, .5f);  //  = TickLabelAlign.center | TickLabelAlign.vertCenter; 
+            m_label.Draw(p); 
+        }
+        #endregion
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLPointsRendererC4bV3f.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLPointsRendererC4bV3f.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLPointsRendererC4bV3f.cs	(revision 9102)
@@ -0,0 +1,102 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using ILNumerics.Drawing.Shapes; 
+using OpenTK.Graphics;
+using OpenTK.Graphics.OpenGL; 
+
+namespace ILNumerics.Drawing.Platform.OpenGL {
+    /// <summary>
+    /// An OpenGL vertex renderer, capable of rendering
+    /// vertex arrays of type C4bV3f (simple /-primitive shapes).
+    /// </summary>
+    public unsafe class ILOGLPointsRendererC4bV3f : ILVertexRenderer {
+
+        #region attributes
+        #endregion
+
+        #region properties
+        #endregion
+
+        public ILOGLPointsRendererC4bV3f () {
+        }
+        public override void Draw(ILRenderProperties props, ILShape shape) {
+            GL.Enable(EnableCap.Blend);
+            GL.BlendFunc (BlendingFactorSrc.SrcAlpha,
+                          BlendingFactorDest.OneMinusSrcAlpha); 
+            GL.Enable(EnableCap.DepthTest);
+            ILPoints points = (shape as ILPoints);
+            
+            fixed (C4bV3f* pVertices = points.Vertices) {
+                GL.InterleavedArrays(InterleavedArrayFormat.C4ubV3f, 0, (IntPtr)pVertices);
+                if (points.Shading == ShadingStyles.Flat) {
+                    GL.DisableClientState(EnableCap.ColorArray);
+                    GL.Color4(points.FillColor);  
+                }
+                GL.Enable(EnableCap.PointSmooth); 
+                GL.PointSize(points.Width); 
+                GL.DrawArrays(BeginMode.Points, 0, points.VertexCount);
+                GL.Finish();
+            }
+        }
+        public override void Draw(ILRenderProperties props, ILShape shape, int[] indices) {
+            GL.Enable(EnableCap.DepthTest);
+            GL.Enable(EnableCap.Blend);
+            GL.BlendFunc (BlendingFactorSrc.SrcAlpha,
+                          BlendingFactorDest.OneMinusSrcAlpha); 
+            ILPoints points = shape as ILPoints;
+            fixed (int* pIndices = indices) 
+            fixed (C4bV3f* pVertices = points.Vertices) {
+                GL.InterleavedArrays(InterleavedArrayFormat.C4ubV3f, 0, (IntPtr)pVertices);
+                if (points.Shading == ShadingStyles.Flat) {
+                    GL.DisableClientState(EnableCap.ColorArray);
+                    GL.Color4(points.FillColor);  
+                }
+                GL.Enable(EnableCap.PointSmooth); 
+                GL.PointSize(points.Width); 
+                GL.DrawElements(BeginMode.Points, indices.Length,
+                                DrawElementsType.UnsignedInt, (IntPtr)pIndices);
+                GL.Finish(); 
+            }
+
+        }
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLRenderer.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLRenderer.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLRenderer.cs	(revision 9102)
@@ -0,0 +1,373 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Text;
+using System.Drawing;  
+using System.Collections.Generic;
+using ILNumerics.Drawing.Interfaces; 
+using OpenTK; 
+using OpenTK.Graphics;
+using OpenTK.Graphics.OpenGL; 
+using OpenTK.Graphics.OpenGL.Enums; 
+using ILNumerics.Drawing; 
+using ILNumerics.Drawing.Labeling;  
+
+namespace ILNumerics.Drawing.Platform.OpenGL {
+    /// <summary>
+    /// OpenGL text renderer in screen coords
+    /// </summary>
+    [ILRenderer(GraphicDeviceType.OpenGL,"Outline","OpenGL cached, outlined textures",true,CoordSystem.Screen)] 
+    public class ILOGLRenderer : IILTextRenderer {
+
+        #region event handling
+        /// <summary>
+        /// (IILTextRenderer) Event firing if the texture storage has been cleared 
+        /// </summary>
+        public event EventHandler CacheCleared; 
+        void m_textureManager_TextureCacheCleared(object sender, EventArgs e) {
+            if (CacheCleared != null) 
+                CacheCleared(this,null);
+        }
+        #endregion
+
+        #region member / properties
+        ILTextureManager m_textureManager; 
+        float[] m_curPosition = new float[16];
+        Color m_colorOverride = Color.Empty;
+        float m_xMin, m_xMax, m_yMin, m_yMax; 
+        #endregion
+
+        #region constructors
+
+        public ILOGLRenderer (ILPanel panel) {
+            m_textureManager = panel.TextureManager;
+            m_textureManager.TextureCacheCleared += new EventHandler(m_textureManager_TextureCacheCleared);
+        }
+           
+        #endregion
+
+        #region IILTextRenderer Member
+
+        public CoordSystem CoordSystem {
+            get { return CoordSystem.Screen; }
+        }
+
+        public bool Cached { 
+            get {
+                return true; 
+            }
+        }
+
+        public string Name {
+            get { return "Outline fonts"; }
+        }
+
+        public string NameLong {
+            get { return "OpenGL outline fonts (OpenTK)"; }
+        }
+
+        public GraphicDeviceType DeviceType {
+            get { return GraphicDeviceType.OpenGL; }
+        }
+
+        public bool DrawAfterBufferSwapped {
+            get { return false; }
+        }
+
+        public void Begin(ILRenderProperties p) {
+            if (GraphicsContext.CurrentContext == null)
+                throw new GraphicsContextException("No GraphicsContext is current in the calling thread.");
+
+            float[] viewport = new float[4]; 
+            GL.GetFloat(GetPName.Viewport, viewport);
+
+            // Prepare to draw text. We want pixel perfect precision, so we setup a 2D mode,
+            // with size equal to the window (in pixels). 
+            // While we could also render text in 3D mode, it would be very hard to get
+            // pixel-perfect precision.
+            GL.MatrixMode(MatrixMode.Projection);
+            GL.PushMatrix();     
+            GL.LoadIdentity();
+            GL.Ortho(viewport[0], viewport[2], viewport[3], viewport[1], -1.0, 1.0);
+
+            GL.MatrixMode(MatrixMode.Modelview);
+            GL.PushMatrix();
+            GL.LoadIdentity();
+
+            GL.PushAttrib(AttribMask.TextureBit | AttribMask.EnableBit | AttribMask.ColorBufferBit);
+
+            GL.Enable(EnableCap.Texture2D);
+            GL.Enable(EnableCap.Blend);
+            GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
+            GL.Disable(EnableCap.DepthTest);
+            if (p.Clipping) {
+                GL.Disable(EnableCap.ClipPlane0); 
+                GL.Disable(EnableCap.ClipPlane1); 
+                GL.Disable(EnableCap.ClipPlane2); 
+                GL.Disable(EnableCap.ClipPlane3); 
+                GL.Disable(EnableCap.ClipPlane4); 
+                GL.Disable(EnableCap.ClipPlane5); 
+            }
+            if (p.PassCount == 0) {
+                m_xMin = float.MaxValue;
+                m_xMax = float.MinValue;
+                m_yMin = float.MaxValue;
+                m_yMax = float.MinValue;
+            }
+        }
+        
+        public void Begin (ILRenderProperties p, ref double[] modelview) {
+            if (modelview == null || modelview.Length < 16) {
+                modelview = new double[16]; 
+            }
+            GL.GetDouble(GetPName.ModelviewMatrix,modelview);
+            Begin(p); 
+        }
+        public void End(ILRenderProperties p) {
+            if (p.Clipping) {
+                GL.Enable(EnableCap.ClipPlane0); 
+                GL.Enable(EnableCap.ClipPlane1); 
+                GL.Enable(EnableCap.ClipPlane2); 
+                GL.Enable(EnableCap.ClipPlane3); 
+                GL.Enable(EnableCap.ClipPlane4); 
+                GL.Enable(EnableCap.ClipPlane5); 
+            }
+            GL.PopAttrib();
+            GL.MatrixMode(MatrixMode.Modelview);
+            GL.PopMatrix();
+            GL.MatrixMode(MatrixMode.Projection);
+            GL.PopMatrix();
+            if (p.PassCount == 0) {
+                if (p.MinX > m_xMin) p.MinX = (int)m_xMin;
+                if (p.MaxX < m_xMax) p.MaxX = (int)m_xMax;
+                if (p.MaxY < m_yMax) p.MaxY = (int)m_yMax;
+                if (p.MinY > m_yMin) p.MinY = (int)m_yMin;
+            }
+        }
+        #endregion
+
+        #region IILTextRenderer Member
+        /// <summary>
+        /// Place a new item into the texture cache 
+        /// </summary>
+        /// <param name="key">unique key to identify the item for later reference</param>
+        /// <param name="bmp">bitmap containing the item data</param>
+        /// <param name="rect">area in <paramref name="bmp"/> containing the item's data</param>
+        public void Cache(string key, Bitmap bmp, RectangleF rect) {
+            m_textureManager.StoreTextureItem(key,bmp,rect); 
+        }
+
+        /// <summary>
+        /// Test if the cache contains an item with a specific key
+        /// </summary>
+        /// <param name="key">key</param>
+        /// <returns>true if the item was cached, false otherwise</returns>
+        public bool ExistsKey(string key) {
+            return m_textureManager.Exists(key); 
+        }
+
+        /// <summary>
+        /// try to get the size (screen pixels) of an item
+        /// </summary>
+        /// <param name="key">unique key identifying the item</param>
+        /// <param name="size">[output] size of the item (if found)</param>
+        /// <returns>true, if the item was found, false otherwise</returns>
+        public bool TryGetSize(string key, ref Size size) {
+            ILTextureData item; 
+            if (m_textureManager.TryGetTextureItem(key,out item)) {
+                size = new Size(item.Width,item.Height); 
+                return true; 
+            } else {
+                return false; 
+            }
+        }
+
+        /// <summary>
+        /// Draws all items contained in a given render queue
+        /// </summary>
+        /// <param name="queue">render queue</param>
+        /// <param name="location">starting point</param>
+        /// <param name="orientation">orientation for the whole queues output</param>
+        /// <param name="color">starting color</param>
+        /// <remarks><para>The render queue must contain only keys for already cached items!</para>
+        /// <para>The color parameter serves as a global color definition. It may be overridem 
+        /// by individual color specifications of the queue items.</para>
+        /// </remarks>
+        public void Draw(ILRenderQueue queue, 
+                        System.Drawing.Point location, 
+                        TextOrientation orientation,
+                        Color color) {
+            float w, h;
+            if (String.IsNullOrEmpty(queue.Expression.Trim())) return; 
+            w = queue.Size.Width; 
+            h = queue.Size.Height; 
+            // compensate for unexact glx.MeasureString results... (to be fixed!)
+            //w *= 1.09f;
+            //h *= 1.09f;
+            if (orientation == TextOrientation.Vertical) {
+                GL.Rotate(90,0,0,1);
+            }
+            GL.GetFloat(GetPName.ModelviewMatrix,m_curPosition); 
+            m_curPosition[12] = location.X; 
+            m_curPosition[13] = location.Y; 
+
+            GL.LoadMatrix(m_curPosition);
+            m_textureManager.Reset(); 
+            w = 0.5f; h = 0.5f; 
+            int lineHeight = 0;
+            float drawPosY;
+            float xMin = float.MaxValue; // relative to label (include rotation)
+            float yMin = float.MaxValue;
+            float xMax = float.MinValue;
+            float yMax = float.MinValue; 
+            GLColor3(color); 
+            foreach (ILRenderQueueItem item in queue) {
+                // special symbols & control sequences 
+                switch (item.Key) {
+                case "\r":
+                    w = 0.5f; 
+                    break; 
+                case "\n": 
+                    w = 0.5f; 
+                    h += lineHeight; 
+                    lineHeight = 0; 
+                    break; 
+                default: 
+                    //since textures (may) lay on different sheets in GL memory,
+                    // we cannot switch them in between Begin() and End(), 
+                    // we must start a new Begin with each Quad :(
+                    // possible workaround: If only one sheet is used, draw all 
+                    // quads at once.
+                    ILTextureData textData = m_textureManager.GetTextureItem(item.Key,true); 
+                    if (item.Color != Color.Empty) {
+                        GLColor3(item.Color); 
+                    } else {
+                        GLColor3(color); 
+                    }
+                    drawPosY = h + item.Offset.Y; 
+
+                    GL.Begin(BeginMode.Quads); 
+                    RectangleF rectF = textData.TextureRectangle; 
+                    GL.TexCoord2(rectF.Left,rectF.Bottom);
+                    GL.Vertex2(w, drawPosY + textData.Height - 1);      // bl
+                    GL.TexCoord2(rectF.Left,rectF.Top);
+                    GL.Vertex2(w, drawPosY);                    // tl
+                    if (xMin > w) xMin = w;
+                    if (yMin > drawPosY) yMin = drawPosY;
+
+                    w += textData.Width-1; 
+                    GL.TexCoord2(rectF.Right,rectF.Top);
+                    GL.Vertex2(w, drawPosY);                    // tr
+                    GL.TexCoord2(rectF.Right,rectF.Bottom);
+                    GL.Vertex2(w, drawPosY + textData.Height - 1);      // br
+                    if (textData.Height > lineHeight)
+                        lineHeight = textData.Height; 
+                    GL.End();
+                    if (xMax < w) xMax = w;
+                    if (yMax < drawPosY + textData.Height - 1) 
+                        yMax = drawPosY + textData.Height - 1;
+
+#if BOUNDINGBOXES_ITEM
+            // define DEBUG symbol to draw bounding box around each item (debug feature)
+            GL.Color3(Color.Red); 
+            GL.Begin(BeginMode.LineLoop); 
+                w-= textData.Width; 
+                GL.Vertex2(w,h + textData.Height);      // ul
+                GL.Vertex2(w,h);                    // bl
+                w += textData.Width; 
+                GL.Vertex2(w,h);                    // br
+                GL.Vertex2(w,h + textData.Height);      // tr
+            GL.End();
+#endif
+                        break; 
+                }
+            }
+#if BOUNDINGBOXES
+            // define debugsymbol "BOUNDINGBOXES", to draw bounding box around whole expression
+            GL.Disable(EnableCap.Texture2D); 
+            GL.Color3(Color.Red); 
+            GL.LineWidth(1);
+            GL.Disable(EnableCap.LineStipple);
+            GL.Begin(BeginMode.LineLoop); 
+                GL.Vertex2(0,0);      // ul
+                GL.Vertex2(0,queue.Size.Height);                    // bl
+                GL.Vertex2(queue.Size.Width,queue.Size.Height);                    // br
+                GL.Vertex2(queue.Size.Width,0);      // tr
+            GL.End();
+            GL.Enable(EnableCap.Texture2D); 
+#endif
+            // check outer limits 
+            if (orientation == TextOrientation.Horizontal) {
+                if (m_xMin > location.X + xMin) m_xMin = location.X + xMin;
+                if (m_xMax < location.X + xMax) m_xMax = location.X + xMax;
+                if (m_yMin > location.Y + yMin) m_yMin = location.Y + yMin;
+                if (m_yMax < location.Y + yMax) m_yMax = location.Y + yMax;
+            } else if (orientation == TextOrientation.Vertical) {
+                if (m_xMin > location.X - yMax) m_xMin = location.X - yMax;
+                if (m_xMax < location.X - yMin) m_xMax = location.X - yMin;
+                if (m_yMin > location.Y - xMin) m_yMin = location.Y - xMin;
+                if (m_yMax < location.Y - xMax) m_yMax = location.Y - xMax;
+            }
+        }
+
+        public void Draw(ILRenderQueue renderQueue, float x1, float y1, float z1, float x2, float y2, float z2, Color color) {
+            Draw(renderQueue,new Point((int)x1,(int)y1),TextOrientation.Horizontal,color); 
+        }
+        public Color ColorOverride {
+            get {
+                return m_colorOverride; 
+            }
+            set {
+                m_colorOverride = value; 
+            }
+        }
+
+        #endregion
+
+        private void GLColor3(Color color) {
+            if (m_colorOverride.IsEmpty) {
+                GL.Color3(color);
+            } else {
+                GL.Color3(m_colorOverride);
+            }
+        }
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLStyledMarkerShape.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLStyledMarkerShape.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLStyledMarkerShape.cs	(revision 9102)
@@ -0,0 +1,173 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing; 
+using ILNumerics.Drawing.Marker; 
+using ILNumerics.Drawing; 
+using OpenTK.Graphics; 
+using OpenTK.Graphics.OpenGL;
+using OpenTK.Platform;
+using OpenTK.Graphics.OpenGL.Enums;
+using ILNumerics.Drawing.Labeling; 
+using ILNumerics.Drawing.Shapes; 
+
+
+namespace ILNumerics.Drawing.Platform.OpenGL {
+    public class ILOGLStyledMarkerShape : ILStyledMarkerShape {
+
+        #region constructors
+        internal ILOGLStyledMarkerShape (ILPanel panel, MarkerStyle style) 
+            : base (panel,style) { }
+        #endregion
+
+        #region public interface 
+
+        internal override void Draw(ILRenderProperties p, ILMarker marker, C4bV3f[] vertices, int startID, int vertCount) {
+            // some implementations need to know we are drawing in 
+            // screen coords, vertcount give the signal: -1
+            if (vertCount == 0 || vertCount < -1) return; 
+            if (m_style != MarkerStyle.None) {
+               if (m_style == MarkerStyle.Dot || m_style == MarkerStyle.Square) {
+                    SetupMarkerStyle(marker);
+                    unsafe { 
+                        fixed(C4bV3f* pVertArr = vertices) {
+                            //GL.TexCoord2(0.5,0.5); 
+                            GL.InterleavedArrays(InterleavedArrayFormat.V2f,0,(IntPtr)pVertArr); 
+                            GL.DrawArrays(BeginMode.Points,0,Math.Abs(vertCount));
+                        }
+                    }
+                } else {
+                    #region draw textured points (slow version: textured quads)
+                    string markerTexKey = Hash(); 
+                    ILTextureData texData; 
+                    if (!m_panel.TextureManager.Exists(markerTexKey)) {
+                        CacheMarkerBitmap();
+                    }
+                    texData = m_panel.TextureManager.GetTextureItem(markerTexKey,true); 
+        System.Diagnostics.Debug.Assert(texData != null,"The texture for marker was expected to exist in texture storage, but it was not found!"); 
+                    // prepare for plotting
+                    GL.Color3(marker.Color); 
+                    GL.PushAttrib(AttribMask.AllAttribBits);
+
+                    GL.Enable(EnableCap.Texture2D);
+                    GL.Enable(EnableCap.Blend);
+                    GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
+                    GL.Disable(EnableCap.DepthTest);
+                    RectangleF rectF = texData.TextureRectangle; 
+                    float w,h;
+                    ILClippingData clip = m_panel.Limits; 
+                    float s05x; 
+                    float s05y; 
+                    //if (m_marker.)
+                    s05x = Math.Abs(marker.Size * clip.WidthF / (m_panel.ClientSize.Width)); 
+                    s05y = Math.Abs(marker.Size * clip.HeightF / (m_panel.ClientSize.Height)); 
+                    if (vertCount > 0) {
+                        #region determine size for markers in world coords (graph limits)
+
+                        #endregion
+                        // draw all markers using quads. 
+                        // this is slow! Todo: replace by point sprites! 
+                        GL.Begin(BeginMode.Quads); 
+                        for (int i = 0; i < vertCount; i++) {
+                            w = vertices[i].XPosition; 
+                            h = vertices[i].YPosition;           
+                            if (m_panel.ClipViewData && (w < clip.XMin || w > clip.XMax || h < clip.YMin || h > clip.YMax)) 
+                                continue; 
+                            w -= s05x;             
+                            h -= s05y; 
+                            GL.TexCoord2(rectF.Left,rectF.Bottom);              
+                            GL.Vertex2(w,h);                                    // ul
+                            GL.TexCoord2(rectF.Left,rectF.Top);                 
+                            GL.Vertex2(w,h + 2 * s05y);                         // bl
+                            w += 2 * s05x;                                
+                            GL.TexCoord2(rectF.Right,rectF.Top);                
+                            GL.Vertex2(w,h + 2 * s05y);                         // br
+                            GL.TexCoord2(rectF.Right,rectF.Bottom);             
+                            GL.Vertex2(w,h);                                    // tr
+                        }
+                        GL.End(); 
+                    } else if (vertCount == -1) {
+                        GL.Begin(BeginMode.Quads); 
+                            w = vertices[0].XPosition - marker.Size; 
+                            h = vertices[0].YPosition - marker.Size;           
+                            GL.TexCoord2(rectF.Left,rectF.Top);              
+                            GL.Vertex2(w,h);                                    // ul
+                            GL.TexCoord2(rectF.Left,rectF.Bottom);                 
+                            GL.Vertex2(w,h + marker.Size * 2);                  // bl
+                            w += marker.Size;                                
+                            GL.TexCoord2(rectF.Right,rectF.Bottom);                
+                            GL.Vertex2(w,h + marker.Size * 2);                  // br
+                            GL.TexCoord2(rectF.Right,rectF.Top);             
+                            GL.Vertex2(w,h);                                    // tr
+                        GL.End(); 
+                    }
+                    GL.PopAttrib();
+                    #endregion
+                }
+           }
+        } 
+        #endregion
+
+        #region private helper
+        private void SetupMarkerStyle(ILMarker marker) {
+            GL.PointSize(marker.Size); 
+            GL.Color3(marker.Color);
+            GL.Disable(EnableCap.DepthTest);
+            switch (m_style) {
+                case MarkerStyle.Dot:
+                    GL.Enable(EnableCap.PointSmooth); 
+                    break;
+                case MarkerStyle.Square:
+                    GL.Disable(EnableCap.PointSmooth); 
+                    break;
+                case MarkerStyle.None:
+                    GL.PointSize(0.0f); 
+                    break;
+                default:
+                    throw new NotImplementedException(); 
+            }
+        }
+
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLSurfaceGraph.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLSurfaceGraph.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLSurfaceGraph.cs	(revision 9102)
@@ -0,0 +1,486 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing;
+using System.Data;
+using System.Windows.Forms;
+using ILNumerics.Exceptions; 
+using ILNumerics.Drawing; 
+using System.Resources; 
+using OpenTK; 
+using OpenTK.Graphics.OpenGL; 
+using OpenTK.Graphics; 
+using OpenTK.Graphics.OpenGL.Enums; 
+using ILNumerics.Drawing.Graphs; 
+using ILNumerics.Drawing.Platform.OpenGL; 
+using ILNumerics.Drawing.Misc; 
+using ILNumerics.Misc; 
+using VERTEXTYPEDEF = ILNumerics.Drawing.Platform.OpenGL.ILOGLSurfaceGraph.VertexC4N3V3; 
+
+namespace ILNumerics.Drawing.Platform.OpenGL
+{
+    /// <summary>
+    /// OpenGL implementation for ILSurfaceGraph
+    /// </summary>
+    public class ILOGLSurfaceGraph : ILSurfaceGraph {
+        
+        #region attributes
+        protected float[] m_vertices;
+        protected ShadingStyles m_oldShading; 
+        protected ILColormap m_oldColormap; 
+        #endregion
+
+
+        #region vertex definition
+        /// <summary>
+        /// Vertex definition: 4Color, 3Normal, 3 Vertex - all float
+        /// </summary>
+        /// <remarks>CAUTION! The vertex is not usable with OpenGL via vartex arrays this way!
+        /// We had to recognize sporadic crashs when drawing this way! Todo: ... to be investigated.</remarks>
+        [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
+        public struct VertexC4N3V3 {
+            public float CR;
+            public float CG;
+            public float CB; 
+            public float CA; 
+            public float Nx; 
+            public float Ny;
+            public float Nz; 
+            public float Vx; 
+            public float Vy; 
+            public float Vz; 
+        }
+
+        protected override void CreateVertices() {
+            ILColormap colormap = m_panel.Colormap; 
+            if (m_vertices == null) {
+                m_vertices = ILMemoryPool.Pool.New<float>(m_Vertcount*10); 
+            }
+            float val = 0.0f; 
+            float minZ = m_globalClipping.ZMin, minC = (ILMath.isnullorempty(m_colors))? 0.0f : m_colors.MinValue; 
+            float maxZ = m_globalClipping.ZMax; 
+            bool useColorArray = !(object.Equals(m_colors,null) || m_colors.IsEmpty); 
+            float a;
+            if (useColorArray)
+                a = colormap.Length / (m_colors.MaxValue - minC);
+            else {
+                if (maxZ - minZ != 0.0f)
+                    a = colormap.Length / (maxZ - minZ);
+                else
+                    a = 0.0f;
+            }
+            int curVertPos = 0, curVecPos = 0; 
+            if (m_shading == ShadingStyles.Interpolate) {
+                #region shading interpolate
+                for (int r = 0; r < m_rows; r++) {
+                    for (int c = 0; c < m_cols; c++) {
+                        curVecPos = r + c * m_rows; 
+                        val = m_sourceArray.GetValue(r,c);
+                        // set color values 
+                        if (useColorArray)
+                            colormap.Map((m_colors.GetValue(curVecPos) - minC) * a, m_vertices, ref curVertPos);
+                        else {
+                            if (a != 0) {
+                                colormap.Map((val - minZ) * a, m_vertices, ref curVertPos);
+                            } else {
+                                // plane: minz == maxz
+                                colormap.Map(colormap.Length / 2, m_vertices, ref curVertPos);
+                            }
+                        }
+                        m_vertices[curVertPos++] = m_opacity;
+                        curVertPos += 3; 
+                        m_vertices[curVertPos++] = m_xCoords[curVecPos]; 
+                        m_vertices[curVertPos++] = m_yCoords[curVecPos]; 
+                        m_vertices[curVertPos++] = val;
+                    }
+                }
+                #endregion
+            } else if (m_shading == ShadingStyles.Flat) {
+                #region shading flat
+                /*  Consider a surface area like this: 
+                 * 
+                 *  8 - 9 -10 -11
+                 *  | / | / | / |
+                 *  4 - 5 - 6 - 7
+                 *  | / | / | / | 
+                 *  0 - 1 - 2 - 3
+                 * 
+                 *  The rectangle surrounded by 0-1-4-5 is than colored by the 
+                 *  vertex 5. This rectangle will be assembled by 2 triangles: 
+                 *  0-1-5 and 0-4-5. Therefore the color for both rectangles 
+                 *  is the same and must be stored in the vertex No.5. 
+                 *  The vertices can be assembled in natural order, beginning 
+                 *  with 0 and approching m_vertexCount-1. The color for flat 
+                 *  shading is averaged over the neighbor corners of each
+                 *  rectangle. In our Example the color stored in 5 is averaged 
+                 *  over the values of the vertices 0,1,4 and 5. The first row 
+                 *  and the first column are not used for the surface. However
+                 *  it may _be_ used for the wireframe grid if that is drawn with 
+                 *  interpolated colors (Wireframe.Color.IsEmpty). So we must 
+                 *  prepare the color for it -> here we just take the value itself.
+                 */
+                // first row: no color average
+                for (int c = 0; c < m_cols; c++) {
+                    val = m_sourceArray.GetValue(0,c);
+                    if (useColorArray)
+                        colormap.Map((m_colors.GetValue(0,c) - minC) * a, m_vertices,ref curVertPos); 
+                    else 
+                        colormap.Map((val - minZ) * a, m_vertices,ref curVertPos); 
+                    m_vertices[curVertPos++] = m_opacity;
+                    curVertPos += 3; 
+                    m_vertices[curVertPos++] = m_xCoords[m_rows*c]; 
+                    m_vertices[curVertPos++] = m_yCoords[m_rows*c]; 
+                    m_vertices[curVertPos++] = val;
+                }
+                for (int r = 1; r < m_rows; r++) {
+                    val = m_sourceArray.GetValue(r,0);
+                    if (useColorArray)
+                        colormap.Map((m_colors.GetValue(r) - minC) * a, m_vertices,ref curVertPos); 
+                    else 
+                        colormap.Map((val - minZ) * a, m_vertices,ref curVertPos); 
+                    m_vertices[curVertPos++] = m_opacity;
+                    curVertPos += 3; 
+                    m_vertices[curVertPos++] = m_xCoords[r]; 
+                    m_vertices[curVertPos++] = m_yCoords[r]; 
+                    m_vertices[curVertPos++] = val;
+                    // next columns: average color over precomputed corners
+                    for (int c = 1; c < m_cols; c++) {
+                        curVecPos = r + c * m_rows; 
+                        val = m_sourceArray.GetValue(r,c);
+                        val += m_sourceArray.GetValue(r-1,c); 
+                        val += m_sourceArray.GetValue(r,c-1); 
+                        val += m_sourceArray.GetValue(r-1,c-1); 
+                        val /= 4;
+                        if (useColorArray)
+                            colormap.Map((m_colors.GetValue(curVecPos) - minC) * a, m_vertices,ref curVertPos); 
+                        else 
+                            colormap.Map((val - minZ) * a, m_vertices,ref curVertPos); 
+                        m_vertices[curVertPos++] = m_opacity; 
+                        curVertPos += 3; 
+                        m_vertices[curVertPos++] = m_xCoords[curVecPos]; 
+                        m_vertices[curVertPos++] = m_yCoords[curVecPos]; 
+                        m_vertices[curVertPos++] = m_sourceArray.GetValue(r,c); 
+                    }
+                }
+                #endregion
+                m_oldColormap = colormap; 
+            }
+            #region create normals 
+            // todo: depends on lighting enabled or not...! 
+            // reset vertices pointer and start all over 
+            curVertPos = 0; float nx,ny,nz;
+            for (int r = 0; r < m_rows; r++) {
+                for (int c = 0; c < m_cols; c++) {
+                    nx= m_vertices[curVertPos+7];
+                    ny= m_vertices[curVertPos+8];
+                    nz= m_vertices[curVertPos+9];
+                    if (c > 0) {
+                        nx += m_vertices[curVertPos-3];
+                        ny += m_vertices[curVertPos-2];
+                        nz += m_vertices[curVertPos-1];
+                    }
+                    if (c < m_cols-1) { 
+                        nx += m_vertices[curVertPos+17];
+                        ny += m_vertices[curVertPos+18];
+                        nz += m_vertices[curVertPos+19];
+                    }
+                    if (r > 0 && r < m_rows) {
+                        nx += m_vertices[curVertPos-m_cols*10+10];
+                        ny += m_vertices[curVertPos-m_cols*10+11];
+                        nz += m_vertices[curVertPos-m_cols*10+12];
+                    }
+                    if (r < m_rows - 1) { 
+                        nx += m_vertices[curVertPos+m_cols*10+10];
+                        ny += m_vertices[curVertPos+m_cols*10+11];
+                        nz += m_vertices[curVertPos+m_cols*10+12];
+                    }
+                    // normalize
+                    float len = (float)Math.Sqrt(nx*nx+ny*ny+nz*nz); 
+                    m_vertices[curVertPos+4] = nx / len; 
+                    m_vertices[curVertPos+5] = ny / len; 
+                    m_vertices[curVertPos+6] = nz / len; 
+                    curVertPos+=10; 
+                }
+            }
+            #endregion
+            m_oldShading = m_shading; 
+            m_vertexReady = true;
+        }
+
+
+        #endregion
+
+        #region constructor
+        internal ILOGLSurfaceGraph(ILOGLPanel panel, ILArray<float> X,
+                                    ILArray<float> Y, ILArray<float> Z, ILArray<float> C,
+                                    ILClippingData clippingContainer) 
+                              : base(panel,X,Y,Z,C,clippingContainer) {
+            m_indexReady = false; 
+            m_vertexReady = false; 
+        }
+
+        #endregion
+
+        #region abstract interface
+        /// <summary>
+        /// Dispose off this graph's vertices
+        /// </summary>
+        public override void Dispose() {
+            base.Dispose(); 
+            if (m_vertices != null) {
+                ILMemoryPool.Pool.Free<float>(m_vertices); 
+            }
+        }
+        /// <summary>
+        /// Draw the graph
+        /// </summary>
+        public override void Draw(ILRenderProperties p) {
+            GL.BlendFunc (BlendingFactorSrc.SrcAlpha,
+                          BlendingFactorDest.OneMinusSrcAlpha);            
+            ILLineProperties wireprops = m_wireLines;
+            ILOGLPanel.SetupLineStyle(wireprops);
+            unsafe {
+                fixed (float* pVertices = m_vertices) {
+                    // populate vertex array to GL
+                    GL.InterleavedArrays(InterleavedArrayFormat.C4fN3fV3f
+                                         ,0,(IntPtr)pVertices); 
+                    // general setup shading & transparency
+                    if (m_shading == ShadingStyles.Interpolate) {                      
+                        GL.ShadeModel(ShadingModel.Smooth);
+                        //GL.Disable(EnableCap.DepthTest);
+                    } else {
+                        GL.ShadeModel(ShadingModel.Flat); 
+                        //if (m_opacity < 1.0f) 
+                        //else
+                        //    GL.Enable(EnableCap.DepthTest);
+                    }
+                    GL.Enable(EnableCap.DepthTest);
+                    
+                    
+                    if (m_opacity == 1.0f && m_shading == ShadingStyles.Interpolate) {
+                        #region no transpareny
+                        GL.Disable(EnableCap.Blend); 
+                        GL.Enable(EnableCap.DepthTest); 
+                        fixed (UInt32* pGridIndices = m_gridIndices)
+                        fixed (UInt32* pIndices = m_indices) {
+                            UInt32* pGridIndWalk = pGridIndices; 
+                            // first surface strip
+                            if (m_filled) {
+                                GL.DrawElements(BeginMode.TriangleStrip,m_stripesLen,
+                                                DrawElementsType.UnsignedInt,
+                                                (IntPtr)pIndices);
+                            }    
+                            // first grid strip
+                            if (m_wireLines.Visible) {
+                                if (!wireprops.Color.IsEmpty) {
+                                    // if a color was specified, use it for wireframes!
+                                    GL.DisableClientState(EnableCap.ColorArray);
+                                    //GL.Color3(wireprops.ForeColor); // color for grid lines  
+                                }
+                                GL.DrawElements(BeginMode.Lines,
+                                            m_gridStripsLen + m_gridStripsLenOnce, // 2*(m_cols-1),
+                                            DrawElementsType.UnsignedInt,
+                                            (IntPtr)pGridIndWalk);
+                                pGridIndWalk += (m_gridStripsLen + m_gridStripsLenOnce); 
+                                if (!wireprops.Color.IsEmpty) {
+                                    GL.EnableClientState(EnableCap.ColorArray); 
+                                }
+                            }
+                            for (int i = 1; i < m_stripesCount; i++) {
+                                // subsequent surface strips
+                                if (m_filled) {
+                                    GL.DrawElements(BeginMode.TriangleStrip,
+                                                    m_stripesLen,
+                                                    DrawElementsType.UnsignedInt,
+                                                    (IntPtr)(pIndices+i*m_stripesLen));
+                                }
+                                // subsequent grid strips 
+                                if (m_wireLines.Visible) {
+                                    GL.Disable(EnableCap.Blend); 
+                                    if (!wireprops.Color.IsEmpty) {
+                                        // if a color was specified, use it for wireframes!
+                                        GL.DisableClientState(EnableCap.ColorArray);
+                                        //GL.Color3(wireprops.ForeColor); // color for grid lines  
+                                    }
+                                    GL.DrawElements(BeginMode.Lines,
+                                                m_gridStripsLen,
+                                                DrawElementsType.UnsignedInt,
+                                                (IntPtr)(pGridIndWalk));
+                                    pGridIndWalk += m_gridStripsLen; 
+                                    if (!wireprops.Color.IsEmpty) {
+                                        GL.EnableClientState(EnableCap.ColorArray); 
+                                    }
+                                }
+                            }
+                            GL.Finish(); 
+                        }
+                        #endregion
+                    } else {
+                        #region transparency or flat shading 
+                        GL.Enable(EnableCap.Blend); 
+                        fixed (UInt32* pGridIndices = m_gridIndices)
+                        fixed (UInt32* pIndices = m_indices) {
+                            UInt32* pGridIndWalk = pGridIndices; 
+                            // first surface strip
+                            if (m_filled) {
+                                GL.DrawElements(BeginMode.Triangles,m_stripesLen,
+                                                DrawElementsType.UnsignedInt,
+                                                (IntPtr)pIndices);
+                            }    
+                            // first grid strip
+                            if (m_wireLines.Visible) {
+                                GL.Disable(EnableCap.Blend); 
+                                if (!wireprops.Color.IsEmpty) {
+                                    // if a color was specified, use it for wireframes!
+                                    GL.DisableClientState(EnableCap.ColorArray);
+                                    GL.Color3(m_wireLines.Color); 
+                                }
+                                GL.DrawElements(BeginMode.Lines,
+                                            m_gridStripsLen + m_gridStripsLenOnce,
+                                            DrawElementsType.UnsignedInt,
+                                            (IntPtr)pGridIndWalk);
+                                pGridIndWalk += m_gridStripsLen + m_gridStripsLenOnce; 
+                                if (!wireprops.Color.IsEmpty) {
+                                    // if a color was specified, use it for wireframes!
+                                    GL.EnableClientState(EnableCap.ColorArray); 
+                                }
+                                GL.Enable(EnableCap.Blend); 
+                            }
+                            for (int i = 1; i < m_stripesCount; i++) {
+                                // subsequent surface strips
+                                if (m_filled) {
+                                    GL.DrawElements(BeginMode.Triangles,
+                                                    m_stripesLen,
+                                                    DrawElementsType.UnsignedInt,
+                                                    (IntPtr)(pIndices+i*m_stripesLen));
+                                }
+                                // subsequent grid strips 
+                                if (m_wireLines.Visible) {
+                                    GL.Disable(EnableCap.Blend); 
+                                    if (!wireprops.Color.IsEmpty) {
+                                        // if a color was specified, use it for wireframes!
+                                        GL.DisableClientState(EnableCap.ColorArray);
+                                        GL.Color3(m_wireLines.Color); 
+                                    }
+                                    GL.DrawElements(BeginMode.Lines,
+                                                m_gridStripsLen,
+                                                DrawElementsType.UnsignedInt,
+                                                (IntPtr)(pGridIndWalk));
+                                    if (!wireprops.Color.IsEmpty) {
+                                        GL.EnableClientState(EnableCap.ColorArray); 
+                                    }
+                                    GL.Enable(EnableCap.Blend); 
+                                    pGridIndWalk += m_gridStripsLen; 
+                                }
+                            }
+                            GL.Finish(); 
+                        }
+                        #endregion
+                    }
+                }
+            }
+            //GL.Disable(EnableCap.Lighting);
+            //GL.PopMatrix(); 
+        }
+        /// <summary>
+        /// Ensures the recreation of the graph if neccessary
+        /// </summary>
+        public override void Invalidate() {
+            if (m_panel == null) return; 
+            if (Math.Floor(m_panel.Camera.Phi / (Math.PI / 4.0)) != m_oldSubQuadrant) {    
+                //must only recalculate indices, and only if the camera subquadrant has changed
+                m_indexReady = false; 
+                m_isReady = false; 
+            } 
+            if (m_oldShading != m_shading) {
+                m_indexReady = false; 
+                m_vertexReady = false; 
+                m_isReady = false; 
+            }
+            if (m_oldColormap != m_panel.Colormap) {
+                m_vertexReady = false; 
+                m_isReady = false; 
+            }
+        }
+        public override void DrawToLegend(ILRenderProperties p, Rectangle sampleRect, Rectangle labelRect) {
+            if (m_filled) {
+                // draw inner filled area
+                GL.ShadeModel(ShadingModel.Smooth); 
+                GL.Begin(BeginMode.TriangleStrip); 
+                    GL.Color3(m_panel.Colormap[m_panel.Colormap.Length-1]); 
+                    GL.Vertex2(sampleRect.X,sampleRect.Y + sampleRect.Height); 
+                    GL.Color3(m_panel.Colormap[(int)(m_panel.Colormap.Length/2)]); 
+                    GL.Vertex2(sampleRect.X,sampleRect.Y); 
+                    GL.Vertex2(sampleRect.X+sampleRect.Width,sampleRect.Y + sampleRect.Height); 
+                    GL.Color3(m_panel.Colormap[0]); 
+                    GL.Vertex2(sampleRect.X+sampleRect.Width,sampleRect.Y); 
+                GL.End(); 
+            } 
+            if (m_wireLines.Visible) {
+                ILNumerics.Drawing.Platform.OpenGL.ILOGLPanel.SetupLineStyle(m_wireLines); 
+                GL.Begin(BeginMode.LineStrip); 
+                    GL.Vertex2(sampleRect.X,sampleRect.Y); 
+                    GL.Vertex2(sampleRect.X+sampleRect.Width,sampleRect.Y); 
+                    GL.Vertex2(sampleRect.X+sampleRect.Width,sampleRect.Y + sampleRect.Height); 
+                    GL.Vertex2(sampleRect.X,sampleRect.Y + sampleRect.Height); 
+                    GL.Vertex2(sampleRect.X,sampleRect.Y); 
+                GL.End(); 
+            }
+            m_label.m_position.X = labelRect.X + labelRect.Width / 2;
+            m_label.m_position.Y = labelRect.Y + labelRect.Height / 2; 
+            m_label.Anchor = new PointF(.5f,0);  //  = TickLabelAlign.center | TickLabelAlign.vertCenter; 
+            m_label.Draw(p); 
+        }
+        #endregion
+
+        #region helper function 
+
+        protected override void m_globalClipping_Changed(object sender, ClippingChangedEventArgs e) {
+            base.m_globalClipping_Changed(sender, e);
+            m_vertexReady = false; 
+            m_indexReady = false; 
+            Configure(); 
+        }
+        
+        #endregion
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLTextureStorage.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLTextureStorage.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLTextureStorage.cs	(revision 9102)
@@ -0,0 +1,174 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Drawing.Labeling; 
+using ILNumerics.Misc;
+using OpenTK.Graphics.OpenGL; 
+using OpenTK.Graphics;
+using System.Drawing;
+using System.Drawing.Imaging;
+using ILNumerics.Exceptions; 
+
+namespace ILNumerics.Drawing.Platform.OpenGL {
+    /// <summary>
+    /// OpenGL implementation of ILTextureStorage
+    /// </summary>
+    public class ILOGLTextureStorage : ILTextureStorage {
+
+        #region attributes
+        new int [] m_tmpData = new int[20*20];
+        #endregion
+
+        #region constructor
+        public ILOGLTextureStorage (int width, int height) : base (width, height) { }
+        #endregion
+
+        #region abstract overrides 
+        /// <summary>
+        /// Select this storage to be current in GL
+        /// </summary>
+        public override void MakeCurrent() {
+            GL.BindTexture(TextureTarget.Texture2D,m_textureId);  
+            //System.Diagnostics.Debug.WriteLine(String.Format("ILOGLTextureStorage: switched to ID#{0}",m_textureId)); 
+        }
+        /// <summary>
+        /// initialize texture sheet 
+        /// </summary>
+        protected override void InitTexture() {
+            GL.GenTextures(1, out m_textureId);
+            //System.Diagnostics.Debug.WriteLine(String.Format("ILTextureStorage{2}: TextureID={0}, Thread={1}"
+            //        ,m_textureId, System.Threading.Thread.CurrentThread.ManagedThreadId,this.GetHashCode())); 
+            GL.BindTexture(TextureTarget.Texture2D, m_textureId);
+            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)All.Repeat);
+            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)All.Repeat);
+            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.Linear);
+            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Linear);
+            GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Alpha, m_width, m_height, 0,
+                OpenTK.Graphics.PixelFormat.Rgba, PixelType.UnsignedByte, IntPtr.Zero);
+            // todo: error handling! 
+        }
+        /// <summary>
+        /// store item in texture sheet in GL
+        /// </summary>
+        /// <param name="bmp">new item bitmap data, ARGB format</param>
+        /// <param name="bmpRectF">rectangle used in bitmap</param>
+        /// <param name="rect">rectangle specifying area to store the data into the texture sheet, 
+        /// integer pixels coords: range from 0...m_width|m_height (e.g. '512')</param>
+        protected override void Store(Bitmap bmp,RectangleF bmpRectF, RectangleF rect) {
+            if (rect.Size.Width == 0 || rect.Size.Height == 0) return; 
+            if (m_disposed) 
+                throw new InvalidOperationException("The texture storage has been disposed already! (Need to create a new storage)"); 
+            if (bmp == null) 
+                throw new ILArgumentException("Bitmap argument must not be null!"); 
+            Rectangle bmpRect = Rectangle.Ceiling(bmpRectF); 
+            if (bmp.PixelFormat != System.Drawing.Imaging.PixelFormat.Format32bppArgb) {
+                bmp = bmp.Clone(bmpRect,System.Drawing.Imaging.PixelFormat.Format32bppArgb); 
+                bmpRect.X = 0; bmpRect.Y = 0; 
+            }
+            GL.BindTexture(TextureTarget.Texture2D, m_textureId);
+            BitmapData bmp_data = bmp.LockBits(new Rectangle(0,0,bmp.Width,bmp.Height), ImageLockMode.ReadOnly,System.Drawing.Imaging.PixelFormat.Format32bppArgb);
+            // setup OpenGL pixel store
+            GL.PixelStore(PixelStoreParameter.UnpackAlignment,1.0f); 
+            GL.PixelStore(PixelStoreParameter.UnpackRowLength,bmp.Width); 
+            GL.PixelStore(PixelStoreParameter.UnpackSkipRows,bmpRect.Y); 
+            GL.PixelStore(PixelStoreParameter.UnpackSkipPixels,bmpRect.X); 
+            GL.TexSubImage2D(TextureTarget.Texture2D, 0, (int)rect.Left, (int)rect.Top, bmpRect.Width, bmpRect.Height,
+                     OpenTK.Graphics.PixelFormat.Rgba, PixelType.UnsignedByte, bmp_data.Scan0);
+#region DEBUGGING only
+#if EXPORTBMP
+            // must copy to new data array
+            if (m_tmpData.Length < bmpRect.Height * bmpRect.Width) {
+                if (m_tmpData != null) 
+                    ILMemoryPool.Pool.RegisterObject(m_tmpData); 
+                m_tmpData = ILMemoryPool.Pool.New<int>(bmpRect.Height * bmpRect.Width);    
+            }
+            unsafe {
+            fixed (int* tmpDataP = m_tmpData) {
+                int* pOut = tmpDataP; 
+                int* pIn; 
+                int* pInEnd;
+                for (int r = 0; r < bmpRect.Height; r++) {
+                    //pIn = (int*)bitmap_data.Scan0 + (r+(int)location.Y) * data.Width + (int)location.X; 
+                    pIn = ((int*)bmp_data.Scan0) + r * (bmp_data.Stride / 4) + bmpRect.X; 
+                    pInEnd = pIn + bmpRect.Width; 
+                    while (pIn < pInEnd) {
+                        *(pOut++) = *(pIn++);     
+                    }
+                }
+                //GL.TexSubImage2D(TextureTarget.Texture2D, 0, (int)rect.Left, (int)rect.Top, bmpRect.Width, bmpRect.Height,
+                //     OpenTK.Graphics.PixelFormat.Rgba, PixelType.UnsignedByte, (IntPtr)tmpDataP);
+                Bitmap outB = new Bitmap(bmpRect.Width, bmpRect.Height);
+                for (int i = 0; i < bmpRect.Width * bmpRect.Height; i++)
+                    outB.SetPixel(i%bmpRect.Width,(int)(i/bmpRect.Width),Color.FromArgb(m_tmpData[i]));
+                outB.Save("EXPORTBMP_textureCached.bmp",ImageFormat.Bmp); 
+                outB.Dispose(); 
+                string dbTrOut = String.Format("usedArea:{0}:{1}:{2}:{3} data:{4} bmp_data: {5}:{6} stride:{7} Loc:{8}"
+                                ,bmpRect.Left, bmpRect.Top, bmpRect.Width, bmpRect.Height
+                                ,bmp.Size.ToString()
+                                ,bmp_data.Width,bmp_data.Height
+                                ,bmp_data.Stride
+                                ,bmpRectF.Location); 
+
+                Console.Out.WriteLine(dbTrOut); 
+                System.Diagnostics.Debug.WriteLine(dbTrOut); 
+            }}
+#endif
+#endregion
+            bmp.UnlockBits(bmp_data);
+        }
+        /// <summary>
+        /// dispose off the texture storage's ressources
+        /// </summary>
+        /// <param name="manual"></param>
+        public override void Dispose(bool manual) {
+            if (!m_disposed) {
+                if (manual) {
+                    // free texture from OGL 
+                    GL.DeleteTextures(1, ref m_textureId);
+                }
+                m_disposed = true; 
+            }
+        }
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLVertexRendererC4bV3f.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLVertexRendererC4bV3f.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLVertexRendererC4bV3f.cs	(revision 9102)
@@ -0,0 +1,155 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using ILNumerics.Drawing.Shapes; 
+using OpenTK.Graphics;
+using OpenTK.Graphics.OpenGL; 
+
+namespace ILNumerics.Drawing.Platform.OpenGL {
+    /// <summary>
+    /// An OpenGL vertex renderer, capable of rendering
+    /// vertex arrays of type C4bV3f (simple /-primitive shapes).
+    /// </summary>
+    public unsafe class ILOGLVertexRendererC4bV3f : ILVertexRenderer {
+
+        #region attributes
+        BeginMode m_primitiveType; 
+        #endregion
+
+        #region properties
+        public BeginMode PrimitiveType {
+            get {
+                return m_primitiveType; 
+            } 
+            set {
+                m_primitiveType = value; 
+            }
+        }
+        #endregion
+
+        public ILOGLVertexRendererC4bV3f (BeginMode primitiveType) {
+            m_primitiveType = primitiveType; 
+        }
+        public override void Draw(ILRenderProperties props, ILShape shape) {
+            GL.Enable(EnableCap.Blend);
+            GL.BlendFunc (BlendingFactorSrc.SrcAlpha,
+                          BlendingFactorDest.OneMinusSrcAlpha); 
+            GL.Enable(EnableCap.DepthTest);
+            //GL.Disable(EnableCap.PolygonOffsetFill); 
+            GL.Disable(EnableCap.LineSmooth); 
+            ILShape<C4bV3f> cShape = (shape as ILShape<C4bV3f>);
+            ILBorderedShape<C4bV3f> bShape = (shape as ILBorderedShape<C4bV3f>); 
+            if (bShape != null && bShape.Border.Visible) {
+                fixed (C4bV3f* pVertices = bShape.Vertices) {
+                    ILOGLPanel.SetupLineStyle(bShape.Border);
+                    GL.InterleavedArrays(InterleavedArrayFormat.C4ubV3f, 0, (IntPtr)pVertices);
+                    GL.DisableClientState(EnableCap.ColorArray);
+                    if (CloseLines)
+                        GL.DrawArrays(BeginMode.LineLoop, 0, bShape.VertexCount);
+                    else 
+                        GL.DrawArrays(BeginMode.LineStrip, 0, bShape.VertexCount);
+                }
+            }
+            if (cShape is ILLine) {
+                ILOGLPanel.SetupLineStyle((cShape as ILLine).Properties);
+                GL.Disable(EnableCap.DepthTest); 
+            }
+            fixed (C4bV3f* pVertices = cShape.Vertices) {
+                GL.InterleavedArrays(InterleavedArrayFormat.C4ubV3f, 0, (IntPtr)pVertices);
+                if (cShape.Shading == ShadingStyles.Interpolate)
+                    GL.ShadeModel(ShadingModel.Smooth);
+                else {
+                    GL.ShadeModel(ShadingModel.Flat);
+                    GL.DisableClientState(EnableCap.ColorArray);
+                    GL.Color4(shape.FillColor);  
+                }
+                GL.DrawArrays(m_primitiveType, 0, cShape.VertexCount);
+            }
+
+        }
+        public override void Draw(ILRenderProperties props, ILShape shape, int[] indices) {
+            System.Diagnostics.Debug.Assert(indices != null); 
+            GL.Enable(EnableCap.DepthTest);
+            GL.Disable(EnableCap.Blend); 
+            ILBorderedShape<C4bV3f> bShape = (shape as ILBorderedShape<C4bV3f>); 
+            if (bShape != null && bShape.Border.Visible) {
+                fixed (int* pIndices = indices) 
+                fixed (C4bV3f* pVertices = bShape.Vertices) {
+                    ILOGLPanel.SetupLineStyle(bShape.Border);
+                    GL.InterleavedArrays(
+                                    InterleavedArrayFormat.C4ubV3f, 0, (IntPtr)pVertices);
+                    GL.DisableClientState(EnableCap.ColorArray);
+                    if (CloseLines)
+                        GL.DrawElements(BeginMode.LineLoop, indices.Length, 
+                                    DrawElementsType.UnsignedInt, (IntPtr)pIndices);
+                    else 
+                        GL.DrawElements(BeginMode.LineStrip, indices.Length, 
+                                    DrawElementsType.UnsignedInt, (IntPtr)pIndices);
+                }
+            }
+            
+            GL.Enable(EnableCap.Blend);
+            GL.BlendFunc (BlendingFactorSrc.SrcAlpha,
+                          BlendingFactorDest.OneMinusSrcAlpha); 
+            ILShape<C4bV3f> cShape = (shape as ILShape<C4bV3f>);
+            if (cShape is ILLine) {
+                ILOGLPanel.SetupLineStyle((cShape as ILLine).Properties);
+                GL.Disable(EnableCap.DepthTest); 
+            } else {
+                GL.Disable(EnableCap.LineSmooth);
+            }
+            fixed (int* pIndices = indices) 
+            fixed (C4bV3f* pVertices = cShape.Vertices) {
+                GL.InterleavedArrays(InterleavedArrayFormat.C4ubV3f, 0, (IntPtr)pVertices);
+                if (cShape.Shading == ShadingStyles.Interpolate)
+                    GL.ShadeModel(ShadingModel.Smooth);
+                else {
+                    GL.ShadeModel(ShadingModel.Flat);
+                    GL.DisableClientState(EnableCap.ColorArray);
+                    GL.Color4(shape.FillColor); 
+                }
+                GL.DrawElements(m_primitiveType, indices.Length,
+                                DrawElementsType.UnsignedInt, (IntPtr)pIndices);
+            }
+
+        }
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLVertexRendererC4fN3fV3f.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLVertexRendererC4fN3fV3f.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLVertexRendererC4fN3fV3f.cs	(revision 9102)
@@ -0,0 +1,201 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using ILNumerics.Drawing.Shapes; 
+using OpenTK.Graphics;
+using OpenTK.Graphics.OpenGL; 
+using ILNumerics.Drawing.Interfaces; 
+
+namespace ILNumerics.Drawing.Platform.OpenGL {
+    /// <summary>
+    /// An OpenGL vertex renderer, capable of rendering
+    /// vertex arrays of type C4fN3fV3f (for lit shapes).
+    /// </summary>
+    public unsafe class ILOGLVertexRendererC4fN3fV3f : ILVertexRenderer {
+
+        #region attributes
+        BeginMode m_primitiveType; 
+        InterleavedArrayFormat m_vertexFormat; 
+        #endregion
+
+        #region properties
+        public BeginMode PrimitiveType {
+            get {
+                return m_primitiveType; 
+            } 
+            set {
+                m_primitiveType = value; 
+            }
+        }
+        #endregion
+
+        public ILOGLVertexRendererC4fN3fV3f (BeginMode primitiveType) {
+            m_primitiveType = primitiveType; 
+        }
+
+        public override void Draw(ILRenderProperties props, ILShape shape) {
+            if (shape.VertexCount == 0) return; 
+            GL.Enable(EnableCap.Blend);
+            GL.BlendFunc (BlendingFactorSrc.SrcAlpha,
+                          BlendingFactorDest.OneMinusSrcAlpha); 
+            GL.Enable(EnableCap.DepthTest);
+            //GL.Disable(EnableCap.PolygonOffsetFill); 
+            ILShape<C4fN3fV3f> cShape = (shape as ILShape<C4fN3fV3f>);
+            fixed (C4fN3fV3f* pVertices = cShape.Vertices) {
+                if (UseLight && (cShape is IILSupportsLight)) {
+                    setupLight(cShape as IILSupportsLight);  
+                } else {
+                    GL.Disable(EnableCap.Lighting); 
+                }
+                GL.InterleavedArrays(InterleavedArrayFormat.C4fN3fV3f, 0, (IntPtr)pVertices);
+                if (cShape.Shading == ShadingStyles.Interpolate)
+                    GL.ShadeModel(ShadingModel.Smooth);
+                else {
+                    GL.ShadeModel(ShadingModel.Flat);
+                    GL.DisableClientState(EnableCap.ColorArray);
+                    GL.Color4(shape.FillColor);  
+                }
+                GL.DrawArrays(m_primitiveType, 0, cShape.VertexCount);
+                GL.Finish(); 
+            }
+            GL.Disable(EnableCap.Lighting); 
+            ILBorderedShape<C4fN3fV3f> bShape = (shape as ILBorderedShape<C4fN3fV3f>); 
+            if (bShape != null && bShape.Border.Visible) {
+                fixed (C4fN3fV3f* pVertices = bShape.Vertices) {
+                    ILOGLPanel.SetupLineStyle(bShape.Border);
+                    GL.InterleavedArrays(InterleavedArrayFormat.C4fN3fV3f, 0, (IntPtr)pVertices);
+                    GL.DisableClientState(EnableCap.ColorArray);
+                    GL.DrawArrays(BeginMode.LineLoop, 0, bShape.VertexCount);
+                    GL.Finish(); 
+                }
+            }
+        }
+        public override void Draw(ILRenderProperties props, ILShape shape, int[] indices) {
+            System.Diagnostics.Debug.Assert(indices != null); 
+            GL.Enable(EnableCap.DepthTest);
+            GL.Enable(EnableCap.Blend);
+            GL.BlendFunc (BlendingFactorSrc.SrcAlpha,
+                          BlendingFactorDest.OneMinusSrcAlpha); 
+            // draw shape
+            ILShape<C4fN3fV3f> cShape = (shape as ILShape<C4fN3fV3f>);
+            fixed (int* pIndices = indices) 
+            fixed (C4fN3fV3f* pVertices = cShape.Vertices) {
+                if (UseLight && (cShape is ILLitCompositeShape<C4fN3fV3f>)) {
+                    setupLight(cShape as ILLitCompositeShape<C4fN3fV3f>);
+                } else {
+                    GL.Disable(EnableCap.Lighting);
+                }
+                GL.InterleavedArrays(InterleavedArrayFormat.C4fN3fV3f, 0, (IntPtr)pVertices);
+                if (cShape.Shading == ShadingStyles.Interpolate)
+                    GL.ShadeModel(ShadingModel.Smooth);
+                else {
+                    GL.ShadeModel(ShadingModel.Flat);
+                    GL.DisableClientState(EnableCap.ColorArray);
+                    GL.Color4(shape.FillColor); 
+                }
+                GL.DrawElements(m_primitiveType, indices.Length,DrawElementsType.UnsignedInt, (IntPtr)pIndices);
+                //IntPtr pObj = Glu.NewQuadric();
+                //GL.MatrixMode(MatrixMode.Modelview);
+                //GL.PushMatrix();
+                //GL.Translate(cShape.Vertices[0].Position.X, cShape.Vertices[0].Position.Y, cShape.Vertices[0].Position.Z);
+                //Glu.QuadricDrawStyle(pObj, QuadricDrawStyle.Fill);
+                //Glu.Sphere(pObj, 2, 20, 10);
+                //GL.PopMatrix(); 
+                GL.Finish(); 
+            }
+            // draw border 
+            ILBorderedShape<C4fN3fV3f> bShape = (shape as ILBorderedShape<C4fN3fV3f>); 
+            if (bShape != null && bShape.Border.Visible) {
+                fixed (int* pIndices = indices) 
+                fixed (C4fN3fV3f* pVertices = bShape.Vertices) {
+                    ILOGLPanel.SetupLineStyle(bShape.Border);
+                    GL.InterleavedArrays(
+                                    InterleavedArrayFormat.C4fN3fV3f, 0, (IntPtr)pVertices);
+                    GL.DisableClientState(EnableCap.ColorArray);
+                    GL.DrawElements(BeginMode.LineLoop, indices.Length, 
+                                    DrawElementsType.UnsignedInt, (IntPtr)pIndices);
+                    GL.Finish(); 
+
+                }
+            }
+
+#if RENDERER_DRAW_NORMALS
+            #region DEBUG_DRAW_NORMALS 
+            GL.Color3(0,0,0); 
+            GL.Begin(BeginMode.Lines);
+            for (int i = 0; i < shape.VertexCount; i++) {
+                GL.Vertex3(cShape.Vertices[i].XPosition,cShape.Vertices[i].YPosition,cShape.Vertices[i].ZPosition); 
+                GL.Vertex3( cShape.Vertices[i].XPosition+cShape.Vertices[i].Normal.X,
+                            cShape.Vertices[i].YPosition+cShape.Vertices[i].Normal.Y,
+                            cShape.Vertices[i].ZPosition+cShape.Vertices[i].Normal.Z); 
+            }
+            GL.End(); 
+            #endregion
+#endif
+            GL.Disable(EnableCap.Lighting); 
+
+        }
+        private void setupLight(IILSupportsLight shape) {
+            GL.Enable(EnableCap.Lighting);
+            GL.Enable(EnableCap.ColorMaterial);
+            //GL.Enable(EnableCap.Normalize); 
+            GL.ColorMaterial(MaterialFace.FrontAndBack,ColorMaterialParameter.AmbientAndDiffuse);
+            
+            //GL.LightModel(LightModelParameter.LightModelAmbient, 0.2f);
+            float[] tmp = new float[4] { 
+                  shape.Material.Specular.R / 255f
+                , shape.Material.Specular.G / 255f
+                , shape.Material.Specular.B / 255f
+                , shape.Material.Specular.A / 255f};
+            GL.Materialv(MaterialFace.FrontAndBack, MaterialParameter.Specular, tmp);
+
+            GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Shininess, shape.Material.Shininess );
+
+            tmp = new float[4] { 
+                  shape.Material.Emission.R / 255f
+                , shape.Material.Emission.G / 255f
+                , shape.Material.Emission.B / 255f
+                , shape.Material.Emission.A / 255f};
+            GL.Materialv(MaterialFace.FrontAndBack, MaterialParameter.Emission, tmp); 
+            
+        }
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLWorldRenderer.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLWorldRenderer.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLWorldRenderer.cs	(revision 9102)
@@ -0,0 +1,295 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Text;
+using System.Drawing;  
+using System.Collections.Generic;
+using ILNumerics.Drawing.Interfaces; 
+using OpenTK; 
+using OpenTK.Graphics;
+using OpenTK.Graphics.OpenGL; 
+using OpenTK.Graphics.OpenGL.Enums; 
+using ILNumerics.Drawing; 
+using ILNumerics.Drawing.Labeling;  
+
+namespace ILNumerics.Drawing.Platform.OpenGL {
+    /// <summary>
+    /// Basic OpenGL implementation for IILTextRenderer
+    /// </summary>
+    [ILRenderer(GraphicDeviceType.OpenGL,"Outline","OpenGL cached, outlined textures, world coords",true,CoordSystem.World3D)] 
+    public class ILOGLWorldRenderer : IILTextRenderer {
+
+        #region event handling
+        /// <summary>
+        /// fires when the texture storage has been cleared 
+        /// </summary>
+        public event EventHandler CacheCleared; 
+        void m_textureManager_TextureCacheCleared(object sender, EventArgs e) {
+            if (CacheCleared != null) 
+                CacheCleared(this,null);
+        }
+        #endregion
+
+        #region member / properties
+        ILTextureManager m_textureManager; 
+        float[] m_curPosition = new float[16];
+        Color m_colorOverride; 
+        #endregion
+
+        #region constructors
+
+        public ILOGLWorldRenderer (ILPanel panel) {
+            m_textureManager = panel.TextureManager;
+            m_textureManager.TextureCacheCleared += new EventHandler(m_textureManager_TextureCacheCleared);
+        }
+           
+        #endregion
+
+        #region IILTextRenderer Member
+        
+        public CoordSystem CoordSystem {
+            get { return CoordSystem.World3D; }
+        }
+
+        public bool Cached { 
+            get {
+                return true; 
+            }
+        }
+
+        public string Name {
+            get { return "Outline fonts"; }
+        }
+
+        public string NameLong {
+            get { return "OpenGL outline fonts (OpenTK)"; }
+        }
+
+        public GraphicDeviceType DeviceType {
+            get { return GraphicDeviceType.OpenGL; }
+        }
+
+        public bool DrawAfterBufferSwapped {
+            get { return false; }
+        }
+
+        public void Begin(ILRenderProperties p) {
+            if (GraphicsContext.CurrentContext == null)
+                throw new GraphicsContextException("No GraphicsContext is current in the calling thread.");
+
+            GL.PushAttrib(AttribMask.TextureBit | AttribMask.EnableBit | AttribMask.ColorBufferBit);
+
+            GL.Enable(EnableCap.Texture2D);
+            GL.Enable(EnableCap.Blend);
+            GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
+            GL.Disable(EnableCap.DepthTest);
+        }
+        public void Begin (ILRenderProperties p, ref double[] modelview) {
+            if (modelview == null || modelview.Length < 12) {
+                modelview = new double[16]; 
+            }
+            GL.GetDouble(GetPName.ModelviewMatrix,modelview);
+            Begin(p); 
+        }
+
+        public void End(ILRenderProperties p) {
+            GL.PopAttrib();
+        }
+        #endregion
+
+        #region IILTextRenderer Member
+        /// <summary>
+        /// Place a new item into the texture cache 
+        /// </summary>
+        /// <param name="key">unique key to identify the item for later reference</param>
+        /// <param name="bmp">bitmap containing the item data</param>
+        /// <param name="rect">area in <paramref name="bmp"/> containing the item's data</param>
+        public void Cache(string key, Bitmap bmp, RectangleF rect) {
+            m_textureManager.StoreTextureItem(key,bmp,rect); 
+        }
+
+        /// <summary>
+        /// Test if the cache contains an item with a specific key
+        /// </summary>
+        /// <param name="key">key</param>
+        /// <returns>true if the item was cached, false otherwise</returns>
+        public bool ExistsKey(string key) {
+            return m_textureManager.Exists(key); 
+        }
+
+        /// <summary>
+        /// try to get the size (screen pixels) of an item
+        /// </summary>
+        /// <param name="key">unique key identifying the item</param>
+        /// <param name="size">[output] size of the item (if found)</param>
+        /// <returns>true, if the item was found, false otherwise</returns>
+        public bool TryGetSize(string key, ref Size size) {
+            ILTextureData item; 
+            if (m_textureManager.TryGetTextureItem(key,out item)) {
+                size = new Size(item.Width,item.Height); 
+                return true; 
+            } else {
+                return false; 
+            }
+        }
+
+        /// <summary>
+        /// Draws all items contained in a given render queue
+        /// </summary>
+        /// <param name="queue">render queue</param>
+        /// <param name="x1">x1-position</param>
+        /// <param name="y1">y1-position</param>
+        /// <param name="z1">z1-position</param>
+        /// <param name="x2">x2-position</param>
+        /// <param name="y2">y2-position</param>
+        /// <param name="z2">z2-position</param>
+        /// <param name="color">base color for items not containing individual colors</param>
+        /// <remarks><para>The render queue must contain only keys for already cached items!</para>
+        /// <para>The color parameter serves as a global color definition. It may be overwritten 
+        /// by individual color specifications of the queue items.</para>
+        /// <para>Use this function to draw the render queue in world coords. The position parameters mark the upper left 
+        /// and lower right corner of the quads to contain the render queue content.</para>
+        /// </remarks>
+        public void Draw(ILRenderQueue queue, 
+                        float x1, float y1, float z1, float x2, float y2, float z2, 
+                        Color color) {
+            float x, y, xm, ym;
+
+            xm = (x2 - x1)/(queue.Size.Width);
+            ym = (y2 - y1)/(queue.Size.Height); 
+            x = 0.5f; y = 0.5f; 
+            int lineHeight = 0; 
+            m_textureManager.Reset(); 
+            GLColor3(color); 
+            
+            foreach (ILRenderQueueItem item in queue) {
+                // special symbols & control sequences 
+                switch (item.Key) {
+                case "\r":
+                    x = 0.5f; 
+                    break; 
+                case "\n": 
+                    x = 0.5f; 
+                    y += lineHeight; 
+                    lineHeight = 0; 
+                    break; 
+                default: 
+                    //since textures (may) lay on different sheets in GL memory,
+                    // we cannot switch them in between Begin() and End(), 
+                    // we must start a new Begin with each Quad :(
+                    // possible workaround: If only one sheet is used, draw all 
+                    // quads at once.
+                    ILTextureData textData = m_textureManager.GetTextureItem(item.Key,true); 
+                    if (item.Color != Color.Empty) {
+                        GLColor3(item.Color); 
+                    } else {
+                        GLColor3(color); 
+                    }
+                    GL.Begin(BeginMode.Quads); 
+                    RectangleF rectF = textData.TextureRectangle; 
+                    GL.TexCoord2(rectF.Left,rectF.Bottom);   
+                    GL.Vertex3(x*xm + x1,(y + textData.Height + item.Offset.Y-1)*ym+y1,z1);      // ul
+                    GL.TexCoord2(rectF.Left,rectF.Top); 
+                    GL.Vertex3(x*xm + x1,(y+ item.Offset.Y)*ym+y1,z1);                    // bl
+                    x += textData.Width-1; 
+                    GL.TexCoord2(rectF.Right,rectF.Top); 
+                    GL.Vertex3(x*xm + x1,(y+ item.Offset.Y)*ym+y1,z1);                    // br
+                    GL.TexCoord2(rectF.Right,rectF.Bottom); 
+                    GL.Vertex3(x*xm + x1,(y + textData.Height+ item.Offset.Y-1)*ym+y1,z1);      // tr
+                    if (textData.Height > lineHeight)
+                        lineHeight = textData.Height; 
+                    GL.End(); 
+#if BOUNDINGBOXES_ITEM
+            //// define DEBUG symbol to draw bounding box around each item (debug feature)
+            // todo: modify to draw in world coords if needed!!
+            //GL.Color3(Color.Red); 
+            //GL.Begin(BeginMode.LineLoop); 
+            //    w-= textData.Width; 
+            //    GL.Vertex2(w,h + textData.Height);      // ul
+            //    GL.Vertex2(w,h);                    // bl
+            //    w += textData.Width; 
+            //    GL.Vertex2(w,h);                    // br
+            //    GL.Vertex2(w,h + textData.Height);      // tr
+            //GL.End();
+#endif
+                    break; 
+                }
+            }
+#if BOUNDINGBOXES
+            //// define debugsymbol "BOUNDINGBOXES", to draw bounding box around whole expression
+            // todo: modify to draw in world coords if needed!!
+            //GL.Disable(EnableCap.Texture2D); 
+            //GL.Color3(Color.Red); 
+            //GL.LineWidth(1); 
+            //GL.Begin(BeginMode.LineLoop); 
+            //    GL.Vertex2(0,0);      // ul
+            //    GL.Vertex2(0,queue.Size.Height);                    // bl
+            //    GL.Vertex2(queue.Size.Width,queue.Size.Height);                    // br
+            //    GL.Vertex2(queue.Size.Width,0);      // tr
+            //GL.End();
+            //GL.Enable(EnableCap.Texture2D); 
+#endif
+        }
+
+        public void Draw(ILRenderQueue renderQueue, Point position, TextOrientation orientation, Color color) {
+            Draw(renderQueue,position.X,position.Y,0,position.X + renderQueue.Size.Width,position.Y+renderQueue.Size.Height,0,color); 
+        }
+
+        public Color ColorOverride {
+            get {
+                return m_colorOverride;
+            }
+            set {
+                m_colorOverride = value;
+            }
+        }
+
+        #endregion
+
+        private void GLColor3(Color color) {
+            if (m_colorOverride.IsEmpty) {
+                GL.Color3(color);
+            } else {
+                GL.Color3(m_colorOverride);
+            }
+        }
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLXAxis.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLXAxis.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLXAxis.cs	(revision 9102)
@@ -0,0 +1,223 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing; 
+using OpenTK; 
+using OpenTK.Graphics; 
+using OpenTK.Graphics.OpenGL; 
+using OpenTK.Graphics.OpenGL.Enums; 
+using ILNumerics.Drawing; 
+using ILNumerics.Drawing.Interfaces; 
+using ILNumerics.Drawing.Labeling; 
+
+
+namespace ILNumerics.Drawing.Platform.OpenGL {
+    /// <summary>
+    /// OpenGL implementation of ILAxis (X axis)
+    /// </summary>
+    class ILOGLXAxis : ILOGLAxis {
+        
+        /// <summary>
+        /// Constructor - this class should be created only from within ILNumerics assemblies! 
+        /// </summary>
+        /// <param name="clippingView">panels clipping view</param>
+        /// <param name="layout">instance with layout informations</param>
+        /// <param name="panel">the panel containing the axis</param>
+        internal ILOGLXAxis (ILClippingData clippingView,
+                            ILLayoutData layout,
+                            ILOGLPanel panel)
+            : base (AxisNames.XAxis,clippingView,layout,panel) {}
+
+        /// <summary>
+        /// draw all lines for the x axis 
+        /// </summary>
+        /// <param name="p">render properties</param>
+        /// <param name="background">true: draw lines in the back only, false: draw foreground lines</param>
+        protected override void iDrawAxis(ILRenderProperties p, bool background) {
+            // create vertex data: main axis and ticks 
+            if (m_visible) { 
+                float tickLen;
+                float x,y,z
+                    ,xmin = m_clipping.XMin
+                    ,xmax = m_clipping.XMax
+                    ,ymin = m_clipping.YMin
+                    ,ymax = m_clipping.YMax
+                    ,zmin = m_clipping.ZMin
+                    ,zmax = m_clipping.ZMax;
+                tickLen = m_labeledTicks.TickFraction
+                    * ((m_labeledTicks.Direction == TickDirection.Inside) ? m_clipping.HeightF : -m_clipping.HeightF);
+                // must draw ticks? 
+                bool drawticks = false, drawLines = false; 
+                if (m_labeledTicks.Display == TickDisplay.BothSides) {
+                    drawticks = true; 
+                } else {
+                    drawticks = (background && !m_layoutData.CameraPosition.LooksFromTop) 
+                              ||(!background && m_layoutData.CameraPosition.LooksFromTop);  
+                }
+                x = xmin; z = zmin; 
+                // determine which axis to draw: find front
+                if (!m_layoutData.CameraPosition.LooksFromFront) {
+                    tickLen *= -1.0f; 
+                    y = ymax; 
+                } else {
+                    y = ymin; 
+                }
+                if (background) {
+                    if (m_farLines.Visible) {
+                        ILOGLPanel.SetupLineStyle(m_farLines);
+                        drawLines = true;
+                    }
+                    if (y == ymax) y = ymin; else y = ymax; 
+                    GL.Disable(EnableCap.DepthTest);
+                    tickLen *= -1.0f;
+                } else {
+                    if (m_nearLines.Visible) {
+                        ILOGLPanel.SetupLineStyle(m_nearLines); 
+                        drawLines = true; 
+                    }
+                }
+                if (drawLines) {
+                    GL.Begin(BeginMode.Lines); 
+                    GL.Vertex3(x,y,z); 
+                    x = xmax;
+                    GL.Vertex3(x,y,z); 
+                    if (m_layoutData.CameraPosition.SinRho > 1e-5) {
+                        z = zmax; 
+                        GL.Vertex3(x,y,z); 
+                        x = xmin;
+                        GL.Vertex3(x,y,z); 
+                    }
+                    GL.End();
+                }
+                GL.Enable(EnableCap.DepthTest);
+                if (drawticks && drawLines) {
+                    #region create ticks 
+                    if (!m_layoutData.CameraPosition.LooksFromTop) {
+                        //tickLen *= -1.0f;
+                        //y *= -1.0f;
+                        if (background) 
+                            GL.Color3(m_labeledTicks.NearColor);
+                        else 
+                            GL.Color3(m_labeledTicks.FarColor); 
+                    } else {
+                        if (background) 
+                            GL.Color3(m_labeledTicks.FarColor);
+                        else 
+                            GL.Color3(m_labeledTicks.NearColor); 
+
+                    }
+                    //scale = m_clipping.ScaleToUnitCube().X; 
+                    //offse = m_clipping.CenterToUnitCube().X; 
+                    GL.Disable(EnableCap.LineStipple); 
+                    GL.Begin(BeginMode.Lines);
+                    foreach (LabeledTick tick in m_labeledTicks) {
+                        if (tick.Position >= xmin 
+                            && tick.Position <= xmax) {
+                            x = tick.Position;
+                            if (m_layoutData.CameraPosition.SinRho > 1e-5) {
+                                z = zmax;
+                                GL.Vertex3(x, y, z);
+                                y += tickLen;
+                                GL.Vertex3(x, y, z);
+                            } else {
+                                y += tickLen;
+                            }
+                            z = zmin; 
+                            GL.Vertex3(x,y,z); 
+                            y -= tickLen; 
+                            GL.Vertex3(x,y,z);
+                        }
+                    }
+                    GL.End();
+                    #endregion
+                }
+                if (background && m_grid.Visible) 
+                    drawGrid();
+            }
+        }
+
+        /// <summary>
+        /// draw all grid lines for axis
+        /// </summary>
+        protected override void drawGrid() {
+            float x,y,z;
+            float zmax = m_clipping.ZMax;
+            float zmin = m_clipping.ZMin;
+            float ymin = m_clipping.YMin;
+            float ymax = m_clipping.YMax;
+            bool drawBottom = m_layoutData.CameraPosition.LooksFromTop; 
+            ILOGLPanel.SetupLineStyle(m_grid); 
+            GL.Disable(EnableCap.DepthTest);
+            GL.Enable(EnableCap.Blend); 
+            GL.Begin(BeginMode.Lines);
+            if (m_layoutData.CameraPosition.LooksFromFront) {
+                y = ymax; 
+            } else {
+                y = ymin; 
+            }
+            foreach (LabeledTick tick in m_labeledTicks) {
+                if (tick.Position > m_clipping.XMin 
+                    && tick.Position < m_clipping.XMax) {
+                    x = tick.Position;
+                    if (!m_layoutData.CameraPosition.Is2DView) {
+                        z = zmax;
+                        GL.Vertex3(x, y, z);
+                        z = zmin;
+                        GL.Vertex3(x, y, z);
+                    } else {
+                        z = zmin; 
+                    }
+                    if (drawBottom) {
+                        GL.Vertex3(x,y,z);
+                        if (y == ymin) y = ymax; else y = ymin; 
+                        GL.Vertex3(x,y,z);
+                        if (y == ymin) y = ymax; else y = ymin; 
+                    }
+                }
+            }            
+            GL.End(); 
+        }
+
+
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLYAxis.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLYAxis.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLYAxis.cs	(revision 9102)
@@ -0,0 +1,222 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing; 
+using OpenTK; 
+using OpenTK.Graphics; 
+using OpenTK.Graphics.OpenGL; 
+using OpenTK.Graphics.OpenGL.Enums; 
+using ILNumerics.Drawing; 
+using ILNumerics.Drawing.Interfaces; 
+using ILNumerics.Drawing.Labeling; 
+
+
+namespace ILNumerics.Drawing.Platform.OpenGL {
+    /// <summary>
+    /// OpenGL implementation of ILAxis (X axis)
+    /// </summary>
+    class ILOGLYAxis : ILOGLAxis {
+        
+        /// <summary>
+        /// Constructor - this class should be created only from within ILNumerics assemblies! 
+        /// </summary>
+        /// <param name="clippingView">panels clipping view</param>
+        /// <param name="layoutData">instance with layout informations</param>
+        /// <param name="panel">the panel containing the axis</param>
+        internal ILOGLYAxis (ILClippingData clippingView,
+                            ILLayoutData layoutData,
+                            ILOGLPanel panel)
+            : base (AxisNames.YAxis,clippingView,layoutData,panel) { }
+
+        /// <summary>
+        /// draw all lines for the axis 
+        /// </summary>
+        /// <param name="p">render properties</param>
+        /// <param name="background">true: draw lines in the back only, false: draw foreground lines</param>
+        protected override void iDrawAxis(ILRenderProperties p, bool background) {
+            // create vertex data: main axis and ticks 
+            if (m_visible) { 
+                float tickLen;
+                float x, y, z
+                    , xmin = m_clipping.XMin
+                    , xmax = m_clipping.XMax
+                    , ymin = m_clipping.YMin
+                    , ymax = m_clipping.YMax
+                    , zmin = m_clipping.ZMin
+                    , zmax = m_clipping.ZMax;
+                tickLen = m_labeledTicks.TickFraction
+                    * ((m_labeledTicks.Direction == TickDirection.Inside) ? -m_clipping.WidthF : m_clipping.WidthF);
+                // must draw ticks? 
+                bool drawticks = false, drawlines = false; 
+                if (m_labeledTicks.Display == TickDisplay.BothSides) {
+                    drawticks = true; 
+                } else {
+                    drawticks = (background ^ m_layoutData.CameraPosition.LooksFromTop); 
+                }
+                y = ymin; z = zmin; 
+                // determine which axis to draw: find front
+                if (!m_layoutData.CameraPosition.LooksFromLeft && !m_layoutData.CameraPosition.Is2DView) {
+                    x = xmax; 
+                } else {
+                    x = xmin; 
+                    tickLen *= -1.0f; 
+                }
+                if (background) {
+                    if (x == xmin) x = xmax; else x = xmin; 
+                    tickLen *= -1.0f;
+                    GL.Disable(EnableCap.DepthTest);
+                    if (m_farLines.Visible) {
+                        ILOGLPanel.SetupLineStyle(m_farLines);
+                        drawlines = true; 
+                    }
+                } else {
+                    if (m_nearLines.Visible) {
+                        ILOGLPanel.SetupLineStyle(m_nearLines);
+                        drawlines = true; 
+                    }
+                }
+                if (drawlines) {
+                    GL.Begin(BeginMode.Lines); 
+                    GL.Vertex3(x,y,z); 
+                    y = ymax; 
+                    GL.Vertex3(x,y,z); 
+                    if (m_layoutData.CameraPosition.SinRho > 1e-5) {
+                        z = zmax; 
+                        GL.Vertex3(x,y,z); 
+                        y = ymin; 
+                        GL.Vertex3(x,y,z); 
+                    }
+                    GL.End();
+                }
+                if (drawticks && drawlines) {
+                    #region create ticks 
+                    if (!m_layoutData.CameraPosition.LooksFromTop) {
+                        //tickLen *= -1.0f;
+                        //x *= -1.0f;
+                        if (background) 
+                            GL.Color3(m_labeledTicks.NearColor);
+                        else 
+                            GL.Color3(m_labeledTicks.FarColor); 
+                    } else {
+                        if (background) 
+                            GL.Color3(m_labeledTicks.FarColor);
+                        else 
+                            GL.Color3(m_labeledTicks.NearColor); 
+                    }
+                    //scale = m_clipping.ScaleToUnitCube().Y; 
+                    //offse = m_clipping.CenterToUnitCube().Y; 
+                    GL.Enable(EnableCap.DepthTest);
+                    GL.Disable(EnableCap.LineStipple); 
+                    GL.Begin(BeginMode.Lines);
+                    foreach (LabeledTick tick in m_labeledTicks) {
+                        if (tick.Position >= ymin 
+                            && tick.Position <= ymax) {
+                            y = tick.Position;
+                            if (m_layoutData.CameraPosition.SinRho > 1e-5) {
+                                z = zmax;
+                                GL.Vertex3(x, y, z);
+                                x += tickLen;
+                                GL.Vertex3(x, y, z);
+                            } else {
+                                x += tickLen;
+                            }
+                            z = zmin; 
+                            GL.Vertex3(x,y,z); 
+                            x -= tickLen;               
+                            GL.Vertex3(x,y,z); 
+                        }
+                    }
+                    GL.End();
+                }
+                if (background && m_grid.Visible) 
+                    drawGrid(); 
+                #endregion
+            }
+        }
+
+        /// <summary>
+        /// draw all grid lines for axis
+        /// </summary>
+        protected override void drawGrid() {
+            GL.Color3(m_grid.Color); 
+            float x,y,z;
+            float zmax = m_clipping.ZMax;
+            float zmin = m_clipping.ZMin;
+            float xmin = m_clipping.XMin;
+            float xmax = m_clipping.XMax;
+            bool drawBottom = m_layoutData.CameraPosition.LooksFromTop; 
+            ILOGLPanel.SetupLineStyle(m_grid);
+            GL.Disable(EnableCap.DepthTest);
+            GL.Disable(EnableCap.Blend); 
+            GL.Begin(BeginMode.Lines);
+            if (!m_layoutData.CameraPosition.LooksFromLeft) {
+                x = xmin; 
+            } else {
+                x = xmax; 
+            }
+            foreach (LabeledTick tick in m_labeledTicks) {
+                if (tick.Position >= m_clipping.YMin 
+                    && tick.Position <= m_clipping.YMax) {
+                    y = tick.Position;
+                    if (!m_layoutData.CameraPosition.Is2DView) {
+                        z = zmax;
+                        GL.Vertex3(x, y, z);
+                        z = zmin;
+                        GL.Vertex3(x, y, z);
+                    } else {
+                        z = zmin; 
+                    }
+                    if (drawBottom) {
+                        GL.Vertex3(x,y,z);
+                        if (x == xmin) x = xmax; else x = xmin; 
+                        GL.Vertex3(x,y,z);
+                        if (x == xmin) x = xmax; else x = xmin;
+                    }
+                }
+            }
+            GL.End(); 
+        }
+
+
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLZAxis.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLZAxis.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Platform/OpenGL/ILOGLZAxis.cs	(revision 9102)
@@ -0,0 +1,251 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing; 
+using OpenTK; 
+using OpenTK.Graphics; 
+using OpenTK.Graphics.OpenGL; 
+using OpenTK.Graphics.OpenGL.Enums; 
+using ILNumerics.Drawing; 
+using ILNumerics.Drawing.Interfaces; 
+using ILNumerics.Drawing.Labeling; 
+
+namespace ILNumerics.Drawing.Platform.OpenGL {
+    /// <summary>
+    /// OpenGL implementation of ILAxis (X axis)
+    /// </summary>
+    class ILOGLZAxis : ILOGLAxis {
+        
+        /// <summary>
+        /// Constructor - this class should be created only from within ILNumerics assemblies! 
+        /// </summary>
+        /// <param name="clippingView">panels clipping view</param>
+        /// <param name="layout">instance with layout informations</param>
+        /// <param name="panel">the panel containing the axis</param>
+        internal ILOGLZAxis (ILClippingData clippingView,
+                            ILLayoutData layout,
+                            ILOGLPanel panel)
+            : base (AxisNames.ZAxis,clippingView,layout,panel) { }
+
+        /// <summary>
+        /// draw all lines for the axis 
+        /// </summary>
+        /// <param name="g">graphics object (ignored)</param>
+        /// <param name="background">true: draw lines in the back only, false: draw foreground lines</param>
+        protected override void iDrawAxis(ILRenderProperties p, bool background) {
+            // create vertex data: main axis and ticks 
+            if (!m_visible) return;  
+            float tickLen;
+            float x, y, z
+                    , xmin = m_clipping.XMin
+                    , xmax = m_clipping.XMax
+                    , ymin = m_clipping.YMin
+                    , ymax = m_clipping.YMax
+                    , zmin = m_clipping.ZMin
+                    , zmax = m_clipping.ZMax;
+            tickLen = m_labeledTicks.TickFraction
+                * ((m_labeledTicks.Direction == TickDirection.Inside) ? m_clipping.WidthF : -m_clipping.WidthF);
+            //ConfigureOGLLineProperties(LineStyle.Solid,1); 
+            // must draw ticks? 
+            bool drawticks,drawlines = false; 
+            if (m_labeledTicks.Display == TickDisplay.BothSides) {
+                drawticks = true; 
+            } else {
+                drawticks = (background && !m_layoutData.CameraPosition.LooksFromTop) 
+                          ||(!background && m_layoutData.CameraPosition.LooksFromTop);  
+            }
+            x = xmin; y = ymin; z = zmin; 
+            float x2, y2, tickLen2 = tickLen;
+            switch (m_layoutData.CameraPosition.Quadrant) {
+                case CameraQuadrant.TopLeftFront: // Q1
+                case CameraQuadrant.BottomLeftFront:
+                    x = xmin;
+                    x2 = xmin; 
+                    y = ymax; 
+                    y2 = ymin;
+                    //tickLen2 *= -1.0f; 
+                    break;
+                case CameraQuadrant.TopLeftBack:  // Q2
+                case CameraQuadrant.BottomLeftBack: 
+                    x = xmax;
+                    y = ymax; 
+                    x2 = xmin; 
+                    y2 = ymax; 
+                    tickLen *= -1.0f; 
+                    break;
+                case CameraQuadrant.TopRightBack:   // Q3
+                case CameraQuadrant.BottomRightBack:
+                    x = xmax;
+                    x2 = xmax; 
+                    y = ymin; 
+                    y2 = ymax;
+                    tickLen *= -1.0f; 
+                    tickLen2 *= -1.0f;
+                    break;
+                case CameraQuadrant.TopRightFront:
+                case CameraQuadrant.BottomRightFront:  // Q4
+                default:
+                    x = xmin; 
+                    x2 = xmax; 
+                    y = ymin; 
+                    y2 = ymin; 
+                    tickLen2 *= -1.0f; 
+                    break;
+            }
+            if (background) {
+                if (x == xmin) x = xmax; else x = xmin;
+                if (y == ymin) y = ymax; else y = ymin;
+                if (x2 == xmin) x2 = xmax; else x2 = xmin;
+                if (y2 == ymin) y2 = ymax; else y2 = ymin; 
+                GL.Disable(EnableCap.DepthTest);
+                if (m_farLines.Visible) {
+                    drawlines = true; 
+                    ILOGLPanel.SetupLineStyle(m_farLines);
+                }
+            } else {
+                if (m_nearLines.Visible) {
+                    drawlines = true; 
+                    ILOGLPanel.SetupLineStyle(m_nearLines); 
+                }
+            }
+            if (drawlines) {
+                GL.Begin(BeginMode.Lines);
+                GL.Vertex3(x,y,z); 
+                z = zmax; 
+                GL.Vertex3(x,y,z); 
+                GL.Vertex3(x2,y2,z); 
+                z = zmin; 
+                GL.Vertex3(x2,y2,z);
+                GL.End();
+            }
+            if (m_labeledTicks.Display == TickDisplay.BothSides || (!background && drawlines)) {
+                #region create ticks 
+                GL.Enable(EnableCap.DepthTest);
+                if (background) {
+                    GL.Color3(m_labeledTicks.FarColor);
+                    tickLen *= -1.0f;
+                    tickLen2 *= -1.0f;
+                } else 
+                    GL.Color3(m_labeledTicks.NearColor); 
+                GL.Disable(EnableCap.LineStipple); 
+                GL.Begin(BeginMode.Lines);
+                foreach (LabeledTick tick in m_labeledTicks) {
+                    if (tick.Position >= m_clipping.ZMin 
+                        && tick.Position <= m_clipping.ZMax) {
+                        z = tick.Position; 
+                        GL.Vertex3(x,y,z); 
+                        x += tickLen; 
+                        GL.Vertex3(x,y,z); 
+                        x -= tickLen; 
+                        GL.Vertex3(x2,y2,z); 
+                        x2 += tickLen2;               
+                        GL.Vertex3(x2,y2,z); 
+                        x2 -= tickLen2; 
+                    }
+                }
+                GL.End();
+                #endregion
+            }
+            if (background && m_grid.Visible) 
+                drawGrid();
+        }
+
+        /// <summary>
+        /// draw all grid lines for axis
+        /// </summary>
+        protected override void drawGrid() {
+            float x1,y1,z;
+            float x2,y2,x3,y3;
+            float xmin = m_clipping.XMin;
+            float ymin = m_clipping.YMin;
+            float xmax = m_clipping.XMax;
+            float ymax = m_clipping.YMax; 
+
+            ILOGLPanel.SetupLineStyle(m_grid);
+            GL.Disable(EnableCap.DepthTest);
+            GL.Enable(EnableCap.Blend); 
+            GL.Begin(BeginMode.Lines);
+            #region determine which side to draw on
+            switch (m_layoutData.CameraPosition.Quadrant)
+	        {
+		        case CameraQuadrant.TopLeftFront:
+                case CameraQuadrant.BottomLeftFront:
+                    x1 = xmin; y1 = ymax;
+                    x2 = xmax; y2 = ymax;
+                    x3 = xmax; y3 = ymin; 
+                    break;
+                case CameraQuadrant.TopLeftBack:
+                case CameraQuadrant.BottomLeftBack:
+                    x1 = xmax; y1 = ymax;
+                    x2 = xmax; y2 = ymin;
+                    x3 = xmin; y3 = ymin; 
+                    break;
+                case CameraQuadrant.TopRightBack:
+                case CameraQuadrant.BottomRightBack:
+                    x1 = xmax; y1 = ymin;
+                    x2 = xmin; y2 = ymin;
+                    x3 = xmin; y3 = ymax; 
+                    break;
+                default:
+                case CameraQuadrant.TopRightFront:
+                case CameraQuadrant.BottomRightFront:
+                    x1 = xmin; y1 = ymin;
+                    x2 = xmin; y2 = ymax;
+                    x3 = xmax; y3 = ymax; 
+                    break;
+	        }
+            #endregion
+            foreach (LabeledTick tick in m_labeledTicks) {
+                if (tick.Position >= m_clipping.ZMin 
+                    && tick.Position <= m_clipping.ZMax) {
+                    z = tick.Position; 
+                    GL.Vertex3(x1,y1,z); 
+                    GL.Vertex3(x2,y2,z);
+                    GL.Vertex3(x2,y2,z);
+                    GL.Vertex3(x3,y3,z);
+                }
+            }            
+            GL.End(); 
+        }
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Plots/ILBarGraph2D.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Plots/ILBarGraph2D.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Plots/ILBarGraph2D.cs	(revision 9102)
@@ -0,0 +1,236 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Collections;
+using System.Text;
+using ILNumerics.Drawing.Shapes; 
+using ILNumerics.Drawing; 
+using ILNumerics.Exceptions; 
+using ILNumerics.Drawing.Misc; 
+using System.Drawing; 
+using ILNumerics.Drawing.Interfaces;
+using ILNumerics.Drawing.Labeling;
+using ILNumerics.Drawing.Plots;
+
+namespace ILNumerics.Drawing.Plots {
+    /// <summary>
+    /// simple updatable bar graph implementation, fixed number of bars, simple example implementation derived from ILSceneGraph
+    /// </summary>
+    public sealed class ILBarGraph2D : ILPlot, IILLegendRenderer, IILPanelConfigurator {
+
+        #region attributes 
+        float m_barWidth; 
+        ILQuad[] m_quads;
+        ILLabel m_legendSampleLabel;
+        ILLabel m_legendTextLabel; 
+        int m_oldestBarIndex;
+        int m_oldestOpacity; 
+        #endregion 
+
+        #region properties
+        /// <summary>
+        /// Sets the opacity for the 'oldest' bar. May be used as 'Fading-Out' effect. (Default: 255)
+        /// </summary>
+        int OpacityOldest {
+            get { return m_oldestOpacity; }
+            set { m_oldestOpacity = value; }
+        }
+        /// <summary>
+        /// padding between graphs 
+        /// </summary>
+        public float BarWidth {
+            get {
+                return m_barWidth; 
+            }
+            set {
+                m_barWidth = value;
+                Invalidate(); 
+            }
+        }
+        /// <summary>
+        /// number of bars in the graph
+        /// </summary>
+        public override int Count {
+            get {
+                return m_quads.Length; 
+            }
+        }
+        #endregion
+
+        #region constructors
+        /// <summary>
+        /// create new 2D bar graph
+        /// </summary>
+        /// <param name="panel">hosting panel</param>
+        /// <param name="data">numeric vector data, heights of bars</param>
+        public ILBarGraph2D(ILPanel panel, ILInArray<float> data)
+            : base(panel) {
+            using (ILScope.Enter(data)) {
+                // spacing between + width of bars
+                m_barWidth = 0.6f;
+                m_oldestOpacity = 255;
+                // create the bars
+                createQuads(data);
+                m_legendSampleLabel = new ILLabel(m_panel);
+                m_legendSampleLabel.Text = "Bars";
+
+                m_legendTextLabel = new ILLabel(m_panel);
+                m_legendTextLabel.Text = "3D";
+
+                m_oldestBarIndex = 0;
+            }
+        }
+        #endregion
+
+        #region public interface
+        /// <summary>
+        /// return reference to single bar (ILQuad) by index
+        /// </summary>
+        /// <param name="index">index of the bar</param>
+        /// <returns>the bar shape as ILQuad</returns>
+        public new ILQuad this [int index] {
+            get { return m_quads[index]; }
+        }
+        /// <summary>
+        /// add 'new' bar with new value and remove oldest bar
+        /// </summary>
+        /// <param name="value">height of new bar</param>
+        /// <returns>discarded value</returns>
+        public float Queue(float value) {
+            // we move all shapes by 1 left
+            ILPoint3Df offset = new ILPoint3Df(-1f,0,0);
+            for (int i = 0; i < m_quads.Length; i++) {
+                m_quads[i].Translate(offset);
+                // FADE OUt old barsss .... 
+                m_quads[(i + m_oldestBarIndex) % (m_quads.Length - 1)].Opacity
+                    = (byte)(m_oldestOpacity + i * (255 - m_oldestOpacity) / m_quads.Length);
+                // tell the scene to update its size
+                m_quads[i].Invalidate();
+            }
+            // configure oldest graph
+            ILQuad newestQuad = m_quads[m_oldestBarIndex];
+            offset.X = m_quads.Length; 
+            newestQuad.Translate(offset);
+            float ret = newestQuad.Vertices[2].YPosition; 
+            newestQuad.Vertices[2].YPosition = value;
+            newestQuad.Vertices[3].YPosition = value;
+            newestQuad.Opacity = 255; 
+
+            if (++m_oldestBarIndex >= m_quads.Length) 
+                m_oldestBarIndex = 0; 
+            return ret;        
+        }
+        #endregion
+
+        #region IILLegendRenderer Member
+        /* In order to show up in the legend, the plot needs to 
+         * implement the IILLegendRenderer interface. Here this is 
+         * done very simple via a ILShapeLabel. The first one simple draws 
+         * the text "Bars" in the sample area of the legend. The original 
+         * ILLabel of the graph is then used to draw its text into the 
+         * label area of the legend. 
+         * Better implementations should check for 
+         * ** the drawing not to exceed the sampleArea and labelArea rectangles
+         * ** use 2 distinct labels instead of one (performance) 
+         */ 
+        public void DrawToLegend(ILRenderProperties p, Rectangle sampleArea, Rectangle labelArea) {
+            m_legendSampleLabel.Position = sampleArea.Location;
+            m_legendSampleLabel.Draw(p);
+
+            m_legendTextLabel.Position = labelArea.Location;
+            m_legendTextLabel.Draw(p); 
+        }
+        public Size LabelSize { get { return m_legendTextLabel.Size; } }
+        #endregion
+
+        #region private helper 
+        protected void createQuads(ILInArray<float> data) {
+            using (ILScope.Enter(data)) {
+                if (data == null || data.Length == 0) {
+                    Clear();
+                    m_quads = new ILQuad[0];
+                } else {
+                    Clear();
+                    m_quads = new ILQuad[data.Length];
+                    ILColorEnumerator colors = new ILColorEnumerator();
+                    ILArray<float> fData = ILMath.check(data);
+
+                    for (int i = 0; i < m_quads.Length; i++) {
+                        m_quads[i] = new ILQuad(m_panel);
+                        m_quads[i].Border.Visible = true;
+                        m_quads[i].FillColor = colors.NextColor();
+                        ILPoint3Df pos = new ILPoint3Df();
+                        pos.X = i - m_barWidth / 2;
+                        pos.Y = 0;
+                        pos.Z = -0.5f;
+                        m_quads[i].Vertices[0].Position = pos;
+                        pos.X += m_barWidth;
+                        m_quads[i].Vertices[1].Position = pos;
+                        pos.Y += fData.GetValue(i);
+                        m_quads[i].Vertices[2].Position = pos;
+                        pos.X -= m_barWidth;
+                        m_quads[i].Vertices[3].Position = pos;
+                        // label the bar
+                        m_quads[i].Label.Text = i.ToString();
+                        m_quads[i].Label.Anchor = new PointF(.5f, -1);
+
+                        // bars will be transparent, oldest fading to OpacityOldest
+                        m_quads[i].Opacity = (byte)(m_oldestOpacity + i * (255 - m_oldestOpacity) / m_quads.Length);
+                        // add the bar to the scene graph node (base)
+                        Add(m_quads[i]);
+                    }
+                }
+            }
+        }
+        #endregion
+
+        #region IILPanelConfigurator Members
+
+        public void  ConfigurePanel(ILPanel panel) {
+            panel.Axes.XAxis.Visible = false;
+            panel.InteractiveMode = InteractiveModes.ZoomRectangle;
+            panel.Axes.YAxis.FarLines.Visible = false;
+            panel.PlotBoxScreenSizeMode = PlotBoxScreenSizeMode.Optimal; 
+        }
+
+        #endregion
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Plots/ILBarGraph3d.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Plots/ILBarGraph3d.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Plots/ILBarGraph3d.cs	(revision 9102)
@@ -0,0 +1,225 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System.Collections.Generic;
+using System.Drawing;
+using ILNumerics.Drawing.Interfaces;
+using ILNumerics.Drawing.Misc;
+using ILNumerics.Exceptions; 
+
+namespace ILNumerics.Drawing.Plots {
+    
+    /// <summary>
+    /// Simple 3D Bar Graph - plot
+    /// </summary>
+    public sealed class ILBarGraph3D : ILPlot, IILPanelConfigurator {
+
+        #region attributes
+        ILLitBox3D[,] m_boxes;
+        float m_barLengthX = 1.0f;
+        float m_barLengthY = 1.0f;
+        float m_paddingX = 0.3f;
+        float m_paddingY = 0.4f;
+        Color m_barColor = Color.FromArgb(170, 210, 210, 255); 
+        Color m_barColorGradient = Color.FromArgb(170, 180, 180, 255);
+        #endregion
+
+        /// <summary>
+        /// create a new 3D Bar Graph plot, provide data matrix
+        /// </summary>
+        /// <param name="panel">panel hosting the scene</param>
+        /// <param name="data">data matrix, at least 2x2 entries</param>
+        public ILBarGraph3D(ILPanel panel, ILInArray<float> data)
+            : base(panel) {
+            using (ILScope.Enter(data)) {
+                if (data == null)
+                    throw new ILArgumentException("data argument must not be null!");
+                create(data, Colormaps.ILNumerics);
+            }
+        }
+        /// <summary>
+        /// get/set opacity of the bars
+        /// </summary>
+        public byte Opacity {
+            set {
+                foreach (ILLitBox3D box in m_boxes) {
+                    box.Opacity = value; 
+                }
+            }
+        }
+        /// <summary>
+        /// individual access to each bar (ILLitBox) 
+        /// </summary>
+        /// <param name="row">row index, 0 based</param>
+        /// <param name="col">column index, 0 based</param>
+        /// <returns>lit box shape at specified position</returns>
+        public ILLitBox3D this[int row, int col] {
+            get { 
+                return m_boxes[row,col];   
+            }
+        }
+
+        #region public interface
+        /// <summary>
+        /// set axes labels and tick labels at once
+        /// </summary>
+        /// <param name="panel">panel hosting the plot</param>
+        /// <param name="xlabel">label text for x axis</param>
+        /// <param name="ylabel">label text for y axis</param>
+        /// <param name="zlabel">label text for z axis</param>
+        /// <param name="xtickLabels">collection of strings for columns labels (x-direction)</param>
+        /// <param name="ytickLabels">collection of strings for row labels (x-direction)</param>
+        public void SetLabels(ILPanel panel
+                                , string xlabel, string ylabel, string zlabel
+                                , ICollection<string> xtickLabels
+                                , ICollection<string> ytickLabels
+                                ) {
+            panel.Axes[0].LabeledTicks.Clear();
+            int counter = 0;
+            if (xtickLabels != null)
+                foreach (string s in xtickLabels) {
+                    panel.Axes[0].LabeledTicks.Add(m_boxes[0, counter].Center.X, s);
+                    counter++;
+                }
+            panel.Axes[1].LabeledTicks.Clear();
+            counter = 0;
+            if (ytickLabels != null)
+                foreach (string s in ytickLabels) {
+                    panel.Axes[1].LabeledTicks.Add(m_boxes[counter, 0].Center.Y, s);
+                    counter++;
+                }
+            panel.Axes[0].Label.Text = xlabel;
+            panel.Axes[1].Label.Text = ylabel;
+            panel.Axes[2].Label.Text = zlabel;
+
+        }
+
+        #endregion
+
+        #region private helper
+        private void create(ILInArray<float> data, Colormaps colormap) {
+            using (ILScope.Enter(data)) {
+                ILArray<float> dataF = ILMath.check(data);
+                m_boxes = new ILLitBox3D[data.Size[0], data.Size[1]];
+                float maxY = data.Size[0] * (m_barLengthY + m_paddingY);
+                // prepare coloring for top quads 
+                ILColormap cmap = new ILColormap(colormap);
+                float minV, maxV, mult;
+                dataF.GetLimits(out minV, out maxV);
+                if (maxV > minV) {
+                    mult = (cmap.Length - 1) / (maxV - minV);
+                } else {
+                    minV = 0;
+                    mult = 0;
+                }
+                for (int r = 0; r < data.Size[0]; r++) {
+                    for (int c = 0; c < data.Size[1]; c++) {
+                        float val = dataF.GetValue(r, c);
+                        ILPoint3Df max = new ILPoint3Df(
+                            (float)(c * (m_paddingX + m_barLengthX) + m_barLengthX)
+                            , (float)(maxY - r * (m_paddingY + m_barLengthY))
+                            , val);
+                        ILPoint3Df min = new ILPoint3Df(
+                            max.X - m_barLengthX
+                            , max.Y - m_barLengthY
+                            , 0);
+                        Color topColor = cmap.Map((double)(val - minV) * mult);
+                        ILLitBox3D box = new ILLitBox3D(m_panel, min, max, m_barColor, topColor);
+                        box.GradientColor = m_barColorGradient;
+                        box.TopLabel.Color = topColor;
+                        box.TopLabel.Text = "";
+                        m_boxes[r, c] = box;
+                        Add(box);
+                    }
+                }
+            }
+        }
+        #endregion
+
+
+        #region IILPanelConfigurator Members
+        /// <summary>
+        /// configure default view of panel, called when adding the plot to the panel
+        /// </summary>
+        /// <param name="panel">panel hosting the plot</param>
+        public void ConfigurePanel(ILPanel panel) {
+            panel.BackgroundFilled = false;
+            panel.ClipViewData = false;
+            panel.Axes.LinesVisible = false;
+            panel.Projection = Projection.Perspective;
+            panel.DefaultView.SetDeg(-35, 55, 250);
+
+            // configure light
+            panel.Lights[0].Enabled = true;
+            panel.Lights[0].Position = new ILPoint3Df(0, 0, 250);
+
+            panel.BackgroundFilled = false;
+            panel.BackColor = Color.White;
+            panel.Axes.GridVisible = false;
+            panel.Axes.LinesVisible = false;
+            // configure X axis
+            panel.Axes[0].LabeledTicks.Mode = TickMode.Manual;
+            panel.Axes[0].LabeledTicks.Color = Color.Black;
+            panel.Axes[0].LabeledTicks.Clear(); 
+
+            panel.Axes[1].NearLines.Visible = false;
+            panel.Axes[1].FarLines.Visible = false;
+            panel.Axes[1].Label.Color = Color.Black;
+
+            panel.Axes[2].NearLines.Visible = false;
+            panel.Axes[2].FarLines.Visible = false;
+            panel.Axes[2].Grid.Visible = true;
+            panel.Axes[2].Grid.Color = Color.DarkGray;
+            panel.Axes[2].Grid.Antialiasing = true;
+
+            panel.Axes[2].Label.Color = Color.Black;
+
+            panel.Axes[2].LabeledTicks.Color = Color.Black;
+            panel.Axes[0].NearLines.Visible = false;
+            panel.Axes[0].FarLines.Visible = false;
+            panel.Axes[0].Label.Color = Color.Black;
+
+            // configure Y axis
+            panel.Axes[1].LabeledTicks.Mode = TickMode.Manual;
+            panel.Axes[1].LabeledTicks.Color = Color.Black;
+        }
+
+        #endregion
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Plots/ILLitBox3D.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Plots/ILLitBox3D.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Plots/ILLitBox3D.cs	(revision 9102)
@@ -0,0 +1,307 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics;
+using ILNumerics.Drawing;
+using ILNumerics.Drawing.Graphs;
+using ILNumerics.Drawing.Shapes; 
+using ILNumerics.Drawing.Labeling; 
+using System.Drawing; 
+
+namespace ILNumerics.Drawing.Plots {
+    /// <summary>
+    /// the plot displays a simple colored lit 3D box
+    /// </summary>
+     public class ILLitBox3D : ILPlot {
+
+         #region public enums
+         /// <summary>
+         /// enum for all 
+         /// </summary>
+         public static class QuadIndices {
+             public static readonly int front = 0;
+             public static readonly int right = 1;
+             public static readonly int back = 2;
+             public static readonly int left = 3;
+             public static readonly int top = 4;
+             public static readonly int bottom = 5;
+         }
+        #endregion
+
+         #region attributes
+         ILLitQuad[] m_quads;
+         ILLineProperties m_lineProperties;
+         Color m_gradColor;
+         Color m_fillColor;
+         Color m_topColor; 
+         byte m_opacity = 255;
+         ILWorldLabel m_valLabel;
+         ILShapeLabel m_topLabel; 
+         #endregion
+
+         #region properties
+         /// <summary>
+         /// get the opacity for the box or set it
+         /// </summary>
+         public byte Opacity {
+             get { return m_opacity; }
+             set {
+                 foreach (ILLitQuad s in m_quads) {
+                     s.Opacity = value;
+                     for (int i = 0; i < s.Vertices.Length; i++) {
+                         s.Vertices[i].Alpha = value;                          
+                     }
+                 }
+                 m_opacity = value; }
+         }
+         /// <summary>
+         /// the color used at one corner for each quad to generate a simple gradient effect 
+         /// </summary>
+         public Color GradientColor {
+             get { return m_gradColor; }
+             set {
+                m_gradColor = value;
+                updateColors(); 
+             }
+         }
+         /// <summary>
+         /// properties of the edge lines 
+         /// </summary>
+         public ILLineProperties Edges {
+             get {
+                 return m_lineProperties; 
+             }
+         }
+         /// <summary>
+         /// overall fill color (bottom and lower area of color gradient) 
+         /// </summary>
+         public Color FillColor {
+             get { return m_fillColor; }
+             set {
+                 m_fillColor = value; 
+                 updateColors(); 
+             }
+         }
+         /// <summary>
+         /// top color (top and upper area of color gradient)
+         /// </summary>
+         public Color TopColor {
+             get { return m_topColor; }
+             set {
+                 m_topColor = value; 
+                 updateColors(); 
+             }
+         }
+         /// <summary>
+         /// reference to the label which renders the current z-value onto the top area (world coords)
+         /// </summary>
+         public ILWorldLabel ValueLabel {
+             get {
+                 return m_valLabel; 
+             }
+         }
+         /// <summary>
+         /// label drawn in screen coords on top of the lit box
+         /// </summary>
+         public ILShapeLabel TopLabel {
+             get { return m_topLabel; }
+         }
+         /// <summary>
+         /// get reference to the quads, the lit box is assembled out of
+         /// </summary>
+         public ILLitQuad[] Quads {
+             get { return m_quads; }
+         }
+         #endregion
+
+         #region constructor
+         /// <summary>
+         /// create new lit 3D box
+         /// </summary>
+         /// <param name="panel">panel hosting the scene</param>
+         /// <param name="min">minimum coordinates defining the box' dimensions (x,y,z)</param>
+         /// <param name="max">minimum coordinates defining the box' dimensions (x,y,z)</param>
+         /// <param name="fillColor">overall color for the box</param>
+         /// <param name="topColor">color used to color the top edges of the box</param>
+         public ILLitBox3D(ILPanel panel, ILPoint3Df min, ILPoint3Df max, Color fillColor, Color topColor)
+             : base(panel) {
+             m_lineProperties = new ILLineProperties();
+             m_lineProperties.Changed += new EventHandler(m_lineProperties_Changed);
+             m_valLabel = new ILWorldLabel(panel);
+             m_valLabel.Text = ""; // (max * 1000).Z.ToString("F3");
+
+             ILPoint3Df mi = ILPoint3Df.Min(min, max);
+             ILPoint3Df ma = ILPoint3Df.Max(min, max);
+             m_valLabel.PositionMax = new ILPoint3Df(ma.X,mi.Y,ma.Z);
+             m_valLabel.PositionMin = new ILPoint3Df(mi.X, ma.Y, ma.Z); ;
+
+             m_topLabel = new ILShapeLabel(panel);
+             m_topLabel.Color = Color.Blue;
+             //m_topLabel.Font = new Font("Arial", 10, FontStyle.Bold);
+             string tval = max.Z.ToString("F2");
+             m_topLabel.Text =  String.Format("{0}",tval);
+             m_topLabel.Anchor = new PointF(0.5f, 1); 
+
+             m_topColor = topColor;
+
+             #region setup quads
+             m_quads = new ILLitQuad[6];
+
+             // front
+             ILLitQuad quad = new ILLitQuad(m_panel);
+             quad.Vertices[0].Position = new ILPoint3Df(min.X, min.Y, min.Z);
+             quad.Vertices[1].Position = new ILPoint3Df(min.X, min.Y, max.Z);
+             quad.Vertices[2].Position = new ILPoint3Df(max.X, min.Y, max.Z);
+             quad.Vertices[3].Position = new ILPoint3Df(max.X, min.Y, min.Z);
+             m_quads[QuadIndices.front] = quad; 
+             // right
+             quad = new ILLitQuad(m_panel);
+             quad.Vertices[0].Position = new ILPoint3Df(max.X, min.Y, min.Z);
+             quad.Vertices[1].Position = new ILPoint3Df(max.X, min.Y, max.Z);
+             quad.Vertices[2].Position = new ILPoint3Df(max.X, max.Y, max.Z);
+             quad.Vertices[3].Position = new ILPoint3Df(max.X, max.Y, min.Z);
+             m_quads[QuadIndices.right] = quad;
+             // back
+             quad = new ILLitQuad(m_panel);
+             quad.Vertices[0].Position = new ILPoint3Df(max.X, max.Y, min.Z);
+             quad.Vertices[1].Position = new ILPoint3Df(max.X, max.Y, max.Z);
+             quad.Vertices[2].Position = new ILPoint3Df(min.X, max.Y, max.Z);
+             quad.Vertices[3].Position = new ILPoint3Df(min.X, max.Y, min.Z);
+             m_quads[QuadIndices.back] = quad;
+             // left
+             quad = new ILLitQuad(m_panel);
+             quad.Vertices[0].Position = new ILPoint3Df(min.X, max.Y, min.Z);
+             quad.Vertices[1].Position = new ILPoint3Df(min.X, max.Y, max.Z);
+             quad.Vertices[2].Position = new ILPoint3Df(min.X, min.Y, max.Z);
+             quad.Vertices[3].Position = new ILPoint3Df(min.X, min.Y, min.Z);
+             m_quads[QuadIndices.left] = quad;
+             // top
+             quad = new ILLitQuad(m_panel); 
+             quad.Vertices[0].Position = new ILPoint3Df(min.X, min.Y, max.Z);
+             quad.Vertices[1].Position = new ILPoint3Df(max.X, min.Y, max.Z);
+             quad.Vertices[2].Position = new ILPoint3Df(max.X, max.Y, max.Z);
+             quad.Vertices[3].Position = new ILPoint3Df(min.X, max.Y, max.Z);
+             m_quads[QuadIndices.top] = quad;
+             // bottom
+             quad = new ILLitQuad(m_panel);
+             quad.Vertices[0].Position = new ILPoint3Df(min.X, min.Y, min.Z);
+             quad.Vertices[1].Position = new ILPoint3Df(max.X, min.Y, min.Z);
+             quad.Vertices[2].Position = new ILPoint3Df(max.X, max.Y, min.Z);
+             quad.Vertices[3].Position = new ILPoint3Df(min.X, max.Y, min.Z);
+             m_quads[QuadIndices.bottom] = quad;
+             #endregion
+             EventingSuspend();
+             foreach (ILLitQuad s in m_quads) {
+                 s.Label.Text = "";
+                 s.Shading = ShadingStyles.Interpolate;
+                 s.Opacity = m_opacity;
+                 s.Border.Color = Color.Gray;
+                 s.Border.Width = 1;
+                 s.Border.Visible = true;
+                 s.Border.Antialiasing = false; 
+                 Add(s); 
+             }
+             EventingResume(); 
+             m_fillColor = fillColor;
+             updateColors();
+         }
+         #endregion
+
+         #region public interface
+         /// <summary>
+         /// (internally used) draws the plot 
+         /// </summary>
+         /// <param name="props"></param>
+         internal override void Draw(ILRenderProperties props) {
+             base.Draw(props);
+             m_valLabel.Draw(props);
+             ILPoint3Df labPos = m_quads[QuadIndices.top].Center; 
+             labPos.Z = Math.Max(m_quads[QuadIndices.top].Center.Z,m_quads[QuadIndices.bottom].Center.Z); 
+             m_topLabel.Draw(props,labPos); 
+         }
+         #endregion
+
+         #region private helpers
+         /// <summary>
+         /// update all quad borders with new settings
+         /// </summary>
+         /// <param name="sender"></param>
+         /// <param name="e"></param>
+         void m_lineProperties_Changed(object sender, EventArgs e) {
+             foreach (ILLitQuad quad in m_quads) {
+                 quad.Border.CopyFrom(m_lineProperties); 
+             }
+
+         }
+         /// <summary>
+         /// distribute changed color settings to all quads 
+         /// </summary>
+         private void updateColors() {
+             SetColorGradient(m_quads[QuadIndices.front], m_fillColor, m_topColor, m_topColor, m_gradColor);
+             SetColorGradient(m_quads[QuadIndices.right], m_fillColor, m_topColor, m_topColor, m_gradColor);
+             SetColorGradient(m_quads[QuadIndices.back], m_fillColor, m_topColor, m_topColor, m_gradColor);
+             SetColorGradient(m_quads[QuadIndices.left], m_fillColor, m_topColor, m_topColor, m_gradColor);
+             SetColorGradient(m_quads[QuadIndices.top], m_topColor, m_topColor, m_topColor, m_topColor);
+             SetColorGradient(m_quads[QuadIndices.bottom], m_topColor, m_topColor, m_topColor, m_topColor); 
+         }
+         /// <summary>
+         /// color settings helper
+         /// </summary>
+         /// <param name="quad">quad index</param>
+         /// <param name="col0">color 1</param>
+         /// <param name="col1">color 2</param>
+         /// <param name="col2">color 3</param>
+         /// <param name="col3">color 4</param>
+         private void SetColorGradient(
+                        ILLitQuad quad, Color col0, Color col1, Color col2, Color col3) {
+                quad.Vertices[0].Color = col0; 
+                quad.Vertices[0].Alpha = m_opacity; 
+                quad.Vertices[1].Color = col1; 
+                quad.Vertices[1].Alpha = m_opacity; 
+                quad.Vertices[2].Color = col2; 
+                quad.Vertices[2].Alpha = m_opacity; 
+                quad.Vertices[3].Color = col3; 
+                quad.Vertices[3].Alpha = m_opacity; 
+         }
+         #endregion
+     }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Plots/ILLitSink.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Plots/ILLitSink.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Plots/ILLitSink.cs	(revision 9102)
@@ -0,0 +1,397 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Windows.Forms;
+using ILNumerics.Drawing.Misc;
+using ILNumerics.Drawing.Shapes;
+
+namespace ILNumerics.Drawing.Plots {
+    /// <summary>
+    /// ILNumerics.Drawing plot demonstration, supports multiple shapes, dynamic shape management, light and transparency
+    /// </summary>
+    public class ILLitSink : ILPlot , ILNumerics.Drawing.Interfaces.IILPanelConfigurator {
+
+        #region eventing
+        /// <summary>
+        /// timer tick event handler, called for updates of the interval timer
+        /// </summary>
+        /// <param name="sender">(not used) always this sink plot itself</param>
+        /// <param name="e">(not used)</param>
+        void m_timer_Tick(object sender, EventArgs e) {
+            if (m_timer.Interval > 0 && m_panel != null && m_panel.IsHandleCreated) {
+                m_timer.Stop(); 
+                LinesPositionOffset += 0.005f * m_gridSpacing;
+                //Opacity = (byte)(255 * (LinesPositionOffset / m_gridSpacing)); 
+                m_panel.Refresh(); 
+                m_timer.Start(); 
+            }
+        }
+        #endregion
+
+        #region attributes
+        float m_lowCut; 
+        protected int m_res;
+        ILLineProperties m_gridProperties;
+        protected float m_max;
+        protected float m_gridSpacing; 
+        protected float m_linesPositionOffset = 0.5f; 
+        bool m_linesUpdateNeeded; 
+        Timer m_timer; 
+        // the shapes and other plots contained in this plot
+        ILLitSurface m_surface;
+        List<ILLine> m_lines; 
+        ILLitSphere m_sphere;
+        #endregion
+
+        #region properties
+        /// <summary>
+        /// get/ set the interval for updates of the moving grid lines [ms]
+        /// </summary>
+        public int Interval {
+            get { return m_timer.Interval; }
+            set {
+                if (value < int.MaxValue && value > 0) {
+                    m_timer.Interval = value;
+                    m_timer.Start();  
+                } else {
+                    m_timer.Stop(); 
+                }
+            }
+        }
+        /// <summary>
+        /// Overall opacity for the ground 
+        /// </summary>
+        public byte Opacity {
+            get { return m_surface.Opacity; }
+            set { 
+                m_surface.Opacity = value;
+                m_surface.Invalidate(); 
+            }
+        }
+        /// <summary>
+        /// colormap used for coloring the ground
+        /// </summary>
+        public ILColormap Colormap {
+            get { return m_surface.Colormap; }
+            set {
+                m_surface.Colormap = value;
+                m_surface.Invalidate();  
+            }
+        }
+        /// <summary>
+        /// get reference to the lit sphere 
+        /// </summary>
+        public ILLitSphere Sphere {
+            get  { return m_sphere; }
+        }
+        /// <summary>
+        /// get reference to ILLitSurface (i.e. the ground)
+        /// </summary>
+        public ILLitSurface Ground {
+            get { return m_surface; }
+        }
+        /// <summary>
+        /// offset for the grid lines (for moving effect) 
+        /// </summary>
+        public float LinesPositionOffset  {
+            get { return m_linesPositionOffset; }
+            set { 
+                m_linesPositionOffset = value;
+                if (m_linesPositionOffset > m_gridSpacing) {
+                    m_linesPositionOffset = 0; 
+                }
+                m_linesUpdateNeeded = true;  
+                Invalidate(); 
+            }
+        }
+        #endregion
+
+        #region constructor
+        /// <summary>
+        /// create new lit sink plot, assign default values 
+        /// </summary>
+        /// <param name="panel">panel hosting the scene</param>
+        public ILLitSink (ILPanel panel) : this (panel,10,150) {}
+        /// <summary>
+        /// create new lit sink
+        /// </summary>
+        /// <param name="max">lenght of the squared ground</param>
+        /// <param name="panel">panel hosting the scene</param>
+        /// <param name="resolution">horizontal and vertical resolution</param>
+        public ILLitSink(ILPanel panel, float max, int resolution)
+            : base(panel) {
+            m_max = max; 
+            m_res = resolution; 
+            m_lowCut = -3; 
+            m_gridProperties = new ILLineProperties(); 
+            m_gridProperties.Color = Color.LightBlue; 
+            m_gridProperties.Width = 1; 
+            m_gridProperties.Antialiasing = false; 
+            m_gridProperties.Style = LineStyle.Solid; 
+            m_gridSpacing = 1.0f; 
+            m_linesUpdateNeeded = false; 
+            m_timer = new Timer(); 
+            m_timer.Interval = int.MaxValue;
+            m_timer.Tick += new EventHandler(m_timer_Tick);
+            createShapes(); 
+            Invalidate();
+        }
+        #endregion
+
+        #region public API
+        /// <summary>
+        /// called once before rendering the frame, (re)configures the shapes after changes have been made to them
+        /// </summary>
+        /// <remarks><para>ILPlot plots can (not must) override this method. It is called, right before the scene is 
+        /// rendered on screen. Since the containing shapes are independently configured, here (in ILPlot) we
+        /// do only need to (re)configure those content of the plot, which must be recreated after changes have been 
+        /// applied. In ILLitSink, e.g., changes to the sphere and the ground (ILLitSurface) are directly distributed 
+        /// to the related shapes respectively. This happens, when calling any ILShape.Update() overload or after 
+        /// ILShape.Invalidate() has been called. Those shapes will than reconfigure itself and must not be handled here. </para> 
+        /// <para>In contrast to that, the (moving) grid lines of the sink plot are constantly created and removed.</para>
+        /// </remarks>
+        internal override void Configure() {
+            if (m_linesUpdateNeeded) {
+                updateLines(); 
+            }
+            base.Configure();
+        }
+
+        /// <summary>
+        /// configure the panel according to default settings of this plot
+        /// </summary>
+        /// <param name="panel">panel hosting the scene</param>
+        /// <remarks>In order to force a custom configuration of the panel, 
+        /// the plot implements the IILPanelConfigurator interface. For every plot 
+        /// implementing this interface, the panel will be configured by this 
+        /// function once the plot was added to the scene/ to the panel graphs collection.
+        /// If the plot does not implement this interface, the panel settings will 
+        /// not be altered.</remarks>
+        public void ConfigurePanel(ILPanel panel) {
+            panel.Projection = Projection.Perspective;
+            panel.BackColor = Color.White;
+            panel.BackColorCube = Color.White;
+            panel.Axes.GridVisible = false;
+            panel.Axes.Visible = false; 
+            panel.BackgroundFilled = false; 
+            panel.AspectRatio = AspectRatioMode.MaintainRatios; 
+            panel.PlotBoxScreenSizeMode = PlotBoxScreenSizeMode.Maximum; 
+            panel.ClipViewData = false; 
+            panel.InteractiveMode = InteractiveModes.Rotating; 
+            panel.AutoZoomContent =  AutoZoomOptions.OnStartup; 
+            panel.ZoomMode = ZoomModes.Jump;
+ 
+        }
+        #endregion
+
+        #region private helper
+
+        private void updateLines() {
+            using (ILScope.Enter()) {
+                // since we do not want the whole panel to get updated for every line, we disable 
+                // eventing for this scene graph node
+                EventingSuspend();
+                // the grid is made out of individual line shapes
+                ILCell lines =  Computation.CreateLines(-m_max, m_max,
+                               m_lowCut, 0, m_res, m_gridSpacing, m_linesPositionOffset);
+                // make sure, we have the exact number of lines needed
+                int needCount = lines[0].Size[1] * 2; // x and y direction -> * 2
+                if (m_lines.Count > needCount) {
+                    // if we have to many line shapes, we make unneeded lines invisible
+                    for (int i = m_lines.Count; i-- > needCount; ) {
+                        ILLine shape = m_lines[i];
+                        shape.Visible = false;
+                    }
+                    // just as well, we could instead have removed the shape from both: 
+                    // the shape collection of the container (ILSceneGraphInnerNode) and
+                    // the (convenient but redundant) shape collection of the plot: 
+                    //Remove(shape);
+                    //m_lines.Remove(shape);
+                }
+                while (m_lines.Count < needCount) {
+                    // we do not have enough lines - so we add new lines here 
+                    ILLine newLine = new ILLine(m_panel);
+                    newLine.Properties.Color = m_gridProperties.Color;
+                    newLine.Label.Text = "";
+                    newLine.Properties.Width = m_gridProperties.Width;
+                    newLine.CustomCenter = new ILPoint3Df(0, 0, -200);
+                    Add(newLine);
+                    m_lines.Add(newLine);
+                }
+                // reconfigures all lines 
+                for (int i = 0; i < lines[0].Size[1]; i++) {
+                    // x - grid
+                    ILLine line = m_lines[i];
+                    line.Visible = true;
+                    line.Update(lines.GetArray<float>(0)[":", i]
+                                , lines.GetArray<float>(1)[":", i]
+                                , lines.GetArray<float>(2)[":", i]);
+                    // y - grid
+                    line = m_lines[i + lines[0].Size[1]];
+                    line.Update(lines.GetArray<float>(0)[":", i]
+                                 , lines.GetArray<float>(1)[":", i]
+                                 , lines.GetArray<float>(2)[":", i]);
+                }
+                // re-enable eventing
+                EventingResume();
+            }
+        }
+        private void createShapes() {
+            // disable eventing, otherwise, for each line added the whole panel would get reconfigured 
+            // which would lead to a poor startup performance
+            EventingSuspend(); 
+            // the ground is a lit surface 
+            if (m_surface == null) {
+                ILCell mesh = Computation.CreateMesh(-m_max, m_max, m_lowCut, 0, m_res);
+                m_surface = new ILLitSurface(m_panel, X : mesh.GetArray<float>(0), Y : mesh.GetArray<float>(1), Z : mesh.GetArray<float>(2), colormap : new ILColormap(Colormaps.Jet));
+                m_surface.Opacity = 190;
+                Add(m_surface); 
+            }
+            if (m_lines == null) {
+                // we create all individual lines and save them (redundantly) for later convenient reference.
+                // (the grid is made out of individual line shapes)
+                ILCell lines = Computation.CreateLines(-m_max, m_max,
+                                    m_lowCut, 0, m_res, m_gridSpacing, m_linesPositionOffset);
+                m_lines = new List<ILLine>();
+                for (int i = 0; i < lines[0].Size[1]; i++) {
+                    // x - grid
+                    int len = lines.GetArray<float>(0).S[0]; 
+                    ILLine line = new ILLine(m_panel,len); 
+                    line.Update(lines.GetArray<float>(0)[":", i]
+                                , lines.GetArray<float>(1)[":", i]
+                                , lines.GetArray<float>(2)[":", i]);
+                    line.Properties.Color = m_gridProperties.Color;
+                    line.Label.Text = "";
+                    line.Properties.Width = m_gridProperties.Width;
+                    line.CustomCenter = new ILPoint3Df(0,0,-200); 
+                    m_lines.Add(line);
+                    Add(line);
+                    // y - grid
+                    line = new ILLine(m_panel, len); 
+                    line.Update(lines.GetArray<float>(0)[":", i]
+                                , lines.GetArray<float>(1)[":", i]
+                                , lines.GetArray<float>(2)[":", i]);
+                    line.Properties.Color = m_gridProperties.Color;
+                    line.Label.Text = "";
+                    line.Properties.Width = m_gridProperties.Width;
+                    line.CustomCenter = new ILPoint3Df(0,0,-200); 
+                    m_lines.Add(line);
+                    Add(line);
+                }
+            }
+            // re-enable eventing, still one shape to be added: the sphere, which will cause a reconfiguration 
+            // of the whole panel
+            EventingResume(); 
+            // lit sphere
+            if (m_sphere == null) {
+                m_sphere = new ILLitSphere(m_panel, new ILPoint3Df(0,0,1.4f), 1.8f, Color.FromArgb(190,Color.Gold)); 
+                Add(m_sphere); 
+                m_sphere.Label.Text = ""; 
+                m_sphere.Opacity = 190; 
+            } 
+        }
+
+        private class Computation : ILNumerics.ILMath {
+            /// <summary>
+            /// create data needed to create the ground (ILLitSurface)
+            /// </summary>
+            /// <param name="Min">minimum (x and y)</param>
+            /// <param name="Max">maximum (x and y)</param>
+            /// <param name="cut">minimum sinkhole level</param>
+            /// <param name="zNiveau">overall zero level</param>
+            /// <param name="resol">horizontal and vertical resolution</param>
+            /// <param name="result">cell vector with X, Y and Z array</param>
+            public static ILRetCell CreateMesh(
+                                            float Min, float Max, 
+                                            float cut, float zNiveau, 
+                                            int resol) {
+                using (ILScope.Enter())  {
+                    ILArray<double> x = linspace(Min, Max, resol);
+                    ILArray<double> y = empty(); 
+                    ILCell ret = new ILCell(3,1); 
+                    ret[0] = meshgrid(x, linspace(Max ,Min, resol), y);
+                    ret[1] = y; 
+                    // Z coords
+                    ret[2] = max(-1.0 / (ret.GetArray<double>(0) * ret.GetArray<double>(0))
+                                                + (ret.GetArray<double>(1) * ret.GetArray<double>(1)) + zNiveau, cut);
+                    //ret.Add(find(ret[2] == cut));
+                    return ret; 
+                }
+            }
+            /// <summary>
+            /// create data needed to create grid lines 
+            /// </summary>
+            /// <param name="Min">minimum (x and y)</param>
+            /// <param name="Max">maximum (x and y)</param>
+            /// <param name="cut">minimum sinkhole level</param>
+            /// <param name="zNiveau">overall zero level</param>
+            /// <param name="resol">horizontal and vertical resolution</param>
+            /// <param name="gridSpacing">spacing between adjacent grid lines</param>
+            /// <param name="gridOffset">starting offset for the grid lines at edges</param>
+            /// <param name="result">list of X,Y and Z arrays</param>
+            /// <remarks>Only the X grid is created. Since we only have squared sink ground, the 
+            /// same data can be used for the y grid. </remarks>
+            public static ILRetCell CreateLines(
+                                            float Min, float Max, 
+                                            float cut, float zNiveau, 
+                                            int resol, float gridSpacing,
+                                            float gridOffset) {
+                using (ILScope.Enter()) {
+                    ILCell ret = new ILCell(2,1);
+                    // X coords
+                    ret[0] = repmat(vec<float>(Min + gridOffset, gridSpacing, Max).T, resol, 1); 
+                    // Y coords
+                    ret[1] = repmat(linspace<float>(Min, Max, resol).T, 1, ret[0].Size[1]);
+                    // Z coords
+                    ret[2] = max(-1 /   (ret.GetArray<float>(0) * ret.GetArray<float>(0) 
+                                       + ret.GetArray<float>(1) * ret.GetArray<float>(1)) 
+                                       + zNiveau, cut) + MachineParameterSingle.eps;
+                    //ret.Add(zeros(resol, resol) + 10000);
+                    //ret[2][0] += 0.01; 
+                    return ret; 
+                }
+            }
+        }
+
+        #endregion
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Plots/ILLitSurface.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Plots/ILLitSurface.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Plots/ILLitSurface.cs	(revision 9102)
@@ -0,0 +1,300 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing; 
+using ILNumerics;
+using ILNumerics.Drawing;
+using ILNumerics.Drawing.Graphs;
+using ILNumerics.Drawing.Shapes; 
+using ILNumerics.Drawing.Misc;
+using ILNumerics.Drawing.Labeling;
+
+namespace ILNumerics.Drawing.Plots {
+    /// <summary>
+    /// surface plot supporting light and transparency
+    /// </summary>
+    public sealed class ILLitSurface : ILPlot, Interfaces.IILPanelConfigurator {
+
+        #region attributes
+        protected ILColormap m_colorMap;
+        protected ILArray<float> m_xVals = ILMath.returnType<float>();
+        protected ILArray<float> m_yVals = ILMath.returnType<float>();
+        protected ILArray<float> m_zVals = ILMath.returnType<float>();
+        protected byte m_opacity = 255;
+        ILArray<float> m_colorIndices = ILMath.returnType<float>(); 
+        ILLitQuads m_quads;
+        #endregion
+
+        #region properties
+        /// <summary>
+        /// Overall opacity for the surface 
+        /// </summary>
+        public byte Opacity {
+            get { return m_opacity; }
+            set { 
+                m_opacity = value;
+                m_quads.Opacity = value; 
+                Invalidate(); 
+            }
+        }
+        /// <summary>
+        /// colormap used for coloring the surface 
+        /// </summary>
+        public ILColormap Colormap {
+            get { return m_colorMap; }
+            set {
+                m_colorMap = value;
+                Invalidate();
+            }
+        }
+        /// <summary>
+        /// reference to the label for the surface
+        /// </summary>
+        public ILShapeLabel Label {
+            get { return m_quads.Label; }
+        }
+        /// <summary>
+        /// get a reference to the data values or sets it, used for updates to the plot
+        /// </summary>
+        public ILRetArray<float> XValues {
+            get { return m_xVals.C; }
+            set {
+                using (ILScope.Enter(value)) {
+                    if (object.Equals(value, null)) {
+                        m_xVals.a = ILMath.empty<float>(); 
+                    } else if (value.Size.IsSameSize(m_zVals.Size)) {
+                        m_xVals.a = value.C;
+                        Invalidate();
+                    } else {
+                        throw new ArgumentException("invalid size: XValues must be null or have the same size as ZValues");
+                    }
+                }
+            }
+        }
+        /// <summary>
+        /// get a reference to the data values or sets it, used for updates to the plot
+        /// </summary>
+        public ILRetArray<float> YValues {
+            get { return m_yVals; }
+            set {
+                using (ILScope.Enter(value)) {
+                    if (object.Equals(value, null)) {
+                        m_yVals.a = ILMath.empty<float>();
+                    } else if (value.Size.IsSameSize(m_zVals.Size)) {
+                        m_yVals.a = value.C;
+                        Invalidate();
+                    } else {
+                        throw new ArgumentException("invalid size: YValues must be null or have the same size as ZValues");
+                    }
+                }
+            }
+        }
+        /// <summary>
+        /// get a reference to the data values or sets it, used for updates to the plot
+        /// </summary>
+        public ILRetArray<float> ZValues {
+            get { return m_zVals; }
+            set {
+                using (ILScope.Enter(value)) {
+                    if (value != null && (m_zVals.IsEmpty || value.Size.IsSameSize(m_zVals.Size))) {
+                        m_zVals.a = value.C;
+                        Invalidate();
+                    } else {
+                        throw new ArgumentException("invalid size: ZValues must be a matrix");
+                    }
+                }
+            }
+        }
+        /// <summary>
+        /// get a reference to the color index values or sets it, used for updates to the plot
+        /// </summary>
+        public ILRetArray<float> ColorIndices {
+            get { return m_colorIndices; }
+            set {
+                using (ILScope.Enter(value)) {
+                    if (object.Equals(value, null)) {
+                        m_colorIndices.a = ILMath.empty<float>();
+                    } else if (value.Size.IsSameSize(m_zVals.Size)) {
+                        m_colorIndices.a = value.C;
+                        Invalidate();
+                    } else {
+                        throw new ArgumentException("invalid size: ColorIndices must be null or have the same size as ZValues");
+                    }
+                }
+            }
+        }
+        /// <summary>
+        /// get reference to IILLitQuads lit composite shape used for rendering the surface
+        /// </summary>
+        public ILLitQuads Quads {
+            get { return m_quads; }
+        }
+        #endregion
+
+        #region constructors
+        /// <summary>
+        /// create new lit surface, provide data for X,Y and Z coordinates
+        /// </summary>
+        /// <param name="panel">the panel hosting the scene</param>
+        /// <param name="X">X coordinates matrix, same size as Z or null</param>
+        /// <param name="Y">Y coordinates matrix, same size as Z or null</param>
+        /// <param name="Z">Z data matrix, at least 2 rows, 2 columns</param>
+        /// <param name="colormap">colormap used for auto coloring the surface</param>
+        public ILLitSurface(ILPanel panel, ILInArray<float> Z, ILInArray<float> X = null, ILInArray<float> Y = null, ILColormap colormap = null, ILInArray<float> colorIndices = null)
+            : base(panel) {
+            using (ILScope.Enter(X, Y, Z, colorIndices)) {
+                ZValues = ILMath.check(Z, (a) => { return (a.S[0] >= 2 || a.S[1] >= 2) ? Z : null; }, ErrorMessage: "invalid parameter: Z must be a matrix");
+                XValues = X;
+                YValues = Y; 
+                ColorIndices = colorIndices; 
+                m_quads = new ILLitQuads(panel, Z.S.NumberOfElements);
+                m_quads.Label.Text = "";
+                m_quads.Shading = ShadingStyles.Interpolate;
+                if (colormap == null) {
+                    colormap = new ILColormap(Colormaps.ILNumerics); 
+                }
+                Add(m_quads);
+                m_colorMap = colormap;
+                Invalidate();
+            }
+        }
+        #endregion
+
+        #region public interface
+        /// <summary>
+        /// (re)configure the plot, causes a recreation of all quads due to changed parameters
+        /// </summary>
+        internal override void Configure() {
+            if (m_invalidated) {
+                m_quads.Indices = Computation.configureVertices(
+                                XValues,YValues,ZValues, 
+                                m_colorMap, m_quads.Vertices, m_opacity,
+                                ColorIndices);
+                m_quads.Invalidate();
+                m_quads.Configure();
+                m_invalidated = false; 
+            }
+            base.Configure();
+        }
+        #endregion
+
+        #region private helper
+        private class Computation : ILMath {
+            public static ILRetArray<int> configureVertices(
+                    ILInArray<float> xVals, ILInArray<float> yVals,
+                    ILInArray<float> zVals, ILColormap cmap, C4fN3fV3f[] Vertices, byte opacity, 
+                    ILInArray<float> colors = null) {
+                        using (ILScope.Enter(xVals,yVals,zVals)) {
+                            int i = 0, x, y, y0 = zVals.Size[0] - 1;
+                            x = 0;
+                            y = 0;
+                            ILArray<float> colorIndices;
+                            float minZ, maxZ;
+                            // if matching colors were given, scale them to colormap range
+                            // otherwise take zvalues as base
+                            if (isnullorempty(colors) || !colors.S.IsSameShape(zVals.S)) {
+                                if (!zVals.GetLimits(out minZ, out maxZ, false))
+                                    minZ = maxZ = 1.0f;
+                                colorIndices = (tosingle((zVals - minZ) / (maxZ - minZ)))[":"] * (cmap.Length - 1);
+                            } else {
+                                if (!colors.GetLimits(out minZ, out maxZ, false))
+                                    minZ = maxZ = 1.0f;
+                                colorIndices = (tosingle((colors - minZ) / (maxZ - minZ)))[":"] * (cmap.Length - 1);
+                            }
+                            colorIndices[isnan(colorIndices)] = 0;
+                            bool useXvals = (xVals != null && !xVals.IsEmpty);
+                            bool useYvals = (yVals != null && !yVals.IsEmpty);
+                            foreach (float a in zVals) {
+                                C4fN3fV3f v = Vertices[i];
+                                v.Position = new ILPoint3Df(
+                                     (useXvals) ? xVals.GetValue(y, x) : x
+                                    , (useYvals) ? yVals.GetValue(y, x) : y0 - y
+                                    , a);
+                                byte r, g, b;
+                                cmap.Map(colorIndices.GetValue(i), out r, out g, out b);
+                                v.Color = Color.FromArgb(255, r, g, b);
+                                v.Alpha = opacity;
+                                Vertices[i++] = v;
+                                // set next position
+                                if (++y >= zVals.S[0]) {
+                                    x++;
+                                    y = 0;
+                                }
+                            }
+
+                            // create quad indices
+                            int numQuad = (zVals.Size[0] - 1) * (zVals.Size[1] - 1);
+                            x = 0; y = 0;
+                            ILArray<int> ret = zeros<int>(4, numQuad);
+                            ILArray<int> mult = counter<int>(0.0, 1.0, zVals.Size);
+                            mult.a = mult["0:" + (zVals.Size[0] - 2), "0:" + (zVals.Size[1] - 2)];
+                            mult.a = mult[":"].T;
+
+                            ret["0;:"] = mult;
+                            ret["3;:"] = mult + 1;
+                            mult.a = mult + zVals.Size.SequentialIndexDistance(1);
+                            ret["2;:"] = mult + 1;
+                            ret["1;:"] = mult;
+
+                            // remove quads having NaN values involved
+
+                            return ret;
+                        }
+            }
+        }
+        #endregion
+
+        #region IILPanelConfigurator Members
+
+        public void ConfigurePanel(ILPanel panel) {
+            panel.InteractiveMode = InteractiveModes.Rotating;
+            if (panel.AutoDefaultView) {
+                panel.DefaultView.EventingSuspend(); 
+                panel.DefaultView.SetDeg(-25, 45, 100);
+                panel.DefaultView.EventingResume(false); 
+            }
+            panel.BackgroundFilled = false; 
+        }
+
+        #endregion
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Plots/ILPlot.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Plots/ILPlot.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Plots/ILPlot.cs	(revision 9102)
@@ -0,0 +1,57 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Drawing;
+using ILNumerics.Drawing.Graphs; 
+
+namespace ILNumerics.Drawing.Plots {
+    /// <summary>
+    /// (abstract) base class for all higher level plot objects
+    /// </summary>
+    public abstract class ILPlot : ILSceneGraphInnerNode {
+
+        public ILPlot(ILPanel panel)
+            : base(panel) {
+
+        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Plots/ILVectorField2D.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Plots/ILVectorField2D.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Plots/ILVectorField2D.cs	(revision 9102)
@@ -0,0 +1,301 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Drawing.Graphs;
+using ILNumerics.Drawing.Shapes;
+using ILNumerics.Drawing.Misc;
+using ILNumerics.Exceptions;
+using ILNumerics.Drawing.Interfaces;
+using ILNumerics.Drawing.Collections; 
+
+namespace ILNumerics.Drawing.Plots {
+    /// <summary>
+    /// visualizes 2D vector fields
+    /// </summary>
+    public sealed class ILVectorField2D : ILPlot, IILPanelConfigurator {
+
+        #region attributes
+        ILLines m_lines;
+        float m_beta = (float)(5 * Math.PI / 180);
+        float m_scaling = 0.9f;
+        ILArray<float> m_data = ILMath.returnType<float>();
+        ICollection<string> m_xLabels;
+        ICollection<string> m_yLabels;
+        #endregion
+
+        #region properties
+        /// <summary>
+        /// Colormap used to map values to colors
+        /// </summary>
+        private ILColormap m_colormap;
+        /// <summary>
+        /// gets reference to data of all vectors or sets it (restricted to same size)
+        /// </summary>
+        public ILRetArray<float> Data {
+            get {
+                return m_data;
+            }
+            set {
+                if (value != null && value.Size.IsSameSize(m_data.Size)) {
+                    m_data.a = value.C; 
+                    Invalidate(); 
+                }
+            }
+        }
+
+        /// <summary>
+        /// get the colormap used for coloring the arrows or sets it
+        /// </summary>
+        public ILColormap Colormap {
+            get { return m_colormap; }
+            set {
+                m_colormap = value;
+                Invalidate();
+            }
+        }
+        /// <summary>
+        /// opening angle for the arrow heads, default: 5 deg
+        /// </summary>
+        public float ArrowHeadAngle {
+            get { return m_beta; }
+            set {
+                m_beta = value;
+                Invalidate();
+            }
+        }
+
+        /// <summary>
+        /// Scaling of arrow length, 1.0: full size; default: 0.9
+        /// </summary>
+        public float ArrowScale {
+            get { return m_scaling; }
+            set {
+                m_scaling = value;
+                Invalidate();
+            }
+        }
+
+        /// <summary>
+        /// enables access to the lines composite shape used for rendering
+        /// </summary>
+        public ILLines LinesShape {
+            get {
+                return m_lines; 
+            }
+        }
+
+        /// <summary>
+        /// collection of label texts for x axis
+        /// </summary>
+        public ICollection<string> XLabels {
+            get { return m_xLabels; }
+            set { 
+                m_xLabels = value;
+                Invalidate();
+            }
+        }
+
+        /// <summary>
+        /// collection of label texts for y axis
+        /// </summary>
+        public ICollection<string> YLabels {
+            get { return m_yLabels; }
+            set { 
+                m_yLabels = value;
+                Invalidate();
+            }
+        }
+
+        #endregion
+
+        #region constructors
+
+        /// <summary>
+        /// create new vector field (2D) plot 
+        /// </summary>
+        /// <param name="panel">panel hosting the scene</param>
+        /// <param name="data">3d data array: :;:;0 - X coords of vectors, :;:;1 - Y coords</param>
+        /// <param name="colormap">Colormap used for coloring, on null: Colormaps.ILNumerics is used as default</param>
+        /// <param name="XLabels">labels for X axis, on null: auto labeling</param>
+        /// <param name="YLabels">labels for Y axis, on null: auto labeling</param>
+        public ILVectorField2D(ILPanel panel, ILInArray<float> data
+            , ILColormap colormap, ICollection<string> XLabels
+            , ICollection<string> YLabels)
+            : base(panel) {
+            using (ILScope.Enter(data)) {
+                m_data.a = ILMath.check(data, (a) => { return (a.S[2] == 2 && !a.IsEmpty) ? a : null; }, ErrorMessage: "Invalid parameter: data"); 
+                m_xLabels = XLabels;
+                m_yLabels = YLabels;
+                m_colormap = colormap;
+                m_lines = new ILLines(m_panel, data.Size[0] * data.Size[1] * 4);
+                m_lines.Shading = ShadingStyles.Interpolate;
+                m_lines.Properties.Width = 2;
+                m_lines.Properties.Antialiasing = true;
+                m_lines.Label.Text = "";
+                ArrowHeadAngle = (float)(10 * Math.PI / 180);
+                Invalidate();
+                Add(m_lines);
+            }
+        }
+        #endregion
+
+        #region public interface
+        /// <summary>
+        /// (internal use) reconfigures the plot after changes
+        /// </summary>
+        internal override void Configure() {
+            using (ILScope.Enter()) {
+                if (m_invalidated) {
+                    ILArray<int> indices = ILMath.empty<int>();
+                    ILArray<float> vertices = Computation.CreateVertices(
+                        m_data, indices, m_beta, m_scaling / 2, m_colormap);
+                    m_lines.Update(vertices["0;:"], vertices["1;:"], vertices["2;:"], indices, ILMath.toint32(vertices["3:5;:"].T));
+                    // configure axes
+                    configureAxis(AxisNames.XAxis, XLabels);
+                    configureAxis(AxisNames.YAxis, YLabels);
+                }
+                base.Configure();
+            }
+        }
+        #endregion
+
+        #region IILPanelConfigurator Members
+        /// <summary>
+        /// configure the panel, called after the plot was added to the scene
+        /// </summary>
+        /// <param name="panel"></param>
+        public void ConfigurePanel(ILPanel panel) {
+            panel.DefaultView.SetDeg(0, 0, 100);
+        }
+
+        #endregion
+
+        #region private helper
+        private void configureAxis(AxisNames axis
+                                    , ICollection<string> values) {
+            ILTickCollection labels = m_panel.Axes[axis].LabeledTicks;
+            if (values != null) {
+                labels.Mode = TickMode.Manual;
+                labels.Clear();
+                int pos = 1;
+                int axisIdx = (axis == AxisNames.XAxis) ?
+                    1 : (axis == AxisNames.YAxis) ?
+                    0 : 1; 
+                foreach (string labelString in values) {
+                    if (pos > m_data.Size[axisIdx])
+                        break;
+                    labels.Add(pos++, labelString); 
+                }
+            } else {
+                labels.Mode = TickMode.Auto; 
+            }
+        }
+        #endregion
+
+        #region computation
+        public class Computation : ILNumerics.ILMath {
+
+            internal static ILRetArray<float> CreateVertices(ILInArray<float> inData
+                                            , ILOutArray<int> outIndices
+                                            , float beta, float scaling
+                                            , ILColormap colormap) {
+                using (ILScope.Enter(inData)) {
+                    // each arrow needs 4 vertices (indexed rendering)
+                    ILArray<float> data = check(inData);
+                    ILArray<int> indices = empty<int>(); 
+
+                    int numRows = data.Size[0];
+                    int numCols = data.Size[1];
+                    ILArray<float> ret = zeros<float>(4, numCols * numRows, 2);
+                    // prepare indices
+                    indices.a = repmat(new ILArray<int>(new int[] { 0, 2, 1, 2, 3, 2 }, 6, 1), 1, numCols * numRows);
+                    indices.a = indices + repmat(toint32(counter(0.0, 4.0, 1, numCols * numRows)), 6, 1);
+                    indices.a = indices.Reshape(new ILSize(2, numRows * numCols * 3));
+                    // normalize incoming data to length 1.0 
+                    ILArray<float> l = sqrt(sum(data * data, 2));
+                    float maxL = (float)max(maxall(l), epsf);
+                    l.a = (l / maxL)[":"].T * scaling;
+                    ILArray<float> alpha = atan2(data[":;:;1"], data[":;:;0"]);
+                    alpha.a = alpha[":"].T;
+                    ILArray<float> x = data[":;:;0"][":"].T * scaling;
+                    ILArray<float> y = data[":;:;1"][":"].T * scaling;
+                    ILArray<float> xO = repmat(linspace<float>(1, numCols, numCols), numRows, 1)[":"].T;
+                    ILArray<float> yO = repmat(linspace<float>(numRows, 1, numRows).T, 1, numCols)[":"].T;
+                    ret["0;:;0"] = xO - x;
+                    ret["1;:;0"] = xO + x - l / 2 * cos(alpha + beta);
+                    ret["2;:;0"] = xO + x;
+                    ret["3;:;0"] = xO + x - l / 2 * cos(alpha - beta);
+
+                    ret["0;:;1"] = yO - y;
+                    ret["1;:;1"] = yO + y - l / 2 * sin(alpha + beta);
+                    ret["2;:;1"] = yO + y;
+                    ret["3;:;1"] = yO + y - l / 2 * sin(alpha - beta);
+
+                    ret["0;0;2"] = 0.0f;
+                    // prepare colors 
+                    ret[":;:;3:5"] = 
+                        repmat(colormap.Map(l * colormap.Length).Reshape(1, l.Length, 3) * 255, 4, 1, 1);
+                    return ret.Reshape(4 * numRows * numCols, 6).T;
+                }
+            }
+            /// <summary>
+            /// create data for a simple vector field for demonstration purposes
+            /// </summary>
+            /// <param name="numRows">number of rows</param>
+            /// <param name="numCols">number of colums</param>
+            /// <param name="offs">offset, linearly varing values lets the field 'roll'</param>
+            /// <returns>three dimensional data array</returns>
+            public static ILRetArray<float> CreateTestData(int numRows, int numCols, float offs) {
+                using (ILScope.Enter()) {
+                    ILArray<float> Y = repmat(linspace<float>(offs, pi * 2 + offs, numCols), numRows, 1);
+                    ILArray<float> X = cos(Y);
+                    X[":;:;1"] = sin(Y);
+                    // scale vector length
+                    X.a = X * repmat(0.6f + sin(Y) * 0.4f, 1, 1, 2);
+                    return X;
+                }
+            }
+        }
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Resources/Images.resx
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Resources/Images.resx	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Resources/Images.resx	(revision 9102)
@@ -0,0 +1,124 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+  <data name="close" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\close.bmp;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+</root>
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Resources/Images1.Designer.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Resources/Images1.Designer.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Resources/Images1.Designer.cs	(revision 9102)
@@ -0,0 +1,99 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+namespace ILNumerics.Drawing.Resources {
+    using System;
+    
+    
+    /// <summary>
+    ///   A strongly-typed resource class, for looking up localized strings, etc.
+    /// </summary>
+    // This class was auto-generated by the StronglyTypedResourceBuilder
+    // class via a tool like ResGen or Visual Studio.
+    // To add or remove a member, edit your .ResX file then rerun ResGen
+    // with the /str option, or rebuild your VS project.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Images {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Images() {
+        }
+        
+        /// <summary>
+        ///   Returns the cached ResourceManager instance used by this class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ILNumerics.Drawing.Resources.Images", typeof(Images).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// <summary>
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+        
+        internal static System.Drawing.Bitmap close {
+            get {
+                object obj = ResourceManager.GetObject("close", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Resources/Markers.resx
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Resources/Markers.resx	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Resources/Markers.resx	(revision 9102)
@@ -0,0 +1,145 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+  <data name="Circle25x25" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>Circle25x25.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="Cross25x25" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>Cross25x25.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="Diamond25x25" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>Diamond25x25.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="Plus25x25" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>Plus25x25.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="TriangleDown25x25" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>TriangleDown25x25.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="TriangleLeft25x25" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>TriangleLeft25x25.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="TriangleRight25x25" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>TriangleRight25x25.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="TriangleUp25x25" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>TriangleUp25x25.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+</root>
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Resources/Markers1.Designer.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Resources/Markers1.Designer.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Resources/Markers1.Designer.cs	(revision 9102)
@@ -0,0 +1,148 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+namespace ILNumerics.Drawing.Resources {
+    using System;
+    
+    
+    /// <summary>
+    ///   A strongly-typed resource class, for looking up localized strings, etc.
+    /// </summary>
+    // This class was auto-generated by the StronglyTypedResourceBuilder
+    // class via a tool like ResGen or Visual Studio.
+    // To add or remove a member, edit your .ResX file then rerun ResGen
+    // with the /str option, or rebuild your VS project.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Markers {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Markers() {
+        }
+        
+        /// <summary>
+        ///   Returns the cached ResourceManager instance used by this class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ILNumerics.Drawing.Resources.Markers", typeof(Markers).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// <summary>
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+        
+        internal static System.Drawing.Bitmap Circle25x25 {
+            get {
+                object obj = ResourceManager.GetObject("Circle25x25", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap Cross25x25 {
+            get {
+                object obj = ResourceManager.GetObject("Cross25x25", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap Diamond25x25 {
+            get {
+                object obj = ResourceManager.GetObject("Diamond25x25", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap Plus25x25 {
+            get {
+                object obj = ResourceManager.GetObject("Plus25x25", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap TriangleDown25x25 {
+            get {
+                object obj = ResourceManager.GetObject("TriangleDown25x25", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap TriangleLeft25x25 {
+            get {
+                object obj = ResourceManager.GetObject("TriangleLeft25x25", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap TriangleRight25x25 {
+            get {
+                object obj = ResourceManager.GetObject("TriangleRight25x25", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap TriangleUp25x25 {
+            get {
+                object obj = ResourceManager.GetObject("TriangleUp25x25", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILBorderedShape.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILBorderedShape.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILBorderedShape.cs	(revision 9102)
@@ -0,0 +1,174 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Drawing; 
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Drawing.Graphs;
+using ILNumerics.Exceptions;
+using ILNumerics.Drawing.Interfaces;  
+using ILNumerics.Drawing; 
+namespace ILNumerics.Drawing.Shapes {
+    /// <summary>
+    /// Base class for all simple shapes, rendering a primitive 
+    /// with a border, which is independantly configurable. 
+    /// </summary>
+    /// <typeparam name="VertexType">inner vertex element type (struct)</typeparam>
+    public abstract class ILBorderedShape<VertexType> : ILShape<VertexType> 
+        where VertexType : struct, IILVertexDefinition {
+
+        #region eventing 
+        #endregion
+
+        #region attributes
+        protected ILLineProperties m_border; 
+        #endregion
+
+        #region properties 
+        /// <summary>
+        /// get reference to the properties of the shapes border 
+        /// </summary>
+        public ILLineProperties Border {
+            get {
+                return m_border; 
+            }
+        }
+        #endregion
+
+        /// <summary>
+        /// create new bordered shape
+        /// </summary>
+        /// <param name="panel">panel hosting the scene</param>
+        /// <param name="numVertices">number of vertices, this bordered shape will be made out of</param>
+        public ILBorderedShape (ILPanel panel, int numVertices) 
+            : base(panel,numVertices,numVertices) {
+            m_border = new ILLineProperties();
+            m_border.Changed += new EventHandler(m_border_Changed);
+            m_fillColor = Color.Yellow;
+            m_border.Width = 1; 
+            m_border.Antialiasing = false; 
+            m_border.Color = Color.Bisque; 
+            m_shading = ShadingStyles.Flat; 
+            m_vertexStoresColor = false; 
+        }
+
+        /// <summary>
+        /// update vertices of the shape
+        /// </summary>
+        /// <param name="X">X positions vector</param>
+        /// <param name="Y">Y positions vector</param>
+        /// <param name="Z">Z positions vector</param>
+        /// <remarks><para> The positions of the vertices are altered only. Other attributes are not altered. X, Y and Z must be 
+        /// vectors, scalars or <c>null</c>.</para>
+        /// <para>If any of <paramref name="X"/>,<paramref name="Y"/> or <paramref name="Z"/> is a vector, its elements are transfered to the corresponding position part (X,Y or Z) 
+        /// of the corresponding vertices. If any vector is longer than the current <see cref="VertexCount"/>, the number of vertices currently managed by this shape is expanded. If any of 
+        /// the vectors is smaller than <see cref="VertexCount"/>, trailing vertices are not touched.</para>
+        /// <para>If any of <paramref name="X"/>,<paramref name="Y"/> or <paramref name="Z"/> is a scalar, its value is applied to <b>all</b> corresponding positioning parts of all vertices.</para>
+        /// <para>If any of <paramref name="X"/>,<paramref name="Y"/> or <paramref name="Z"/> is <c>null</c>, the corresponding part of the vertices are not altered.</para></remarks>
+        public virtual void Update(ILInArray<float> X = null, ILInArray<float> Y = null, ILInArray<float> Z = null) {
+            using (ILScope.Enter(X,Y,Z)) {
+                int minLen = 0; 
+                ILArray<float> x = ILMath.check(X, (a) => { if (a.IsVector) { minLen = a.Length; return a; } else { return null; } }, true, "X must be vector, scalar or null");
+                ILArray<float> y = ILMath.check(Y, (a) => { if (a.IsVector) { minLen = Math.Max(minLen, a.Length); return a; } else { return null; } }, true, "Y must be vector, scalar or null");
+                ILArray<float> z = ILMath.check(Z, (a) => { if (a.IsVector) { minLen = Math.Max(minLen, a.Length); return a; } else { return null; } }, true, "Z must be vector, scalar or null"); 
+                
+                if (VertexCount < minLen) {
+                    m_numVerticesPerShape = minLen;
+                    Resize(minLen);
+                }
+                if (!ILMath.isnull(x)) {
+                    if (x.IsScalar) {
+                        float scalar = x.GetValue(0);
+                        for (int i = 0; i < VertexCount; i++) {
+                            Vertices[i].XPosition = scalar;
+                        }
+                    } else {
+                        for (int i = 0; i < x.Length; i++) {
+                            Vertices[i].XPosition = x.GetValue(i);
+                        }
+                    }
+                }
+                if (!ILMath.isnull(y)) {
+                    if (y.IsScalar) {
+                        float scalar = y.GetValue(0);
+                        for (int i = 0; i < VertexCount; i++) {
+                            Vertices[i].YPosition = scalar;
+                        }
+                    } else {
+                        for (int i = 0; i < y.Length; i++) {
+                            Vertices[i].YPosition = y.GetValue(i);
+                        }
+                    }
+                }
+                if (!ILMath.isnull(z)) {
+                    if (z.IsScalar) {
+                        float scalar = z.GetValue(0);
+                        for (int i = 0; i < VertexCount; i++) {
+                            Vertices[i].ZPosition = scalar;
+                        }
+                    } else {
+                        for (int i = 0; i < z.Length; i++) {
+                            Vertices[i].ZPosition = z.GetValue(i);
+                        }
+                    }
+                }
+                Invalidate();
+            }
+        }
+
+
+        void m_border_Changed(object sender, EventArgs e) {
+            OnChanged(); 
+        }
+        protected override void IntDrawShape(ILRenderProperties props) {
+            if (m_vertCount == 0 || m_vertCount >= VerticesPerShape) {
+                m_renderer.Draw(props,this);   
+            }
+        }
+        protected override void IntDrawLabel(ILRenderProperties props) {
+            if (m_vertCount == 0 || m_vertCount >= VerticesPerShape) {
+                if (!String.IsNullOrEmpty(m_label.Text) && m_vertCount > 1) {
+                    ILPoint3Df cent = m_vertices[0].Position + m_vertices[1].Position;
+                    m_label.Draw(props, cent / 2); 
+                }
+            }
+        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILCompositeShape.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILCompositeShape.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILCompositeShape.cs	(revision 9102)
@@ -0,0 +1,397 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+
+
+using System;
+using System.Drawing; 
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Drawing.Graphs; 
+using ILNumerics; 
+using ILNumerics.Exceptions; 
+using ILNumerics.Drawing.Interfaces; 
+using ILNumerics.Drawing; 
+using ILNumerics.Misc; 
+
+namespace ILNumerics.Drawing.Shapes {
+    public abstract class ILCompositeShape<VertexType> : ILShape<VertexType> 
+        where VertexType : struct, IILVertexDefinition {
+
+        #region eventing 
+        #endregion
+
+        #region attributes
+        /// <summary>
+        /// actual indices used for rendering (sorted for translucent shapes)
+        /// </summary>
+        protected int[] m_renderIndices;
+        /// <summary>
+        /// cache indices defining each shapes corners
+        /// </summary>
+        protected ILArray<int> m_shapeIndices = ILMath.returnType<int>(); 
+        /// <summary>
+        /// cache camera position of last sorting
+        /// </summary>
+        protected ILPoint3Df m_oldCameraPosition;
+
+        //private float[] m_vertexPositions; 
+        #endregion
+
+        #region properties
+        /// <summary>
+        /// Indices used to render primitives from vertices 
+        /// </summary>
+        public ILRetArray<int> Indices {
+            get {
+                return m_shapeIndices.C; 
+            }
+            set {
+                m_shapeIndices.a = value; 
+            }
+        }
+        #endregion
+
+        #region constructors
+        /// <summary>
+        /// create composite shape
+        /// </summary>
+        /// <param name="panel">scene hosting the scene</param>
+        /// <param name="numVertices">number of overall vertices for the shape</param>
+        /// <param name="verticesPerShape">Number of vertices per shape</param>
+        public ILCompositeShape (ILPanel panel, int numVertices, int verticesPerShape) 
+            : base(panel,numVertices,verticesPerShape) {
+            Opacity = 255; 
+            m_shapeIndices.a = ILMath.toint32(
+                ILMath.counter(0.0,1.0,VerticesPerShape,numVertices / VerticesPerShape)); 
+        }
+
+        ///// <summary>
+        ///// create composite shape 
+        ///// </summary>
+        ///// <param name="panel">hosting panel</param>
+        ///// <param name="verticesPerShape">number of vertices per shape</param>
+        ///// <param name="X">x coordinates vector </param>
+        ///// <param name="Y">y coordinates vector </param>
+        ///// <param name="Z">z coordinates vector </param>
+        ///// <remarks>The constructor creates a new composite shape out of all vertices specified in X,Y and Z.
+        ///// Every vertex is only used once. Every shape uses 
+        ///// <see cref="ILNumerics.Drawing.Shapes.ILShape&lt;T>.VerticesPerShape"/> vertices one after another.</remarks>
+        //public ILCompositeShape(ILPanel panel, int verticesPerShape, ILBaseArray X, ILBaseArray Y, ILBaseArray Z)
+        //    : base(panel, X.Length, verticesPerShape) {
+        //    Update(X, Y, Z);
+        //    m_shapeIndices.a = ILMath.toint32(
+        //        ILMath.counter(0.0, 1.0, VerticesPerShape, m_vertCount / VerticesPerShape));
+        //    Opacity = 255;
+        //    m_shading = ShadingStyles.Flat;
+        //}
+
+        ///// <summary>
+        ///// create composite shape 
+        ///// </summary>
+        ///// <param name="panel">hosting panel</param>
+        ///// <param name="verticesPerShape">number of vertices per shape</param>
+        ///// <param name="X">x coordinates vector </param>
+        ///// <param name="Y">y coordinates vector </param>
+        ///// <param name="Z">z coordinates vector </param>
+        ///// <param name="mapping">Mapping of shapes, composes shapes out of vertices. Matrix having  
+        ///// <see cref="ILNumerics.Drawing.Shapes.ILShape&lt;T>.VerticesPerShape"/> rows.
+        ///// Every element in a column specifies the index of a vertex according to its position in X,Y,Z.
+        ///// The <see cref="ILNumerics.Drawing.Shapes.ILShape&lt;T>.VerticesPerShape"/> elements in a column therefore 
+        ///// compose a single shape. Vertices may get used arbitrary times (or not at all). All elements must be 
+        ///// positive integer values in range 0...[<see cref="ILNumerics.Drawing.Shapes.ILShape.VertexCount"/>-1].</param>
+        //public ILCompositeShape (ILPanel panel, int verticesPerShape, ILBaseArray X, ILBaseArray Y, ILBaseArray Z, ILBaseArray mapping) 
+        //    : base (panel,X.Length,verticesPerShape) {
+        //    Update(X, Y, Z, mapping);
+        //    Opacity = 255; 
+        //    m_shading = ShadingStyles.Interpolate; 
+        //}
+
+        ///// <summary>
+        ///// create composite shape 
+        ///// </summary>
+        ///// <param name="panel">hosting panel</param>
+        ///// <param name="verticesPerShape">number of vertices per shape</param>
+        ///// <param name="X">x coordinates vector </param>
+        ///// <param name="Y">y coordinates vector </param>
+        ///// <param name="Z">z coordinates vector </param>
+        ///// <param name="colors">matrix with <see cref="ILNumerics.Drawing.Shapes.ILShape.VertexCount"/> 
+        ///// rows, 3 columns for (R,G,B) or 4 columns for 
+        ///// (A,R,G,B) for every vertex specified by X,Y,Z. Elements must range from 0..255. If colors 
+        ///// has 3 columns only, alpha values of 255 are used as default.</param>
+        ///// <param name="mapping">Mapping of shapes, composes shapes out of vertices. Matrix having  
+        ///// <see cref="ILNumerics.Drawing.Shapes.ILShape&lt;T>.VerticesPerShape"/> rows.
+        ///// Every element in a column specifies the index of a vertex according to its position in X,Y,Z.
+        ///// The <see cref="ILNumerics.Drawing.Shapes.ILShape&lt;T>.VerticesPerShape"/> elements in a column therefore 
+        ///// compose a single shape. Vertices may get used arbitrary times (or not at all). All elements must be 
+        ///// positive integer values in range 0...[<see cref="ILNumerics.Drawing.Shapes.ILShape.VertexCount"/>-1].</param>
+        //public ILCompositeShape (ILPanel panel, int verticesPerShape, ILBaseArray X, ILBaseArray Y, ILBaseArray Z, ILBaseArray colors, ILBaseArray mapping) 
+        //    : base (panel,X.Length,verticesPerShape) {
+        //    Update(X, Y, Z, mapping, colors);
+        //    System.Diagnostics.Debug.Assert(ILMath.toint32(mapping).MaxValue < Vertices.Length); 
+        //    Opacity = 255;
+        //    m_shading = ShadingStyles.Interpolate; 
+        //}
+
+        #endregion
+
+        #region public interface 
+        /// <summary>
+        /// update vertices of this shape
+        /// </summary>
+        /// <param name="inX">x coordinates, vector of length <see cref="ILNumerics.Drawing.Shapes.ILShape.VertexCount"/></param>
+        /// <param name="inY">y coordinates, vector of length <see cref="ILNumerics.Drawing.Shapes.ILShape.VertexCount"/></param>
+        /// <param name="inZ">z coordinates, vector of length <see cref="ILNumerics.Drawing.Shapes.ILShape.VertexCount"/></param>
+        /// <param name="mapping">Mapping of shapes, composes shapes out of vertices. Matrix having
+        /// <see cref="ILNumerics.Drawing.Shapes.ILShape&lt;T>.VerticesPerShape"/> rows.
+        /// Every element in a column specifies the index of a vertex according to its position in X,Y,Z.
+        /// The <see cref="ILNumerics.Drawing.Shapes.ILShape&lt;T>.VerticesPerShape"/> elements in a column therefore
+        /// compose a single shape. Vertices may get used arbitrary times (or not at all). All elements must be
+        /// positive integer values in range 0...[<see cref="ILNumerics.Drawing.Shapes.ILShape.VertexCount"/>-1].</param>
+        /// <param name="colors">matrix with <see cref="ILNumerics.Drawing.Shapes.ILShape.VertexCount"/> 
+        /// rows, 3 columns for (R,G,B) or 4 columns for 
+        /// (A,R,G,B) for every vertex specified by X,Y,Z. Elements must range from 0..255. If colors 
+        /// has 3 columns only, alpha values of 255 are used as default.</param>
+        /// <remarks>All vertices of the shape are updated with the data specified in X,Y and Z. Neither the colors or any
+        /// other data of vertices are changed, if they are not provided. The shape is invalidated for reconfiguration at next redraw. </remarks>
+        public void Update(ILInArray<float> inX, ILInArray<float> inY, ILInArray<float> inZ, ILInArray<int> inMapping = null, ILInArray<int> inColors = null) {
+            using (ILScope.Enter(inX, inY, inZ, inMapping, inColors)) {
+                if (!VertexDefinition.StoresColor)
+                    throw new NotSupportedException("The underlying vertex type cannot store individual color values! Use another shape type, flat shading or ommit color values!");
+                ILArray<float> X = ILMath.check(inX, (a) => { return (a.IsVector) ? a : null; }, true, "numeric vectors of same length expected for: X, Y and Z");
+                ILArray<float> Y = ILMath.check(inY, (a) => { return (a.IsVector && a.Length == X.Length) ? a : null; }, true, "numeric vectors of same length expected for: X, Y and Z");
+                ILArray<float> Z = ILMath.check(inZ, (a) => { return (a.IsVector && a.Length == X.Length) ? a : null; }, true, "numeric vectors of same length expected for: X, Y and Z");
+                ILArray<int> mapping = ILMath.check(inMapping, (a) => { return (inMapping.IsMatrix && inMapping.S[0] == VerticesPerShape) ? a : null; }, true
+                                                    , "mapping must be a numeric matrix, " + VerticesPerShape.ToString() + " rows, each column specifies indices for the vertices of a single shape.");
+                ILArray<int> colors = ILMath.check(inColors, (a) => { return ((a.S[1] == 3 || a.S[1] == 4) && a.S[0] == X.Length) ? a : null; }, true 
+                                                    , "invalid size of colors data! Colors must have 3 or 4 columns with color components (RGB) or alpha value + color components (ARGB) respectively. Number of rows must match number of vertices.");
+
+                if (!ILMath.isnull(mapping)) {
+                    int minInd, maxInd;
+                    if (mapping.GetLimits(out minInd, out maxInd) && (minInd < 0 || maxInd >= X.Length))
+                        throw new ILArgumentException("invalid mapping: indices out of range of vertices");
+                    m_shapeIndices.a = mapping.C; 
+                }
+                if (ILMath.isnull(colors)) {
+                    for (int i = 0; i < m_vertices.Length && i < X.Length && i < Y.Length && i < Z.Length; i++) {
+                        m_vertices[i].XPosition = X.GetValue(i);
+                        m_vertices[i].YPosition = Y.GetValue(i);
+                        m_vertices[i].ZPosition = Z.GetValue(i);
+                    }
+                } else if (colors.Size[1] == 3) {
+                    for (int i = 0; i < m_vertices.Length; i++) {
+                        m_vertices[i].XPosition = X.GetValue(i);
+                        m_vertices[i].YPosition = Y.GetValue(i);
+                        m_vertices[i].ZPosition = Z.GetValue(i);
+                        m_vertices[i].Color = Color.FromArgb(
+                                colors.GetValue(i, 0),
+                                colors.GetValue(i, 1),
+                                colors.GetValue(i, 2));
+                    }
+                } else if (colors.Size[1] == 4) {
+                    for (int i = 0; i < m_vertices.Length; i++) {
+                        m_vertices[i].XPosition = X.GetValue(i);
+                        m_vertices[i].YPosition = Y.GetValue(i);
+                        m_vertices[i].ZPosition = Z.GetValue(i);
+                        m_vertices[i].Color = Color.FromArgb(
+                                colors.GetValue(i, 1),
+                                colors.GetValue(i, 2),
+                                colors.GetValue(i, 3));
+                        m_vertices[i].Alpha = (byte)colors.GetValue(i);
+                    }
+                }
+                Invalidate();
+            }
+        }
+        protected override void IntDrawShape(ILRenderProperties props) {
+            if (m_vertCount >= VerticesPerShape) {
+                // draw from back to front
+                if (m_oldCameraPosition != m_panel.Camera.Position
+                    || m_renderIndices == null) {
+                    if (m_shading == ShadingStyles.Flat && m_fillColor.A == byte.MaxValue) {
+                        m_shapeIndices.ExportValues(ref m_renderIndices); 
+                    } else {
+                        sortPrimitives();
+                    }
+                }
+                m_renderer.Draw(props,this,m_renderIndices);
+            }
+        }
+        protected override void IntDrawLabel(ILRenderProperties props) {
+            if (m_vertCount >= VerticesPerShape) {
+                ILPoint3Df cent = m_vertices[m_shapeIndices.GetValue(0)].Position; 
+                // draw label at center of first shape
+                if (!String.IsNullOrEmpty(m_label.Text)) {
+                    for (int i = 1; i < VerticesPerShape; i++) {
+                        cent += m_vertices[m_shapeIndices.GetValue(i)].Position;
+                    }
+                    m_label.Draw(props, cent / VerticesPerShape); 
+                }
+            }
+        }
+        protected override void  ComputeLimits() {
+            // only consider used(!) vertices (having indices in mapping)         
+ 	        ILPoint3Df cent = new ILPoint3Df();
+            if (m_shapeIndices.IsEmpty) {
+                // fast exit
+                m_positionCenter = cent;
+                m_positionMin = cent;
+                m_positionMax = cent;
+                return;
+            }
+            ILPoint3Df max = ILPoint3Df.MinValue, min = ILPoint3Df.MaxValue, cur;
+            foreach (int vertexID in m_shapeIndices) {
+                cur = m_vertices[vertexID].Position;
+                cent = cent + cur;
+                max = ILPoint3Df.Max(max, cur);
+                min = ILPoint3Df.Min(min, cur);
+            }
+            m_positionCenter = cent / m_vertices.Length;
+            m_positionMax = max;
+            m_positionMin = min;
+            //updateVertexPositions(Vertices, ref m_vertexPositions);
+        }
+        #endregion
+
+        #region private helper
+
+        //protected void sortPrimitives() {
+        //    m_oldCameraPosition = m_panel.Camera.Position;
+        //    Computation.SortIndices(
+        //                m_vertices, m_shapeIndices, m_vertCount, m_panel.Camera.Position,
+        //                VerticesPerShape).ExportValues(ref m_renderIndices);
+        //}
+
+        private void sortPrimitives() {
+            m_oldCameraPosition = m_panel.Camera.Position;
+            if (m_renderIndices == null || m_renderIndices.Length < m_shapeIndices.Size.NumberOfElements)
+                m_renderIndices = new int[m_shapeIndices.Size.NumberOfElements];
+            float camScale = (ILPoint3Df.Max(m_positionMax, m_positionMin) - m_positionCenter).GetLength(); 
+            Computation.SortIndices(
+                        Vertices
+                        , m_shapeIndices
+                        , m_vertCount
+                        , m_panel.Camera.LookAt + ((m_panel.Camera.LookAt - m_panel.Camera.Position) * camScale)
+                        , VerticesPerShape
+                        , m_renderIndices);
+        }
+        
+        private void updateVertexPositions(VertexType[] vertices, ref float[] vertexPositions) {
+            if (vertexPositions == null || vertexPositions.Length < 3 * vertices.Length) {
+                vertexPositions = new float[3 * vertices.Length];
+            }
+            int p = 0;
+            if (vertices is C4bV3f[]) {
+                C4bV3f[] verticesC4bV3f = (C4bV3f[])(object)vertices; 
+                foreach (C4bV3f vertex in verticesC4bV3f) {
+                    vertexPositions[p++] = vertex.XPosition;
+                    vertexPositions[p++] = vertex.YPosition;
+                    vertexPositions[p++] = vertex.ZPosition;
+                }
+            } else if (vertices is C4fN3fV3f[]) {
+                C4fN3fV3f[] verticesC4fN3fV3f = (C4fN3fV3f[])(object)vertices; 
+                foreach (C4fN3fV3f vertex in verticesC4fN3fV3f) {
+                    vertexPositions[p++] = vertex.XPosition;
+                    vertexPositions[p++] = vertex.YPosition;
+                    vertexPositions[p++] = vertex.ZPosition;
+                }
+            } 
+            // ... more vertex types here? 
+        }
+
+        private class Computation : ILMath {
+            
+            public static void SortIndices(VertexType[] vertices,
+                                            ILInArray<int> shapeIndices, int vertCount,
+                                            ILPoint3Df camera, int vertPerPrimitive, int[] renderIndices) {
+                using (ILScope.Enter(shapeIndices)) {
+                    bool dummy; 
+                    ILArray<float> dist = array<float>(ILMemoryPool.Pool.New<float>(vertCount, false, out dummy) ,1,vertCount); 
+                    float[] distArr = dist.GetArrayForWrite(); 
+                    for (int vPos = 0; vPos < vertCount; ) {
+                        distArr[vPos] = (vertices[vPos++].Position - camera).GetLength(); 
+                    }
+#if DEBUG
+                    //ILArray<double> indDeb; 
+                    //ILArray<float> minID = sort(new ILArray<float>(dist, 1, dist.Length), out indDeb,1,false);
+                    //System.Diagnostics.Debug.Write("ind: " + shapeIndices.ValuesToString(0));
+                    //System.Diagnostics.Debug.Write("dist: " + new ILArray<float>(dist, 1, dist.Length).ValuesToString(0));
+                    //System.Diagnostics.Debug.Write("dist[ind]: " + (new ILArray<float>(dist, 1, dist.Length)[shapeIndices]).ValuesToString(0));
+                    //System.Diagnostics.Debug.Write("sum(dist[ind]): " + sum(new ILArray<float>(dist, 1, dist.Length)[shapeIndices]).ValuesToString(0));
+#endif
+                    ILArray<double> idx = empty(); 
+                    sort(sum(dist[shapeIndices], 0), idx, 1, false).Dispose(); 
+                    // ind: indices into shapeIndices' columns 
+                    shapeIndices[full, idx].ExportValues(ref renderIndices);
+                }
+            }
+
+            //public static ILArray<int> SortIndices(VertexType[] vertices,
+            //                                ILArray<int> shapeIndices, int vertCount,
+            //                                ILPoint3Df camera, int vertPerPrimitive) {
+            //    //System.Diagnostics.Debug.Assert(Math.IEEERemainder(vertCount,vertPerPrimitive) == 0); 
+            //    float[] posArr = new float[3 * vertCount];
+            //    int p = 0;
+            //    foreach (VertexType vertex in vertices) {
+            //        posArr[p++] = vertex.XPosition;
+            //        posArr[p++] = vertex.YPosition;
+            //        posArr[p++] = vertex.ZPosition;
+            //    }
+            //    ILArray<float> pos = new ILArray<float>(posArr, 3, vertCount);
+            //    ILArray<float> cam = new ILArray<float>(
+            //                         new float[] { camera.X, camera.Y, camera.Z }, 3, 1);
+            //    // flip the camera around and move it outside the scene 
+            //    ILArray<double> ind = null;
+            //    cam = -cam * maxall(pos);
+            //    cam = repmat(cam, 1, vertCount);
+            //    pos = pos - cam;
+            //    pos = sum(pos * pos, 0);   // pos holds distances for eaech vertex now
+            //    // sort per primitive
+            //    pos = sum(reshape(pos[shapeIndices[":"]], vertPerPrimitive, shapeIndices.Dimensions[1]), 0);
+            //    ind = ILArray<double>.empty();
+            //    sort(pos, out ind, 1, false);
+            //    // ind: indices into shapeIndices' columns 
+            //    return shapeIndices[null, ind][":"];
+            //}
+
+        }
+
+        #endregion
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILLine.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILLine.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILLine.cs	(revision 9102)
@@ -0,0 +1,220 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Drawing;
+using ILNumerics.Drawing.Interfaces;
+using ILNumerics.Exceptions;
+
+namespace ILNumerics.Drawing.Shapes {
+    /// <summary>
+    /// A simple single line
+    /// </summary>
+    public class ILLine : ILBorderedShape<C4bV3f> {
+
+        #region attributes 
+        ILLineProperties m_properties;
+        int m_autoLimitsUpdateCount = 0;
+        int m_updateCount = 0; 
+
+        public int AutoLimitsUpdateCount {
+            get { return m_autoLimitsUpdateCount; }
+            set { m_autoLimitsUpdateCount = value; }
+        }
+        int m_oldestVertexID; 
+        #endregion
+
+        #region properties
+        /// <summary>
+        /// [deprecated] line properties, use individual properties of ILLine instead
+        /// </summary>
+        public ILLineProperties Properties {
+            get { return m_properties; }
+            private set { m_properties = value; }
+        } 
+        /// <summary>
+        /// the oldest vertex to be removed on the next Queue() call
+        /// </summary>
+        internal int OldestVertexID {
+            get { return m_oldestVertexID; }
+        }
+        /// <summary>
+        /// determines, if the line is to be drawn antialiased (on width > 1 only)
+        /// </summary>
+        public bool Antialiasing {
+            get { return m_properties.Antialiasing; }
+            set { m_properties.Antialiasing = value; }
+        }
+        /// <summary>
+        /// stipple pattern for the line, if Style is set to custom pattern
+        /// </summary>
+        public short Pattern {
+            get { return m_properties.Pattern; }
+            set { m_properties.Pattern = value; }
+        }
+        /// <summary>
+        /// scaling for the stipple pattern
+        /// </summary>
+        public float PatternScale {
+            get { return m_properties.PatternScale; }
+            set { m_properties.PatternScale = value; }
+        }
+        /// <summary>
+        /// line style, default: solid
+        /// </summary>
+        public LineStyle Style {
+            get { return m_properties.Style; }
+            set { m_properties.Style = value; }
+        }
+        /// <summary>
+        /// line width (pixels)
+        /// </summary>
+        public int Width {
+            get { return m_properties.Width; }
+            set { m_properties.Width = value; }
+        }
+        /// <summary>
+        /// inner color of the line
+        /// </summary>
+        public override Color FillColor {
+            get {
+                return m_properties.Color;
+            }
+            set {
+                m_properties.Color = value;
+            }
+        }
+        #endregion
+
+        #region constructors
+        /// <summary>
+        /// create new simple line with 2 ends
+        /// </summary>
+        /// <param name="panel"></param>
+        public ILLine (ILPanel panel) 
+            : this (panel,2) { }
+        /// <summary>
+        /// create new line, determine number of vertices
+        /// </summary>
+        /// <param name="panel">panel hosting the scene</param>
+        /// <param name="numVertices">number of vertices for the line</param>
+        public ILLine (ILPanel panel, int numVertices) 
+            : base (panel,numVertices) {
+            if (numVertices < 2) 
+                throw new ILArgumentException("line must have at least 2 points!"); 
+            m_fillColor = Color.Black; 
+            m_border.Visible = false;
+            m_oldestVertexID = 0;  
+            m_properties = new ILLineProperties(); 
+            m_properties.Changed += new EventHandler(m_properties_Changed);
+            m_properties.Color = Color.Blue;
+            m_properties.Width = 2; 
+            m_properties.Antialiasing = true; 
+
+            // default for border
+            m_border.Width = 5; 
+            m_border.Antialiasing = true; 
+            m_border.Color = Color.LightGray; 
+
+            m_autoLimitsUpdateCount = numVertices;
+            m_shading = ShadingStyles.Flat; 
+        }
+        ///// <summary>
+        ///// create new line, give vertices positions also
+        ///// </summary>
+        ///// <param name="panel">panel hosting the scene</param>
+        ///// <param name="X">X coordinates</param>
+        ///// <param name="Y">Y coordinates</param>
+        ///// <param name="Z">Z coordinates</param>
+        //public ILLine(ILPanel panel, ILBaseArray X, ILBaseArray Y, ILBaseArray Z) 
+        //    : base (panel, X,Y,Z) {
+        //    m_fillColor = Color.Black;
+        //    m_border.Visible = false;
+        //    m_oldestVertexID = 0;
+        //    m_properties = new ILLineProperties();
+        //    m_properties.Changed += new EventHandler(m_properties_Changed);
+        //    m_properties.Color = Color.Blue;
+        //    m_shading = ShadingStyles.Flat; 
+        //    m_autoLimitsUpdateCount = Vertices.Length; 
+        //}
+        #endregion
+
+        #region private helpers 
+        void m_properties_Changed(object sender, EventArgs e) {
+            m_fillColor = m_properties.Color;
+            OnChanged();
+        }
+        protected override void IntDrawShape(ILRenderProperties props) {
+            if (m_vertCount == 0 || m_vertCount >= VerticesPerShape) {
+                m_renderer.Draw(props, this);
+            }
+        }
+        protected override void IntDrawLabel(ILRenderProperties props) {
+            if (m_vertCount == 0 || m_vertCount >= VerticesPerShape) {
+                if (!String.IsNullOrEmpty(m_label.Text) && m_vertCount > 1) {
+                    ILPoint3Df cent = m_vertices[0].Position + m_vertices[1].Position;
+                    m_label.Draw(props, cent / 2);
+                }
+            }
+        }
+        #endregion
+
+        #region public interface
+        public void Queue(IILVertexDefinition vertex) {
+            SetVertex(m_oldestVertexID++, vertex);
+            if (m_oldestVertexID >= m_vertCount) {
+                m_oldestVertexID = 0; 
+            }
+            if (m_updateCount++ < m_autoLimitsUpdateCount) {
+                bool signal = false;
+                m_positionMax = ILPoint3Df.Max(m_positionMax, vertex.Position, ref signal);
+                m_positionMin = ILPoint3Df.Min(m_positionMin, vertex.Position, ref signal); 
+                if (signal) {
+                    OnSizeChanged(); 
+                }
+            } else {
+                m_updateCount = 0; 
+                Invalidate();
+            }
+        }
+        #endregion
+
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILLines.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILLines.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILLines.cs	(revision 9102)
@@ -0,0 +1,189 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Drawing;
+
+
+namespace ILNumerics.Drawing.Shapes {
+    
+    public class ILLines 
+        : ILCompositeShape<C4bV3f> {
+
+        #region attributes 
+        ILLineProperties m_properties;
+        void m_properties_Changed(object sender, EventArgs e) {
+            m_fillColor = m_properties.Color;
+            OnChanged();
+        }
+        #endregion
+
+        #region properties
+        /// <summary>
+        /// all properties for the lines (in shading mode 'flat')
+        /// </summary>
+        public ILLineProperties Properties {
+            get { return m_properties; }
+        }
+        /// <summary>
+        /// determines, if the line is to be drawn antialiased (on width > 1 only)
+        /// </summary>
+        public bool Antialiasing {
+            get { return m_properties.Antialiasing; }
+            set { m_properties.Antialiasing = value; }
+        }
+        /// <summary>
+        /// stipple pattern for the line, if Style is set to custom pattern
+        /// </summary>
+        public short Pattern {
+            get { return m_properties.Pattern; }
+            set { m_properties.Pattern = value; }
+        }
+        /// <summary>
+        /// scaling for the stipple pattern
+        /// </summary>
+        public float PatternScale {
+            get { return m_properties.PatternScale; }
+            set { m_properties.PatternScale = value; }
+        }
+        /// <summary>
+        /// line style, default: solid
+        /// </summary>
+        public LineStyle Style {
+            get { return m_properties.Style; }
+            set { m_properties.Style = value; }
+        }
+        /// <summary>
+        /// line width (pixels)
+        /// </summary>
+        public int Width {
+            get { return m_properties.Width; }
+            set { m_properties.Width = value; }
+        }
+        /// <summary>
+        /// color for the lines (in shading mode 'flat')
+        /// </summary>
+        public override Color FillColor {
+            get {
+                return m_properties.Color;
+            }
+            set {
+                m_properties.Color = value;
+            }
+        }
+
+        #endregion
+
+        #region constructors
+        /// <summary>
+        /// Create new lines composite shapes, prepare memory for vertices only
+        /// </summary>
+        /// <param name="panel">panel hosting the scene</param>
+        /// <param name="numVertices">number of overall vertices in the shape</param>
+        public ILLines (ILPanel panel, int numVertices)
+            : base(panel, numVertices, 2) {
+            m_fillColor = Color.Blue;   
+            m_properties = new ILLineProperties();
+            m_properties.Color = Color.Blue;
+            m_properties.Changed += new EventHandler(m_properties_Changed);
+        }
+        ///// <summary>
+        ///// create new lines composite shape
+        ///// </summary>
+        ///// <param name="panel">panel hosting the scene</param>
+        ///// <param name="X">x coordinates vector </param>
+        ///// <param name="Y">y coordinates vector </param>
+        ///// <param name="Z">z coordinates vector </param>
+        //public ILLines(ILPanel panel, ILBaseArray X, ILBaseArray Y, ILBaseArray Z) 
+        //    : base (panel,2,X,Y,Z) { 
+        //    m_fillColor = Color.Blue;    
+        //    m_properties = new ILLineProperties();
+        //    m_properties.Color = Color.Blue; 
+        //    m_properties.Changed += new EventHandler(m_properties_Changed);
+        //}
+        ///// <summary>
+        ///// create new lines composite shape
+        ///// </summary>
+        ///// <param name="panel">panel hosting the scene</param>
+        ///// <param name="X">X coords vector</param>
+        ///// <param name="Y">Y coords vector</param>
+        ///// <param name="Z">Z coords vector</param>
+        ///// <param name="mapping">Mapping of shapes, composes shapes out of vertices. Matrix having  
+        ///// 2 rows. Every element in a column specifies the index of a vertex according to its position in X,Y,Z.
+        ///// The 2 elements in a column therefore compose a single line. Vertices may get used arbitrary times 
+        ///// (or not at all). All elements must be positive integer values in range 
+        ///// 0...[<see cref="ILNumerics.Drawing.Shapes.ILShape.VertexCount"/>-1].</param>
+        //public ILLines(ILPanel panel, ILBaseArray X, ILBaseArray Y, ILBaseArray Z, ILBaseArray mapping)
+        //    : base(panel, 2, X, Y, Z, mapping) {
+        //    m_fillColor = Color.Blue;
+        //    m_properties = new ILLineProperties();
+        //    m_properties.Color = Color.Blue;
+        //    m_properties.Changed += new EventHandler(m_properties_Changed);
+        //    ILColorEnumerator colors = new ILColorEnumerator();
+        //    for (int i = 0; i < m_vertCount; i++) {
+        //        m_vertices[i].Color = colors.NextColor();
+        //    }
+        //}
+        ///// <summary>
+        ///// create lines composite shape 
+        ///// </summary>
+        ///// <param name="panel">hosting panel</param>
+        ///// <param name="X">x coordinates vector </param>
+        ///// <param name="Y">y coordinates vector </param>
+        ///// <param name="Z">z coordinates vector </param>
+        ///// <param name="colors">matrix with <see cref="ILNumerics.Drawing.Shapes.ILShape.VertexCount"/> 
+        ///// rows, 3 columns for (R,G,B) or 4 columns for 
+        ///// (A,R,G,B) for every vertex specified by X,Y,Z. Elements must range from 0..255. If colors 
+        ///// has 3 columns only, alpha values of 255 are used as default.</param>
+        ///// <param name="mapping">Mapping of shapes, composes shapes out of vertices. Matrix having  
+        ///// 2 rows. Every element in a column specifies the index of a vertex according to its position in X,Y,Z.
+        ///// The 2 elements in a column therefore compose a single line. Vertices may get used arbitrary times 
+        ///// (or not at all). All elements must be positive integer values in range 
+        ///// 0...[<see cref="ILNumerics.Drawing.Shapes.ILShape.VertexCount"/>-1].</param>
+        //public ILLines(ILPanel panel, ILInArray<float> X, ILInArray<float> Y, ILInArray<float> Z, ILInArray<int> mapping, ILInArray<float> colors)
+        //    : base(panel, 2, X, Y, Z,colors, mapping) {
+        //    m_fillColor = Color.Blue;
+        //    m_properties = new ILLineProperties();
+        //    m_properties.Color = Color.Blue;
+        //    m_properties.Changed += new EventHandler(m_properties_Changed);
+        //}
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILLitBorderedShape.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILLitBorderedShape.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILLitBorderedShape.cs	(revision 9102)
@@ -0,0 +1,120 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Drawing.Interfaces; 
+using ILNumerics.Drawing.Lighting;
+using ILNumerics.Drawing; 
+using ILNumerics.Exceptions; 
+
+namespace ILNumerics.Drawing.Shapes {
+    /// <summary>
+    /// Base class for all simple, bordered shapes to be used within ILNumerics.Drawing scene graphs
+    /// </summary>
+    /// <typeparam name="VertexType"></typeparam>
+    public abstract class ILLitBorderedShape<VertexType>
+        : ILBorderedShape<VertexType>, IILSupportsLight
+        where VertexType : struct, IILVertexDefinition {
+
+        #region attributes
+        ILMaterial m_material;
+        bool m_autoNormals;
+        bool m_mustCalcNormals; 
+        #endregion
+
+        #region properties
+        public ILMaterial Material {
+            get {
+                return m_material; 
+            }
+        }
+        public bool AutoNormals {
+            get { return m_autoNormals; }
+            set {
+                if (VerticesPerShape < 3 && value)
+                    throw new InvalidOperationException(
+                            "'auto normals' needs at least 3 vertices per primitive!");
+                m_autoNormals = value;
+                if (value) Configure();
+            }
+        }
+        #endregion
+
+        public ILLitBorderedShape(ILPanel panel, int numVertices)
+        : base(panel, numVertices) {
+            if (!VertexDefinition.StoresNormals)
+                throw new ILInvalidOperationException("The generic vertex type does not support ligthing operations. Choose a vertext type which is able to store individual normal vectors!"); 
+            m_autoNormals = true;
+            m_material = new ILMaterial();
+            m_mustCalcNormals = true; 
+        }
+
+        #region public
+        public override void Configure() {
+            if (m_visible) {
+                if (m_mustCalcNormals && m_autoNormals) {
+                    Computation.CalculateNormals(m_vertices);
+                }
+            }
+            base.Configure();
+        }
+        public override void Invalidate() {
+            base.Invalidate();
+            m_mustCalcNormals = true; 
+        }
+        #endregion
+
+        private class Computation : ILNumerics.ILMath {
+            public static void CalculateNormals (VertexType[] vertices) {
+                if (vertices.Length < 3) return;
+                // crossproduct of vertex: (#1 - #0) x (#2 - #0)
+                ILPoint3Df cross = ILPoint3Df.crossN(
+                    vertices[1].Position - vertices[0].Position,
+                    vertices[1].Position - vertices[2].Position);
+                for (int i = 0; i < vertices.Length; i++) {
+                    vertices[i].Normal = cross;  
+                }
+
+            }
+        }
+    }
+
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILLitCompositeShape.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILLitCompositeShape.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILLitCompositeShape.cs	(revision 9102)
@@ -0,0 +1,219 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Drawing.Interfaces; 
+using ILNumerics.Drawing; 
+using ILNumerics.Drawing.Lighting; 
+using ILNumerics.Exceptions; 
+
+namespace ILNumerics.Drawing.Shapes {
+    public abstract class ILLitCompositeShape<VertexType> 
+        : ILCompositeShape<VertexType>, IILSupportsLight
+        where VertexType : struct, IILVertexDefinition {
+
+        #region attributes
+        bool m_autoNormals;
+        Dictionary<int, List<int>> m_shapeIndicesIndex; // used for speedy normal calculation
+        ILMaterial m_material; 
+        #endregion
+
+        #region properties
+        public ILMaterial Material {
+            get { return m_material; }
+            set { m_material = value; }
+        }
+        public bool AutoNormals {
+            get { return m_autoNormals; }
+            set { 
+                if (VerticesPerShape < 3 && value) 
+                    throw new InvalidOperationException(
+                            "'auto normals' needs at least 3 vertices per primitive!"); 
+                m_autoNormals = value;
+                if (value) Invalidate(); 
+            }
+        }
+        #endregion
+
+        #region constructors
+        /// <summary>
+        /// create light composite shape
+        /// </summary>
+        /// <param name="panel">scene hosting the scene</param>
+        /// <param name="numVertices">number of overall vertices for the shape</param>
+        /// <param name="verticesPerShape">Number of vertices per shape</param>
+        public ILLitCompositeShape (ILPanel panel, int numVertices, int verticesPerShape) 
+            : base(panel,numVertices, verticesPerShape) { 
+            create(); 
+        }
+
+        private void create() {
+            if (VerticesPerShape > 2)             
+                m_autoNormals = true;  
+            else 
+                m_autoNormals = false; 
+            m_oldCameraPosition = ILPoint3Df.Empty;
+            m_material = new ILMaterial(); 
+        }
+        //public ILLitCompositeShape (ILPanel panel, int verticesPerShape, ILBaseArray X, ILBaseArray Y, ILBaseArray Z, ILBaseArray mapping) 
+        //    : base (panel, verticesPerShape, X, Y, Z, mapping) { 
+        //    create(); 
+        //}
+        //public ILLitCompositeShape (ILPanel panel, int verticesPerShape, ILBaseArray X, ILBaseArray Y, ILBaseArray Z) 
+        //    : base (panel, verticesPerShape, X, Y, Z) {
+        //    create(); 
+        //}
+        //public ILLitCompositeShape (ILPanel panel, int verticesPerShape, ILBaseArray X, ILBaseArray Y, ILBaseArray Z, ILBaseArray colors, ILBaseArray mapping) 
+        //    : base (panel, verticesPerShape, X, Y, Z, colors, mapping) {
+        //    create(); 
+        //}
+        #endregion
+
+        #region public interface
+        public override void Configure() {
+            if (m_shapeIndicesIndex == null) { // shape was invalidated
+                m_shapeIndicesIndex = Computation.CreateShapeIndicesIndex(m_shapeIndices);
+                if (m_autoNormals) {
+                    Computation.CalculateNormals(m_vertices, m_shapeIndices, m_shapeIndicesIndex);
+                }
+            }
+            base.Configure();
+        }
+        public override void Invalidate() {
+            base.Invalidate();
+            m_shapeIndicesIndex = null; 
+        }
+        #endregion
+
+        #region private helpers
+        #endregion
+
+        protected class Computation : ILMath {
+
+            /// <summary>
+            /// Creates the index of the shape indices.
+            /// </summary>
+            /// <param name="shapeIndices">The shape indices.</param>
+            /// <returns>index of shape indices</returns>
+            /// <remarks>The index of shape indices is used for fast facette lookup while (auto) creating
+            /// the normal vectors for the vertices. Therefore, the index of every vertex used in the shape
+            /// serves as index for a list of those facettes, where that vertex occures.
+            /// <para>TODO: may be replaced by a custom data structure in order to decrease memory requirements?</para></remarks>
+            public static Dictionary<int, List<int>> CreateShapeIndicesIndex(ILInArray<int> shapeIndices) {
+                using (ILScope.Enter(shapeIndices)) {
+                    Dictionary<int, List<int>> ret = new Dictionary<int, List<int>>();
+                    int shapeCount = shapeIndices.Size[1];
+                    int vertPerShape = shapeIndices.Size[0];
+                    int curShapeIdx = 0;
+                    int curRowIdx = 0;
+                    foreach (int i in shapeIndices) {
+                        if (!ret.ContainsKey(i))
+                            ret.Add(i, new List<int>());
+                        ret[i].Add(curShapeIdx);
+                        curRowIdx++;
+                        if (curRowIdx >= vertPerShape) {
+                            curRowIdx = 0;
+                            curShapeIdx++;
+                        }
+                    }
+                    return ret;
+                }
+            }
+
+            /// <summary>
+            /// Calculates the normals.
+            /// </summary>
+            /// <param name="vertices">vertex array of the shape</param>
+            /// <param name="shapeIndices">The shape mapping indices.</param>
+            /// <param name="shapeIndicesIndex">Index of the shape indices.</param>
+            public static void CalculateNormals(
+                        VertexType[] vertices
+                        , ILInArray<int> shapeIndices
+                        , Dictionary<int, List<int>> shapeIndicesIndex) {
+                using (ILScope.Enter(shapeIndices)) {
+#if MEASURE_NORMAL_CALCULATION
+                DateTime start = DateTime.Now; 
+#endif
+                    System.Diagnostics.Debug.Assert(vertices != null && vertices.Length > 0 && vertices[0].StoresNormals);
+                    // first calculate the normal for all vertices
+                    ILPoint3Df[] snormals = new ILPoint3Df[shapeIndices.Size[1]];
+                    for (int shapeCol = 0; shapeCol < snormals.Length; shapeCol++) {
+                        // crossproduct of vertex: (#1 - #0) x (#2 - #0)
+                        int vi0 = shapeIndices.GetValue(0, shapeCol);
+                        int vi1 = shapeIndices.GetValue(1, shapeCol);
+                        int vi2 = shapeIndices.GetValue(2, shapeCol);
+                        ILPoint3Df cross = ILPoint3Df.crossN(
+                            vertices[vi1].Position - vertices[vi0].Position,
+                            vertices[vi1].Position - vertices[vi2].Position);
+                        snormals[shapeCol] = cross;
+                    }
+#if MEASURE_NORMAL_CALCULATION
+                TimeSpan crossDone = DateTime.Now - start;
+                DateTime startSorting = DateTime.Now; 
+                System.Diagnostics.Debug.WriteLine("Normals Calculation: cross products in " + crossDone.TotalMilliseconds.ToString() + "ms"); 
+#endif
+                    // find all facettes using this vertex
+                    for (int i = 0; i < vertices.Length; i++) {
+                        if (!shapeIndicesIndex.ContainsKey(i)) continue;
+                        ILPoint3Df normal = new ILPoint3Df();
+                        foreach (int shapeIdx in shapeIndicesIndex[i]) {
+                            normal += snormals[shapeIdx];
+                        }
+                        // or should we let OpenGL normalize the normals...?
+                        vertices[i].Normal = ILPoint3Df.normalize(normal);
+
+                        //System.Diagnostics.Debug.Assert(
+                        //    Math.Abs(Math.Sqrt(
+                        //    vertices[0].Normal.X * vertices[0].Normal.X +
+                        //    vertices[0].Normal.Y * vertices[0].Normal.Y +
+                        //    vertices[0].Normal.Z * vertices[0].Normal.Z) - 1.0) < (double)MachineParameterFloat.eps); 
+                    }
+#if MEASURE_NORMAL_CALCULATION
+                TimeSpan sortDone = DateTime.Now - startSorting;
+                System.Diagnostics.Debug.WriteLine("Normals Calculation: sorting done in " + sortDone.TotalMilliseconds.ToString() + "ms");
+#endif
+
+                }
+            }
+        }
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILLitPolygon.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILLitPolygon.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILLitPolygon.cs	(revision 9102)
@@ -0,0 +1,69 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing; 
+using ILNumerics.Drawing; 
+using ILNumerics.Drawing.Misc;
+using ILNumerics.Drawing.Graphs;  
+using ILNumerics.Drawing.Interfaces; 
+using ILNumerics.Drawing.Shapes; 
+
+namespace ILNumerics.Drawing.Shapes {
+    /// <summary>
+    /// A simple lit polygon, rendering arbitrary number of corners, bordered, supports light
+    /// </summary>
+    public class ILLitPolygon : ILLitBorderedShape<C4fN3fV3f> {
+
+        #region constructors
+        /// <summary>
+        /// create a new polygon
+        /// </summary>
+        /// <param name="panel">panel to create the polygon for</param>
+        /// <param name="numVertices">number of vertices for the polygon</param>
+        public ILLitPolygon (ILPanel panel, int numVertices) 
+            : base (panel,numVertices) { 
+            
+        }
+        #endregion
+        
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILLitQuad.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILLitQuad.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILLitQuad.cs	(revision 9102)
@@ -0,0 +1,62 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing; 
+using ILNumerics.Drawing; 
+using ILNumerics.Drawing.Misc;
+using ILNumerics.Drawing.Graphs;  
+using ILNumerics.Drawing.Interfaces; 
+using ILNumerics.Drawing.Shapes; 
+
+namespace ILNumerics.Drawing.Shapes {
+    /// <summary>
+    /// A single simple bordered quad supporting light
+    /// </summary>
+    public class ILLitQuad : ILLitBorderedShape<C4fN3fV3f> {
+
+        #region constructors
+        public ILLitQuad (ILPanel panel) 
+            : base (panel,4) { } 
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILLitQuads.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILLitQuads.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILLitQuads.cs	(revision 9102)
@@ -0,0 +1,127 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System.Drawing;
+
+
+namespace ILNumerics.Drawing.Shapes {
+    /// <summary>
+    /// a litable shape, assembled out of an arbitrary number of quads
+    /// </summary>
+    public class ILLitQuads 
+        : ILLitCompositeShape<C4fN3fV3f> {
+
+        #region constructors
+        /// <summary>
+        /// create composite shape, consisting out of lit quads 
+        /// </summary>
+        /// <param name="panel">hosting panel</param>
+        /// <param name="numVertices">number of vertices needed for all lit quads</param>
+        public ILLitQuads (ILPanel panel, int numVertices)
+            : base(panel, numVertices, 4) {
+            m_fillColor = Color.Green; 
+        }
+        ///// <summary>
+        ///// create composite shape, consisting out of lit quads 
+        ///// </summary>
+        ///// <param name="panel">hosting panel</param>
+        ///// <param name="X">x coordinates vector</param>
+        ///// <param name="Y">y coordinates vector</param>
+        ///// <param name="Z">z coordinates vector</param>
+        //public ILLitQuads (ILPanel panel, ILBaseArray X, ILBaseArray Y, ILBaseArray Z) 
+        //    : base (panel,4,X,Y,Z) { 
+        //    m_fillColor = Color.Green;  
+        //}
+        ///// <summary>
+        ///// create composite shape, consisting out of lit quads 
+        ///// </summary>
+        ///// <param name="panel">hosting panel</param>
+        ///// <param name="X">x coordinates vector</param>
+        ///// <param name="Y">y coordinates vector</param>
+        ///// <param name="Z">z coordinates vector</param>
+        ///// <param name="mapping">Mapping of shapes, composes quads out of vertices. Matrix having 4 rows.
+        ///// Every element in a column specifies the index of a vertex according to its position in X,Y,Z.
+        ///// The 4 elements in a column therefore compose a single quad. Vertices may get used arbitrary 
+        ///// times (or not at all). All elements must be positive integer values in range 
+        ///// 0...[<see cref="ILNumerics.Drawing.Shapes.ILShape.VertexCount"/>-1].</param>
+        //public ILLitQuads (ILPanel panel, ILBaseArray X, ILBaseArray Y, ILBaseArray Z, ILBaseArray mapping) 
+        //    : base (panel,4,X,Y,Z,mapping) {
+        //    m_fillColor = Color.Green;
+        //}
+        ///// <summary>
+        ///// create lit quads, flat shading
+        ///// </summary>
+        ///// <param name="panel">hosting panel</param>
+        ///// <param name="X">x coordinates (true world coords), vector with [vertCount] values</param>
+        ///// <param name="Y">y coordinates (true world coords), vector with [vertCount] values</param>
+        ///// <param name="Z">z coordinates (true world coords), vector with [vertCount] values</param>
+        ///// <param name="color">Color to fill all quads with.</param>
+        ///// <param name="mapping">Mapping of shapes, composes quads out of vertices. Matrix having 4 rows.
+        ///// Every element in a column specifies the index of a vertex according to its position in X,Y,Z.
+        ///// The 4 elements in a column therefore compose a single quad. Vertices may get used arbitrary 
+        ///// times (or not at all). All elements must be positive integer values in range 
+        ///// 0...[<see cref="ILNumerics.Drawing.Shapes.ILShape.VertexCount"/>-1].</param>
+        //public ILLitQuads (ILPanel panel, ILBaseArray X, ILBaseArray Y, ILBaseArray Z, Color color, ILBaseArray mapping) 
+        //    : base (panel,4,X,Y,Z,mapping) {
+        //    m_fillColor = color;
+        //}
+        ///// <summary>
+        ///// create lit quads, interpolated shading
+        ///// </summary>
+        ///// <param name="panel">hosting panel</param>
+        ///// <param name="X">x coordinates (true world coords), vector with [vertCount] values</param>
+        ///// <param name="Y">y coordinates (true world coords), vector with [vertCount] values</param>
+        ///// <param name="Z">z coordinates (true world coords), vector with [vertCount] values</param>
+        ///// <param name="colors">matrix with <see cref="ILNumerics.Drawing.Shapes.ILShape.VertexCount"/> 
+        ///// rows, 3 columns for (R,G,B) or 4 columns for 
+        ///// (A,R,G,B) for every vertex specified by X,Y,Z. Elements must range from 0..255. If colors 
+        ///// has 3 columns only, alpha values of 255 are used as default.</param>
+        ///// <param name="mapping">Mapping of shapes, composes quads out of vertices. Matrix having 4 rows.
+        ///// Every element in a column specifies the index of a vertex according to its position in X,Y,Z.
+        ///// The 4 elements in a column therefore compose a single quad. Vertices may get used arbitrary 
+        ///// times (or not at all). All elements must be positive integer values in range 
+        ///// 0...[<see cref="ILNumerics.Drawing.Shapes.ILShape.VertexCount"/>-1].</param>
+        //public ILLitQuads (ILPanel panel, ILBaseArray X, ILBaseArray Y, ILBaseArray Z, ILBaseArray colors, ILBaseArray mapping) 
+        //    : base (panel,4,X,Y,Z,colors,mapping) {
+        //    m_fillColor = Color.Green;
+        //}
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILLitSphere.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILLitSphere.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILLitSphere.cs	(revision 9102)
@@ -0,0 +1,336 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Drawing; 
+using ILNumerics.Drawing; 
+using ILNumerics; 
+using ILNumerics.Drawing.Graphs; 
+using ILNumerics.Exceptions; 
+
+namespace ILNumerics.Drawing.Shapes {
+    
+    public class ILLitSphere 
+        : ILLitCompositeShape<C4fN3fV3f>
+    {
+
+        #region attributes
+        ILPoint3Df m_center; 
+        float m_radius; 
+        int m_detail = 1;
+        #endregion
+
+        #region properties 
+        #endregion 
+
+        #region constructors
+        /// <summary>
+        /// create new lit sphere, resolution of 3 
+        /// </summary>
+        /// <param name="panel">panel hosting the scene</param>
+        /// <param name="center">center position</param>
+        /// <param name="radius">radius of the sphere</param>
+        /// <param name="color">color of the sphere</param>
+        public ILLitSphere (ILPanel panel, ILPoint3Df center, float radius, Color color) 
+            : this (panel, center, radius, color, 3) {
+        }
+        /// <summary>
+        /// create new lit sphere for a scene graph
+        /// </summary>
+        /// <param name="panel">panel hosting the scene</param>
+        /// <param name="center">center position</param>
+        /// <param name="radius">radius of the sphere</param>
+        /// <param name="color">color of the sphere</param>
+        /// <param name="detail">number of triangularization iterations, typical: 0..4</param>
+        public ILLitSphere (ILPanel panel, ILPoint3Df center, float radius, Color color, int detail) 
+            : base (panel,3,3) {
+            m_fillColor = color;
+            m_center = center;
+            m_radius = radius;
+            m_detail = detail;
+            Material.Shininess = 60;
+            AutoNormals = true;
+            m_shading = ShadingStyles.Interpolate; 
+            createVertices(detail);
+        }
+        #endregion
+
+        #region public interface
+        #endregion
+        
+        private void createVertices(int detail) {
+            using (ILScope.Enter()) {
+                //ILArray<float> vertData = Computation.CreateVertices(
+                //            m_center,m_radius,horRes,vertRes, out m_shapeIndices); 
+                ILArray<float> vertData = Computation.CreateVerticesTri(
+                            detail, m_shapeIndices);
+                Resize(vertData.Size[1]);
+                vertData = vertData * m_radius;
+                for (int r = 0, pos = 0; r < VertexCount; r++) {
+                    m_vertices[pos].XPosition = vertData.GetValue(0, r) + m_center.X;
+                    m_vertices[pos].YPosition = vertData.GetValue(1, r) + m_center.Y;
+                    m_vertices[pos].ZPosition = vertData.GetValue(2, r) + m_center.Z;
+                    m_vertices[pos].Color = m_fillColor;
+                    m_vertices[pos++].Alpha = m_fillColor.A;
+                }
+            }
+        }
+
+        private new class Computation : ILMath {
+
+            private static Dictionary<int, ILCell> s_vertexCache = new Dictionary<int, ILCell>();
+            /// <summary>
+            /// increase the number of triangles by doubling existing triangles
+            /// </summary>
+            /// <param name="vertices">vertices</param>
+            /// <param name="triangles">triangle index definitions</param>
+            /// <param name="iterations">number of iterations. On each iteration, 4 triangles will replace every single triangle!</param>
+            /// <param name="outVertices">The out vertices.</param>
+            /// <param name="outTriangles">The out triangles.</param>
+            /// <remarks><para>Incoming triangles are expected not to be degenerated. This means:
+            /// Every edge is used only twice at most. No triangle shares more than 2
+            /// corners with some other triangle. </para>
+            /// </remarks>
+            public static void Triangularize(ILInArray<float> vertices, ILInArray<int> triangles,
+                                            int iterations,
+                                            ILOutArray<float> outVertices,
+                                            ILOutArray<int> outTriangles) {
+                using (ILScope.Enter(vertices, triangles)) {
+                    int numVertices = vertices.Size[1];
+                    int numTriangles = triangles.Size[1];
+                    outVertices.a = vertices.C;
+                    outTriangles.a = triangles.C;
+                    // beeing pessimistic: expect to create a larger number of vertices than probable
+                    outVertices[0, numVertices * 2] = 0;
+                    outTriangles[0, numTriangles * 2] = 0;
+
+                    int triIndLast = numTriangles - 1;
+                    int vertIndLast = numVertices - 1;
+                    for (int it = 0; it < iterations; it++) {
+                        int triIndItEnd = triIndLast;
+
+                        for (int triInd = 0; triInd <= triIndItEnd; triInd++) {
+                            int vertInd0 = outTriangles.GetValue(0, triInd);
+                            int vertInd1 = outTriangles.GetValue(1, triInd);
+                            int vertInd2 = outTriangles.GetValue(2, triInd);
+                            // create new vertices
+                            float v0x = (outVertices.GetValue(0, vertInd0) + outVertices.GetValue(0, vertInd1)) / 2f;
+                            float v0y = (outVertices.GetValue(1, vertInd0) + outVertices.GetValue(1, vertInd1)) / 2f;
+                            float v0z = (outVertices.GetValue(2, vertInd0) + outVertices.GetValue(2, vertInd1)) / 2f;
+                            float v1x = (outVertices.GetValue(0, vertInd1) + outVertices.GetValue(0, vertInd2)) / 2f;
+                            float v1y = (outVertices.GetValue(1, vertInd1) + outVertices.GetValue(1, vertInd2)) / 2f;
+                            float v1z = (outVertices.GetValue(2, vertInd1) + outVertices.GetValue(2, vertInd2)) / 2f;
+                            float v2x = (outVertices.GetValue(0, vertInd2) + outVertices.GetValue(0, vertInd0)) / 2f;
+                            float v2y = (outVertices.GetValue(1, vertInd2) + outVertices.GetValue(1, vertInd0)) / 2f;
+                            float v2z = (outVertices.GetValue(2, vertInd2) + outVertices.GetValue(2, vertInd0)) / 2f;
+                            #region new vertex exists already? TODO: This needs to be replaced (with a b-tree implementation?)!!
+                            int newVertID0 = -1;
+                            int newVertID1 = -1;
+                            int newVertID2 = -1;
+                            for (int vi = 0; vi <= vertIndLast; vi++) {
+                                float tmpX = outVertices.GetValue(0, vi);
+                                float tmpY = outVertices.GetValue(1, vi);
+                                float tmpZ = outVertices.GetValue(2, vi);
+                                if (tmpX == v0x && tmpY == v0y && tmpZ == v0z) {
+                                    newVertID0 = vi;
+                                }
+                                if (tmpX == v1x && tmpY == v1y && tmpZ == v1z) {
+                                    newVertID1 = vi;
+                                }
+                                if (tmpX == v2x && tmpY == v2y && tmpZ == v2z) {
+                                    newVertID2 = vi;
+                                }
+                                if (newVertID0 >= 0 && newVertID1 >= 0 && newVertID2 >= 0)
+                                    break;
+                            }
+                            #endregion
+
+                            if (newVertID0 < 0) {
+                                newVertID0 = ++vertIndLast;
+                                outVertices[0, newVertID0] = v0x;
+                                outVertices[1, newVertID0] = v0y;
+                                outVertices[2, newVertID0] = v0z;
+                            }
+                            if (newVertID1 < 0) {
+                                newVertID1 = ++vertIndLast;
+                                outVertices[0, newVertID1] = v1x;
+                                outVertices[1, newVertID1] = v1y;
+                                outVertices[2, newVertID1] = v1z;
+                            }
+                            if (newVertID2 < 0) {
+                                newVertID2 = ++vertIndLast;
+                                outVertices[0, newVertID2] = v2x;
+                                outVertices[1, newVertID2] = v2y;
+                                outVertices[2, newVertID2] = v2z;
+                            }
+
+                            if (outTriangles.S[1] <= triIndLast + 3)
+                                outTriangles[0, triIndLast * 2] = 0;
+
+                            // create new triangles 
+                            outTriangles.SetValue(newVertID0, 1, triInd);
+                            outTriangles.SetValue(newVertID2, 2, triInd);
+
+                            outTriangles.SetValue(newVertID2, 0, ++triIndLast);
+                            outTriangles.SetValue(newVertID1, 1, triIndLast);
+                            outTriangles.SetValue(vertInd2, 2, triIndLast);
+
+                            outTriangles.SetValue(newVertID2, 0, ++triIndLast);
+                            outTriangles.SetValue(newVertID0, 1, triIndLast);
+                            outTriangles.SetValue(newVertID1, 2, triIndLast);
+
+                            outTriangles.SetValue(newVertID0, 0, ++triIndLast);
+                            outTriangles.SetValue(vertInd1, 1, triIndLast);
+                            outTriangles.SetValue(newVertID1, 2, triIndLast);
+                        }
+
+                    }
+                    outVertices.a = outVertices[":;0:" + vertIndLast];
+                    outTriangles.a = outTriangles[":;0:" + triIndLast];
+                }
+            }
+
+            /// <summary>
+            /// create vertex data [unevenly distributed, depricated]
+            /// </summary>
+            /// <param name="center"></param>
+            /// <param name="radius"></param>
+            /// <param name="horRes"></param>
+            /// <param name="vertRes"></param>
+            /// <param name="indices"></param>
+            /// <returns></returns>
+            public static ILRetArray<float> CreateVertices(ILPoint3Df center, float radius, int horRes, int vertRes, ILOutArray<int> indices) {
+                using (ILScope.Enter()) {
+                    ILArray<float> phi = repmat(tosingle(linspace(-pi, pi, horRes + 1)), vertRes + 1, 1);
+                    ILArray<float> rho = repmat(tosingle(linspace(0, pi, vertRes + 1)).T, 1, horRes + 1);
+                    bool dummy;
+                    float[] retArr = ILNumerics.ILMemoryPool.Pool.New<float>((horRes + 1) * (vertRes + 1), false, out dummy);
+                    ILArray<float> ret = new ILArray<float>(retArr, vertRes + 1, horRes + 1);
+                    // create normals 
+                    ret[":;:;3"] = sin(phi) * sin(rho);
+                    ret[":;:;4"] = cos(phi) * sin(rho);
+                    ret[":;:;5"] = cos(rho);
+                    // translate + scale vertices
+                    ret[":;:;0"] = (ILArray<float>)radius * ret[":;:;3"] + center.X;
+                    ret[":;:;1"] = (ILArray<float>)radius * ret[":;:;4"] + center.Y;
+                    ret[":;:;2"] = (ILArray<float>)radius * ret[":;:;5"] + center.Z;
+                    // create index mappings 
+                    //horRes--; vertRes--; 
+                    indices.a = zeros<int>(4, (horRes) * (vertRes));
+                    for (int r = 0, pos = 0; r < vertRes; r++) {
+                        for (int c = 0; c < horRes; c++) {
+                            indices.SetValue(c + r * (horRes + 1), pos++);
+                            indices.SetValue(c + (r + 1) * (horRes + 1), pos++);
+                            indices.SetValue((c + 1) + (r + 1) * (horRes + 1), pos++);
+                            indices.SetValue((c + 1) + r * (horRes + 1), pos++);
+                        }
+                    }
+                    System.Diagnostics.Debug.Assert(maxall(indices) <= ret[":;:;0"].Size.NumberOfElements);
+                    System.Diagnostics.Debug.Assert(minall(indices) >= 0);
+                    return ret;
+                }
+            }
+            /// <summary>
+            /// create vertices by triangularization, starting from icosahedron and subseq. creating finer grained details
+            /// </summary>
+            /// <param name="detail">number of iterations for triangularization</param>
+            /// <param name="indices">out param: return triangles</param>
+            /// <returns>vertex data</returns>
+            public static ILRetArray<float> CreateVerticesTri(int detail, ILOutArray<int> indices) {
+                using (ILScope.Enter()) {
+                    if (s_vertexCache.ContainsKey(detail) && s_vertexCache[detail] != null) {
+                        ILCell data = s_vertexCache[detail];
+                        indices.a = data.GetArray<int>(1);
+                        return data.GetArray<float>(0);
+                    } else {
+
+
+                        // regular octahedron
+                        //float[,] pos = new float[,] {
+                        //    {1, 0, 0}, {-1, 0, 0}, 
+                        //    {0, 1, 0}, {0, -1, 0},
+                        //    {0, 0, 1}, {0, 0, -1}
+                        //}; 
+                        //int[,] ind = new int[,] { 
+                        //   {4, 0, 3}, {4, 3, 1}, {4 ,1 ,2}, {4, 2 ,0},
+                        //   {0, 2, 5}, {3, 0, 5}, {1, 3, 5}, {1, 5, 2}
+                        //};
+                        //// regular icosahedron
+                        float X = 0.525731112119133606f;
+                        float Z = 0.850650808352039932f;
+
+                        float[,] pos = new float[,] {
+                   {-X, 0, Z}, {X, 0, Z}, {-X, 0, -Z}, {X, 0, -Z},
+                   {0, Z, X}, {0, Z, -X}, {0, -Z, X}, {0, -Z, -X},
+                   {Z, X, 0}, {-Z, X, 0}, {Z, -X, 0}, {-Z, -X, 0}
+                };
+                        int[,] ind = new int[,] { 
+                   {0,4,1}, {0,9,4}, {9,5,4}, {4,5,8}, {4,8,1},
+                   {8,10,1}, {8,3,10},{5,3,8}, {5,2,3}, {2,7,3},
+                   {7,10,3}, {7,6,10}, {7,11,6}, {11,0,6}, {0,1,6},
+                   {6,1,10}, {9,0,11}, {9,11,2}, {9,2,5}, {7,2,11}
+                };
+                        ILArray<float> vertices = pos;
+                        indices.a = ind;
+                        //vertices = vertices[":;0:2"];
+                        //indices = new int[] { 0, 1, 2 };
+                        //indices = indices.T; 
+                        ILArray<float> outVertices = empty<float>();
+                        Triangularize(vertices, indices, detail, outVertices, indices);
+                        // normalize vertices 
+                        outVertices.a = Normalize(outVertices);
+                        // store in cache
+                        s_vertexCache.Add(detail, cell(new ILSize(2, 1), outVertices, indices));
+                        return outVertices;
+                    }
+                }
+            }
+
+            private static ILRetArray<float> Normalize(ILDenseArray<float> vertices)
+            {
+                using (ILScope.Enter(vertices)) {
+                    return vertices / repmat(sqrt(sum(vertices * vertices, 0)), 3, 1);
+                }
+            }
+        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILLitTriangle.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILLitTriangle.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILLitTriangle.cs	(revision 9102)
@@ -0,0 +1,62 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing; 
+using ILNumerics.Drawing; 
+using ILNumerics.Drawing.Misc;
+using ILNumerics.Drawing.Graphs;  
+using ILNumerics.Drawing.Interfaces; 
+using ILNumerics.Drawing.Shapes; 
+
+namespace ILNumerics.Drawing.Shapes {
+    /// <summary>
+    /// A single simple bordered triangle supporting light
+    /// </summary>
+    public class ILLitTriangle : ILLitBorderedShape<C4fN3fV3f> {
+
+        #region constructors
+        public ILLitTriangle(ILPanel panel) 
+            : base (panel,3) { } 
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILLitTriangles.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILLitTriangles.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILLitTriangles.cs	(revision 9102)
@@ -0,0 +1,125 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System.Drawing;
+
+
+namespace ILNumerics.Drawing.Shapes {
+    
+    public class ILLitTriangles 
+        : ILLitCompositeShape<C4fN3fV3f> {
+
+        #region constructors
+        /// <summary>
+        /// create lit triangles
+        /// </summary>
+        /// <param name="panel">hosting panel</param>
+        /// <param name="numVertices">number of vertices to create. Vertex data must be defined afterwards.</param>
+        public ILLitTriangles (ILPanel panel, int numVertices) 
+            : base (panel, numVertices, 3) {
+            m_fillColor = Color.Yellow; 
+        }
+        ///// <summary>
+        ///// create lit triangles 
+        ///// </summary>
+        ///// <param name="panel">hosting panel</param>
+        ///// <param name="X">x coordinates vector </param>
+        ///// <param name="Y">y coordinates vector </param>
+        ///// <param name="Z">z coordinates vector </param>
+        //public ILLitTriangles (ILPanel panel, ILBaseArray X, ILBaseArray Y, ILBaseArray Z) 
+        //    : base (panel,3,X,Y,Z) { 
+        //    m_fillColor = Color.Yellow;  
+        //}
+        ///// <summary>
+        ///// create lit triangles, indexed storage
+        ///// </summary>
+        ///// <param name="panel">hosting panel</param>
+        ///// <param name="X">x coordinates vector </param>
+        ///// <param name="Y">y coordinates vector </param>
+        ///// <param name="Z">z coordinates vector </param>
+        ///// <param name="mapping">Mapping of shapes, composes lit triangles out of vertices. Matrix having  
+        ///// 3 rows. Every element in a column specifies the index of a vertex according to its position in X,Y,Z.
+        ///// The 3 elements in a column therefore compose a single lit triangle. Vertices may 
+        ///// get used arbitrary times (or not at all). All elements must be positive integer values in 
+        ///// range 0...[<see cref="ILNumerics.Drawing.Shapes.ILShape.VertexCount"/>-1].</param>
+        //public ILLitTriangles (ILPanel panel, ILBaseArray X, ILBaseArray Y, ILBaseArray Z, ILBaseArray mapping) 
+        //    : base (panel,3,X,Y,Z,mapping) {
+        //    m_fillColor = Color.Yellow;
+        //}
+        ///// <summary>
+        ///// create lit triangles, flat shading
+        ///// </summary>
+        ///// <param name="panel">hosting panel</param>
+        ///// <param name="X">x coordinates vector </param>
+        ///// <param name="Y">y coordinates vector </param>
+        ///// <param name="Z">z coordinates vector </param>
+        ///// <param name="color">Fill color for all shapes.</param>
+        ///// <param name="mapping">Mapping of shapes, composes lit triangles out of vertices. Matrix having  
+        ///// 3 rows. Every element in a column specifies the index of a vertex according to its position in X,Y,Z.
+        ///// The 3 elements in a column therefore compose a single lit triangle. Vertices may 
+        ///// get used arbitrary times (or not at all). All elements must be positive integer values in 
+        ///// range 0...[<see cref="ILNumerics.Drawing.Shapes.ILShape.VertexCount"/>-1].</param>
+        //public ILLitTriangles (ILPanel panel, ILBaseArray X, ILBaseArray Y, ILBaseArray Z, Color color, ILBaseArray mapping) 
+        //    : base (panel,3,X,Y,Z,mapping) {
+        //    m_fillColor = color;
+        //}
+        ///// <summary>
+        ///// create lit triangles, interpolated shading
+        ///// </summary>
+        ///// <param name="panel">hosting panel</param>
+        ///// <param name="X">x coordinates vector </param>
+        ///// <param name="Y">y coordinates vector </param>
+        ///// <param name="Z">z coordinates vector </param>
+        ///// <param name="colors">matrix with <see cref="ILNumerics.Drawing.Shapes.ILShape.VertexCount"/> 
+        ///// rows, 3 columns for (R,G,B) or 4 columns for 
+        ///// (A,R,G,B) for every vertex specified by X,Y,Z. Elements must range from 0..255. If colors 
+        ///// has 3 columns only, alpha values of 255 are used as default.</param>
+        ///// <param name="mapping">Mapping of shapes, composes lit triangles out of vertices. Matrix having  
+        ///// 3 rows. Every element in a column specifies the index of a vertex according to its position in X,Y,Z.
+        ///// The 3 elements in a column therefore compose a single lit triangle. Vertices may 
+        ///// get used arbitrary times (or not at all). All elements must be positive integer values in 
+        ///// range 0...[<see cref="ILNumerics.Drawing.Shapes.ILShape.VertexCount"/>-1].</param>
+        //public ILLitTriangles (ILPanel panel, ILBaseArray X, ILBaseArray Y, ILBaseArray Z, ILBaseArray colors, ILBaseArray mapping) 
+        //    : base (panel,3,X,Y,Z,colors,mapping) {
+        //    m_fillColor = Color.Yellow;
+        //}
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILPoints.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILPoints.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILPoints.cs	(revision 9102)
@@ -0,0 +1,173 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing; 
+using ILNumerics.Drawing; 
+using ILNumerics.Drawing.Misc;
+using ILNumerics.Drawing.Graphs;  
+using ILNumerics.Drawing.Interfaces; 
+using ILNumerics.Drawing.Shapes; 
+using ILNumerics.Exceptions; 
+using ILNumerics; 
+
+namespace ILNumerics.Drawing.Shapes {
+    /// <summary>
+    /// points rendering shape, to be used in scene graphs
+    /// </summary>
+    public class ILPoints : ILCompositeShape<C4bV3f> {
+
+        #region attributes
+        int m_width; 
+        #endregion
+
+        #region properties 
+        /// <summary>
+        /// size (of all points)
+        /// </summary>
+        public int Width {
+            get { return m_width; }
+            set { 
+                m_width = value; 
+                OnChanged(); 
+            }
+        }
+        #endregion
+
+        #region constructors
+        /// <summary>
+        /// create new points 
+        /// </summary>
+        /// <param name="panel">panel hosting the scene graph</param>
+        /// <param name="numPoints">number of points to create</param>
+        public ILPoints (ILPanel panel, int numPoints) 
+            : base (panel, numPoints, 1) { 
+            m_fillColor = Color.Black;
+            m_width = 4;
+            m_shading = ShadingStyles.Flat;
+            //// colors 
+            //ILColorEnumerator colors = new ILColorEnumerator(); 
+            //for (int i = 0; i < numPoints; i++) {
+            //    m_vertices[i].Color = colors.NextColor(); 
+            //}
+        }
+        ///// <summary>
+        ///// create point collection 
+        ///// </summary>
+        ///// <param name="panel">panel hosting the scene graph</param>
+        ///// <param name="data">numeric matrix with 1,2 or 3 rows, holding X,Y and Z values respectively</param>
+        ///// <param name="colors">3 rowed matrix with RGB values in columns. Values must lay in range 0...255. 
+        ///// If a 4th row is provided, it specifys the alpha value for the points (0...255). Otherwise the points will
+        ///// be fully opaque. </param>
+        //public ILPoints (ILPanel panel, ILBaseArray data, ILBaseArray colors) 
+        //    : base (panel, data.Dimensions[1],1) {
+        //        using (ILScope.Enter(data, colors)) {
+        //            ILArray<float> fData;
+        //            #region x coords
+        //            if (data != null) {
+        //                if (data is ILArray<float>)
+        //                    fData = (ILArray<float>)data;
+        //                else
+        //                    fData = ILNumerics.ILMath.tosingle(data);
+        //                switch (fData.Dimensions[0]) {
+        //                    case 0: 
+        //                        break; 
+        //                    case 1:
+        //                        for (int i = 0; i < m_vertCount; i++) {
+        //                            m_vertices[i].XPosition = fData.GetValue(i);
+        //                        }
+        //                        break;
+        //                    case 2:
+        //                        for (int i = 0; i < m_vertCount; i++) {
+        //                            m_vertices[i].XPosition = fData.GetValue(0, i);
+        //                            m_vertices[i].YPosition = fData.GetValue(1, i);
+        //                        }
+        //                        break;
+        //                    default:
+        //                        for (int i = 0; i < m_vertCount; i++) {
+        //                            m_vertices[i].XPosition = fData.GetValue(0, i);
+        //                            m_vertices[i].YPosition = fData.GetValue(1, i);
+        //                            m_vertices[i].ZPosition = fData.GetValue(2, i);
+        //                        }
+        //                        break;
+        //                }
+        //            }
+        //            #endregion
+
+        //            #region colors
+        //            if (colors == null) {
+        //                // initialize as dark blue, fully opaque
+        //                for (int i = 0; i < m_vertCount; i++) {
+        //                    m_vertices[i].Color = Color.DarkBlue;
+        //                }
+        //            } else if (colors.IsScalar && colors is ILDenseArray<Color>) {
+        //                Color col = (colors as ILDenseArray<Color>).GetValue(0);
+        //                for (int i = 0; i < m_vertCount; i++) {
+        //                    m_vertices[i].Color = Color.DarkBlue;
+        //                }
+        //            } else {
+        //                ILArray<byte> bCols;
+        //                if (!colors.IsMatrix || !colors.IsNumeric || (colors.Dimensions[0] != 3 && colors.Dimensions[0] != 4)) {
+        //                    throw new ILArgumentException("invalid argument: colors must be numeric matrix, 3 rows with R,G,B values!");
+        //                }
+        //                if (colors is ILArray<byte>)
+        //                    bCols = (ILArray<byte>)colors;
+        //                else
+        //                    bCols = ILNumerics.ILMath.tobyte(colors);
+        //                if (colors.Dimensions[0] == 3) {
+        //                    for (int i = 0; i < m_vertCount; i++) {
+        //                        m_vertices[i].Color = Color.FromArgb(bCols.GetValue(0, i), bCols.GetValue(1, i), bCols.GetValue(2, i));
+        //                    }
+        //                } else {
+        //                    for (int i = 0; i < m_vertCount; i++) {
+        //                        m_vertices[i].Color = Color.FromArgb(bCols.GetValue(3, i), bCols.GetValue(0, i), bCols.GetValue(1, i), bCols.GetValue(2, i));
+        //                    }
+        //                }
+        //            }
+        //            #endregion
+        //            m_width = 4;
+        //            m_shading = ShadingStyles.Interpolate;
+        //        }
+        //}
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILPolygon.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILPolygon.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILPolygon.cs	(revision 9102)
@@ -0,0 +1,64 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing; 
+using ILNumerics.Drawing; 
+using ILNumerics.Drawing.Misc;
+using ILNumerics.Drawing.Graphs;  
+using ILNumerics.Drawing.Interfaces; 
+using ILNumerics.Drawing.Shapes; 
+
+namespace ILNumerics.Drawing.Shapes {
+    /// <summary>
+    /// A simple polygon, rendering arbitrary number of corners, bordered
+    /// </summary>
+    public class ILPolygon : ILBorderedShape<C4bV3f> {
+
+        #region constructors
+        public ILPolygon (ILPanel panel, int numVertices) 
+            : base (panel,numVertices) { 
+            
+        }
+        #endregion
+        
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILQuad.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILQuad.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILQuad.cs	(revision 9102)
@@ -0,0 +1,62 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing; 
+using ILNumerics.Drawing; 
+using ILNumerics.Drawing.Misc;
+using ILNumerics.Drawing.Graphs;  
+using ILNumerics.Drawing.Interfaces; 
+using ILNumerics.Drawing.Shapes; 
+
+namespace ILNumerics.Drawing.Shapes {
+    /// <summary>
+    /// A single simple bordered quad
+    /// </summary>
+    public class ILQuad : ILBorderedShape<C4bV3f> {
+
+        #region constructors
+        public ILQuad (ILPanel panel) 
+            : base (panel,4) { } 
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILQuads.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILQuads.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILQuads.cs	(revision 9102)
@@ -0,0 +1,131 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System.Drawing;
+
+
+namespace ILNumerics.Drawing.Shapes {
+    
+    public class ILQuads 
+        : ILCompositeShape<C4bV3f> {
+
+        #region constructors
+        /// <summary>
+        /// create quads, for delayed vertex definition
+        /// </summary>
+        /// <param name="panel">hosting panel</param>
+        /// <param name="numVertices">number of vertices to create. Vertices must be filled 
+        /// with data manually afterwards.</param>
+        public ILQuads (ILPanel panel, int numVertices) 
+            : base (panel, numVertices, 4) {
+            m_fillColor = Color.Green;    
+        }
+        ///// <summary>
+        ///// create quads, define vertex positions 
+        ///// </summary>
+        ///// <param name="panel">hosting panel</param>
+        ///// <param name="X">x coordinates vector </param>
+        ///// <param name="Y">y coordinates vector </param>
+        ///// <param name="Z">z coordinates vector </param>
+        //public ILQuads (ILPanel panel, ILBaseArray X, ILBaseArray Y, ILBaseArray Z) 
+        //    : base (panel,4,X,Y,Z) { 
+        //    m_fillColor = Color.Green;    
+        //}
+        ///// <summary>
+        ///// create quads, indexed storage
+        ///// </summary>
+        ///// <param name="panel">hosting panel</param>
+        ///// <param name="X">x coordinates vector </param>
+        ///// <param name="Y">y coordinates vector </param>
+        ///// <param name="Z">z coordinates vector </param>
+        ///// <param name="mapping">Mapping of shapes, composes quads out of vertices. Matrix having  
+        ///// 4 rows. Every element in a column specifies the index of a vertex according to its position in X,Y,Z.
+        ///// The 4 elements in a column therefore compose a single quad. Vertices may 
+        ///// get used arbitrary times (or not at all). All elements must be positive integer values in 
+        ///// range 0...[<see cref="ILNumerics.Drawing.Shapes.ILShape.VertexCount"/>-1].</param>
+        //public ILQuads (ILPanel panel, ILBaseArray X, ILBaseArray Y, ILBaseArray Z, ILBaseArray mapping) 
+        //    : base (panel,4,X,Y,Z,mapping) { 
+        //    m_fillColor = Color.Green;    
+        //}
+        ///// <summary>
+        ///// create quads, flat shading
+        ///// </summary>
+        ///// <param name="panel">hosting panel</param>
+        ///// <param name="X">x coordinates vector </param>
+        ///// <param name="Y">y coordinates vector </param>
+        ///// <param name="Z">z coordinates vector </param>
+        ///// <param name="color">Fill color for all shapes.</param>
+        ///// <param name="mapping">Composes shapes out of given vertices. Matrix having 4 rows.
+        ///// Every element in a column specifies the index of a vertex according to its position in X,Y,Z. 
+        ///// The 4 elements in a column therefore compose a single quad. Vertices may 
+        ///// get used arbitrary times (or not at all). All elements must be positive integer values in 
+        ///// range 0...[vertCount-1].</param>
+        ///// <param name="mapping">Mapping composes quads out of vertices. Matrix having  
+        ///// 4 rows. Every element in a column specifies the index of a vertex according to its position in X,Y,Z.
+        ///// The 4 elements in a column therefore compose a single quad. Vertices may 
+        ///// get used arbitrary times (or not at all). All elements must be positive integer values in 
+        ///// range 0...[<see cref="ILNumerics.Drawing.Shapes.ILShape.VertexCount"/>-1].</param>
+        //public ILQuads (ILPanel panel, ILBaseArray X, ILBaseArray Y, ILBaseArray Z, Color color, ILBaseArray mapping) 
+        //    : base (panel,4,X,Y,Z,mapping) {
+        //    m_fillColor = color;
+        //}
+        ///// <summary>
+        ///// create quads, interpolated shading
+        ///// </summary>
+        ///// <param name="panel">hosting panel</param>
+        ///// <param name="X">x coordinates vector </param>
+        ///// <param name="Y">y coordinates vector </param>
+        ///// <param name="Z">z coordinates vector </param>
+        ///// <param name="colors">matrix with <see cref="ILNumerics.Drawing.Shapes.ILShape.VertexCount"/> 
+        ///// rows, 3 columns for (R,G,B) or 4 columns for 
+        ///// (A,R,G,B) for every vertex specified by X,Y,Z. Elements must range from 0..255. If colors 
+        ///// has 3 columns only, alpha values of 255 are used as default.</param>
+        ///// <param name="mapping">Mapping of shapes, composes quads out of vertices. Matrix having  
+        ///// 4 rows. Every element in a column references a vertex according to its position index in vectors X,Y,Z.
+        ///// The 4 elements in a column therefore compose a single quad. Vertices may 
+        ///// get used arbitrary times (or not at all). All elements must be positive integer values in 
+        ///// range 0...[<see cref="ILNumerics.Drawing.Shapes.ILShape.VertexCount"/>-1].</param>
+        //public ILQuads (ILPanel panel, ILBaseArray X, ILBaseArray Y, ILBaseArray Z, ILBaseArray colors, ILBaseArray mapping) 
+        //    : base (panel,4,X,Y,Z,colors,mapping) {
+        //    m_fillColor = Color.Green;
+        //}
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILShape.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILShape.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILShape.cs	(revision 9102)
@@ -0,0 +1,495 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing;
+using ILNumerics.Drawing; 
+using ILNumerics.Drawing.Graphs; 
+using ILNumerics.Drawing.Labeling;
+using ILNumerics.Drawing.Interfaces;  
+
+namespace ILNumerics.Drawing.Shapes {
+    #region ILShape<VertexType> class definition
+    /// <summary>
+    /// abstract generic shape, specific vertex type
+    /// </summary>
+    /// <typeparam name="VertexType">the internal vertex type, IILVertexDefinition</typeparam>
+    public abstract class ILShape<VertexType> : ILShape
+        where VertexType : struct, IILVertexDefinition {
+
+        #region attributes 
+        protected VertexType[] m_vertices; 
+        protected VertexType m_sampleVertex = new VertexType(); 
+        protected int m_numVerticesPerShape;
+        #endregion
+
+        #region properties
+
+        /// <summary>
+        /// access to internal vertex array
+        /// </summary>
+        public virtual VertexType[] Vertices {
+            get {
+                return m_vertices; 
+            }
+        } 
+        /// <summary>
+        /// number of vertices per shape
+        /// </summary>
+        public int VerticesPerShape { 
+            get { return m_numVerticesPerShape; }
+        }
+        /// <summary>
+        /// get or manually define the center of the shape
+        /// </summary>
+        /// <remarks>Once an individual (custom) center was assigned to the CustomCenter
+        /// property, that point is returned and used on subsequent queries for Center. 
+        /// <para>In order to clear the custom center, set the CustomCenter property to ILPoint3Df.Emtpy.</para>
+        /// <para>The center is important to position the shape in the scene - according to 
+        /// other shapes. This defines the order in which the shapes are rendered, which 
+        /// is neccessary for transparency to appear correctly. In general one should
+        /// not alter the center. This will compute the center of a shape accordingly to its 
+        /// real vertices weight average. However, for certain special shapes it might 
+        /// be helpful to override the center to manually determine the rendering order in the scene.</para></remarks>
+        public ILPoint3Df CustomCenter {
+            get {
+                return m_customCenter;
+            }
+            set {
+                if (value.IsEmtpy()) {
+                    m_useCustomCenter = false;
+                } else {
+                    m_useCustomCenter = true;
+                    m_customCenter = value;
+                }
+                OnChanged();
+            }
+        }
+        /// <summary>
+        /// internal vertex definition (readonly)
+        /// </summary>
+        public override IILVertexDefinition VertexDefinition {
+            get {
+                return (IILVertexDefinition)m_sampleVertex; 
+            }
+        }
+        #endregion
+
+        #region constructors
+        public ILShape (ILPanel panel, int numberVertices, int verticesPerShape) 
+            : base (panel) {
+            m_numVerticesPerShape = verticesPerShape; 
+            m_renderer = panel.GetCreationFactory().CreateVertexRenderer(typeof(VertexType), this);
+            Resize(numberVertices);
+            VertexType a = new VertexType(); 
+            m_vertexStoresColor = a.StoresColor; 
+        }
+
+        #endregion
+
+        #region public interface 
+        /// <summary>
+        /// Query single vertex via IILVertexDefinition interface 
+        /// </summary>
+        /// <param name="i">index of vertex in vertex array</param>
+        /// <returns>vertex definition</returns>
+        public override IILVertexDefinition GetVertex(int i) {
+            return (IILVertexDefinition)m_vertices[i]; 
+        }
+        /// <summary>
+        /// alter single vertex via IILVertexDefinition interface
+        /// </summary>
+        /// <param name="vertexIdx">index of vertex in vertex array</param>
+        /// <param name="vertex">new vertex definition</param>
+        public override void SetVertex(int vertexIdx,IILVertexDefinition vertex) {
+            VertexType curVert = m_vertices[vertexIdx]; 
+            if (VertexDefinition.StoresColor && vertex.StoresColor) {
+                curVert.Color = vertex.Color; 
+            }
+            if (VertexDefinition.StoresNormals && vertex.StoresNormals) {
+                curVert.Normal = vertex.Normal; 
+            }
+            curVert.Position = vertex.Position;
+            m_vertices[vertexIdx] = curVert; 
+        }
+        /// <summary>
+        /// set color for single vertex (color only, no alpha!)
+        /// </summary>
+        /// <param name="vertexID">index of vertex in vertex array</param>
+        /// <param name="color">new color</param>
+        public override void SetColor(int vertexID,Color color) {
+            if (VertexDefinition.StoresColor) {
+                VertexType vert = m_vertices[vertexID]; 
+                vert.Color = color; 
+                m_vertices[vertexID] = vert; 
+            }
+        }
+        /// <summary>
+        /// set position of single vertex 
+        /// </summary>
+        /// <param name="vertexID">index of vertex in vertex array</param>
+        /// <param name="position">new position </param>
+        public override void SetPosition(int vertexID,ILPoint3Df position) {
+            VertexType vert = m_vertices[vertexID]; 
+            vert.Position = position; 
+            m_vertices[vertexID] = vert; 
+        }
+        /// <summary>
+        /// set normal vector of single vertex
+        /// </summary>
+        /// <param name="vertexID">index of vertex in vertex array</param>
+        /// <param name="normal">new normal vector</param>
+        public override void SetNormal(int vertexID,ILPoint3Df normal) {
+            if (VertexDefinition.StoresNormals) {
+                VertexType vert = m_vertices[vertexID]; 
+                vert.Normal = normal; 
+                m_vertices[vertexID] = vert; 
+            }
+        }
+        /// <summary>
+        /// translate all vertices of the shape
+        /// </summary>
+        /// <param name="offset">offset, all vertices will be moved by that amount</param>
+        public override void Translate(ILPoint3Df offset) {
+            for (int i = 0; i < m_vertCount; i++) {
+                VertexType tmp = m_vertices[i]; 
+                tmp.Position += offset; 
+                m_vertices[i] = tmp; 
+			}
+        }
+        #endregion
+
+        #region private helper 
+        protected void Resize(int numberVertices) {
+            m_vertCount = numberVertices;
+            m_vertices = new VertexType[numberVertices];
+        }
+        protected override void ComputeLimits() {
+            ILPoint3Df cent = new ILPoint3Df();
+            if (m_vertices.Length == 0) {
+                // fast exit
+                m_positionCenter = cent;
+                m_positionMin = cent;
+                m_positionMax = cent;
+                return;
+            }
+            ILPoint3Df max = ILPoint3Df.MinValue, min = ILPoint3Df.MaxValue, cur;
+            foreach (IILVertexDefinition vertex in m_vertices) {
+                cur = vertex.Position;
+                cent = cent + cur;
+                max = ILPoint3Df.Max(max, cur);
+                min = ILPoint3Df.Min(min, cur);
+            }
+            m_positionCenter = cent / m_vertices.Length;
+            m_positionMax = max;
+            m_positionMin = min;
+        }
+        #endregion
+
+    }
+    #endregion
+
+    #region ILShape base class definition
+    /// <summary>
+    /// abstract base class for all shapes 
+    /// </summary>
+    public abstract class ILShape  :  IDisposable {
+
+        #region events 
+        /// <summary>
+        /// fires, when any properties of the shape have changed
+        /// </summary>
+        public event EventHandler Changed; 
+        protected virtual void OnChanged() {
+            if (Changed != null) {
+                Changed(this, new EventArgs()); 
+            }
+        }
+        /// <summary>
+        /// fires when the size of the shape has changed
+        /// </summary>
+        public event EventHandler SizeChanged; 
+        protected virtual void OnSizeChanged() {
+            if (SizeChanged != null) {
+                SizeChanged(this, new EventArgs()); 
+            }
+        }
+        #endregion 
+
+        #region attributes
+        protected ILPanel m_panel; 
+        protected bool m_useCustomCenter; 
+        protected ILPoint3Df m_customCenter;
+        protected ILPoint3Df m_positionMin;
+        protected ILPoint3Df m_positionMax;
+        protected ILPoint3Df m_positionCenter; 
+        protected Color m_fillColor; 
+        protected ShadingStyles m_shading; 
+        protected ILShapeLabel m_label; 
+        protected bool m_vertexStoresColor;
+        private bool m_invalidated; 
+        protected int m_vertCount;
+        protected ILVertexRenderer m_renderer;
+        protected ILSceneGraphShapedLeaf m_sceneNode; 
+        protected bool m_visible; 
+        #endregion 
+
+        #region properties 
+        /// <summary>
+        /// Gets visibility of the shape or sets it
+        /// </summary>
+        public bool Visible {
+            get { return m_visible; }
+            set { m_visible = value; }
+        }
+        /// <summary>
+        /// returns the scene graph node holding this shape
+        /// </summary>
+        public ILSceneGraphShapedLeaf SceneGraphNode {
+            get {
+                return m_sceneNode; 
+            }
+            set {
+                m_sceneNode = value; 
+            }
+        }
+        /// <summary>
+        /// Get minimum coordinate of the cube enclosing the shape
+        /// </summary>
+        public ILPoint3Df PositionMin {
+            get {
+                if (m_positionMin.IsEmtpy())
+                    ComputeLimits();
+                return m_positionMin;
+            }
+        }
+        /// <summary>
+        /// Get maximum coordinate of the cube enclosing the shape
+        /// </summary>
+        public ILPoint3Df PositionMax {
+            get {
+                if (m_positionMax.IsEmtpy())
+                    ComputeLimits();
+                return m_positionMax;
+            }
+        }
+        /// <summary>
+        /// Get weight center of vertices 
+        /// </summary>
+        public ILPoint3Df Center {
+            get {
+                if (m_useCustomCenter && !m_customCenter.IsEmtpy())
+                    return m_customCenter; 
+                if (m_positionCenter.IsEmtpy())
+                    ComputeLimits();
+                return m_positionCenter;
+            }
+        }
+        /// <summary>
+        /// Get/set method of area filling 
+        /// </summary>
+        /// <remarks><para>Two methods are available: 'Interpolate' and 'Flat'. For 'Interpolate' mode,
+        /// the color and alpha values stored in individual vertices are used for rendering. 
+        /// In 'Flat' mode, only the single properties 'FillColor' and 'Opacity' determine 
+        /// the color and transparency of the whole shape. Even if vertices store individual
+        /// color values, those are ignored in that case.</para></remarks>
+        public ShadingStyles Shading {
+            get { 
+                return m_shading; 
+            }
+            set {
+                if (m_shading == ShadingStyles.Interpolate && !VertexDefinition.StoresColor) {
+                    throw new NotSupportedException("The underlying vertex type does not support individual colors! Use shading mode 'Flat' instead!"); 
+                }
+                m_shading = value; 
+                OnChanged(); 
+            }
+        }
+        /// <summary>
+        /// fill color for shape areas in flat shading mode
+        /// </summary>
+        /// <remarks>Setting this value will not alter the alpha value 
+        /// (opacity). The alpha of the new value will be ignored.</remarks>
+        public virtual Color FillColor { 
+            get {
+                return m_fillColor; 
+            } 
+            set {
+                m_fillColor = Color.FromArgb(m_fillColor.A, value); 
+                m_shading = ShadingStyles.Flat; 
+                OnChanged(); 
+            }
+        }
+        /// <summary>
+        /// definition of internal vertex type (readonly)
+        /// </summary>
+        public abstract IILVertexDefinition VertexDefinition { get; }
+        /// <summary>
+        /// opacity for areas of the shape in flat shading mode 
+        /// </summary>
+        public byte Opacity { 
+            get { return m_fillColor.A; }
+            set { m_fillColor = Color.FromArgb(value, m_fillColor); }
+        }
+        /// <summary>
+        /// Shape label
+        /// </summary>
+        public ILShapeLabel Label {
+            get {
+                return m_label; 
+            }
+        }
+        /// <summary>
+        /// number of vertices a shape (or all components of a shape) of this type is made out of
+        /// </summary>
+        /// <remarks>For triangle shapes and related (lit triangles, triangles etc.) this is 3, for quads it is 4 and so on...</remarks>
+        public int VertexCount { 
+            get { return m_vertCount; }
+        }
+        #endregion
+
+        #region constructors
+        /// <summary>
+        /// create new shape (protected) 
+        /// </summary>
+        /// <param name="panel">panel hosting the scene</param>
+        protected ILShape (ILPanel panel) {
+            m_panel = panel; 
+            m_fillColor = Color.White;
+            m_label = new ILShapeLabel(panel);
+            m_label.Changed += new EventHandler(m_label_Changed); 
+            m_label.Text = ""; //GetType().Name + " " + GetHashCode();
+            m_shading = ShadingStyles.Flat;
+            m_visible = true; 
+            Invalidate(); 
+        }
+        #endregion
+
+        #region public interface
+        /// <summary>
+        /// may be overwritten in derived classes to clean up ressources
+        /// </summary>
+        public virtual void Dispose() {}
+        /// <summary>
+        /// Query single vertex via IILVertexDefinition interface 
+        /// </summary>
+        /// <param name="id">index of vertex in vertex array</param>
+        /// <returns>vertex definition</returns>
+        public abstract IILVertexDefinition GetVertex(int id);
+        /// <summary>
+        /// set color for single vertex (color only, no alpha!)
+        /// </summary>
+        /// <param name="id">index of vertex in vertex array</param>
+        /// <param name="color">new color</param>
+        public abstract void SetColor(int id, Color color);
+        /// <summary>
+        /// set position if single vertex 
+        /// </summary>
+        /// <param name="id">index of vertex in vertex array</param>
+        /// <param name="position">new position </param>
+        public abstract void SetPosition(int id, ILPoint3Df position);
+        /// <summary>
+        /// set normal vector for single vertex
+        /// </summary>
+        /// <param name="id">index of vertex in vertex array</param>
+        /// <param name="normal">new normal vector</param>
+        public abstract void SetNormal(int id, ILPoint3Df normal);
+        /// <summary>
+        /// alter single vertex via IILVertexDefinition interface
+        /// </summary>
+        /// <param name="vertexID">index of vertex in vertex array</param>
+        /// <param name="vertex">new vertex definition</param>
+        public abstract void SetVertex(int vertexID, IILVertexDefinition vertex);
+        /// <summary>
+        /// translate all vertices of the shape
+        /// </summary>
+        /// <param name="offset">offset, all vertices will be moved by that amount</param>
+        public abstract void Translate(ILPoint3Df offset); 
+        /// <summary>
+        /// draw this shape (internal use) 
+        /// </summary>
+        /// <param name="props"></param>
+        public void Draw (ILRenderProperties props) {
+            if (m_visible) {
+                IntDrawShape(props); 
+                IntDrawLabel(props);
+            }
+        }
+        /// <summary>
+        /// configure this shape (internal use)
+        /// </summary>
+        /// <remarks>Configure is called once for each rendering frame. If the shape 
+        /// is invalidated, this causes IntConfigure to be called on the shape.</remarks>
+        public virtual void Configure() {
+            if (m_invalidated) {
+                m_invalidated = false;
+            }
+        }
+        /// <summary>
+        /// Invalidates this shape, needed after altering any vertex data
+        /// </summary>
+        public virtual void Invalidate() {
+            m_invalidated = true; 
+            m_positionMin = ILPoint3Df.Empty;
+            m_positionMax = ILPoint3Df.Empty;
+            m_positionCenter = ILPoint3Df.Empty;
+            if (m_sceneNode != null) {
+                m_sceneNode.Invalidate(false); 
+            }
+        }
+        protected virtual void IntDrawLabel(ILRenderProperties p) {
+            if (!String.IsNullOrEmpty(m_label.Text)) 
+                m_label.Draw(p, Center); 
+        }
+        protected virtual void IntDrawShape(ILRenderProperties p) {
+            m_renderer.Draw(p,this);
+        }
+        protected abstract void ComputeLimits();
+        #endregion
+
+        #region private helpers
+        void m_label_Changed(object sender, EventArgs e) {
+            OnChanged(); 
+        }
+        #endregion
+    }
+    #endregion
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILTriangle.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILTriangle.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILTriangle.cs	(revision 9102)
@@ -0,0 +1,62 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing; 
+using ILNumerics.Drawing; 
+using ILNumerics.Drawing.Misc;
+using ILNumerics.Drawing.Graphs;  
+using ILNumerics.Drawing.Interfaces; 
+using ILNumerics.Drawing.Shapes; 
+
+namespace ILNumerics.Drawing.Shapes {
+    /// <summary>
+    /// A simple bordered triangle
+    /// </summary>
+    public class ILTriangle : ILBorderedShape<C4bV3f> {
+
+        #region constructors
+        public ILTriangle (ILPanel panel) 
+            : base (panel,3) { } 
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILTriangles.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILTriangles.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILTriangles.cs	(revision 9102)
@@ -0,0 +1,122 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System.Drawing;
+
+
+namespace ILNumerics.Drawing.Shapes {
+    
+    public class ILTriangles 
+        : ILCompositeShape<C4bV3f> {
+ 
+        #region constructors
+        /// <summary>
+        /// create triangles, for delayed vertex definition
+        /// </summary>
+        /// <param name="panel">hosting panel</param>
+        /// <param name="numVertices">number of vertices to create. Vertices must be filled 
+        /// with data manually afterwards.</param>
+        public ILTriangles (ILPanel panel, int numTriangles) 
+            : base (panel, numTriangles * 3, 3) {
+            m_fillColor = Color.Blue;    
+        }
+        ///// <summary>
+        ///// create triangles 
+        ///// </summary>
+        ///// <param name="panel">hosting panel</param>
+        ///// <param name="X">x coordinates vector </param>
+        ///// <param name="Y">y coordinates vector </param>
+        ///// <param name="Z">z coordinates vector </param>
+        //public ILTriangles (ILPanel panel, ILBaseArray X, ILBaseArray Y, ILBaseArray Z) 
+        //    : base (panel,3, X,Y,Z) { }
+        ///// <summary>
+        ///// create triangles, indexed storage
+        ///// </summary>
+        ///// <param name="panel">hosting panel</param>
+        ///// <param name="X">x coordinates vector </param>
+        ///// <param name="Y">y coordinates vector </param>
+        ///// <param name="Z">z coordinates vector </param>
+        ///// <param name="mapping">Mapping of shapes, composes triangles out of vertices. Matrix having  
+        ///// 3 rows. Every element in a column specifies the index of a vertex according to its position in X,Y,Z.
+        ///// The 3 elements in a column therefore compose a single triangle. Vertices may 
+        ///// get used arbitrary times (or not at all). All elements must be positive integer values in 
+        ///// range 0...[<see cref="ILNumerics.Drawing.Shapes.ILShape.VertexCount"/>-1].</param>
+        //public ILTriangles (ILPanel panel, ILBaseArray X, ILBaseArray Y, ILBaseArray Z, ILBaseArray mapping) 
+        //    : base (panel, 3,X,Y,Z,mapping) { }
+        ///// <summary>
+        ///// create triangles, flat shading
+        ///// </summary>
+        ///// <param name="panel">hosting panel</param>
+        ///// <param name="X">x coordinates vector </param>
+        ///// <param name="Y">y coordinates vector </param>
+        ///// <param name="Z">z coordinates vector </param>
+        ///// <param name="color">Fill color for all shapes.</param>
+        ///// <param name="mapping">Mapping of shapes, composes lit triangles out of vertices. Matrix having  
+        ///// 3 rows. Every element in a column specifies the index of a vertex according to its position in X,Y,Z.
+        ///// The 3 elements in a column therefore compose a single lit triangle. Vertices may 
+        ///// get used arbitrary times (or not at all). All elements must be positive integer values in 
+        ///// range 0...[<see cref="ILNumerics.Drawing.Shapes.ILShape.VertexCount"/>-1].</param>
+        //public ILTriangles (ILPanel panel, ILBaseArray X, ILBaseArray Y, ILBaseArray Z, Color color, ILBaseArray mapping) 
+        //    : base (panel,3,X,Y,Z,mapping) {
+        //    m_fillColor = color;
+        //}
+        ///// <summary>
+        ///// create lit triangles, interpolated shading
+        ///// </summary>
+        ///// <param name="panel">hosting panel</param>
+        ///// <param name="X">x coordinates vector </param>
+        ///// <param name="Y">y coordinates vector </param>
+        ///// <param name="Z">z coordinates vector </param>
+        ///// <param name="colors">matrix with <see cref="ILNumerics.Drawing.Shapes.ILShape.VertexCount"/> 
+        ///// rows, 3 columns for (R,G,B) or 4 columns for 
+        ///// (A,R,G,B) for every vertex specified by X,Y,Z. Elements must range from 0..255. If colors 
+        ///// has 3 columns only, alpha values of 255 are used as default.</param>
+        ///// <param name="mapping">Mapping of shapes, composes triangles out of vertices. Matrix having  
+        ///// 3 rows. Every element in a column specifies the index of a vertex according to its position in X,Y,Z.
+        ///// The 3 elements in a column therefore compose a single triangle. Vertices may 
+        ///// get used arbitrary times (or not at all). All elements must be positive integer values in 
+        ///// range 0...[<see cref="ILNumerics.Drawing.Shapes.ILShape.VertexCount"/>-1].</param>
+        //public ILTriangles (ILPanel panel, ILBaseArray X, ILBaseArray Y, ILBaseArray Z, ILBaseArray colors, ILBaseArray mapping) 
+        //    : base (panel,3,X,Y,Z,colors,mapping) {
+        //    m_fillColor = Color.Yellow;
+        //}
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILVertexRenderer.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILVertexRenderer.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/ILVertexRenderer.cs	(revision 9102)
@@ -0,0 +1,52 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Drawing.Interfaces; 
+
+namespace ILNumerics.Drawing.Shapes {
+    public abstract class ILVertexRenderer {
+        public abstract void Draw(ILRenderProperties props, ILShape shape); 
+        public abstract void Draw(ILRenderProperties props, ILShape shape, int[] indices); 
+        public bool UseLight = false; 
+        public bool CloseLines = true; 
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/VertexDefinitions.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/VertexDefinitions.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Shapes/VertexDefinitions.cs	(revision 9102)
@@ -0,0 +1,200 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+#pragma warning disable 1591
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing; 
+using System.Runtime.InteropServices; 
+using ILNumerics.Drawing.Interfaces;
+
+namespace ILNumerics.Drawing.Shapes { 
+
+    [StructLayout(LayoutKind.Sequential)]
+    public struct C4bV3f : IILVertexDefinition {
+        private byte R; 
+        private byte G; 
+        private byte B; 
+        private byte A; 
+        private float X; 
+        private float Y; 
+        private float Z;
+
+        #region IILVertexDefinition Member
+
+        public bool StoresAlpha {
+            get { return true; }
+        }
+
+        public bool StoresColor {
+            get { return true; }
+        }
+
+        public bool StoresNormals {
+            get { return false; }
+        }
+
+        public int VertexSize { 
+            get { return 16; } 
+        }
+        public byte Alpha {
+            get { return A;  }
+            set { A = value; }
+        }
+        public Color Color { 
+            get { 
+                return Color.FromArgb(A,R,G,B);  
+            }
+            set { 
+                R = value.R; 
+                G = value.G; 
+                B = value.B;
+                A = value.A; 
+            }
+        }
+        public ILPoint3Df Position { 
+            get {
+                return new ILPoint3Df(X,Y,Z);    
+            } 
+            set{
+                X = value.X; 
+                Y = value.Y; 
+                Z = value.Z; 
+            }
+        }
+        public ILPoint3Df Normal { 
+            get { throw new NotSupportedException(); }
+            set { throw new NotSupportedException(); }
+        }
+        public float XPosition { 
+            get { return X; }
+            set { X = value; }
+        }
+        public float YPosition { 
+            get { return Y; }
+            set { Y = value; }
+        }
+        public float ZPosition { 
+            get { return Z; }
+            set { Z = value; }
+        }
+        #endregion
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    public struct C4fN3fV3f : IILVertexDefinition {
+        private float R; 
+        private float G; 
+        private float B; 
+        private float A; 
+        private float NX; 
+        private float NY; 
+        private float NZ; 
+        private float X; 
+        private float Y; 
+        private float Z;
+
+        #region IILVertexDefinition Member
+
+        public bool StoresAlpha {
+            get { return true; }
+        }
+
+        public bool StoresColor {
+            get { return true; }
+        }
+
+        public bool StoresNormals {
+            get { return true; }
+        }
+
+        public int VertexSize { 
+            get { return 40; } 
+        }
+        public byte Alpha {
+            get { return (byte)(A*255f);  }
+            set { A = value/255f; }
+        }
+        public Color Color { 
+            get { 
+                return Color.FromArgb((int)(A*255),(int)(R*255),(int)(G*255),(int)(B*255));  
+            }
+            set { 
+                R = value.R/255f; 
+                G = value.G/255f; 
+                B = value.B/255f;
+            }
+        }
+        public ILPoint3Df Position { 
+            get {
+                return new ILPoint3Df(X,Y,Z);    
+            } 
+            set{
+                X = value.X; 
+                Y = value.Y; 
+                Z = value.Z; 
+            }
+        }
+        public ILPoint3Df Normal { 
+            get { 
+                return new ILPoint3Df(NX,NY,NZ); 
+            }
+            set { 
+                NX = value.X; 
+                NY = value.Y; 
+                NZ = value.Z; 
+            }
+        }
+        public float XPosition { 
+            get { return X; }
+            set { X = value; }
+        }
+        public float YPosition { 
+            get { return Y; }
+            set { Y = value; }
+        }
+        public float ZPosition { 
+            get { return Z; }
+            set { Z = value; }
+        }
+        #endregion
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/ILMath_General.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/ILMath_General.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/ILMath_General.cs	(revision 9102)
@@ -0,0 +1,171 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.InteropServices;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Native;
+using ILNumerics.Exceptions; 
+using System.IO; 
+
+namespace ILNumerics {
+
+    /// <summary>
+    /// Main math class, exposes all static math functions. Users should write algorithms in a class derived from <c>ILMath</c>. 
+    /// </summary>
+    public partial class ILMath {
+		/// <summary>
+		/// Concrete interface wrapper class providing the native LAPACK functions
+		/// </summary>
+		/// <remarks>The LAPACK wrapper will be initialized the first time, 
+		/// a call to any static method of ILMath is made. The decision, which 
+		/// native module to load is done by use of native CPUID assembly statements.
+		/// If the current processor does not support those calls or is not recognizable
+		/// by ILNumerics, a generic - not optimized - version of native LAPACK code will
+		/// be used than.</remarks>
+        public static IILLapack Lapack;
+
+        /// <summary>
+        /// Platform specific FFT implementation, <b>internally</b> used to compute fft 
+        /// </summary>
+        public static IILFFT FFTImplementation; 
+        
+        /// <summary>
+        /// Main math class providing static builtin functions
+        /// </summary>
+        static ILMath() {
+            #region initialize proc specific interfaces
+            // for now we rely on the existance of the Intel MKL! 
+            try {
+                ILMKLFFT mkl = new ILMKLFFT();
+                FFTImplementation = mkl;
+                ILLapackMKL10_0 lapack = new ILLapackMKL10_0(); 
+                Lapack = lapack;
+                fft(1.0);
+            } catch (Exception exc) {
+                Console.Write("Error initializing Lapack implementation: " + exc.ToString()); 
+                // MKL missing ... no fallback by now
+            }
+            #endregion 
+            #region initialize machine parameter infos 
+            macharD(ref m_machparDouble.ibeta, ref m_machparDouble.it,ref m_machparDouble.irnd,ref m_machparDouble.ngrd,ref m_machparDouble.machep,ref m_machparDouble.negep,ref m_machparDouble.iexp,ref m_machparDouble.minexp,ref m_machparDouble.maxexp,ref m_machparDouble.eps,ref m_machparDouble.epsneg,ref m_machparDouble.xmin,ref m_machparDouble.xmax); 
+            macharF(ref m_machparSingle.ibeta, ref m_machparSingle.it,ref m_machparSingle.irnd,ref m_machparSingle.ngrd,ref m_machparSingle.machep,ref m_machparSingle.negep,ref m_machparSingle.iexp,ref m_machparSingle.minexp,ref m_machparSingle.maxexp,ref m_machparSingle.eps,ref m_machparSingle.epsneg,ref m_machparSingle.xmin,ref m_machparSingle.xmax); 
+            #endregion
+
+        }
+		/// <summary>
+		/// Minimal size of dimensions, expensive operations will be carried out by native LAPACK libs. 
+		/// </summary>
+		/// <remarks>This property is not yet implemented. All computations (unless for scalars) will be using LAPACK.
+		/// </remarks>
+        internal static readonly int ILAtlasMinimumElementSize = 1;
+
+        #region private helper 
+        private static readonly char TRANS_NONE = 'n';
+
+        private static byte saturateByte(double a) {
+            if (double.IsNaN(a)) return 0;
+            a = Math.Round(a, MidpointRounding.AwayFromZero);
+            if (a > byte.MaxValue) return byte.MaxValue;
+            if (a < byte.MinValue) return byte.MinValue;
+            return (byte)a;
+        }
+        private static sbyte saturateSByte(double a) {
+            if (double.IsNaN(a)) return 0;
+            a = Math.Round(a, MidpointRounding.AwayFromZero);
+            if (a > sbyte.MaxValue) return sbyte.MaxValue;
+            if (a < sbyte.MinValue) return sbyte.MinValue;
+            return (sbyte)a;
+        }
+        private static char saturateChar(double a) {
+            if (double.IsNaN(a)) return (char)0;
+            a = Math.Round(a, MidpointRounding.AwayFromZero);
+            if (a > char.MaxValue) return char.MaxValue;
+            if (a < char.MinValue) return char.MinValue;
+            return (char)a;
+        }
+        private static short saturateInt16(double a) {
+            if (double.IsNaN(a)) return 0;
+            a = Math.Round(a, MidpointRounding.AwayFromZero);
+            if (a > short.MaxValue) return short.MaxValue;
+            if (a < short.MinValue) return short.MinValue;
+            return (short)a;
+        }
+        private static int saturateInt32(double a) {
+            if (double.IsNaN(a)) return 0;
+            a = Math.Round(a, MidpointRounding.AwayFromZero);
+            if (a > int.MaxValue) return int.MaxValue;
+            if (a < int.MinValue) return int.MinValue;
+            return (int)a;
+        }
+        private static long saturateInt64(double a) {
+            if (double.IsNaN(a)) return 0;
+            a = Math.Round(a, MidpointRounding.AwayFromZero);
+            if (a > long.MaxValue) return long.MaxValue;
+            if (a < long.MinValue) return long.MinValue;
+            return (long)a;
+        }
+        private static ushort saturateUInt16(double a) {
+            if (double.IsNaN(a)) return 0;
+            a = Math.Round(a, MidpointRounding.AwayFromZero);
+            if (a > ushort.MaxValue) return ushort.MaxValue;
+            if (a < ushort.MinValue) return ushort.MinValue;
+            return (ushort)a;
+        }
+        private static uint saturateUInt32(double a) {
+            if (double.IsNaN(a)) return 0;
+            a = Math.Round(a, MidpointRounding.AwayFromZero);
+            if (a > uint.MaxValue) return uint.MaxValue;
+            if (a < uint.MinValue) return uint.MinValue;
+            return (uint)a;
+        }
+        private static ulong saturateUInt64(double a) {
+            if (double.IsNaN(a)) return 0;
+            a = Math.Round(a, MidpointRounding.AwayFromZero);
+            if (a > ulong.MaxValue) return ulong.MaxValue;
+            if (a < ulong.MinValue) return ulong.MinValue;
+            return (ulong)a;
+        }
+
+        #endregion
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/Add.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/Add.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/Add.cs	(revision 9102)
@@ -0,0 +1,5130 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using ILNumerics;
+using ILNumerics.Misc;
+using ILNumerics.Storage;
+using ILNumerics.Native;
+using ILNumerics.Exceptions;
+
+
+
+namespace ILNumerics {
+
+    public partial class ILMath {
+
+        private enum BinOpItMode {
+            AAIA,
+            AAIB,
+            AAN,
+            ASI,
+            ASN,
+            SAI,
+            SAN
+        }
+
+        private enum BinOptItExMode {
+            /// <summary>
+            /// vector op. array - not in-place
+            /// </summary>
+            VAN,
+            /// <summary>
+            /// vector op. arra - in-place
+            /// </summary>
+            VAI,
+            /// <summary>
+            /// array op. vector - not in-place
+            /// </summary>
+            AVN,
+            /// <summary>
+            /// array op. vector - in-place
+            /// </summary>
+            AVI
+        }
+         
+
+
+        /// <summary>Add arrays elementwise</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Array with elementwise sum of A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<double>  add(ILInArray<double> A, ILInArray<double> B) {
+            using (ILScope.Enter(A,B)) {
+                int outLen; 
+                BinOpItMode mode; 
+                 double [] retArr;
+                 double [] arrA = A.GetArrayForRead();
+                 double[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size; 
+                    if (B.IsScalar) {
+                        
+                        return new  ILRetArray<double> (new  double [1]{ /*dummy*/ (A.GetValue(0)  + B.GetValue(0))}, A.Size);
+                    } else if (B.IsEmpty) {
+                        return  ILRetArray<double>.empty(outDims); 
+                    } else {
+                        outLen = outDims.NumberOfElements; 
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< double > (outLen);
+                            mode = BinOpItMode.SAN; 
+                        } else {
+                            mode = BinOpItMode.SAI; 
+                        }
+                    }
+                } else {
+                    outDims = A.Size; 
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return  ILRetArray<double>.empty(A.Size);  
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< double > (outLen);
+                            mode = BinOpItMode.ASN; 
+                        } else {
+                            mode = BinOpItMode.ASI; 
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  addEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (A.TryGetStorage4InplaceOp(out retArr)) 
+                            mode  = BinOpItMode.AAIA; 
+                        else if (B.TryGetStorage4InplaceOp(out retArr)) 
+                            mode = BinOpItMode.AAIB; 
+                        else {
+                            retArr = ILMemoryPool.Pool.New< double > (outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<double> retStorage = new ILDenseStorage<double>(retArr, outDims);
+                int i = 0, workerCount = 1; 
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                     double* cp = (double*)range.Item5 + range.Item1;
+                     double scalar;
+                    int j = range.Item2; 
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                            double* bp = ((double*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                                cp[0] =  /*dummy*/ (cp[0]  + bp[0]);
+                                cp[1] =  /*dummy*/ (cp[1]  + bp[1]);
+                                cp[2] =  /*dummy*/ (cp[2]  + bp[2]);
+                                cp[3] =  /*dummy*/ (cp[3]  + bp[3]);
+                                cp[4] =  /*dummy*/ (cp[4]  + bp[4]);
+                                cp[5] =  /*dummy*/ (cp[5]  + bp[5]);
+                                cp[6] =  /*dummy*/ (cp[6]  + bp[6]);
+                                cp[7] =  /*dummy*/ (cp[7]  + bp[7]);
+                                cp[8] =  /*dummy*/ (cp[8]  + bp[8]);
+                                cp[9] =  /*dummy*/ (cp[9]  + bp[9]);
+                                cp[10] =  /*dummy*/ (cp[10]  + bp[10]);
+                                cp[11] =  /*dummy*/ (cp[11]  + bp[11]);
+                                cp[12] =  /*dummy*/ (cp[12]  + bp[12]);
+                                cp[13] =  /*dummy*/ (cp[13]  + bp[13]);
+                                cp[14] =  /*dummy*/ (cp[14]  + bp[14]);
+                                cp[15] =  /*dummy*/ (cp[15]  + bp[15]);
+                                cp[16] =  /*dummy*/ (cp[16]  + bp[16]);
+                                cp[17] =  /*dummy*/ (cp[17]  + bp[17]);
+                                cp[18] =  /*dummy*/ (cp[18]  + bp[18]);
+                                cp[19] =  /*dummy*/ (cp[19]  + bp[19]);
+                                cp[20] =  /*dummy*/ (cp[20]  + bp[20]);
+                                cp += 21; bp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                                
+                                *cp =  /*dummy*/ (*cp  + *bp);
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                            double* ap = ((double*)range.Item3 + range.Item1);
+                            while (j > 20) {
+                                
+                                cp[0] =  /*dummy*/ (ap[0]   + cp[0]);
+                                cp[1] =  /*dummy*/ (ap[1]   + cp[1]);
+                                cp[2] =  /*dummy*/ (ap[2]   + cp[2]);
+                                cp[3] =  /*dummy*/ (ap[3]   + cp[3]);
+                                cp[4] =  /*dummy*/ (ap[4]   + cp[4]);
+                                cp[5] =  /*dummy*/ (ap[5]   + cp[5]);
+                                cp[6] =  /*dummy*/ (ap[6]   + cp[6]);
+                                cp[7] =  /*dummy*/ (ap[7]   + cp[7]);
+                                cp[8] =  /*dummy*/ (ap[8]   + cp[8]);
+                                cp[9] =  /*dummy*/ (ap[9]   + cp[9]);
+                                cp[10] =  /*dummy*/ (ap[10]  + cp[10]);
+                                cp[11] =  /*dummy*/ (ap[11]  + cp[11]);
+                                cp[12] =  /*dummy*/ (ap[12]  + cp[12]);
+                                cp[13] =  /*dummy*/ (ap[13]  + cp[13]);
+                                cp[14] =  /*dummy*/ (ap[14]  + cp[14]);
+                                cp[15] =  /*dummy*/ (ap[15]  + cp[15]);
+                                cp[16] =  /*dummy*/ (ap[16]  + cp[16]);
+                                cp[17] =  /*dummy*/ (ap[17]  + cp[17]);
+                                cp[18] =  /*dummy*/ (ap[18]  + cp[18]);
+                                cp[19] =  /*dummy*/ (ap[19]  + cp[19]);
+                                cp[20] =  /*dummy*/ (ap[20]  + cp[20]);
+                                ap += 21; cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                                
+                                *cp =  /*dummy*/ (*ap  + *cp);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((double*)range.Item3 + range.Item1);
+                            bp = ((double*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                                
+                                cp[0] =  /*dummy*/ (ap[0]   + bp[0]);
+                                cp[1] =  /*dummy*/ (ap[1]   + bp[1]);
+                                cp[2] =  /*dummy*/ (ap[2]   + bp[2]);
+                                cp[3] =  /*dummy*/ (ap[3]   + bp[3]);
+                                cp[4] =  /*dummy*/ (ap[4]   + bp[4]);
+                                cp[5] =  /*dummy*/ (ap[5]   + bp[5]);
+                                cp[6] =  /*dummy*/ (ap[6]   + bp[6]);
+                                cp[7] =  /*dummy*/ (ap[7]   + bp[7]);
+                                cp[8] =  /*dummy*/ (ap[8]   + bp[8]);
+                                cp[9] =  /*dummy*/ (ap[9]   + bp[9]);
+                                cp[10] =  /*dummy*/ (ap[10]  + bp[10]);
+                                cp[11] =  /*dummy*/ (ap[11]  + bp[11]);
+                                cp[12] =  /*dummy*/ (ap[12]  + bp[12]);
+                                cp[13] =  /*dummy*/ (ap[13]  + bp[13]);
+                                cp[14] =  /*dummy*/ (ap[14]  + bp[14]);
+                                cp[15] =  /*dummy*/ (ap[15]  + bp[15]);
+                                cp[16] =  /*dummy*/ (ap[16]  + bp[16]);
+                                cp[17] =  /*dummy*/ (ap[17]  + bp[17]);
+                                cp[18] =  /*dummy*/ (ap[18]  + bp[18]);
+                                cp[19] =  /*dummy*/ (ap[19]  + bp[19]);
+                                cp[20] =  /*dummy*/ (ap[20]  + bp[20]);
+                                ap+=21; bp+=21; cp+=21; j-=21;
+                            }
+                            while (j --> 0) {
+                                
+                                *cp =  /*dummy*/ (*ap  + *bp);
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((double*)range.Item4);
+                            while (j > 20) {
+                                
+                                cp[0] =  /*dummy*/ (cp[0]   + scalar);
+                                cp[1] =  /*dummy*/ (cp[1]   + scalar);
+                                cp[2] =  /*dummy*/ (cp[2]   + scalar);
+                                cp[3] =  /*dummy*/ (cp[3]   + scalar);
+                                cp[4] =  /*dummy*/ (cp[4]   + scalar);
+                                cp[5] =  /*dummy*/ (cp[5]   + scalar);
+                                cp[6] =  /*dummy*/ (cp[6]   + scalar);
+                                cp[7] =  /*dummy*/ (cp[7]   + scalar);
+                                cp[8] =  /*dummy*/ (cp[8]   + scalar);
+                                cp[9] =  /*dummy*/ (cp[9]   + scalar);
+                                cp[10] =  /*dummy*/ (cp[10]  + scalar);
+                                cp[11] =  /*dummy*/ (cp[11]  + scalar);
+                                cp[12] =  /*dummy*/ (cp[12]  + scalar);
+                                cp[13] =  /*dummy*/ (cp[13]  + scalar);
+                                cp[14] =  /*dummy*/ (cp[14]  + scalar);
+                                cp[15] =  /*dummy*/ (cp[15]  + scalar);
+                                cp[16] =  /*dummy*/ (cp[16]  + scalar);
+                                cp[17] =  /*dummy*/ (cp[17]  + scalar);
+                                cp[18] =  /*dummy*/ (cp[18]  + scalar);
+                                cp[19] =  /*dummy*/ (cp[19]  + scalar);
+                                cp[20] =  /*dummy*/ (cp[20]  + scalar);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                                
+                                *cp =  /*dummy*/ (*cp  + scalar);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((double*)range.Item3 + range.Item1);
+                            scalar = *((double*)range.Item4);
+                            while (j > 20) {
+                                
+                                cp[0] =  /*dummy*/ (ap[0]   + scalar);
+                                cp[1] =  /*dummy*/ (ap[1]   + scalar);
+                                cp[2] =  /*dummy*/ (ap[2]   + scalar);
+                                cp[3] =  /*dummy*/ (ap[3]   + scalar);
+                                cp[4] =  /*dummy*/ (ap[4]   + scalar);
+                                cp[5] =  /*dummy*/ (ap[5]   + scalar);
+                                cp[6] =  /*dummy*/ (ap[6]   + scalar);
+                                cp[7] =  /*dummy*/ (ap[7]   + scalar);
+                                cp[8] =  /*dummy*/ (ap[8]   + scalar);
+                                cp[9] =  /*dummy*/ (ap[9]   + scalar);
+                                cp[10] =  /*dummy*/ (ap[10]  + scalar);
+                                cp[11] =  /*dummy*/ (ap[11]  + scalar);
+                                cp[12] =  /*dummy*/ (ap[12]  + scalar);
+                                cp[13] =  /*dummy*/ (ap[13]  + scalar);
+                                cp[14] =  /*dummy*/ (ap[14]  + scalar);
+                                cp[15] =  /*dummy*/ (ap[15]  + scalar);
+                                cp[16] =  /*dummy*/ (ap[16]  + scalar);
+                                cp[17] =  /*dummy*/ (ap[17]  + scalar);
+                                cp[18] =  /*dummy*/ (ap[18]  + scalar);
+                                cp[19] =  /*dummy*/ (ap[19]  + scalar);
+                                cp[20] =  /*dummy*/ (ap[20]  + scalar);
+                                ap+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                                
+                                *cp =  /*dummy*/ (*ap  + scalar);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((double*)range.Item3);
+                            while (j > 20) {
+                                
+                                cp[0] =  /*dummy*/ (scalar  + cp[0]);
+                                cp[1] =  /*dummy*/ (scalar  + cp[1]);
+                                cp[2] =  /*dummy*/ (scalar  + cp[2]);
+                                cp[3] =  /*dummy*/ (scalar  + cp[3]);
+                                cp[4] =  /*dummy*/ (scalar  + cp[4]);
+                                cp[5] =  /*dummy*/ (scalar  + cp[5]);
+                                cp[6] =  /*dummy*/ (scalar  + cp[6]);
+                                cp[7] =  /*dummy*/ (scalar  + cp[7]);
+                                cp[8] =  /*dummy*/ (scalar  + cp[8]);
+                                cp[9] =  /*dummy*/ (scalar  + cp[9]);
+                                cp[10] =  /*dummy*/ (scalar  + cp[10]);
+                                cp[11] =  /*dummy*/ (scalar  + cp[11]);
+                                cp[12] =  /*dummy*/ (scalar  + cp[12]);
+                                cp[13] =  /*dummy*/ (scalar  + cp[13]);
+                                cp[14] =  /*dummy*/ (scalar  + cp[14]);
+                                cp[15] =  /*dummy*/ (scalar  + cp[15]);
+                                cp[16] =  /*dummy*/ (scalar  + cp[16]);
+                                cp[17] =  /*dummy*/ (scalar  + cp[17]);
+                                cp[18] =  /*dummy*/ (scalar  + cp[18]);
+                                cp[19] =  /*dummy*/ (scalar  + cp[19]);
+                                cp[20] =  /*dummy*/ (scalar  + cp[20]);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                                
+                                *cp =  /*dummy*/ (scalar  + *cp);
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((double*)range.Item3);
+                            bp = ((double*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                                
+                                cp[0] =  /*dummy*/ (scalar  + bp[0]);
+                                cp[1] =  /*dummy*/ (scalar  + bp[1]);
+                                cp[2] =  /*dummy*/ (scalar  + bp[2]);
+                                cp[3] =  /*dummy*/ (scalar  + bp[3]);
+                                cp[4] =  /*dummy*/ (scalar  + bp[4]);
+                                cp[5] =  /*dummy*/ (scalar  + bp[5]);
+                                cp[6] =  /*dummy*/ (scalar  + bp[6]);
+                                cp[7] =  /*dummy*/ (scalar  + bp[7]);
+                                cp[8] =  /*dummy*/ (scalar  + bp[8]);
+                                cp[9] =  /*dummy*/ (scalar  + bp[9]);
+                                cp[10] =  /*dummy*/ (scalar  + bp[10]);
+                                cp[11] =  /*dummy*/ (scalar  + bp[11]);
+                                cp[12] =  /*dummy*/ (scalar  + bp[12]);
+                                cp[13] =  /*dummy*/ (scalar  + bp[13]);
+                                cp[14] =  /*dummy*/ (scalar  + bp[14]);
+                                cp[15] =  /*dummy*/ (scalar  + bp[15]);
+                                cp[16] =  /*dummy*/ (scalar  + bp[16]);
+                                cp[17] =  /*dummy*/ (scalar  + bp[17]);
+                                cp[18] =  /*dummy*/ (scalar  + bp[18]);
+                                cp[19] =  /*dummy*/ (scalar  + bp[19]);
+                                cp[20] =  /*dummy*/ (scalar  + bp[20]);
+                                bp+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                                
+                                *cp =  /*dummy*/ (scalar  + *bp);
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work 
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                
+                fixed ( double* arrAP = arrA)
+                fixed ( double* arrBP = arrB)
+                fixed ( double* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range 
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new  ILRetArray< double>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<double>  addEx(ILInArray<double> A, ILInArray<double> B) {
+            //using (ILScope.Enter(A, B)) { we cannot start a new scope here, since this would prevent A and B to be used implace if applicable
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<double>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<double>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<double>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                dim = -(dim - 1);  // 0 -> 1, 1 -> 0
+                #endregion
+
+                #region parameter preparation
+                
+                double[] retArr;
+                
+                double[] arrA = A.GetArrayForRead();
+                
+                double[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int workItemMultiplierLenA;
+                int workItemMultiplierLenB;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<double>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    workItemMultiplierLenB = outDims[0]; 
+                    workItemMultiplierLenA = dim;  // 0 for column, 1 for row vector
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<double>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    workItemMultiplierLenB = dim;  // 0 for column, 1 for row vector
+                    workItemMultiplierLenA = outDims[0]; 
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one singleton dimension in either A or B");
+                }
+                int itLen = outDims[0]; // (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<double> retStorage = new ILDenseStorage<double>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, IntPtr, IntPtr, IntPtr>)data;
+                    
+                    double* ap;
+                    
+                    double* bp;
+                    
+                    double* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            if (dim == 0) {
+                                bp = (double*)range.Item3;
+                                cp = (double*)range.Item4; 
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (double*)range.Item2;
+                                    int l = itLen; 
+                                    while (l > 10) {
+                                        cp[0] =  /*dummy*/ (ap[0]  + bp[0]);
+                                        cp[1] =  /*dummy*/ (ap[1]  + bp[1]);
+                                        cp[2] =  /*dummy*/ (ap[2]  + bp[2]);
+                                        cp[3] =  /*dummy*/ (ap[3]  + bp[3]);
+                                        cp[4] =  /*dummy*/ (ap[4]  + bp[4]);
+                                        cp[5] =  /*dummy*/ (ap[5]  + bp[5]);
+                                        cp[6] =  /*dummy*/ (ap[6]  + bp[6]);
+                                        cp[7] =  /*dummy*/ (ap[7]  + bp[7]);
+                                        cp[8] =  /*dummy*/ (ap[8]  + bp[8]);
+                                        cp[9] =  /*dummy*/ (ap[9]  + bp[9]);
+                                        cp[10] =  /*dummy*/ (ap[10]  + bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =  /*dummy*/ (*ap++  + *bp++);
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                ap = (double*)range.Item2;
+                                bp = (double*)range.Item3;
+                                cp = (double*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    double val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  /*dummy*/ (val  + bp[0]);
+                                        cp[1] =  /*dummy*/ (val  + bp[1]);
+                                        cp[2] =  /*dummy*/ (val  + bp[2]);
+                                        cp[3] =  /*dummy*/ (val  + bp[3]);
+                                        cp[4] =  /*dummy*/ (val  + bp[4]);
+                                        cp[5] =  /*dummy*/ (val  + bp[5]);
+                                        cp[6] =  /*dummy*/ (val  + bp[6]);
+                                        cp[7] =  /*dummy*/ (val  + bp[7]);
+                                        cp[8] =  /*dummy*/ (val  + bp[8]);
+                                        cp[9] =  /*dummy*/ (val  + bp[9]);
+                                        cp[10] =  /*dummy*/ (val  + bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11; 
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =  /*dummy*/ (val  + *bp++);
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            if (dim == 0) {
+                                cp = (double*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (double*)range.Item2;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  /*dummy*/ (ap[0]  + cp[0]);
+                                        cp[1] =  /*dummy*/ (ap[1]  + cp[1]);
+                                        cp[2] =  /*dummy*/ (ap[2]  + cp[2]);
+                                        cp[3] =  /*dummy*/ (ap[3]  + cp[3]);
+                                        cp[4] =  /*dummy*/ (ap[4]  + cp[4]);
+                                        cp[5] =  /*dummy*/ (ap[5]  + cp[5]);
+                                        cp[6] =  /*dummy*/ (ap[6]  + cp[6]);
+                                        cp[7] =  /*dummy*/ (ap[7]  + cp[7]);
+                                        cp[8] =  /*dummy*/ (ap[8]  + cp[8]);
+                                        cp[9] =  /*dummy*/ (ap[9]  + cp[9]);
+                                        cp[10] =  /*dummy*/ (ap[10]  + cp[10]);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  /*dummy*/ (*ap++  + *cp);
+                                        cp++; 
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                cp = (double*)range.Item4;
+                                ap = (double*)range.Item2;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    
+                                    double val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  /*dummy*/ (val  + cp[0]);
+                                        cp[1] =  /*dummy*/ (val  + cp[1]);
+                                        cp[2] =  /*dummy*/ (val  + cp[2]);
+                                        cp[3] =  /*dummy*/ (val  + cp[3]);
+                                        cp[4] =  /*dummy*/ (val  + cp[4]);
+                                        cp[5] =  /*dummy*/ (val  + cp[5]);
+                                        cp[6] =  /*dummy*/ (val  + cp[6]);
+                                        cp[7] =  /*dummy*/ (val  + cp[7]);
+                                        cp[8] =  /*dummy*/ (val  + cp[8]);
+                                        cp[9] =  /*dummy*/ (val  + cp[9]);
+                                        cp[10] =  /*dummy*/ (val  + cp[10]);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  /*dummy*/ (val  + *cp);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            if (dim == 0) {
+                                ap = (double*)range.Item2;
+                                cp = (double*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (double*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  /*dummy*/ (ap[0]  + bp[0]);
+                                        cp[1] =  /*dummy*/ (ap[1]  + bp[1]);
+                                        cp[2] =  /*dummy*/ (ap[2]  + bp[2]);
+                                        cp[3] =  /*dummy*/ (ap[3]  + bp[3]);
+                                        cp[4] =  /*dummy*/ (ap[4]  + bp[4]);
+                                        cp[5] =  /*dummy*/ (ap[5]  + bp[5]);
+                                        cp[6] =  /*dummy*/ (ap[6]  + bp[6]);
+                                        cp[7] =  /*dummy*/ (ap[7]  + bp[7]);
+                                        cp[8] =  /*dummy*/ (ap[8]  + bp[8]);
+                                        cp[9] =  /*dummy*/ (ap[9]  + bp[9]);
+                                        cp[10] =  /*dummy*/ (ap[10]  + bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  /*dummy*/ (*ap  + *bp);
+                                        ap++;
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                ap = (double*)range.Item2;
+                                bp = (double*)range.Item3;
+                                cp = (double*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    double val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  /*dummy*/ (ap[0]  + val);
+                                        cp[1] =  /*dummy*/ (ap[1]  + val);
+                                        cp[2] =  /*dummy*/ (ap[2]  + val);
+                                        cp[3] =  /*dummy*/ (ap[3]  + val);
+                                        cp[4] =  /*dummy*/ (ap[4]  + val);
+                                        cp[5] =  /*dummy*/ (ap[5]  + val);
+                                        cp[6] =  /*dummy*/ (ap[6]  + val);
+                                        cp[7] =  /*dummy*/ (ap[7]  + val);
+                                        cp[8] =  /*dummy*/ (ap[8]  + val);
+                                        cp[9] =  /*dummy*/ (ap[9]  + val);
+                                        cp[10] =  /*dummy*/ (ap[10]  + val);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  /*dummy*/ (*ap  + val);
+                                        ap++;
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            if (dim == 0) {
+                                cp = (double*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (double*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  /*dummy*/ (cp[0]  + bp[0]);
+                                        cp[1] =  /*dummy*/ (cp[1]  + bp[1]);
+                                        cp[2] =  /*dummy*/ (cp[2]  + bp[2]);
+                                        cp[3] =  /*dummy*/ (cp[3]  + bp[3]);
+                                        cp[4] =  /*dummy*/ (cp[4]  + bp[4]);
+                                        cp[5] =  /*dummy*/ (cp[5]  + bp[5]);
+                                        cp[6] =  /*dummy*/ (cp[6]  + bp[6]);
+                                        cp[7] =  /*dummy*/ (cp[7]  + bp[7]);
+                                        cp[8] =  /*dummy*/ (cp[8]  + bp[8]);
+                                        cp[9] =  /*dummy*/ (cp[9]  + bp[9]);
+                                        cp[10] =  /*dummy*/ (cp[10]  + bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  /*dummy*/ (*cp  + *bp);
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                bp = (double*)range.Item3;
+                                cp = (double*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    
+                                    double val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  /*dummy*/ (cp[0]  + val);
+                                        cp[1] =  /*dummy*/ (cp[1]  + val);
+                                        cp[2] =  /*dummy*/ (cp[2]  + val);
+                                        cp[3] =  /*dummy*/ (cp[3]  + val);
+                                        cp[4] =  /*dummy*/ (cp[4]  + val);
+                                        cp[5] =  /*dummy*/ (cp[5]  + val);
+                                        cp[6] =  /*dummy*/ (cp[6]  + val);
+                                        cp[7] =  /*dummy*/ (cp[7]  + val);
+                                        cp[8] =  /*dummy*/ (cp[8]  + val);
+                                        cp[9] =  /*dummy*/ (cp[9]  + val);
+                                        cp[10] =  /*dummy*/ (cp[10]  + val);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l --> 0) {
+                                        *cp =  /*dummy*/ (*cp  + val);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outDims.NumberOfElements >= Settings.s_minParallelElement1Count
+                    && outDims[1] > 1) {
+                        if (outDims[1] > workItemCount) {
+                        workItemLength = outDims[1] / workItemCount;
+                    } else {
+                        workItemLength = outDims[1] / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outDims[1];
+                    workItemCount = 1;
+                }
+
+                fixed ( double* arrAP = arrA)
+                fixed ( double* arrBP = arrB)
+                fixed ( double* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, IntPtr, IntPtr, IntPtr> range = new Tuple<int, IntPtr, IntPtr, IntPtr>
+                               (workItemLength
+                               , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                               , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                               , (IntPtr)(retArrP + i * outDims[0] * workItemLength)); 
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, IntPtr, IntPtr, IntPtr>
+                                (outDims[1] - i * workItemLength
+                                , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                                , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                                , (IntPtr)(retArrP + i * outDims[0] * workItemLength)));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<double>(retStorage);
+            //}  // no scopes here! it disables implace operations
+        }
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>Add arrays elementwise</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Array with elementwise sum of A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<Int64>  add(ILInArray<Int64> A, ILInArray<Int64> B) {
+            using (ILScope.Enter(A,B)) {
+                int outLen; 
+                BinOpItMode mode; 
+                Int64 [] retArr;
+                Int64 [] arrA = A.GetArrayForRead();
+                Int64[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size; 
+                    if (B.IsScalar) {
+                       
+                        return new  ILRetArray<Int64> (new  Int64 [1]{ saturateInt64 (A.GetValue(0)  + (double) B.GetValue(0))}, A.Size);
+                    } else if (B.IsEmpty) {
+                        return  ILRetArray<Int64>.empty(outDims); 
+                    } else {
+                        outLen = outDims.NumberOfElements; 
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< Int64 > (outLen);
+                            mode = BinOpItMode.SAN; 
+                        } else {
+                            mode = BinOpItMode.SAI; 
+                        }
+                    }
+                } else {
+                    outDims = A.Size; 
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return  ILRetArray<Int64>.empty(A.Size);  
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< Int64 > (outLen);
+                            mode = BinOpItMode.ASN; 
+                        } else {
+                            mode = BinOpItMode.ASI; 
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  addEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (A.TryGetStorage4InplaceOp(out retArr)) 
+                            mode  = BinOpItMode.AAIA; 
+                        else if (B.TryGetStorage4InplaceOp(out retArr)) 
+                            mode = BinOpItMode.AAIB; 
+                        else {
+                            retArr = ILMemoryPool.Pool.New< Int64 > (outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<Int64> retStorage = new ILDenseStorage<Int64>(retArr, outDims);
+                int i = 0, workerCount = 1; 
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    Int64* cp = (Int64*)range.Item5 + range.Item1;
+                    Int64 scalar;
+                    int j = range.Item2; 
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           Int64* bp = ((Int64*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                                cp[0] =  saturateInt64 (cp[0]  + (double) bp[0]);
+                                cp[1] =  saturateInt64 (cp[1]  + (double) bp[1]);
+                                cp[2] =  saturateInt64 (cp[2]  + (double) bp[2]);
+                                cp[3] =  saturateInt64 (cp[3]  + (double) bp[3]);
+                                cp[4] =  saturateInt64 (cp[4]  + (double) bp[4]);
+                                cp[5] =  saturateInt64 (cp[5]  + (double) bp[5]);
+                                cp[6] =  saturateInt64 (cp[6]  + (double) bp[6]);
+                                cp[7] =  saturateInt64 (cp[7]  + (double) bp[7]);
+                                cp[8] =  saturateInt64 (cp[8]  + (double) bp[8]);
+                                cp[9] =  saturateInt64 (cp[9]  + (double) bp[9]);
+                                cp[10] =  saturateInt64 (cp[10]  + (double) bp[10]);
+                                cp[11] =  saturateInt64 (cp[11]  + (double) bp[11]);
+                                cp[12] =  saturateInt64 (cp[12]  + (double) bp[12]);
+                                cp[13] =  saturateInt64 (cp[13]  + (double) bp[13]);
+                                cp[14] =  saturateInt64 (cp[14]  + (double) bp[14]);
+                                cp[15] =  saturateInt64 (cp[15]  + (double) bp[15]);
+                                cp[16] =  saturateInt64 (cp[16]  + (double) bp[16]);
+                                cp[17] =  saturateInt64 (cp[17]  + (double) bp[17]);
+                                cp[18] =  saturateInt64 (cp[18]  + (double) bp[18]);
+                                cp[19] =  saturateInt64 (cp[19]  + (double) bp[19]);
+                                cp[20] =  saturateInt64 (cp[20]  + (double) bp[20]);
+                                cp += 21; bp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt64 (*cp  + (double) *bp);
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           Int64* ap = ((Int64*)range.Item3 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt64 (ap[0]  + (double) cp[0]);
+                                cp[1] =  saturateInt64 (ap[1]  + (double) cp[1]);
+                                cp[2] =  saturateInt64 (ap[2]  + (double) cp[2]);
+                                cp[3] =  saturateInt64 (ap[3]  + (double) cp[3]);
+                                cp[4] =  saturateInt64 (ap[4]  + (double) cp[4]);
+                                cp[5] =  saturateInt64 (ap[5]  + (double) cp[5]);
+                                cp[6] =  saturateInt64 (ap[6]  + (double) cp[6]);
+                                cp[7] =  saturateInt64 (ap[7]  + (double) cp[7]);
+                                cp[8] =  saturateInt64 (ap[8]  + (double) cp[8]);
+                                cp[9] =  saturateInt64 (ap[9]  + (double) cp[9]);
+                                cp[10] =  saturateInt64 (ap[10]  + (double) cp[10]);
+                                cp[11] =  saturateInt64 (ap[11]  + (double) cp[11]);
+                                cp[12] =  saturateInt64 (ap[12]  + (double) cp[12]);
+                                cp[13] =  saturateInt64 (ap[13]  + (double) cp[13]);
+                                cp[14] =  saturateInt64 (ap[14]  + (double) cp[14]);
+                                cp[15] =  saturateInt64 (ap[15]  + (double) cp[15]);
+                                cp[16] =  saturateInt64 (ap[16]  + (double) cp[16]);
+                                cp[17] =  saturateInt64 (ap[17]  + (double) cp[17]);
+                                cp[18] =  saturateInt64 (ap[18]  + (double) cp[18]);
+                                cp[19] =  saturateInt64 (ap[19]  + (double) cp[19]);
+                                cp[20] =  saturateInt64 (ap[20]  + (double) cp[20]);
+                                ap += 21; cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt64 (*ap  + (double) *cp);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((Int64*)range.Item3 + range.Item1);
+                            bp = ((Int64*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt64 (ap[0]  + (double) bp[0]);
+                                cp[1] =  saturateInt64 (ap[1]  + (double) bp[1]);
+                                cp[2] =  saturateInt64 (ap[2]  + (double) bp[2]);
+                                cp[3] =  saturateInt64 (ap[3]  + (double) bp[3]);
+                                cp[4] =  saturateInt64 (ap[4]  + (double) bp[4]);
+                                cp[5] =  saturateInt64 (ap[5]  + (double) bp[5]);
+                                cp[6] =  saturateInt64 (ap[6]  + (double) bp[6]);
+                                cp[7] =  saturateInt64 (ap[7]  + (double) bp[7]);
+                                cp[8] =  saturateInt64 (ap[8]  + (double) bp[8]);
+                                cp[9] =  saturateInt64 (ap[9]  + (double) bp[9]);
+                                cp[10] =  saturateInt64 (ap[10]  + (double) bp[10]);
+                                cp[11] =  saturateInt64 (ap[11]  + (double) bp[11]);
+                                cp[12] =  saturateInt64 (ap[12]  + (double) bp[12]);
+                                cp[13] =  saturateInt64 (ap[13]  + (double) bp[13]);
+                                cp[14] =  saturateInt64 (ap[14]  + (double) bp[14]);
+                                cp[15] =  saturateInt64 (ap[15]  + (double) bp[15]);
+                                cp[16] =  saturateInt64 (ap[16]  + (double) bp[16]);
+                                cp[17] =  saturateInt64 (ap[17]  + (double) bp[17]);
+                                cp[18] =  saturateInt64 (ap[18]  + (double) bp[18]);
+                                cp[19] =  saturateInt64 (ap[19]  + (double) bp[19]);
+                                cp[20] =  saturateInt64 (ap[20]  + (double) bp[20]);
+                                ap+=21; bp+=21; cp+=21; j-=21;
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt64 (*ap  + (double) *bp);
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((Int64*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt64 (cp[0]  + (double) scalar);
+                                cp[1] =  saturateInt64 (cp[1]  + (double) scalar);
+                                cp[2] =  saturateInt64 (cp[2]  + (double) scalar);
+                                cp[3] =  saturateInt64 (cp[3]  + (double) scalar);
+                                cp[4] =  saturateInt64 (cp[4]  + (double) scalar);
+                                cp[5] =  saturateInt64 (cp[5]  + (double) scalar);
+                                cp[6] =  saturateInt64 (cp[6]  + (double) scalar);
+                                cp[7] =  saturateInt64 (cp[7]  + (double) scalar);
+                                cp[8] =  saturateInt64 (cp[8]  + (double) scalar);
+                                cp[9] =  saturateInt64 (cp[9]  + (double) scalar);
+                                cp[10] =  saturateInt64 (cp[10]  + (double) scalar);
+                                cp[11] =  saturateInt64 (cp[11]  + (double) scalar);
+                                cp[12] =  saturateInt64 (cp[12]  + (double) scalar);
+                                cp[13] =  saturateInt64 (cp[13]  + (double) scalar);
+                                cp[14] =  saturateInt64 (cp[14]  + (double) scalar);
+                                cp[15] =  saturateInt64 (cp[15]  + (double) scalar);
+                                cp[16] =  saturateInt64 (cp[16]  + (double) scalar);
+                                cp[17] =  saturateInt64 (cp[17]  + (double) scalar);
+                                cp[18] =  saturateInt64 (cp[18]  + (double) scalar);
+                                cp[19] =  saturateInt64 (cp[19]  + (double) scalar);
+                                cp[20] =  saturateInt64 (cp[20]  + (double) scalar);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt64 (*cp  + (double) scalar);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((Int64*)range.Item3 + range.Item1);
+                            scalar = *((Int64*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt64 (ap[0]  + (double) scalar);
+                                cp[1] =  saturateInt64 (ap[1]  + (double) scalar);
+                                cp[2] =  saturateInt64 (ap[2]  + (double) scalar);
+                                cp[3] =  saturateInt64 (ap[3]  + (double) scalar);
+                                cp[4] =  saturateInt64 (ap[4]  + (double) scalar);
+                                cp[5] =  saturateInt64 (ap[5]  + (double) scalar);
+                                cp[6] =  saturateInt64 (ap[6]  + (double) scalar);
+                                cp[7] =  saturateInt64 (ap[7]  + (double) scalar);
+                                cp[8] =  saturateInt64 (ap[8]  + (double) scalar);
+                                cp[9] =  saturateInt64 (ap[9]  + (double) scalar);
+                                cp[10] =  saturateInt64 (ap[10]  + (double) scalar);
+                                cp[11] =  saturateInt64 (ap[11]  + (double) scalar);
+                                cp[12] =  saturateInt64 (ap[12]  + (double) scalar);
+                                cp[13] =  saturateInt64 (ap[13]  + (double) scalar);
+                                cp[14] =  saturateInt64 (ap[14]  + (double) scalar);
+                                cp[15] =  saturateInt64 (ap[15]  + (double) scalar);
+                                cp[16] =  saturateInt64 (ap[16]  + (double) scalar);
+                                cp[17] =  saturateInt64 (ap[17]  + (double) scalar);
+                                cp[18] =  saturateInt64 (ap[18]  + (double) scalar);
+                                cp[19] =  saturateInt64 (ap[19]  + (double) scalar);
+                                cp[20] =  saturateInt64 (ap[20]  + (double) scalar);
+                                ap+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt64 (*ap  + (double) scalar);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((Int64*)range.Item3);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt64 (scalar  + (double) cp[0]);
+                                cp[1] =  saturateInt64 (scalar  + (double) cp[1]);
+                                cp[2] =  saturateInt64 (scalar  + (double) cp[2]);
+                                cp[3] =  saturateInt64 (scalar  + (double) cp[3]);
+                                cp[4] =  saturateInt64 (scalar  + (double) cp[4]);
+                                cp[5] =  saturateInt64 (scalar  + (double) cp[5]);
+                                cp[6] =  saturateInt64 (scalar  + (double) cp[6]);
+                                cp[7] =  saturateInt64 (scalar  + (double) cp[7]);
+                                cp[8] =  saturateInt64 (scalar  + (double) cp[8]);
+                                cp[9] =  saturateInt64 (scalar  + (double) cp[9]);
+                                cp[10] =  saturateInt64 (scalar  + (double) cp[10]);
+                                cp[11] =  saturateInt64 (scalar  + (double) cp[11]);
+                                cp[12] =  saturateInt64 (scalar  + (double) cp[12]);
+                                cp[13] =  saturateInt64 (scalar  + (double) cp[13]);
+                                cp[14] =  saturateInt64 (scalar  + (double) cp[14]);
+                                cp[15] =  saturateInt64 (scalar  + (double) cp[15]);
+                                cp[16] =  saturateInt64 (scalar  + (double) cp[16]);
+                                cp[17] =  saturateInt64 (scalar  + (double) cp[17]);
+                                cp[18] =  saturateInt64 (scalar  + (double) cp[18]);
+                                cp[19] =  saturateInt64 (scalar  + (double) cp[19]);
+                                cp[20] =  saturateInt64 (scalar  + (double) cp[20]);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt64 (scalar  + (double) *cp);
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((Int64*)range.Item3);
+                            bp = ((Int64*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt64 (scalar  + (double) bp[0]);
+                                cp[1] =  saturateInt64 (scalar  + (double) bp[1]);
+                                cp[2] =  saturateInt64 (scalar  + (double) bp[2]);
+                                cp[3] =  saturateInt64 (scalar  + (double) bp[3]);
+                                cp[4] =  saturateInt64 (scalar  + (double) bp[4]);
+                                cp[5] =  saturateInt64 (scalar  + (double) bp[5]);
+                                cp[6] =  saturateInt64 (scalar  + (double) bp[6]);
+                                cp[7] =  saturateInt64 (scalar  + (double) bp[7]);
+                                cp[8] =  saturateInt64 (scalar  + (double) bp[8]);
+                                cp[9] =  saturateInt64 (scalar  + (double) bp[9]);
+                                cp[10] =  saturateInt64 (scalar  + (double) bp[10]);
+                                cp[11] =  saturateInt64 (scalar  + (double) bp[11]);
+                                cp[12] =  saturateInt64 (scalar  + (double) bp[12]);
+                                cp[13] =  saturateInt64 (scalar  + (double) bp[13]);
+                                cp[14] =  saturateInt64 (scalar  + (double) bp[14]);
+                                cp[15] =  saturateInt64 (scalar  + (double) bp[15]);
+                                cp[16] =  saturateInt64 (scalar  + (double) bp[16]);
+                                cp[17] =  saturateInt64 (scalar  + (double) bp[17]);
+                                cp[18] =  saturateInt64 (scalar  + (double) bp[18]);
+                                cp[19] =  saturateInt64 (scalar  + (double) bp[19]);
+                                cp[20] =  saturateInt64 (scalar  + (double) bp[20]);
+                                bp+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt64 (scalar  + (double) *bp);
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work 
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                
+                fixed ( Int64* arrAP = arrA)
+                fixed ( Int64* arrBP = arrB)
+                fixed ( Int64* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range 
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new  ILRetArray< Int64>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<Int64>  addEx(ILInArray<Int64> A, ILInArray<Int64> B) {
+            //using (ILScope.Enter(A, B)) { we cannot start a new scope here, since this would prevent A and B to be used implace if applicable
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<Int64>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<Int64>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<Int64>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                dim = -(dim - 1);  // 0 -> 1, 1 -> 0
+                #endregion
+
+                #region parameter preparation
+               
+                Int64[] retArr;
+               
+                Int64[] arrA = A.GetArrayForRead();
+               
+                Int64[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int workItemMultiplierLenA;
+                int workItemMultiplierLenB;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<Int64>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    workItemMultiplierLenB = outDims[0]; 
+                    workItemMultiplierLenA = dim;  // 0 for column, 1 for row vector
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<Int64>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    workItemMultiplierLenB = dim;  // 0 for column, 1 for row vector
+                    workItemMultiplierLenA = outDims[0]; 
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one singleton dimension in either A or B");
+                }
+                int itLen = outDims[0]; // (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<Int64> retStorage = new ILDenseStorage<Int64>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    Int64* ap;
+                   
+                    Int64* bp;
+                   
+                    Int64* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            if (dim == 0) {
+                                bp = (Int64*)range.Item3;
+                                cp = (Int64*)range.Item4; 
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (Int64*)range.Item2;
+                                    int l = itLen; 
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt64 (ap[0]  + (double) bp[0]);
+                                        cp[1] =  saturateInt64 (ap[1]  + (double) bp[1]);
+                                        cp[2] =  saturateInt64 (ap[2]  + (double) bp[2]);
+                                        cp[3] =  saturateInt64 (ap[3]  + (double) bp[3]);
+                                        cp[4] =  saturateInt64 (ap[4]  + (double) bp[4]);
+                                        cp[5] =  saturateInt64 (ap[5]  + (double) bp[5]);
+                                        cp[6] =  saturateInt64 (ap[6]  + (double) bp[6]);
+                                        cp[7] =  saturateInt64 (ap[7]  + (double) bp[7]);
+                                        cp[8] =  saturateInt64 (ap[8]  + (double) bp[8]);
+                                        cp[9] =  saturateInt64 (ap[9]  + (double) bp[9]);
+                                        cp[10] =  saturateInt64 (ap[10]  + (double) bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =  saturateInt64 (*ap++  + (double) *bp++);
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                ap = (Int64*)range.Item2;
+                                bp = (Int64*)range.Item3;
+                                cp = (Int64*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   Int64 val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt64 (val  + (double) bp[0]);
+                                        cp[1] =  saturateInt64 (val  + (double) bp[1]);
+                                        cp[2] =  saturateInt64 (val  + (double) bp[2]);
+                                        cp[3] =  saturateInt64 (val  + (double) bp[3]);
+                                        cp[4] =  saturateInt64 (val  + (double) bp[4]);
+                                        cp[5] =  saturateInt64 (val  + (double) bp[5]);
+                                        cp[6] =  saturateInt64 (val  + (double) bp[6]);
+                                        cp[7] =  saturateInt64 (val  + (double) bp[7]);
+                                        cp[8] =  saturateInt64 (val  + (double) bp[8]);
+                                        cp[9] =  saturateInt64 (val  + (double) bp[9]);
+                                        cp[10] =  saturateInt64 (val  + (double) bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11; 
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =  saturateInt64 (val  + (double) *bp++);
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            if (dim == 0) {
+                                cp = (Int64*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (Int64*)range.Item2;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt64 (ap[0]  + (double) cp[0]);
+                                        cp[1] =  saturateInt64 (ap[1]  + (double) cp[1]);
+                                        cp[2] =  saturateInt64 (ap[2]  + (double) cp[2]);
+                                        cp[3] =  saturateInt64 (ap[3]  + (double) cp[3]);
+                                        cp[4] =  saturateInt64 (ap[4]  + (double) cp[4]);
+                                        cp[5] =  saturateInt64 (ap[5]  + (double) cp[5]);
+                                        cp[6] =  saturateInt64 (ap[6]  + (double) cp[6]);
+                                        cp[7] =  saturateInt64 (ap[7]  + (double) cp[7]);
+                                        cp[8] =  saturateInt64 (ap[8]  + (double) cp[8]);
+                                        cp[9] =  saturateInt64 (ap[9]  + (double) cp[9]);
+                                        cp[10] =  saturateInt64 (ap[10]  + (double) cp[10]);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt64 (*ap++  + (double) *cp);
+                                        cp++; 
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                cp = (Int64*)range.Item4;
+                                ap = (Int64*)range.Item2;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    Int64 val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt64 (val  + (double) cp[0]);
+                                        cp[1] =  saturateInt64 (val  + (double) cp[1]);
+                                        cp[2] =  saturateInt64 (val  + (double) cp[2]);
+                                        cp[3] =  saturateInt64 (val  + (double) cp[3]);
+                                        cp[4] =  saturateInt64 (val  + (double) cp[4]);
+                                        cp[5] =  saturateInt64 (val  + (double) cp[5]);
+                                        cp[6] =  saturateInt64 (val  + (double) cp[6]);
+                                        cp[7] =  saturateInt64 (val  + (double) cp[7]);
+                                        cp[8] =  saturateInt64 (val  + (double) cp[8]);
+                                        cp[9] =  saturateInt64 (val  + (double) cp[9]);
+                                        cp[10] =  saturateInt64 (val  + (double) cp[10]);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt64 (val  + (double) *cp);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            if (dim == 0) {
+                                ap = (Int64*)range.Item2;
+                                cp = (Int64*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (Int64*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt64 (ap[0]  + (double) bp[0]);
+                                        cp[1] =  saturateInt64 (ap[1]  + (double) bp[1]);
+                                        cp[2] =  saturateInt64 (ap[2]  + (double) bp[2]);
+                                        cp[3] =  saturateInt64 (ap[3]  + (double) bp[3]);
+                                        cp[4] =  saturateInt64 (ap[4]  + (double) bp[4]);
+                                        cp[5] =  saturateInt64 (ap[5]  + (double) bp[5]);
+                                        cp[6] =  saturateInt64 (ap[6]  + (double) bp[6]);
+                                        cp[7] =  saturateInt64 (ap[7]  + (double) bp[7]);
+                                        cp[8] =  saturateInt64 (ap[8]  + (double) bp[8]);
+                                        cp[9] =  saturateInt64 (ap[9]  + (double) bp[9]);
+                                        cp[10] =  saturateInt64 (ap[10]  + (double) bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt64 (*ap  + (double) *bp);
+                                        ap++;
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                ap = (Int64*)range.Item2;
+                                bp = (Int64*)range.Item3;
+                                cp = (Int64*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   Int64 val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt64 (ap[0]  + (double) val);
+                                        cp[1] =  saturateInt64 (ap[1]  + (double) val);
+                                        cp[2] =  saturateInt64 (ap[2]  + (double) val);
+                                        cp[3] =  saturateInt64 (ap[3]  + (double) val);
+                                        cp[4] =  saturateInt64 (ap[4]  + (double) val);
+                                        cp[5] =  saturateInt64 (ap[5]  + (double) val);
+                                        cp[6] =  saturateInt64 (ap[6]  + (double) val);
+                                        cp[7] =  saturateInt64 (ap[7]  + (double) val);
+                                        cp[8] =  saturateInt64 (ap[8]  + (double) val);
+                                        cp[9] =  saturateInt64 (ap[9]  + (double) val);
+                                        cp[10] =  saturateInt64 (ap[10]  + (double) val);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt64 (*ap  + (double) val);
+                                        ap++;
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            if (dim == 0) {
+                                cp = (Int64*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (Int64*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt64 (cp[0]  + (double) bp[0]);
+                                        cp[1] =  saturateInt64 (cp[1]  + (double) bp[1]);
+                                        cp[2] =  saturateInt64 (cp[2]  + (double) bp[2]);
+                                        cp[3] =  saturateInt64 (cp[3]  + (double) bp[3]);
+                                        cp[4] =  saturateInt64 (cp[4]  + (double) bp[4]);
+                                        cp[5] =  saturateInt64 (cp[5]  + (double) bp[5]);
+                                        cp[6] =  saturateInt64 (cp[6]  + (double) bp[6]);
+                                        cp[7] =  saturateInt64 (cp[7]  + (double) bp[7]);
+                                        cp[8] =  saturateInt64 (cp[8]  + (double) bp[8]);
+                                        cp[9] =  saturateInt64 (cp[9]  + (double) bp[9]);
+                                        cp[10] =  saturateInt64 (cp[10]  + (double) bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt64 (*cp  + (double) *bp);
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                bp = (Int64*)range.Item3;
+                                cp = (Int64*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    Int64 val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt64 (cp[0]  + (double) val);
+                                        cp[1] =  saturateInt64 (cp[1]  + (double) val);
+                                        cp[2] =  saturateInt64 (cp[2]  + (double) val);
+                                        cp[3] =  saturateInt64 (cp[3]  + (double) val);
+                                        cp[4] =  saturateInt64 (cp[4]  + (double) val);
+                                        cp[5] =  saturateInt64 (cp[5]  + (double) val);
+                                        cp[6] =  saturateInt64 (cp[6]  + (double) val);
+                                        cp[7] =  saturateInt64 (cp[7]  + (double) val);
+                                        cp[8] =  saturateInt64 (cp[8]  + (double) val);
+                                        cp[9] =  saturateInt64 (cp[9]  + (double) val);
+                                        cp[10] =  saturateInt64 (cp[10]  + (double) val);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l --> 0) {
+                                        *cp =  saturateInt64 (*cp  + (double) val);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outDims.NumberOfElements >= Settings.s_minParallelElement1Count
+                    && outDims[1] > 1) {
+                        if (outDims[1] > workItemCount) {
+                        workItemLength = outDims[1] / workItemCount;
+                    } else {
+                        workItemLength = outDims[1] / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outDims[1];
+                    workItemCount = 1;
+                }
+
+                fixed ( Int64* arrAP = arrA)
+                fixed ( Int64* arrBP = arrB)
+                fixed ( Int64* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, IntPtr, IntPtr, IntPtr> range = new Tuple<int, IntPtr, IntPtr, IntPtr>
+                               (workItemLength
+                               , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                               , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                               , (IntPtr)(retArrP + i * outDims[0] * workItemLength)); 
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, IntPtr, IntPtr, IntPtr>
+                                (outDims[1] - i * workItemLength
+                                , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                                , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                                , (IntPtr)(retArrP + i * outDims[0] * workItemLength)));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<Int64>(retStorage);
+            //}  // no scopes here! it disables implace operations
+        }
+
+        /// <summary>Add arrays elementwise</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Array with elementwise sum of A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<Int32>  add(ILInArray<Int32> A, ILInArray<Int32> B) {
+            using (ILScope.Enter(A,B)) {
+                int outLen; 
+                BinOpItMode mode; 
+                Int32 [] retArr;
+                Int32 [] arrA = A.GetArrayForRead();
+                Int32[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size; 
+                    if (B.IsScalar) {
+                       
+                        return new  ILRetArray<Int32> (new  Int32 [1]{ saturateInt32 (A.GetValue(0)  + (double) B.GetValue(0))}, A.Size);
+                    } else if (B.IsEmpty) {
+                        return  ILRetArray<Int32>.empty(outDims); 
+                    } else {
+                        outLen = outDims.NumberOfElements; 
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< Int32 > (outLen);
+                            mode = BinOpItMode.SAN; 
+                        } else {
+                            mode = BinOpItMode.SAI; 
+                        }
+                    }
+                } else {
+                    outDims = A.Size; 
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return  ILRetArray<Int32>.empty(A.Size);  
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< Int32 > (outLen);
+                            mode = BinOpItMode.ASN; 
+                        } else {
+                            mode = BinOpItMode.ASI; 
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  addEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (A.TryGetStorage4InplaceOp(out retArr)) 
+                            mode  = BinOpItMode.AAIA; 
+                        else if (B.TryGetStorage4InplaceOp(out retArr)) 
+                            mode = BinOpItMode.AAIB; 
+                        else {
+                            retArr = ILMemoryPool.Pool.New< Int32 > (outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<Int32> retStorage = new ILDenseStorage<Int32>(retArr, outDims);
+                int i = 0, workerCount = 1; 
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    Int32* cp = (Int32*)range.Item5 + range.Item1;
+                    Int32 scalar;
+                    int j = range.Item2; 
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           Int32* bp = ((Int32*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                                cp[0] =  saturateInt32 (cp[0]  + (double) bp[0]);
+                                cp[1] =  saturateInt32 (cp[1]  + (double) bp[1]);
+                                cp[2] =  saturateInt32 (cp[2]  + (double) bp[2]);
+                                cp[3] =  saturateInt32 (cp[3]  + (double) bp[3]);
+                                cp[4] =  saturateInt32 (cp[4]  + (double) bp[4]);
+                                cp[5] =  saturateInt32 (cp[5]  + (double) bp[5]);
+                                cp[6] =  saturateInt32 (cp[6]  + (double) bp[6]);
+                                cp[7] =  saturateInt32 (cp[7]  + (double) bp[7]);
+                                cp[8] =  saturateInt32 (cp[8]  + (double) bp[8]);
+                                cp[9] =  saturateInt32 (cp[9]  + (double) bp[9]);
+                                cp[10] =  saturateInt32 (cp[10]  + (double) bp[10]);
+                                cp[11] =  saturateInt32 (cp[11]  + (double) bp[11]);
+                                cp[12] =  saturateInt32 (cp[12]  + (double) bp[12]);
+                                cp[13] =  saturateInt32 (cp[13]  + (double) bp[13]);
+                                cp[14] =  saturateInt32 (cp[14]  + (double) bp[14]);
+                                cp[15] =  saturateInt32 (cp[15]  + (double) bp[15]);
+                                cp[16] =  saturateInt32 (cp[16]  + (double) bp[16]);
+                                cp[17] =  saturateInt32 (cp[17]  + (double) bp[17]);
+                                cp[18] =  saturateInt32 (cp[18]  + (double) bp[18]);
+                                cp[19] =  saturateInt32 (cp[19]  + (double) bp[19]);
+                                cp[20] =  saturateInt32 (cp[20]  + (double) bp[20]);
+                                cp += 21; bp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt32 (*cp  + (double) *bp);
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           Int32* ap = ((Int32*)range.Item3 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt32 (ap[0]  + (double) cp[0]);
+                                cp[1] =  saturateInt32 (ap[1]  + (double) cp[1]);
+                                cp[2] =  saturateInt32 (ap[2]  + (double) cp[2]);
+                                cp[3] =  saturateInt32 (ap[3]  + (double) cp[3]);
+                                cp[4] =  saturateInt32 (ap[4]  + (double) cp[4]);
+                                cp[5] =  saturateInt32 (ap[5]  + (double) cp[5]);
+                                cp[6] =  saturateInt32 (ap[6]  + (double) cp[6]);
+                                cp[7] =  saturateInt32 (ap[7]  + (double) cp[7]);
+                                cp[8] =  saturateInt32 (ap[8]  + (double) cp[8]);
+                                cp[9] =  saturateInt32 (ap[9]  + (double) cp[9]);
+                                cp[10] =  saturateInt32 (ap[10]  + (double) cp[10]);
+                                cp[11] =  saturateInt32 (ap[11]  + (double) cp[11]);
+                                cp[12] =  saturateInt32 (ap[12]  + (double) cp[12]);
+                                cp[13] =  saturateInt32 (ap[13]  + (double) cp[13]);
+                                cp[14] =  saturateInt32 (ap[14]  + (double) cp[14]);
+                                cp[15] =  saturateInt32 (ap[15]  + (double) cp[15]);
+                                cp[16] =  saturateInt32 (ap[16]  + (double) cp[16]);
+                                cp[17] =  saturateInt32 (ap[17]  + (double) cp[17]);
+                                cp[18] =  saturateInt32 (ap[18]  + (double) cp[18]);
+                                cp[19] =  saturateInt32 (ap[19]  + (double) cp[19]);
+                                cp[20] =  saturateInt32 (ap[20]  + (double) cp[20]);
+                                ap += 21; cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt32 (*ap  + (double) *cp);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((Int32*)range.Item3 + range.Item1);
+                            bp = ((Int32*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt32 (ap[0]  + (double) bp[0]);
+                                cp[1] =  saturateInt32 (ap[1]  + (double) bp[1]);
+                                cp[2] =  saturateInt32 (ap[2]  + (double) bp[2]);
+                                cp[3] =  saturateInt32 (ap[3]  + (double) bp[3]);
+                                cp[4] =  saturateInt32 (ap[4]  + (double) bp[4]);
+                                cp[5] =  saturateInt32 (ap[5]  + (double) bp[5]);
+                                cp[6] =  saturateInt32 (ap[6]  + (double) bp[6]);
+                                cp[7] =  saturateInt32 (ap[7]  + (double) bp[7]);
+                                cp[8] =  saturateInt32 (ap[8]  + (double) bp[8]);
+                                cp[9] =  saturateInt32 (ap[9]  + (double) bp[9]);
+                                cp[10] =  saturateInt32 (ap[10]  + (double) bp[10]);
+                                cp[11] =  saturateInt32 (ap[11]  + (double) bp[11]);
+                                cp[12] =  saturateInt32 (ap[12]  + (double) bp[12]);
+                                cp[13] =  saturateInt32 (ap[13]  + (double) bp[13]);
+                                cp[14] =  saturateInt32 (ap[14]  + (double) bp[14]);
+                                cp[15] =  saturateInt32 (ap[15]  + (double) bp[15]);
+                                cp[16] =  saturateInt32 (ap[16]  + (double) bp[16]);
+                                cp[17] =  saturateInt32 (ap[17]  + (double) bp[17]);
+                                cp[18] =  saturateInt32 (ap[18]  + (double) bp[18]);
+                                cp[19] =  saturateInt32 (ap[19]  + (double) bp[19]);
+                                cp[20] =  saturateInt32 (ap[20]  + (double) bp[20]);
+                                ap+=21; bp+=21; cp+=21; j-=21;
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt32 (*ap  + (double) *bp);
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((Int32*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt32 (cp[0]  + (double) scalar);
+                                cp[1] =  saturateInt32 (cp[1]  + (double) scalar);
+                                cp[2] =  saturateInt32 (cp[2]  + (double) scalar);
+                                cp[3] =  saturateInt32 (cp[3]  + (double) scalar);
+                                cp[4] =  saturateInt32 (cp[4]  + (double) scalar);
+                                cp[5] =  saturateInt32 (cp[5]  + (double) scalar);
+                                cp[6] =  saturateInt32 (cp[6]  + (double) scalar);
+                                cp[7] =  saturateInt32 (cp[7]  + (double) scalar);
+                                cp[8] =  saturateInt32 (cp[8]  + (double) scalar);
+                                cp[9] =  saturateInt32 (cp[9]  + (double) scalar);
+                                cp[10] =  saturateInt32 (cp[10]  + (double) scalar);
+                                cp[11] =  saturateInt32 (cp[11]  + (double) scalar);
+                                cp[12] =  saturateInt32 (cp[12]  + (double) scalar);
+                                cp[13] =  saturateInt32 (cp[13]  + (double) scalar);
+                                cp[14] =  saturateInt32 (cp[14]  + (double) scalar);
+                                cp[15] =  saturateInt32 (cp[15]  + (double) scalar);
+                                cp[16] =  saturateInt32 (cp[16]  + (double) scalar);
+                                cp[17] =  saturateInt32 (cp[17]  + (double) scalar);
+                                cp[18] =  saturateInt32 (cp[18]  + (double) scalar);
+                                cp[19] =  saturateInt32 (cp[19]  + (double) scalar);
+                                cp[20] =  saturateInt32 (cp[20]  + (double) scalar);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt32 (*cp  + (double) scalar);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((Int32*)range.Item3 + range.Item1);
+                            scalar = *((Int32*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt32 (ap[0]  + (double) scalar);
+                                cp[1] =  saturateInt32 (ap[1]  + (double) scalar);
+                                cp[2] =  saturateInt32 (ap[2]  + (double) scalar);
+                                cp[3] =  saturateInt32 (ap[3]  + (double) scalar);
+                                cp[4] =  saturateInt32 (ap[4]  + (double) scalar);
+                                cp[5] =  saturateInt32 (ap[5]  + (double) scalar);
+                                cp[6] =  saturateInt32 (ap[6]  + (double) scalar);
+                                cp[7] =  saturateInt32 (ap[7]  + (double) scalar);
+                                cp[8] =  saturateInt32 (ap[8]  + (double) scalar);
+                                cp[9] =  saturateInt32 (ap[9]  + (double) scalar);
+                                cp[10] =  saturateInt32 (ap[10]  + (double) scalar);
+                                cp[11] =  saturateInt32 (ap[11]  + (double) scalar);
+                                cp[12] =  saturateInt32 (ap[12]  + (double) scalar);
+                                cp[13] =  saturateInt32 (ap[13]  + (double) scalar);
+                                cp[14] =  saturateInt32 (ap[14]  + (double) scalar);
+                                cp[15] =  saturateInt32 (ap[15]  + (double) scalar);
+                                cp[16] =  saturateInt32 (ap[16]  + (double) scalar);
+                                cp[17] =  saturateInt32 (ap[17]  + (double) scalar);
+                                cp[18] =  saturateInt32 (ap[18]  + (double) scalar);
+                                cp[19] =  saturateInt32 (ap[19]  + (double) scalar);
+                                cp[20] =  saturateInt32 (ap[20]  + (double) scalar);
+                                ap+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt32 (*ap  + (double) scalar);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((Int32*)range.Item3);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt32 (scalar  + (double) cp[0]);
+                                cp[1] =  saturateInt32 (scalar  + (double) cp[1]);
+                                cp[2] =  saturateInt32 (scalar  + (double) cp[2]);
+                                cp[3] =  saturateInt32 (scalar  + (double) cp[3]);
+                                cp[4] =  saturateInt32 (scalar  + (double) cp[4]);
+                                cp[5] =  saturateInt32 (scalar  + (double) cp[5]);
+                                cp[6] =  saturateInt32 (scalar  + (double) cp[6]);
+                                cp[7] =  saturateInt32 (scalar  + (double) cp[7]);
+                                cp[8] =  saturateInt32 (scalar  + (double) cp[8]);
+                                cp[9] =  saturateInt32 (scalar  + (double) cp[9]);
+                                cp[10] =  saturateInt32 (scalar  + (double) cp[10]);
+                                cp[11] =  saturateInt32 (scalar  + (double) cp[11]);
+                                cp[12] =  saturateInt32 (scalar  + (double) cp[12]);
+                                cp[13] =  saturateInt32 (scalar  + (double) cp[13]);
+                                cp[14] =  saturateInt32 (scalar  + (double) cp[14]);
+                                cp[15] =  saturateInt32 (scalar  + (double) cp[15]);
+                                cp[16] =  saturateInt32 (scalar  + (double) cp[16]);
+                                cp[17] =  saturateInt32 (scalar  + (double) cp[17]);
+                                cp[18] =  saturateInt32 (scalar  + (double) cp[18]);
+                                cp[19] =  saturateInt32 (scalar  + (double) cp[19]);
+                                cp[20] =  saturateInt32 (scalar  + (double) cp[20]);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt32 (scalar  + (double) *cp);
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((Int32*)range.Item3);
+                            bp = ((Int32*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt32 (scalar  + (double) bp[0]);
+                                cp[1] =  saturateInt32 (scalar  + (double) bp[1]);
+                                cp[2] =  saturateInt32 (scalar  + (double) bp[2]);
+                                cp[3] =  saturateInt32 (scalar  + (double) bp[3]);
+                                cp[4] =  saturateInt32 (scalar  + (double) bp[4]);
+                                cp[5] =  saturateInt32 (scalar  + (double) bp[5]);
+                                cp[6] =  saturateInt32 (scalar  + (double) bp[6]);
+                                cp[7] =  saturateInt32 (scalar  + (double) bp[7]);
+                                cp[8] =  saturateInt32 (scalar  + (double) bp[8]);
+                                cp[9] =  saturateInt32 (scalar  + (double) bp[9]);
+                                cp[10] =  saturateInt32 (scalar  + (double) bp[10]);
+                                cp[11] =  saturateInt32 (scalar  + (double) bp[11]);
+                                cp[12] =  saturateInt32 (scalar  + (double) bp[12]);
+                                cp[13] =  saturateInt32 (scalar  + (double) bp[13]);
+                                cp[14] =  saturateInt32 (scalar  + (double) bp[14]);
+                                cp[15] =  saturateInt32 (scalar  + (double) bp[15]);
+                                cp[16] =  saturateInt32 (scalar  + (double) bp[16]);
+                                cp[17] =  saturateInt32 (scalar  + (double) bp[17]);
+                                cp[18] =  saturateInt32 (scalar  + (double) bp[18]);
+                                cp[19] =  saturateInt32 (scalar  + (double) bp[19]);
+                                cp[20] =  saturateInt32 (scalar  + (double) bp[20]);
+                                bp+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt32 (scalar  + (double) *bp);
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work 
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                
+                fixed ( Int32* arrAP = arrA)
+                fixed ( Int32* arrBP = arrB)
+                fixed ( Int32* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range 
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new  ILRetArray< Int32>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<Int32>  addEx(ILInArray<Int32> A, ILInArray<Int32> B) {
+            //using (ILScope.Enter(A, B)) { we cannot start a new scope here, since this would prevent A and B to be used implace if applicable
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<Int32>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<Int32>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<Int32>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                dim = -(dim - 1);  // 0 -> 1, 1 -> 0
+                #endregion
+
+                #region parameter preparation
+               
+                Int32[] retArr;
+               
+                Int32[] arrA = A.GetArrayForRead();
+               
+                Int32[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int workItemMultiplierLenA;
+                int workItemMultiplierLenB;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<Int32>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    workItemMultiplierLenB = outDims[0]; 
+                    workItemMultiplierLenA = dim;  // 0 for column, 1 for row vector
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<Int32>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    workItemMultiplierLenB = dim;  // 0 for column, 1 for row vector
+                    workItemMultiplierLenA = outDims[0]; 
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one singleton dimension in either A or B");
+                }
+                int itLen = outDims[0]; // (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<Int32> retStorage = new ILDenseStorage<Int32>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    Int32* ap;
+                   
+                    Int32* bp;
+                   
+                    Int32* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            if (dim == 0) {
+                                bp = (Int32*)range.Item3;
+                                cp = (Int32*)range.Item4; 
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (Int32*)range.Item2;
+                                    int l = itLen; 
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt32 (ap[0]  + (double) bp[0]);
+                                        cp[1] =  saturateInt32 (ap[1]  + (double) bp[1]);
+                                        cp[2] =  saturateInt32 (ap[2]  + (double) bp[2]);
+                                        cp[3] =  saturateInt32 (ap[3]  + (double) bp[3]);
+                                        cp[4] =  saturateInt32 (ap[4]  + (double) bp[4]);
+                                        cp[5] =  saturateInt32 (ap[5]  + (double) bp[5]);
+                                        cp[6] =  saturateInt32 (ap[6]  + (double) bp[6]);
+                                        cp[7] =  saturateInt32 (ap[7]  + (double) bp[7]);
+                                        cp[8] =  saturateInt32 (ap[8]  + (double) bp[8]);
+                                        cp[9] =  saturateInt32 (ap[9]  + (double) bp[9]);
+                                        cp[10] =  saturateInt32 (ap[10]  + (double) bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =  saturateInt32 (*ap++  + (double) *bp++);
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                ap = (Int32*)range.Item2;
+                                bp = (Int32*)range.Item3;
+                                cp = (Int32*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   Int32 val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt32 (val  + (double) bp[0]);
+                                        cp[1] =  saturateInt32 (val  + (double) bp[1]);
+                                        cp[2] =  saturateInt32 (val  + (double) bp[2]);
+                                        cp[3] =  saturateInt32 (val  + (double) bp[3]);
+                                        cp[4] =  saturateInt32 (val  + (double) bp[4]);
+                                        cp[5] =  saturateInt32 (val  + (double) bp[5]);
+                                        cp[6] =  saturateInt32 (val  + (double) bp[6]);
+                                        cp[7] =  saturateInt32 (val  + (double) bp[7]);
+                                        cp[8] =  saturateInt32 (val  + (double) bp[8]);
+                                        cp[9] =  saturateInt32 (val  + (double) bp[9]);
+                                        cp[10] =  saturateInt32 (val  + (double) bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11; 
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =  saturateInt32 (val  + (double) *bp++);
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            if (dim == 0) {
+                                cp = (Int32*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (Int32*)range.Item2;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt32 (ap[0]  + (double) cp[0]);
+                                        cp[1] =  saturateInt32 (ap[1]  + (double) cp[1]);
+                                        cp[2] =  saturateInt32 (ap[2]  + (double) cp[2]);
+                                        cp[3] =  saturateInt32 (ap[3]  + (double) cp[3]);
+                                        cp[4] =  saturateInt32 (ap[4]  + (double) cp[4]);
+                                        cp[5] =  saturateInt32 (ap[5]  + (double) cp[5]);
+                                        cp[6] =  saturateInt32 (ap[6]  + (double) cp[6]);
+                                        cp[7] =  saturateInt32 (ap[7]  + (double) cp[7]);
+                                        cp[8] =  saturateInt32 (ap[8]  + (double) cp[8]);
+                                        cp[9] =  saturateInt32 (ap[9]  + (double) cp[9]);
+                                        cp[10] =  saturateInt32 (ap[10]  + (double) cp[10]);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt32 (*ap++  + (double) *cp);
+                                        cp++; 
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                cp = (Int32*)range.Item4;
+                                ap = (Int32*)range.Item2;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    Int32 val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt32 (val  + (double) cp[0]);
+                                        cp[1] =  saturateInt32 (val  + (double) cp[1]);
+                                        cp[2] =  saturateInt32 (val  + (double) cp[2]);
+                                        cp[3] =  saturateInt32 (val  + (double) cp[3]);
+                                        cp[4] =  saturateInt32 (val  + (double) cp[4]);
+                                        cp[5] =  saturateInt32 (val  + (double) cp[5]);
+                                        cp[6] =  saturateInt32 (val  + (double) cp[6]);
+                                        cp[7] =  saturateInt32 (val  + (double) cp[7]);
+                                        cp[8] =  saturateInt32 (val  + (double) cp[8]);
+                                        cp[9] =  saturateInt32 (val  + (double) cp[9]);
+                                        cp[10] =  saturateInt32 (val  + (double) cp[10]);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt32 (val  + (double) *cp);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            if (dim == 0) {
+                                ap = (Int32*)range.Item2;
+                                cp = (Int32*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (Int32*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt32 (ap[0]  + (double) bp[0]);
+                                        cp[1] =  saturateInt32 (ap[1]  + (double) bp[1]);
+                                        cp[2] =  saturateInt32 (ap[2]  + (double) bp[2]);
+                                        cp[3] =  saturateInt32 (ap[3]  + (double) bp[3]);
+                                        cp[4] =  saturateInt32 (ap[4]  + (double) bp[4]);
+                                        cp[5] =  saturateInt32 (ap[5]  + (double) bp[5]);
+                                        cp[6] =  saturateInt32 (ap[6]  + (double) bp[6]);
+                                        cp[7] =  saturateInt32 (ap[7]  + (double) bp[7]);
+                                        cp[8] =  saturateInt32 (ap[8]  + (double) bp[8]);
+                                        cp[9] =  saturateInt32 (ap[9]  + (double) bp[9]);
+                                        cp[10] =  saturateInt32 (ap[10]  + (double) bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt32 (*ap  + (double) *bp);
+                                        ap++;
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                ap = (Int32*)range.Item2;
+                                bp = (Int32*)range.Item3;
+                                cp = (Int32*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   Int32 val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt32 (ap[0]  + (double) val);
+                                        cp[1] =  saturateInt32 (ap[1]  + (double) val);
+                                        cp[2] =  saturateInt32 (ap[2]  + (double) val);
+                                        cp[3] =  saturateInt32 (ap[3]  + (double) val);
+                                        cp[4] =  saturateInt32 (ap[4]  + (double) val);
+                                        cp[5] =  saturateInt32 (ap[5]  + (double) val);
+                                        cp[6] =  saturateInt32 (ap[6]  + (double) val);
+                                        cp[7] =  saturateInt32 (ap[7]  + (double) val);
+                                        cp[8] =  saturateInt32 (ap[8]  + (double) val);
+                                        cp[9] =  saturateInt32 (ap[9]  + (double) val);
+                                        cp[10] =  saturateInt32 (ap[10]  + (double) val);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt32 (*ap  + (double) val);
+                                        ap++;
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            if (dim == 0) {
+                                cp = (Int32*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (Int32*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt32 (cp[0]  + (double) bp[0]);
+                                        cp[1] =  saturateInt32 (cp[1]  + (double) bp[1]);
+                                        cp[2] =  saturateInt32 (cp[2]  + (double) bp[2]);
+                                        cp[3] =  saturateInt32 (cp[3]  + (double) bp[3]);
+                                        cp[4] =  saturateInt32 (cp[4]  + (double) bp[4]);
+                                        cp[5] =  saturateInt32 (cp[5]  + (double) bp[5]);
+                                        cp[6] =  saturateInt32 (cp[6]  + (double) bp[6]);
+                                        cp[7] =  saturateInt32 (cp[7]  + (double) bp[7]);
+                                        cp[8] =  saturateInt32 (cp[8]  + (double) bp[8]);
+                                        cp[9] =  saturateInt32 (cp[9]  + (double) bp[9]);
+                                        cp[10] =  saturateInt32 (cp[10]  + (double) bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt32 (*cp  + (double) *bp);
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                bp = (Int32*)range.Item3;
+                                cp = (Int32*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    Int32 val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt32 (cp[0]  + (double) val);
+                                        cp[1] =  saturateInt32 (cp[1]  + (double) val);
+                                        cp[2] =  saturateInt32 (cp[2]  + (double) val);
+                                        cp[3] =  saturateInt32 (cp[3]  + (double) val);
+                                        cp[4] =  saturateInt32 (cp[4]  + (double) val);
+                                        cp[5] =  saturateInt32 (cp[5]  + (double) val);
+                                        cp[6] =  saturateInt32 (cp[6]  + (double) val);
+                                        cp[7] =  saturateInt32 (cp[7]  + (double) val);
+                                        cp[8] =  saturateInt32 (cp[8]  + (double) val);
+                                        cp[9] =  saturateInt32 (cp[9]  + (double) val);
+                                        cp[10] =  saturateInt32 (cp[10]  + (double) val);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l --> 0) {
+                                        *cp =  saturateInt32 (*cp  + (double) val);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outDims.NumberOfElements >= Settings.s_minParallelElement1Count
+                    && outDims[1] > 1) {
+                        if (outDims[1] > workItemCount) {
+                        workItemLength = outDims[1] / workItemCount;
+                    } else {
+                        workItemLength = outDims[1] / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outDims[1];
+                    workItemCount = 1;
+                }
+
+                fixed ( Int32* arrAP = arrA)
+                fixed ( Int32* arrBP = arrB)
+                fixed ( Int32* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, IntPtr, IntPtr, IntPtr> range = new Tuple<int, IntPtr, IntPtr, IntPtr>
+                               (workItemLength
+                               , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                               , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                               , (IntPtr)(retArrP + i * outDims[0] * workItemLength)); 
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, IntPtr, IntPtr, IntPtr>
+                                (outDims[1] - i * workItemLength
+                                , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                                , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                                , (IntPtr)(retArrP + i * outDims[0] * workItemLength)));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<Int32>(retStorage);
+            //}  // no scopes here! it disables implace operations
+        }
+
+        /// <summary>Add arrays elementwise</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Array with elementwise sum of A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<float>  add(ILInArray<float> A, ILInArray<float> B) {
+            using (ILScope.Enter(A,B)) {
+                int outLen; 
+                BinOpItMode mode; 
+                float [] retArr;
+                float [] arrA = A.GetArrayForRead();
+                float[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size; 
+                    if (B.IsScalar) {
+                       
+                        return new  ILRetArray<float> (new  float [1]{  (A.GetValue(0)  + B.GetValue(0))}, A.Size);
+                    } else if (B.IsEmpty) {
+                        return  ILRetArray<float>.empty(outDims); 
+                    } else {
+                        outLen = outDims.NumberOfElements; 
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< float > (outLen);
+                            mode = BinOpItMode.SAN; 
+                        } else {
+                            mode = BinOpItMode.SAI; 
+                        }
+                    }
+                } else {
+                    outDims = A.Size; 
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return  ILRetArray<float>.empty(A.Size);  
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< float > (outLen);
+                            mode = BinOpItMode.ASN; 
+                        } else {
+                            mode = BinOpItMode.ASI; 
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  addEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (A.TryGetStorage4InplaceOp(out retArr)) 
+                            mode  = BinOpItMode.AAIA; 
+                        else if (B.TryGetStorage4InplaceOp(out retArr)) 
+                            mode = BinOpItMode.AAIB; 
+                        else {
+                            retArr = ILMemoryPool.Pool.New< float > (outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<float> retStorage = new ILDenseStorage<float>(retArr, outDims);
+                int i = 0, workerCount = 1; 
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    float* cp = (float*)range.Item5 + range.Item1;
+                    float scalar;
+                    int j = range.Item2; 
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           float* bp = ((float*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                                cp[0] =   (cp[0]  + bp[0]);
+                                cp[1] =   (cp[1]  + bp[1]);
+                                cp[2] =   (cp[2]  + bp[2]);
+                                cp[3] =   (cp[3]  + bp[3]);
+                                cp[4] =   (cp[4]  + bp[4]);
+                                cp[5] =   (cp[5]  + bp[5]);
+                                cp[6] =   (cp[6]  + bp[6]);
+                                cp[7] =   (cp[7]  + bp[7]);
+                                cp[8] =   (cp[8]  + bp[8]);
+                                cp[9] =   (cp[9]  + bp[9]);
+                                cp[10] =   (cp[10]  + bp[10]);
+                                cp[11] =   (cp[11]  + bp[11]);
+                                cp[12] =   (cp[12]  + bp[12]);
+                                cp[13] =   (cp[13]  + bp[13]);
+                                cp[14] =   (cp[14]  + bp[14]);
+                                cp[15] =   (cp[15]  + bp[15]);
+                                cp[16] =   (cp[16]  + bp[16]);
+                                cp[17] =   (cp[17]  + bp[17]);
+                                cp[18] =   (cp[18]  + bp[18]);
+                                cp[19] =   (cp[19]  + bp[19]);
+                                cp[20] =   (cp[20]  + bp[20]);
+                                cp += 21; bp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*cp  + *bp);
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           float* ap = ((float*)range.Item3 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  + cp[0]);
+                                cp[1] =   (ap[1]  + cp[1]);
+                                cp[2] =   (ap[2]  + cp[2]);
+                                cp[3] =   (ap[3]  + cp[3]);
+                                cp[4] =   (ap[4]  + cp[4]);
+                                cp[5] =   (ap[5]  + cp[5]);
+                                cp[6] =   (ap[6]  + cp[6]);
+                                cp[7] =   (ap[7]  + cp[7]);
+                                cp[8] =   (ap[8]  + cp[8]);
+                                cp[9] =   (ap[9]  + cp[9]);
+                                cp[10] =   (ap[10]  + cp[10]);
+                                cp[11] =   (ap[11]  + cp[11]);
+                                cp[12] =   (ap[12]  + cp[12]);
+                                cp[13] =   (ap[13]  + cp[13]);
+                                cp[14] =   (ap[14]  + cp[14]);
+                                cp[15] =   (ap[15]  + cp[15]);
+                                cp[16] =   (ap[16]  + cp[16]);
+                                cp[17] =   (ap[17]  + cp[17]);
+                                cp[18] =   (ap[18]  + cp[18]);
+                                cp[19] =   (ap[19]  + cp[19]);
+                                cp[20] =   (ap[20]  + cp[20]);
+                                ap += 21; cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  + *cp);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((float*)range.Item3 + range.Item1);
+                            bp = ((float*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  + bp[0]);
+                                cp[1] =   (ap[1]  + bp[1]);
+                                cp[2] =   (ap[2]  + bp[2]);
+                                cp[3] =   (ap[3]  + bp[3]);
+                                cp[4] =   (ap[4]  + bp[4]);
+                                cp[5] =   (ap[5]  + bp[5]);
+                                cp[6] =   (ap[6]  + bp[6]);
+                                cp[7] =   (ap[7]  + bp[7]);
+                                cp[8] =   (ap[8]  + bp[8]);
+                                cp[9] =   (ap[9]  + bp[9]);
+                                cp[10] =   (ap[10]  + bp[10]);
+                                cp[11] =   (ap[11]  + bp[11]);
+                                cp[12] =   (ap[12]  + bp[12]);
+                                cp[13] =   (ap[13]  + bp[13]);
+                                cp[14] =   (ap[14]  + bp[14]);
+                                cp[15] =   (ap[15]  + bp[15]);
+                                cp[16] =   (ap[16]  + bp[16]);
+                                cp[17] =   (ap[17]  + bp[17]);
+                                cp[18] =   (ap[18]  + bp[18]);
+                                cp[19] =   (ap[19]  + bp[19]);
+                                cp[20] =   (ap[20]  + bp[20]);
+                                ap+=21; bp+=21; cp+=21; j-=21;
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  + *bp);
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((float*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =   (cp[0]  + scalar);
+                                cp[1] =   (cp[1]  + scalar);
+                                cp[2] =   (cp[2]  + scalar);
+                                cp[3] =   (cp[3]  + scalar);
+                                cp[4] =   (cp[4]  + scalar);
+                                cp[5] =   (cp[5]  + scalar);
+                                cp[6] =   (cp[6]  + scalar);
+                                cp[7] =   (cp[7]  + scalar);
+                                cp[8] =   (cp[8]  + scalar);
+                                cp[9] =   (cp[9]  + scalar);
+                                cp[10] =   (cp[10]  + scalar);
+                                cp[11] =   (cp[11]  + scalar);
+                                cp[12] =   (cp[12]  + scalar);
+                                cp[13] =   (cp[13]  + scalar);
+                                cp[14] =   (cp[14]  + scalar);
+                                cp[15] =   (cp[15]  + scalar);
+                                cp[16] =   (cp[16]  + scalar);
+                                cp[17] =   (cp[17]  + scalar);
+                                cp[18] =   (cp[18]  + scalar);
+                                cp[19] =   (cp[19]  + scalar);
+                                cp[20] =   (cp[20]  + scalar);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*cp  + scalar);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((float*)range.Item3 + range.Item1);
+                            scalar = *((float*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  + scalar);
+                                cp[1] =   (ap[1]  + scalar);
+                                cp[2] =   (ap[2]  + scalar);
+                                cp[3] =   (ap[3]  + scalar);
+                                cp[4] =   (ap[4]  + scalar);
+                                cp[5] =   (ap[5]  + scalar);
+                                cp[6] =   (ap[6]  + scalar);
+                                cp[7] =   (ap[7]  + scalar);
+                                cp[8] =   (ap[8]  + scalar);
+                                cp[9] =   (ap[9]  + scalar);
+                                cp[10] =   (ap[10]  + scalar);
+                                cp[11] =   (ap[11]  + scalar);
+                                cp[12] =   (ap[12]  + scalar);
+                                cp[13] =   (ap[13]  + scalar);
+                                cp[14] =   (ap[14]  + scalar);
+                                cp[15] =   (ap[15]  + scalar);
+                                cp[16] =   (ap[16]  + scalar);
+                                cp[17] =   (ap[17]  + scalar);
+                                cp[18] =   (ap[18]  + scalar);
+                                cp[19] =   (ap[19]  + scalar);
+                                cp[20] =   (ap[20]  + scalar);
+                                ap+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  + scalar);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((float*)range.Item3);
+                            while (j > 20) {
+                               
+                                cp[0] =   (scalar  + cp[0]);
+                                cp[1] =   (scalar  + cp[1]);
+                                cp[2] =   (scalar  + cp[2]);
+                                cp[3] =   (scalar  + cp[3]);
+                                cp[4] =   (scalar  + cp[4]);
+                                cp[5] =   (scalar  + cp[5]);
+                                cp[6] =   (scalar  + cp[6]);
+                                cp[7] =   (scalar  + cp[7]);
+                                cp[8] =   (scalar  + cp[8]);
+                                cp[9] =   (scalar  + cp[9]);
+                                cp[10] =   (scalar  + cp[10]);
+                                cp[11] =   (scalar  + cp[11]);
+                                cp[12] =   (scalar  + cp[12]);
+                                cp[13] =   (scalar  + cp[13]);
+                                cp[14] =   (scalar  + cp[14]);
+                                cp[15] =   (scalar  + cp[15]);
+                                cp[16] =   (scalar  + cp[16]);
+                                cp[17] =   (scalar  + cp[17]);
+                                cp[18] =   (scalar  + cp[18]);
+                                cp[19] =   (scalar  + cp[19]);
+                                cp[20] =   (scalar  + cp[20]);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (scalar  + *cp);
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((float*)range.Item3);
+                            bp = ((float*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (scalar  + bp[0]);
+                                cp[1] =   (scalar  + bp[1]);
+                                cp[2] =   (scalar  + bp[2]);
+                                cp[3] =   (scalar  + bp[3]);
+                                cp[4] =   (scalar  + bp[4]);
+                                cp[5] =   (scalar  + bp[5]);
+                                cp[6] =   (scalar  + bp[6]);
+                                cp[7] =   (scalar  + bp[7]);
+                                cp[8] =   (scalar  + bp[8]);
+                                cp[9] =   (scalar  + bp[9]);
+                                cp[10] =   (scalar  + bp[10]);
+                                cp[11] =   (scalar  + bp[11]);
+                                cp[12] =   (scalar  + bp[12]);
+                                cp[13] =   (scalar  + bp[13]);
+                                cp[14] =   (scalar  + bp[14]);
+                                cp[15] =   (scalar  + bp[15]);
+                                cp[16] =   (scalar  + bp[16]);
+                                cp[17] =   (scalar  + bp[17]);
+                                cp[18] =   (scalar  + bp[18]);
+                                cp[19] =   (scalar  + bp[19]);
+                                cp[20] =   (scalar  + bp[20]);
+                                bp+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (scalar  + *bp);
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work 
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                
+                fixed ( float* arrAP = arrA)
+                fixed ( float* arrBP = arrB)
+                fixed ( float* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range 
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new  ILRetArray< float>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<float>  addEx(ILInArray<float> A, ILInArray<float> B) {
+            //using (ILScope.Enter(A, B)) { we cannot start a new scope here, since this would prevent A and B to be used implace if applicable
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<float>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<float>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<float>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                dim = -(dim - 1);  // 0 -> 1, 1 -> 0
+                #endregion
+
+                #region parameter preparation
+               
+                float[] retArr;
+               
+                float[] arrA = A.GetArrayForRead();
+               
+                float[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int workItemMultiplierLenA;
+                int workItemMultiplierLenB;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<float>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    workItemMultiplierLenB = outDims[0]; 
+                    workItemMultiplierLenA = dim;  // 0 for column, 1 for row vector
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<float>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    workItemMultiplierLenB = dim;  // 0 for column, 1 for row vector
+                    workItemMultiplierLenA = outDims[0]; 
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one singleton dimension in either A or B");
+                }
+                int itLen = outDims[0]; // (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<float> retStorage = new ILDenseStorage<float>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    float* ap;
+                   
+                    float* bp;
+                   
+                    float* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            if (dim == 0) {
+                                bp = (float*)range.Item3;
+                                cp = (float*)range.Item4; 
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (float*)range.Item2;
+                                    int l = itLen; 
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  + bp[0]);
+                                        cp[1] =   (ap[1]  + bp[1]);
+                                        cp[2] =   (ap[2]  + bp[2]);
+                                        cp[3] =   (ap[3]  + bp[3]);
+                                        cp[4] =   (ap[4]  + bp[4]);
+                                        cp[5] =   (ap[5]  + bp[5]);
+                                        cp[6] =   (ap[6]  + bp[6]);
+                                        cp[7] =   (ap[7]  + bp[7]);
+                                        cp[8] =   (ap[8]  + bp[8]);
+                                        cp[9] =   (ap[9]  + bp[9]);
+                                        cp[10] =   (ap[10]  + bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =   (*ap++  + *bp++);
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                ap = (float*)range.Item2;
+                                bp = (float*)range.Item3;
+                                cp = (float*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   float val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (val  + bp[0]);
+                                        cp[1] =   (val  + bp[1]);
+                                        cp[2] =   (val  + bp[2]);
+                                        cp[3] =   (val  + bp[3]);
+                                        cp[4] =   (val  + bp[4]);
+                                        cp[5] =   (val  + bp[5]);
+                                        cp[6] =   (val  + bp[6]);
+                                        cp[7] =   (val  + bp[7]);
+                                        cp[8] =   (val  + bp[8]);
+                                        cp[9] =   (val  + bp[9]);
+                                        cp[10] =   (val  + bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11; 
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =   (val  + *bp++);
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            if (dim == 0) {
+                                cp = (float*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (float*)range.Item2;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  + cp[0]);
+                                        cp[1] =   (ap[1]  + cp[1]);
+                                        cp[2] =   (ap[2]  + cp[2]);
+                                        cp[3] =   (ap[3]  + cp[3]);
+                                        cp[4] =   (ap[4]  + cp[4]);
+                                        cp[5] =   (ap[5]  + cp[5]);
+                                        cp[6] =   (ap[6]  + cp[6]);
+                                        cp[7] =   (ap[7]  + cp[7]);
+                                        cp[8] =   (ap[8]  + cp[8]);
+                                        cp[9] =   (ap[9]  + cp[9]);
+                                        cp[10] =   (ap[10]  + cp[10]);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap++  + *cp);
+                                        cp++; 
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                cp = (float*)range.Item4;
+                                ap = (float*)range.Item2;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    float val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (val  + cp[0]);
+                                        cp[1] =   (val  + cp[1]);
+                                        cp[2] =   (val  + cp[2]);
+                                        cp[3] =   (val  + cp[3]);
+                                        cp[4] =   (val  + cp[4]);
+                                        cp[5] =   (val  + cp[5]);
+                                        cp[6] =   (val  + cp[6]);
+                                        cp[7] =   (val  + cp[7]);
+                                        cp[8] =   (val  + cp[8]);
+                                        cp[9] =   (val  + cp[9]);
+                                        cp[10] =   (val  + cp[10]);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (val  + *cp);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            if (dim == 0) {
+                                ap = (float*)range.Item2;
+                                cp = (float*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (float*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  + bp[0]);
+                                        cp[1] =   (ap[1]  + bp[1]);
+                                        cp[2] =   (ap[2]  + bp[2]);
+                                        cp[3] =   (ap[3]  + bp[3]);
+                                        cp[4] =   (ap[4]  + bp[4]);
+                                        cp[5] =   (ap[5]  + bp[5]);
+                                        cp[6] =   (ap[6]  + bp[6]);
+                                        cp[7] =   (ap[7]  + bp[7]);
+                                        cp[8] =   (ap[8]  + bp[8]);
+                                        cp[9] =   (ap[9]  + bp[9]);
+                                        cp[10] =   (ap[10]  + bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap  + *bp);
+                                        ap++;
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                ap = (float*)range.Item2;
+                                bp = (float*)range.Item3;
+                                cp = (float*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   float val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  + val);
+                                        cp[1] =   (ap[1]  + val);
+                                        cp[2] =   (ap[2]  + val);
+                                        cp[3] =   (ap[3]  + val);
+                                        cp[4] =   (ap[4]  + val);
+                                        cp[5] =   (ap[5]  + val);
+                                        cp[6] =   (ap[6]  + val);
+                                        cp[7] =   (ap[7]  + val);
+                                        cp[8] =   (ap[8]  + val);
+                                        cp[9] =   (ap[9]  + val);
+                                        cp[10] =   (ap[10]  + val);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap  + val);
+                                        ap++;
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            if (dim == 0) {
+                                cp = (float*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (float*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (cp[0]  + bp[0]);
+                                        cp[1] =   (cp[1]  + bp[1]);
+                                        cp[2] =   (cp[2]  + bp[2]);
+                                        cp[3] =   (cp[3]  + bp[3]);
+                                        cp[4] =   (cp[4]  + bp[4]);
+                                        cp[5] =   (cp[5]  + bp[5]);
+                                        cp[6] =   (cp[6]  + bp[6]);
+                                        cp[7] =   (cp[7]  + bp[7]);
+                                        cp[8] =   (cp[8]  + bp[8]);
+                                        cp[9] =   (cp[9]  + bp[9]);
+                                        cp[10] =   (cp[10]  + bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*cp  + *bp);
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                bp = (float*)range.Item3;
+                                cp = (float*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    float val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (cp[0]  + val);
+                                        cp[1] =   (cp[1]  + val);
+                                        cp[2] =   (cp[2]  + val);
+                                        cp[3] =   (cp[3]  + val);
+                                        cp[4] =   (cp[4]  + val);
+                                        cp[5] =   (cp[5]  + val);
+                                        cp[6] =   (cp[6]  + val);
+                                        cp[7] =   (cp[7]  + val);
+                                        cp[8] =   (cp[8]  + val);
+                                        cp[9] =   (cp[9]  + val);
+                                        cp[10] =   (cp[10]  + val);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l --> 0) {
+                                        *cp =   (*cp  + val);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outDims.NumberOfElements >= Settings.s_minParallelElement1Count
+                    && outDims[1] > 1) {
+                        if (outDims[1] > workItemCount) {
+                        workItemLength = outDims[1] / workItemCount;
+                    } else {
+                        workItemLength = outDims[1] / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outDims[1];
+                    workItemCount = 1;
+                }
+
+                fixed ( float* arrAP = arrA)
+                fixed ( float* arrBP = arrB)
+                fixed ( float* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, IntPtr, IntPtr, IntPtr> range = new Tuple<int, IntPtr, IntPtr, IntPtr>
+                               (workItemLength
+                               , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                               , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                               , (IntPtr)(retArrP + i * outDims[0] * workItemLength)); 
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, IntPtr, IntPtr, IntPtr>
+                                (outDims[1] - i * workItemLength
+                                , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                                , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                                , (IntPtr)(retArrP + i * outDims[0] * workItemLength)));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<float>(retStorage);
+            //}  // no scopes here! it disables implace operations
+        }
+
+        /// <summary>Add arrays elementwise</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Array with elementwise sum of A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<fcomplex>  add(ILInArray<fcomplex> A, ILInArray<fcomplex> B) {
+            using (ILScope.Enter(A,B)) {
+                int outLen; 
+                BinOpItMode mode; 
+                fcomplex [] retArr;
+                fcomplex [] arrA = A.GetArrayForRead();
+                fcomplex[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size; 
+                    if (B.IsScalar) {
+                       
+                        return new  ILRetArray<fcomplex> (new  fcomplex [1]{  (A.GetValue(0)  + B.GetValue(0))}, A.Size);
+                    } else if (B.IsEmpty) {
+                        return  ILRetArray<fcomplex>.empty(outDims); 
+                    } else {
+                        outLen = outDims.NumberOfElements; 
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< fcomplex > (outLen);
+                            mode = BinOpItMode.SAN; 
+                        } else {
+                            mode = BinOpItMode.SAI; 
+                        }
+                    }
+                } else {
+                    outDims = A.Size; 
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return  ILRetArray<fcomplex>.empty(A.Size);  
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< fcomplex > (outLen);
+                            mode = BinOpItMode.ASN; 
+                        } else {
+                            mode = BinOpItMode.ASI; 
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  addEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (A.TryGetStorage4InplaceOp(out retArr)) 
+                            mode  = BinOpItMode.AAIA; 
+                        else if (B.TryGetStorage4InplaceOp(out retArr)) 
+                            mode = BinOpItMode.AAIB; 
+                        else {
+                            retArr = ILMemoryPool.Pool.New< fcomplex > (outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<fcomplex> retStorage = new ILDenseStorage<fcomplex>(retArr, outDims);
+                int i = 0, workerCount = 1; 
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    fcomplex* cp = (fcomplex*)range.Item5 + range.Item1;
+                    fcomplex scalar;
+                    int j = range.Item2; 
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           fcomplex* bp = ((fcomplex*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                                cp[0] =   (cp[0]  + bp[0]);
+                                cp[1] =   (cp[1]  + bp[1]);
+                                cp[2] =   (cp[2]  + bp[2]);
+                                cp[3] =   (cp[3]  + bp[3]);
+                                cp[4] =   (cp[4]  + bp[4]);
+                                cp[5] =   (cp[5]  + bp[5]);
+                                cp[6] =   (cp[6]  + bp[6]);
+                                cp[7] =   (cp[7]  + bp[7]);
+                                cp[8] =   (cp[8]  + bp[8]);
+                                cp[9] =   (cp[9]  + bp[9]);
+                                cp[10] =   (cp[10]  + bp[10]);
+                                cp[11] =   (cp[11]  + bp[11]);
+                                cp[12] =   (cp[12]  + bp[12]);
+                                cp[13] =   (cp[13]  + bp[13]);
+                                cp[14] =   (cp[14]  + bp[14]);
+                                cp[15] =   (cp[15]  + bp[15]);
+                                cp[16] =   (cp[16]  + bp[16]);
+                                cp[17] =   (cp[17]  + bp[17]);
+                                cp[18] =   (cp[18]  + bp[18]);
+                                cp[19] =   (cp[19]  + bp[19]);
+                                cp[20] =   (cp[20]  + bp[20]);
+                                cp += 21; bp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*cp  + *bp);
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           fcomplex* ap = ((fcomplex*)range.Item3 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  + cp[0]);
+                                cp[1] =   (ap[1]  + cp[1]);
+                                cp[2] =   (ap[2]  + cp[2]);
+                                cp[3] =   (ap[3]  + cp[3]);
+                                cp[4] =   (ap[4]  + cp[4]);
+                                cp[5] =   (ap[5]  + cp[5]);
+                                cp[6] =   (ap[6]  + cp[6]);
+                                cp[7] =   (ap[7]  + cp[7]);
+                                cp[8] =   (ap[8]  + cp[8]);
+                                cp[9] =   (ap[9]  + cp[9]);
+                                cp[10] =   (ap[10]  + cp[10]);
+                                cp[11] =   (ap[11]  + cp[11]);
+                                cp[12] =   (ap[12]  + cp[12]);
+                                cp[13] =   (ap[13]  + cp[13]);
+                                cp[14] =   (ap[14]  + cp[14]);
+                                cp[15] =   (ap[15]  + cp[15]);
+                                cp[16] =   (ap[16]  + cp[16]);
+                                cp[17] =   (ap[17]  + cp[17]);
+                                cp[18] =   (ap[18]  + cp[18]);
+                                cp[19] =   (ap[19]  + cp[19]);
+                                cp[20] =   (ap[20]  + cp[20]);
+                                ap += 21; cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  + *cp);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((fcomplex*)range.Item3 + range.Item1);
+                            bp = ((fcomplex*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  + bp[0]);
+                                cp[1] =   (ap[1]  + bp[1]);
+                                cp[2] =   (ap[2]  + bp[2]);
+                                cp[3] =   (ap[3]  + bp[3]);
+                                cp[4] =   (ap[4]  + bp[4]);
+                                cp[5] =   (ap[5]  + bp[5]);
+                                cp[6] =   (ap[6]  + bp[6]);
+                                cp[7] =   (ap[7]  + bp[7]);
+                                cp[8] =   (ap[8]  + bp[8]);
+                                cp[9] =   (ap[9]  + bp[9]);
+                                cp[10] =   (ap[10]  + bp[10]);
+                                cp[11] =   (ap[11]  + bp[11]);
+                                cp[12] =   (ap[12]  + bp[12]);
+                                cp[13] =   (ap[13]  + bp[13]);
+                                cp[14] =   (ap[14]  + bp[14]);
+                                cp[15] =   (ap[15]  + bp[15]);
+                                cp[16] =   (ap[16]  + bp[16]);
+                                cp[17] =   (ap[17]  + bp[17]);
+                                cp[18] =   (ap[18]  + bp[18]);
+                                cp[19] =   (ap[19]  + bp[19]);
+                                cp[20] =   (ap[20]  + bp[20]);
+                                ap+=21; bp+=21; cp+=21; j-=21;
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  + *bp);
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((fcomplex*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =   (cp[0]  + scalar);
+                                cp[1] =   (cp[1]  + scalar);
+                                cp[2] =   (cp[2]  + scalar);
+                                cp[3] =   (cp[3]  + scalar);
+                                cp[4] =   (cp[4]  + scalar);
+                                cp[5] =   (cp[5]  + scalar);
+                                cp[6] =   (cp[6]  + scalar);
+                                cp[7] =   (cp[7]  + scalar);
+                                cp[8] =   (cp[8]  + scalar);
+                                cp[9] =   (cp[9]  + scalar);
+                                cp[10] =   (cp[10]  + scalar);
+                                cp[11] =   (cp[11]  + scalar);
+                                cp[12] =   (cp[12]  + scalar);
+                                cp[13] =   (cp[13]  + scalar);
+                                cp[14] =   (cp[14]  + scalar);
+                                cp[15] =   (cp[15]  + scalar);
+                                cp[16] =   (cp[16]  + scalar);
+                                cp[17] =   (cp[17]  + scalar);
+                                cp[18] =   (cp[18]  + scalar);
+                                cp[19] =   (cp[19]  + scalar);
+                                cp[20] =   (cp[20]  + scalar);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*cp  + scalar);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((fcomplex*)range.Item3 + range.Item1);
+                            scalar = *((fcomplex*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  + scalar);
+                                cp[1] =   (ap[1]  + scalar);
+                                cp[2] =   (ap[2]  + scalar);
+                                cp[3] =   (ap[3]  + scalar);
+                                cp[4] =   (ap[4]  + scalar);
+                                cp[5] =   (ap[5]  + scalar);
+                                cp[6] =   (ap[6]  + scalar);
+                                cp[7] =   (ap[7]  + scalar);
+                                cp[8] =   (ap[8]  + scalar);
+                                cp[9] =   (ap[9]  + scalar);
+                                cp[10] =   (ap[10]  + scalar);
+                                cp[11] =   (ap[11]  + scalar);
+                                cp[12] =   (ap[12]  + scalar);
+                                cp[13] =   (ap[13]  + scalar);
+                                cp[14] =   (ap[14]  + scalar);
+                                cp[15] =   (ap[15]  + scalar);
+                                cp[16] =   (ap[16]  + scalar);
+                                cp[17] =   (ap[17]  + scalar);
+                                cp[18] =   (ap[18]  + scalar);
+                                cp[19] =   (ap[19]  + scalar);
+                                cp[20] =   (ap[20]  + scalar);
+                                ap+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  + scalar);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((fcomplex*)range.Item3);
+                            while (j > 20) {
+                               
+                                cp[0] =   (scalar  + cp[0]);
+                                cp[1] =   (scalar  + cp[1]);
+                                cp[2] =   (scalar  + cp[2]);
+                                cp[3] =   (scalar  + cp[3]);
+                                cp[4] =   (scalar  + cp[4]);
+                                cp[5] =   (scalar  + cp[5]);
+                                cp[6] =   (scalar  + cp[6]);
+                                cp[7] =   (scalar  + cp[7]);
+                                cp[8] =   (scalar  + cp[8]);
+                                cp[9] =   (scalar  + cp[9]);
+                                cp[10] =   (scalar  + cp[10]);
+                                cp[11] =   (scalar  + cp[11]);
+                                cp[12] =   (scalar  + cp[12]);
+                                cp[13] =   (scalar  + cp[13]);
+                                cp[14] =   (scalar  + cp[14]);
+                                cp[15] =   (scalar  + cp[15]);
+                                cp[16] =   (scalar  + cp[16]);
+                                cp[17] =   (scalar  + cp[17]);
+                                cp[18] =   (scalar  + cp[18]);
+                                cp[19] =   (scalar  + cp[19]);
+                                cp[20] =   (scalar  + cp[20]);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (scalar  + *cp);
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((fcomplex*)range.Item3);
+                            bp = ((fcomplex*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (scalar  + bp[0]);
+                                cp[1] =   (scalar  + bp[1]);
+                                cp[2] =   (scalar  + bp[2]);
+                                cp[3] =   (scalar  + bp[3]);
+                                cp[4] =   (scalar  + bp[4]);
+                                cp[5] =   (scalar  + bp[5]);
+                                cp[6] =   (scalar  + bp[6]);
+                                cp[7] =   (scalar  + bp[7]);
+                                cp[8] =   (scalar  + bp[8]);
+                                cp[9] =   (scalar  + bp[9]);
+                                cp[10] =   (scalar  + bp[10]);
+                                cp[11] =   (scalar  + bp[11]);
+                                cp[12] =   (scalar  + bp[12]);
+                                cp[13] =   (scalar  + bp[13]);
+                                cp[14] =   (scalar  + bp[14]);
+                                cp[15] =   (scalar  + bp[15]);
+                                cp[16] =   (scalar  + bp[16]);
+                                cp[17] =   (scalar  + bp[17]);
+                                cp[18] =   (scalar  + bp[18]);
+                                cp[19] =   (scalar  + bp[19]);
+                                cp[20] =   (scalar  + bp[20]);
+                                bp+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (scalar  + *bp);
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work 
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                
+                fixed ( fcomplex* arrAP = arrA)
+                fixed ( fcomplex* arrBP = arrB)
+                fixed ( fcomplex* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range 
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new  ILRetArray< fcomplex>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<fcomplex>  addEx(ILInArray<fcomplex> A, ILInArray<fcomplex> B) {
+            //using (ILScope.Enter(A, B)) { we cannot start a new scope here, since this would prevent A and B to be used implace if applicable
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<fcomplex>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<fcomplex>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<fcomplex>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                dim = -(dim - 1);  // 0 -> 1, 1 -> 0
+                #endregion
+
+                #region parameter preparation
+               
+                fcomplex[] retArr;
+               
+                fcomplex[] arrA = A.GetArrayForRead();
+               
+                fcomplex[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int workItemMultiplierLenA;
+                int workItemMultiplierLenB;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<fcomplex>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    workItemMultiplierLenB = outDims[0]; 
+                    workItemMultiplierLenA = dim;  // 0 for column, 1 for row vector
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<fcomplex>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    workItemMultiplierLenB = dim;  // 0 for column, 1 for row vector
+                    workItemMultiplierLenA = outDims[0]; 
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one singleton dimension in either A or B");
+                }
+                int itLen = outDims[0]; // (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<fcomplex> retStorage = new ILDenseStorage<fcomplex>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    fcomplex* ap;
+                   
+                    fcomplex* bp;
+                   
+                    fcomplex* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            if (dim == 0) {
+                                bp = (fcomplex*)range.Item3;
+                                cp = (fcomplex*)range.Item4; 
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (fcomplex*)range.Item2;
+                                    int l = itLen; 
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  + bp[0]);
+                                        cp[1] =   (ap[1]  + bp[1]);
+                                        cp[2] =   (ap[2]  + bp[2]);
+                                        cp[3] =   (ap[3]  + bp[3]);
+                                        cp[4] =   (ap[4]  + bp[4]);
+                                        cp[5] =   (ap[5]  + bp[5]);
+                                        cp[6] =   (ap[6]  + bp[6]);
+                                        cp[7] =   (ap[7]  + bp[7]);
+                                        cp[8] =   (ap[8]  + bp[8]);
+                                        cp[9] =   (ap[9]  + bp[9]);
+                                        cp[10] =   (ap[10]  + bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =   (*ap++  + *bp++);
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                ap = (fcomplex*)range.Item2;
+                                bp = (fcomplex*)range.Item3;
+                                cp = (fcomplex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   fcomplex val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (val  + bp[0]);
+                                        cp[1] =   (val  + bp[1]);
+                                        cp[2] =   (val  + bp[2]);
+                                        cp[3] =   (val  + bp[3]);
+                                        cp[4] =   (val  + bp[4]);
+                                        cp[5] =   (val  + bp[5]);
+                                        cp[6] =   (val  + bp[6]);
+                                        cp[7] =   (val  + bp[7]);
+                                        cp[8] =   (val  + bp[8]);
+                                        cp[9] =   (val  + bp[9]);
+                                        cp[10] =   (val  + bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11; 
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =   (val  + *bp++);
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            if (dim == 0) {
+                                cp = (fcomplex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (fcomplex*)range.Item2;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  + cp[0]);
+                                        cp[1] =   (ap[1]  + cp[1]);
+                                        cp[2] =   (ap[2]  + cp[2]);
+                                        cp[3] =   (ap[3]  + cp[3]);
+                                        cp[4] =   (ap[4]  + cp[4]);
+                                        cp[5] =   (ap[5]  + cp[5]);
+                                        cp[6] =   (ap[6]  + cp[6]);
+                                        cp[7] =   (ap[7]  + cp[7]);
+                                        cp[8] =   (ap[8]  + cp[8]);
+                                        cp[9] =   (ap[9]  + cp[9]);
+                                        cp[10] =   (ap[10]  + cp[10]);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap++  + *cp);
+                                        cp++; 
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                cp = (fcomplex*)range.Item4;
+                                ap = (fcomplex*)range.Item2;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    fcomplex val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (val  + cp[0]);
+                                        cp[1] =   (val  + cp[1]);
+                                        cp[2] =   (val  + cp[2]);
+                                        cp[3] =   (val  + cp[3]);
+                                        cp[4] =   (val  + cp[4]);
+                                        cp[5] =   (val  + cp[5]);
+                                        cp[6] =   (val  + cp[6]);
+                                        cp[7] =   (val  + cp[7]);
+                                        cp[8] =   (val  + cp[8]);
+                                        cp[9] =   (val  + cp[9]);
+                                        cp[10] =   (val  + cp[10]);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (val  + *cp);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            if (dim == 0) {
+                                ap = (fcomplex*)range.Item2;
+                                cp = (fcomplex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (fcomplex*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  + bp[0]);
+                                        cp[1] =   (ap[1]  + bp[1]);
+                                        cp[2] =   (ap[2]  + bp[2]);
+                                        cp[3] =   (ap[3]  + bp[3]);
+                                        cp[4] =   (ap[4]  + bp[4]);
+                                        cp[5] =   (ap[5]  + bp[5]);
+                                        cp[6] =   (ap[6]  + bp[6]);
+                                        cp[7] =   (ap[7]  + bp[7]);
+                                        cp[8] =   (ap[8]  + bp[8]);
+                                        cp[9] =   (ap[9]  + bp[9]);
+                                        cp[10] =   (ap[10]  + bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap  + *bp);
+                                        ap++;
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                ap = (fcomplex*)range.Item2;
+                                bp = (fcomplex*)range.Item3;
+                                cp = (fcomplex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   fcomplex val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  + val);
+                                        cp[1] =   (ap[1]  + val);
+                                        cp[2] =   (ap[2]  + val);
+                                        cp[3] =   (ap[3]  + val);
+                                        cp[4] =   (ap[4]  + val);
+                                        cp[5] =   (ap[5]  + val);
+                                        cp[6] =   (ap[6]  + val);
+                                        cp[7] =   (ap[7]  + val);
+                                        cp[8] =   (ap[8]  + val);
+                                        cp[9] =   (ap[9]  + val);
+                                        cp[10] =   (ap[10]  + val);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap  + val);
+                                        ap++;
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            if (dim == 0) {
+                                cp = (fcomplex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (fcomplex*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (cp[0]  + bp[0]);
+                                        cp[1] =   (cp[1]  + bp[1]);
+                                        cp[2] =   (cp[2]  + bp[2]);
+                                        cp[3] =   (cp[3]  + bp[3]);
+                                        cp[4] =   (cp[4]  + bp[4]);
+                                        cp[5] =   (cp[5]  + bp[5]);
+                                        cp[6] =   (cp[6]  + bp[6]);
+                                        cp[7] =   (cp[7]  + bp[7]);
+                                        cp[8] =   (cp[8]  + bp[8]);
+                                        cp[9] =   (cp[9]  + bp[9]);
+                                        cp[10] =   (cp[10]  + bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*cp  + *bp);
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                bp = (fcomplex*)range.Item3;
+                                cp = (fcomplex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    fcomplex val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (cp[0]  + val);
+                                        cp[1] =   (cp[1]  + val);
+                                        cp[2] =   (cp[2]  + val);
+                                        cp[3] =   (cp[3]  + val);
+                                        cp[4] =   (cp[4]  + val);
+                                        cp[5] =   (cp[5]  + val);
+                                        cp[6] =   (cp[6]  + val);
+                                        cp[7] =   (cp[7]  + val);
+                                        cp[8] =   (cp[8]  + val);
+                                        cp[9] =   (cp[9]  + val);
+                                        cp[10] =   (cp[10]  + val);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l --> 0) {
+                                        *cp =   (*cp  + val);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outDims.NumberOfElements >= Settings.s_minParallelElement1Count
+                    && outDims[1] > 1) {
+                        if (outDims[1] > workItemCount) {
+                        workItemLength = outDims[1] / workItemCount;
+                    } else {
+                        workItemLength = outDims[1] / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outDims[1];
+                    workItemCount = 1;
+                }
+
+                fixed ( fcomplex* arrAP = arrA)
+                fixed ( fcomplex* arrBP = arrB)
+                fixed ( fcomplex* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, IntPtr, IntPtr, IntPtr> range = new Tuple<int, IntPtr, IntPtr, IntPtr>
+                               (workItemLength
+                               , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                               , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                               , (IntPtr)(retArrP + i * outDims[0] * workItemLength)); 
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, IntPtr, IntPtr, IntPtr>
+                                (outDims[1] - i * workItemLength
+                                , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                                , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                                , (IntPtr)(retArrP + i * outDims[0] * workItemLength)));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<fcomplex>(retStorage);
+            //}  // no scopes here! it disables implace operations
+        }
+
+        /// <summary>Add arrays elementwise</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Array with elementwise sum of A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<complex>  add(ILInArray<complex> A, ILInArray<complex> B) {
+            using (ILScope.Enter(A,B)) {
+                int outLen; 
+                BinOpItMode mode; 
+                complex [] retArr;
+                complex [] arrA = A.GetArrayForRead();
+                complex[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size; 
+                    if (B.IsScalar) {
+                       
+                        return new  ILRetArray<complex> (new  complex [1]{  (A.GetValue(0)  + B.GetValue(0))}, A.Size);
+                    } else if (B.IsEmpty) {
+                        return  ILRetArray<complex>.empty(outDims); 
+                    } else {
+                        outLen = outDims.NumberOfElements; 
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< complex > (outLen);
+                            mode = BinOpItMode.SAN; 
+                        } else {
+                            mode = BinOpItMode.SAI; 
+                        }
+                    }
+                } else {
+                    outDims = A.Size; 
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return  ILRetArray<complex>.empty(A.Size);  
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< complex > (outLen);
+                            mode = BinOpItMode.ASN; 
+                        } else {
+                            mode = BinOpItMode.ASI; 
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  addEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (A.TryGetStorage4InplaceOp(out retArr)) 
+                            mode  = BinOpItMode.AAIA; 
+                        else if (B.TryGetStorage4InplaceOp(out retArr)) 
+                            mode = BinOpItMode.AAIB; 
+                        else {
+                            retArr = ILMemoryPool.Pool.New< complex > (outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<complex> retStorage = new ILDenseStorage<complex>(retArr, outDims);
+                int i = 0, workerCount = 1; 
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    complex* cp = (complex*)range.Item5 + range.Item1;
+                    complex scalar;
+                    int j = range.Item2; 
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           complex* bp = ((complex*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                                cp[0] =   (cp[0]  + bp[0]);
+                                cp[1] =   (cp[1]  + bp[1]);
+                                cp[2] =   (cp[2]  + bp[2]);
+                                cp[3] =   (cp[3]  + bp[3]);
+                                cp[4] =   (cp[4]  + bp[4]);
+                                cp[5] =   (cp[5]  + bp[5]);
+                                cp[6] =   (cp[6]  + bp[6]);
+                                cp[7] =   (cp[7]  + bp[7]);
+                                cp[8] =   (cp[8]  + bp[8]);
+                                cp[9] =   (cp[9]  + bp[9]);
+                                cp[10] =   (cp[10]  + bp[10]);
+                                cp[11] =   (cp[11]  + bp[11]);
+                                cp[12] =   (cp[12]  + bp[12]);
+                                cp[13] =   (cp[13]  + bp[13]);
+                                cp[14] =   (cp[14]  + bp[14]);
+                                cp[15] =   (cp[15]  + bp[15]);
+                                cp[16] =   (cp[16]  + bp[16]);
+                                cp[17] =   (cp[17]  + bp[17]);
+                                cp[18] =   (cp[18]  + bp[18]);
+                                cp[19] =   (cp[19]  + bp[19]);
+                                cp[20] =   (cp[20]  + bp[20]);
+                                cp += 21; bp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*cp  + *bp);
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           complex* ap = ((complex*)range.Item3 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  + cp[0]);
+                                cp[1] =   (ap[1]  + cp[1]);
+                                cp[2] =   (ap[2]  + cp[2]);
+                                cp[3] =   (ap[3]  + cp[3]);
+                                cp[4] =   (ap[4]  + cp[4]);
+                                cp[5] =   (ap[5]  + cp[5]);
+                                cp[6] =   (ap[6]  + cp[6]);
+                                cp[7] =   (ap[7]  + cp[7]);
+                                cp[8] =   (ap[8]  + cp[8]);
+                                cp[9] =   (ap[9]  + cp[9]);
+                                cp[10] =   (ap[10]  + cp[10]);
+                                cp[11] =   (ap[11]  + cp[11]);
+                                cp[12] =   (ap[12]  + cp[12]);
+                                cp[13] =   (ap[13]  + cp[13]);
+                                cp[14] =   (ap[14]  + cp[14]);
+                                cp[15] =   (ap[15]  + cp[15]);
+                                cp[16] =   (ap[16]  + cp[16]);
+                                cp[17] =   (ap[17]  + cp[17]);
+                                cp[18] =   (ap[18]  + cp[18]);
+                                cp[19] =   (ap[19]  + cp[19]);
+                                cp[20] =   (ap[20]  + cp[20]);
+                                ap += 21; cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  + *cp);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((complex*)range.Item3 + range.Item1);
+                            bp = ((complex*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  + bp[0]);
+                                cp[1] =   (ap[1]  + bp[1]);
+                                cp[2] =   (ap[2]  + bp[2]);
+                                cp[3] =   (ap[3]  + bp[3]);
+                                cp[4] =   (ap[4]  + bp[4]);
+                                cp[5] =   (ap[5]  + bp[5]);
+                                cp[6] =   (ap[6]  + bp[6]);
+                                cp[7] =   (ap[7]  + bp[7]);
+                                cp[8] =   (ap[8]  + bp[8]);
+                                cp[9] =   (ap[9]  + bp[9]);
+                                cp[10] =   (ap[10]  + bp[10]);
+                                cp[11] =   (ap[11]  + bp[11]);
+                                cp[12] =   (ap[12]  + bp[12]);
+                                cp[13] =   (ap[13]  + bp[13]);
+                                cp[14] =   (ap[14]  + bp[14]);
+                                cp[15] =   (ap[15]  + bp[15]);
+                                cp[16] =   (ap[16]  + bp[16]);
+                                cp[17] =   (ap[17]  + bp[17]);
+                                cp[18] =   (ap[18]  + bp[18]);
+                                cp[19] =   (ap[19]  + bp[19]);
+                                cp[20] =   (ap[20]  + bp[20]);
+                                ap+=21; bp+=21; cp+=21; j-=21;
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  + *bp);
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((complex*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =   (cp[0]  + scalar);
+                                cp[1] =   (cp[1]  + scalar);
+                                cp[2] =   (cp[2]  + scalar);
+                                cp[3] =   (cp[3]  + scalar);
+                                cp[4] =   (cp[4]  + scalar);
+                                cp[5] =   (cp[5]  + scalar);
+                                cp[6] =   (cp[6]  + scalar);
+                                cp[7] =   (cp[7]  + scalar);
+                                cp[8] =   (cp[8]  + scalar);
+                                cp[9] =   (cp[9]  + scalar);
+                                cp[10] =   (cp[10]  + scalar);
+                                cp[11] =   (cp[11]  + scalar);
+                                cp[12] =   (cp[12]  + scalar);
+                                cp[13] =   (cp[13]  + scalar);
+                                cp[14] =   (cp[14]  + scalar);
+                                cp[15] =   (cp[15]  + scalar);
+                                cp[16] =   (cp[16]  + scalar);
+                                cp[17] =   (cp[17]  + scalar);
+                                cp[18] =   (cp[18]  + scalar);
+                                cp[19] =   (cp[19]  + scalar);
+                                cp[20] =   (cp[20]  + scalar);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*cp  + scalar);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((complex*)range.Item3 + range.Item1);
+                            scalar = *((complex*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  + scalar);
+                                cp[1] =   (ap[1]  + scalar);
+                                cp[2] =   (ap[2]  + scalar);
+                                cp[3] =   (ap[3]  + scalar);
+                                cp[4] =   (ap[4]  + scalar);
+                                cp[5] =   (ap[5]  + scalar);
+                                cp[6] =   (ap[6]  + scalar);
+                                cp[7] =   (ap[7]  + scalar);
+                                cp[8] =   (ap[8]  + scalar);
+                                cp[9] =   (ap[9]  + scalar);
+                                cp[10] =   (ap[10]  + scalar);
+                                cp[11] =   (ap[11]  + scalar);
+                                cp[12] =   (ap[12]  + scalar);
+                                cp[13] =   (ap[13]  + scalar);
+                                cp[14] =   (ap[14]  + scalar);
+                                cp[15] =   (ap[15]  + scalar);
+                                cp[16] =   (ap[16]  + scalar);
+                                cp[17] =   (ap[17]  + scalar);
+                                cp[18] =   (ap[18]  + scalar);
+                                cp[19] =   (ap[19]  + scalar);
+                                cp[20] =   (ap[20]  + scalar);
+                                ap+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  + scalar);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((complex*)range.Item3);
+                            while (j > 20) {
+                               
+                                cp[0] =   (scalar  + cp[0]);
+                                cp[1] =   (scalar  + cp[1]);
+                                cp[2] =   (scalar  + cp[2]);
+                                cp[3] =   (scalar  + cp[3]);
+                                cp[4] =   (scalar  + cp[4]);
+                                cp[5] =   (scalar  + cp[5]);
+                                cp[6] =   (scalar  + cp[6]);
+                                cp[7] =   (scalar  + cp[7]);
+                                cp[8] =   (scalar  + cp[8]);
+                                cp[9] =   (scalar  + cp[9]);
+                                cp[10] =   (scalar  + cp[10]);
+                                cp[11] =   (scalar  + cp[11]);
+                                cp[12] =   (scalar  + cp[12]);
+                                cp[13] =   (scalar  + cp[13]);
+                                cp[14] =   (scalar  + cp[14]);
+                                cp[15] =   (scalar  + cp[15]);
+                                cp[16] =   (scalar  + cp[16]);
+                                cp[17] =   (scalar  + cp[17]);
+                                cp[18] =   (scalar  + cp[18]);
+                                cp[19] =   (scalar  + cp[19]);
+                                cp[20] =   (scalar  + cp[20]);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (scalar  + *cp);
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((complex*)range.Item3);
+                            bp = ((complex*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (scalar  + bp[0]);
+                                cp[1] =   (scalar  + bp[1]);
+                                cp[2] =   (scalar  + bp[2]);
+                                cp[3] =   (scalar  + bp[3]);
+                                cp[4] =   (scalar  + bp[4]);
+                                cp[5] =   (scalar  + bp[5]);
+                                cp[6] =   (scalar  + bp[6]);
+                                cp[7] =   (scalar  + bp[7]);
+                                cp[8] =   (scalar  + bp[8]);
+                                cp[9] =   (scalar  + bp[9]);
+                                cp[10] =   (scalar  + bp[10]);
+                                cp[11] =   (scalar  + bp[11]);
+                                cp[12] =   (scalar  + bp[12]);
+                                cp[13] =   (scalar  + bp[13]);
+                                cp[14] =   (scalar  + bp[14]);
+                                cp[15] =   (scalar  + bp[15]);
+                                cp[16] =   (scalar  + bp[16]);
+                                cp[17] =   (scalar  + bp[17]);
+                                cp[18] =   (scalar  + bp[18]);
+                                cp[19] =   (scalar  + bp[19]);
+                                cp[20] =   (scalar  + bp[20]);
+                                bp+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (scalar  + *bp);
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work 
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                
+                fixed ( complex* arrAP = arrA)
+                fixed ( complex* arrBP = arrB)
+                fixed ( complex* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range 
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new  ILRetArray< complex>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<complex>  addEx(ILInArray<complex> A, ILInArray<complex> B) {
+            //using (ILScope.Enter(A, B)) { we cannot start a new scope here, since this would prevent A and B to be used implace if applicable
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<complex>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<complex>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<complex>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                dim = -(dim - 1);  // 0 -> 1, 1 -> 0
+                #endregion
+
+                #region parameter preparation
+               
+                complex[] retArr;
+               
+                complex[] arrA = A.GetArrayForRead();
+               
+                complex[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int workItemMultiplierLenA;
+                int workItemMultiplierLenB;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<complex>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    workItemMultiplierLenB = outDims[0]; 
+                    workItemMultiplierLenA = dim;  // 0 for column, 1 for row vector
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<complex>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    workItemMultiplierLenB = dim;  // 0 for column, 1 for row vector
+                    workItemMultiplierLenA = outDims[0]; 
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one singleton dimension in either A or B");
+                }
+                int itLen = outDims[0]; // (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<complex> retStorage = new ILDenseStorage<complex>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    complex* ap;
+                   
+                    complex* bp;
+                   
+                    complex* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            if (dim == 0) {
+                                bp = (complex*)range.Item3;
+                                cp = (complex*)range.Item4; 
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (complex*)range.Item2;
+                                    int l = itLen; 
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  + bp[0]);
+                                        cp[1] =   (ap[1]  + bp[1]);
+                                        cp[2] =   (ap[2]  + bp[2]);
+                                        cp[3] =   (ap[3]  + bp[3]);
+                                        cp[4] =   (ap[4]  + bp[4]);
+                                        cp[5] =   (ap[5]  + bp[5]);
+                                        cp[6] =   (ap[6]  + bp[6]);
+                                        cp[7] =   (ap[7]  + bp[7]);
+                                        cp[8] =   (ap[8]  + bp[8]);
+                                        cp[9] =   (ap[9]  + bp[9]);
+                                        cp[10] =   (ap[10]  + bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =   (*ap++  + *bp++);
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                ap = (complex*)range.Item2;
+                                bp = (complex*)range.Item3;
+                                cp = (complex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   complex val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (val  + bp[0]);
+                                        cp[1] =   (val  + bp[1]);
+                                        cp[2] =   (val  + bp[2]);
+                                        cp[3] =   (val  + bp[3]);
+                                        cp[4] =   (val  + bp[4]);
+                                        cp[5] =   (val  + bp[5]);
+                                        cp[6] =   (val  + bp[6]);
+                                        cp[7] =   (val  + bp[7]);
+                                        cp[8] =   (val  + bp[8]);
+                                        cp[9] =   (val  + bp[9]);
+                                        cp[10] =   (val  + bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11; 
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =   (val  + *bp++);
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            if (dim == 0) {
+                                cp = (complex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (complex*)range.Item2;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  + cp[0]);
+                                        cp[1] =   (ap[1]  + cp[1]);
+                                        cp[2] =   (ap[2]  + cp[2]);
+                                        cp[3] =   (ap[3]  + cp[3]);
+                                        cp[4] =   (ap[4]  + cp[4]);
+                                        cp[5] =   (ap[5]  + cp[5]);
+                                        cp[6] =   (ap[6]  + cp[6]);
+                                        cp[7] =   (ap[7]  + cp[7]);
+                                        cp[8] =   (ap[8]  + cp[8]);
+                                        cp[9] =   (ap[9]  + cp[9]);
+                                        cp[10] =   (ap[10]  + cp[10]);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap++  + *cp);
+                                        cp++; 
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                cp = (complex*)range.Item4;
+                                ap = (complex*)range.Item2;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    complex val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (val  + cp[0]);
+                                        cp[1] =   (val  + cp[1]);
+                                        cp[2] =   (val  + cp[2]);
+                                        cp[3] =   (val  + cp[3]);
+                                        cp[4] =   (val  + cp[4]);
+                                        cp[5] =   (val  + cp[5]);
+                                        cp[6] =   (val  + cp[6]);
+                                        cp[7] =   (val  + cp[7]);
+                                        cp[8] =   (val  + cp[8]);
+                                        cp[9] =   (val  + cp[9]);
+                                        cp[10] =   (val  + cp[10]);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (val  + *cp);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            if (dim == 0) {
+                                ap = (complex*)range.Item2;
+                                cp = (complex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (complex*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  + bp[0]);
+                                        cp[1] =   (ap[1]  + bp[1]);
+                                        cp[2] =   (ap[2]  + bp[2]);
+                                        cp[3] =   (ap[3]  + bp[3]);
+                                        cp[4] =   (ap[4]  + bp[4]);
+                                        cp[5] =   (ap[5]  + bp[5]);
+                                        cp[6] =   (ap[6]  + bp[6]);
+                                        cp[7] =   (ap[7]  + bp[7]);
+                                        cp[8] =   (ap[8]  + bp[8]);
+                                        cp[9] =   (ap[9]  + bp[9]);
+                                        cp[10] =   (ap[10]  + bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap  + *bp);
+                                        ap++;
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                ap = (complex*)range.Item2;
+                                bp = (complex*)range.Item3;
+                                cp = (complex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   complex val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  + val);
+                                        cp[1] =   (ap[1]  + val);
+                                        cp[2] =   (ap[2]  + val);
+                                        cp[3] =   (ap[3]  + val);
+                                        cp[4] =   (ap[4]  + val);
+                                        cp[5] =   (ap[5]  + val);
+                                        cp[6] =   (ap[6]  + val);
+                                        cp[7] =   (ap[7]  + val);
+                                        cp[8] =   (ap[8]  + val);
+                                        cp[9] =   (ap[9]  + val);
+                                        cp[10] =   (ap[10]  + val);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap  + val);
+                                        ap++;
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            if (dim == 0) {
+                                cp = (complex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (complex*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (cp[0]  + bp[0]);
+                                        cp[1] =   (cp[1]  + bp[1]);
+                                        cp[2] =   (cp[2]  + bp[2]);
+                                        cp[3] =   (cp[3]  + bp[3]);
+                                        cp[4] =   (cp[4]  + bp[4]);
+                                        cp[5] =   (cp[5]  + bp[5]);
+                                        cp[6] =   (cp[6]  + bp[6]);
+                                        cp[7] =   (cp[7]  + bp[7]);
+                                        cp[8] =   (cp[8]  + bp[8]);
+                                        cp[9] =   (cp[9]  + bp[9]);
+                                        cp[10] =   (cp[10]  + bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*cp  + *bp);
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                bp = (complex*)range.Item3;
+                                cp = (complex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    complex val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (cp[0]  + val);
+                                        cp[1] =   (cp[1]  + val);
+                                        cp[2] =   (cp[2]  + val);
+                                        cp[3] =   (cp[3]  + val);
+                                        cp[4] =   (cp[4]  + val);
+                                        cp[5] =   (cp[5]  + val);
+                                        cp[6] =   (cp[6]  + val);
+                                        cp[7] =   (cp[7]  + val);
+                                        cp[8] =   (cp[8]  + val);
+                                        cp[9] =   (cp[9]  + val);
+                                        cp[10] =   (cp[10]  + val);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l --> 0) {
+                                        *cp =   (*cp  + val);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outDims.NumberOfElements >= Settings.s_minParallelElement1Count
+                    && outDims[1] > 1) {
+                        if (outDims[1] > workItemCount) {
+                        workItemLength = outDims[1] / workItemCount;
+                    } else {
+                        workItemLength = outDims[1] / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outDims[1];
+                    workItemCount = 1;
+                }
+
+                fixed ( complex* arrAP = arrA)
+                fixed ( complex* arrBP = arrB)
+                fixed ( complex* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, IntPtr, IntPtr, IntPtr> range = new Tuple<int, IntPtr, IntPtr, IntPtr>
+                               (workItemLength
+                               , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                               , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                               , (IntPtr)(retArrP + i * outDims[0] * workItemLength)); 
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, IntPtr, IntPtr, IntPtr>
+                                (outDims[1] - i * workItemLength
+                                , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                                , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                                , (IntPtr)(retArrP + i * outDims[0] * workItemLength)));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<complex>(retStorage);
+            //}  // no scopes here! it disables implace operations
+        }
+
+        /// <summary>Add arrays elementwise</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Array with elementwise sum of A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<byte>  add(ILInArray<byte> A, ILInArray<byte> B) {
+            using (ILScope.Enter(A,B)) {
+                int outLen; 
+                BinOpItMode mode; 
+                byte [] retArr;
+                byte [] arrA = A.GetArrayForRead();
+                byte[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size; 
+                    if (B.IsScalar) {
+                       
+                        return new  ILRetArray<byte> (new  byte [1]{ saturateByte (A.GetValue(0)  + (double) B.GetValue(0))}, A.Size);
+                    } else if (B.IsEmpty) {
+                        return  ILRetArray<byte>.empty(outDims); 
+                    } else {
+                        outLen = outDims.NumberOfElements; 
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< byte > (outLen);
+                            mode = BinOpItMode.SAN; 
+                        } else {
+                            mode = BinOpItMode.SAI; 
+                        }
+                    }
+                } else {
+                    outDims = A.Size; 
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return  ILRetArray<byte>.empty(A.Size);  
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< byte > (outLen);
+                            mode = BinOpItMode.ASN; 
+                        } else {
+                            mode = BinOpItMode.ASI; 
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  addEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (A.TryGetStorage4InplaceOp(out retArr)) 
+                            mode  = BinOpItMode.AAIA; 
+                        else if (B.TryGetStorage4InplaceOp(out retArr)) 
+                            mode = BinOpItMode.AAIB; 
+                        else {
+                            retArr = ILMemoryPool.Pool.New< byte > (outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<byte> retStorage = new ILDenseStorage<byte>(retArr, outDims);
+                int i = 0, workerCount = 1; 
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cp = (byte*)range.Item5 + range.Item1;
+                    byte scalar;
+                    int j = range.Item2; 
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           byte* bp = ((byte*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                                cp[0] =  saturateByte (cp[0]  + (double) bp[0]);
+                                cp[1] =  saturateByte (cp[1]  + (double) bp[1]);
+                                cp[2] =  saturateByte (cp[2]  + (double) bp[2]);
+                                cp[3] =  saturateByte (cp[3]  + (double) bp[3]);
+                                cp[4] =  saturateByte (cp[4]  + (double) bp[4]);
+                                cp[5] =  saturateByte (cp[5]  + (double) bp[5]);
+                                cp[6] =  saturateByte (cp[6]  + (double) bp[6]);
+                                cp[7] =  saturateByte (cp[7]  + (double) bp[7]);
+                                cp[8] =  saturateByte (cp[8]  + (double) bp[8]);
+                                cp[9] =  saturateByte (cp[9]  + (double) bp[9]);
+                                cp[10] =  saturateByte (cp[10]  + (double) bp[10]);
+                                cp[11] =  saturateByte (cp[11]  + (double) bp[11]);
+                                cp[12] =  saturateByte (cp[12]  + (double) bp[12]);
+                                cp[13] =  saturateByte (cp[13]  + (double) bp[13]);
+                                cp[14] =  saturateByte (cp[14]  + (double) bp[14]);
+                                cp[15] =  saturateByte (cp[15]  + (double) bp[15]);
+                                cp[16] =  saturateByte (cp[16]  + (double) bp[16]);
+                                cp[17] =  saturateByte (cp[17]  + (double) bp[17]);
+                                cp[18] =  saturateByte (cp[18]  + (double) bp[18]);
+                                cp[19] =  saturateByte (cp[19]  + (double) bp[19]);
+                                cp[20] =  saturateByte (cp[20]  + (double) bp[20]);
+                                cp += 21; bp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateByte (*cp  + (double) *bp);
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           byte* ap = ((byte*)range.Item3 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateByte (ap[0]  + (double) cp[0]);
+                                cp[1] =  saturateByte (ap[1]  + (double) cp[1]);
+                                cp[2] =  saturateByte (ap[2]  + (double) cp[2]);
+                                cp[3] =  saturateByte (ap[3]  + (double) cp[3]);
+                                cp[4] =  saturateByte (ap[4]  + (double) cp[4]);
+                                cp[5] =  saturateByte (ap[5]  + (double) cp[5]);
+                                cp[6] =  saturateByte (ap[6]  + (double) cp[6]);
+                                cp[7] =  saturateByte (ap[7]  + (double) cp[7]);
+                                cp[8] =  saturateByte (ap[8]  + (double) cp[8]);
+                                cp[9] =  saturateByte (ap[9]  + (double) cp[9]);
+                                cp[10] =  saturateByte (ap[10]  + (double) cp[10]);
+                                cp[11] =  saturateByte (ap[11]  + (double) cp[11]);
+                                cp[12] =  saturateByte (ap[12]  + (double) cp[12]);
+                                cp[13] =  saturateByte (ap[13]  + (double) cp[13]);
+                                cp[14] =  saturateByte (ap[14]  + (double) cp[14]);
+                                cp[15] =  saturateByte (ap[15]  + (double) cp[15]);
+                                cp[16] =  saturateByte (ap[16]  + (double) cp[16]);
+                                cp[17] =  saturateByte (ap[17]  + (double) cp[17]);
+                                cp[18] =  saturateByte (ap[18]  + (double) cp[18]);
+                                cp[19] =  saturateByte (ap[19]  + (double) cp[19]);
+                                cp[20] =  saturateByte (ap[20]  + (double) cp[20]);
+                                ap += 21; cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateByte (*ap  + (double) *cp);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((byte*)range.Item3 + range.Item1);
+                            bp = ((byte*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateByte (ap[0]  + (double) bp[0]);
+                                cp[1] =  saturateByte (ap[1]  + (double) bp[1]);
+                                cp[2] =  saturateByte (ap[2]  + (double) bp[2]);
+                                cp[3] =  saturateByte (ap[3]  + (double) bp[3]);
+                                cp[4] =  saturateByte (ap[4]  + (double) bp[4]);
+                                cp[5] =  saturateByte (ap[5]  + (double) bp[5]);
+                                cp[6] =  saturateByte (ap[6]  + (double) bp[6]);
+                                cp[7] =  saturateByte (ap[7]  + (double) bp[7]);
+                                cp[8] =  saturateByte (ap[8]  + (double) bp[8]);
+                                cp[9] =  saturateByte (ap[9]  + (double) bp[9]);
+                                cp[10] =  saturateByte (ap[10]  + (double) bp[10]);
+                                cp[11] =  saturateByte (ap[11]  + (double) bp[11]);
+                                cp[12] =  saturateByte (ap[12]  + (double) bp[12]);
+                                cp[13] =  saturateByte (ap[13]  + (double) bp[13]);
+                                cp[14] =  saturateByte (ap[14]  + (double) bp[14]);
+                                cp[15] =  saturateByte (ap[15]  + (double) bp[15]);
+                                cp[16] =  saturateByte (ap[16]  + (double) bp[16]);
+                                cp[17] =  saturateByte (ap[17]  + (double) bp[17]);
+                                cp[18] =  saturateByte (ap[18]  + (double) bp[18]);
+                                cp[19] =  saturateByte (ap[19]  + (double) bp[19]);
+                                cp[20] =  saturateByte (ap[20]  + (double) bp[20]);
+                                ap+=21; bp+=21; cp+=21; j-=21;
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateByte (*ap  + (double) *bp);
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((byte*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateByte (cp[0]  + (double) scalar);
+                                cp[1] =  saturateByte (cp[1]  + (double) scalar);
+                                cp[2] =  saturateByte (cp[2]  + (double) scalar);
+                                cp[3] =  saturateByte (cp[3]  + (double) scalar);
+                                cp[4] =  saturateByte (cp[4]  + (double) scalar);
+                                cp[5] =  saturateByte (cp[5]  + (double) scalar);
+                                cp[6] =  saturateByte (cp[6]  + (double) scalar);
+                                cp[7] =  saturateByte (cp[7]  + (double) scalar);
+                                cp[8] =  saturateByte (cp[8]  + (double) scalar);
+                                cp[9] =  saturateByte (cp[9]  + (double) scalar);
+                                cp[10] =  saturateByte (cp[10]  + (double) scalar);
+                                cp[11] =  saturateByte (cp[11]  + (double) scalar);
+                                cp[12] =  saturateByte (cp[12]  + (double) scalar);
+                                cp[13] =  saturateByte (cp[13]  + (double) scalar);
+                                cp[14] =  saturateByte (cp[14]  + (double) scalar);
+                                cp[15] =  saturateByte (cp[15]  + (double) scalar);
+                                cp[16] =  saturateByte (cp[16]  + (double) scalar);
+                                cp[17] =  saturateByte (cp[17]  + (double) scalar);
+                                cp[18] =  saturateByte (cp[18]  + (double) scalar);
+                                cp[19] =  saturateByte (cp[19]  + (double) scalar);
+                                cp[20] =  saturateByte (cp[20]  + (double) scalar);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateByte (*cp  + (double) scalar);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((byte*)range.Item3 + range.Item1);
+                            scalar = *((byte*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateByte (ap[0]  + (double) scalar);
+                                cp[1] =  saturateByte (ap[1]  + (double) scalar);
+                                cp[2] =  saturateByte (ap[2]  + (double) scalar);
+                                cp[3] =  saturateByte (ap[3]  + (double) scalar);
+                                cp[4] =  saturateByte (ap[4]  + (double) scalar);
+                                cp[5] =  saturateByte (ap[5]  + (double) scalar);
+                                cp[6] =  saturateByte (ap[6]  + (double) scalar);
+                                cp[7] =  saturateByte (ap[7]  + (double) scalar);
+                                cp[8] =  saturateByte (ap[8]  + (double) scalar);
+                                cp[9] =  saturateByte (ap[9]  + (double) scalar);
+                                cp[10] =  saturateByte (ap[10]  + (double) scalar);
+                                cp[11] =  saturateByte (ap[11]  + (double) scalar);
+                                cp[12] =  saturateByte (ap[12]  + (double) scalar);
+                                cp[13] =  saturateByte (ap[13]  + (double) scalar);
+                                cp[14] =  saturateByte (ap[14]  + (double) scalar);
+                                cp[15] =  saturateByte (ap[15]  + (double) scalar);
+                                cp[16] =  saturateByte (ap[16]  + (double) scalar);
+                                cp[17] =  saturateByte (ap[17]  + (double) scalar);
+                                cp[18] =  saturateByte (ap[18]  + (double) scalar);
+                                cp[19] =  saturateByte (ap[19]  + (double) scalar);
+                                cp[20] =  saturateByte (ap[20]  + (double) scalar);
+                                ap+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateByte (*ap  + (double) scalar);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((byte*)range.Item3);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateByte (scalar  + (double) cp[0]);
+                                cp[1] =  saturateByte (scalar  + (double) cp[1]);
+                                cp[2] =  saturateByte (scalar  + (double) cp[2]);
+                                cp[3] =  saturateByte (scalar  + (double) cp[3]);
+                                cp[4] =  saturateByte (scalar  + (double) cp[4]);
+                                cp[5] =  saturateByte (scalar  + (double) cp[5]);
+                                cp[6] =  saturateByte (scalar  + (double) cp[6]);
+                                cp[7] =  saturateByte (scalar  + (double) cp[7]);
+                                cp[8] =  saturateByte (scalar  + (double) cp[8]);
+                                cp[9] =  saturateByte (scalar  + (double) cp[9]);
+                                cp[10] =  saturateByte (scalar  + (double) cp[10]);
+                                cp[11] =  saturateByte (scalar  + (double) cp[11]);
+                                cp[12] =  saturateByte (scalar  + (double) cp[12]);
+                                cp[13] =  saturateByte (scalar  + (double) cp[13]);
+                                cp[14] =  saturateByte (scalar  + (double) cp[14]);
+                                cp[15] =  saturateByte (scalar  + (double) cp[15]);
+                                cp[16] =  saturateByte (scalar  + (double) cp[16]);
+                                cp[17] =  saturateByte (scalar  + (double) cp[17]);
+                                cp[18] =  saturateByte (scalar  + (double) cp[18]);
+                                cp[19] =  saturateByte (scalar  + (double) cp[19]);
+                                cp[20] =  saturateByte (scalar  + (double) cp[20]);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateByte (scalar  + (double) *cp);
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((byte*)range.Item3);
+                            bp = ((byte*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateByte (scalar  + (double) bp[0]);
+                                cp[1] =  saturateByte (scalar  + (double) bp[1]);
+                                cp[2] =  saturateByte (scalar  + (double) bp[2]);
+                                cp[3] =  saturateByte (scalar  + (double) bp[3]);
+                                cp[4] =  saturateByte (scalar  + (double) bp[4]);
+                                cp[5] =  saturateByte (scalar  + (double) bp[5]);
+                                cp[6] =  saturateByte (scalar  + (double) bp[6]);
+                                cp[7] =  saturateByte (scalar  + (double) bp[7]);
+                                cp[8] =  saturateByte (scalar  + (double) bp[8]);
+                                cp[9] =  saturateByte (scalar  + (double) bp[9]);
+                                cp[10] =  saturateByte (scalar  + (double) bp[10]);
+                                cp[11] =  saturateByte (scalar  + (double) bp[11]);
+                                cp[12] =  saturateByte (scalar  + (double) bp[12]);
+                                cp[13] =  saturateByte (scalar  + (double) bp[13]);
+                                cp[14] =  saturateByte (scalar  + (double) bp[14]);
+                                cp[15] =  saturateByte (scalar  + (double) bp[15]);
+                                cp[16] =  saturateByte (scalar  + (double) bp[16]);
+                                cp[17] =  saturateByte (scalar  + (double) bp[17]);
+                                cp[18] =  saturateByte (scalar  + (double) bp[18]);
+                                cp[19] =  saturateByte (scalar  + (double) bp[19]);
+                                cp[20] =  saturateByte (scalar  + (double) bp[20]);
+                                bp+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateByte (scalar  + (double) *bp);
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work 
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                
+                fixed ( byte* arrAP = arrA)
+                fixed ( byte* arrBP = arrB)
+                fixed ( byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range 
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new  ILRetArray< byte>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<byte>  addEx(ILInArray<byte> A, ILInArray<byte> B) {
+            //using (ILScope.Enter(A, B)) { we cannot start a new scope here, since this would prevent A and B to be used implace if applicable
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<byte>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<byte>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<byte>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                dim = -(dim - 1);  // 0 -> 1, 1 -> 0
+                #endregion
+
+                #region parameter preparation
+               
+                byte[] retArr;
+               
+                byte[] arrA = A.GetArrayForRead();
+               
+                byte[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int workItemMultiplierLenA;
+                int workItemMultiplierLenB;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    workItemMultiplierLenB = outDims[0]; 
+                    workItemMultiplierLenA = dim;  // 0 for column, 1 for row vector
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    workItemMultiplierLenB = dim;  // 0 for column, 1 for row vector
+                    workItemMultiplierLenA = outDims[0]; 
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one singleton dimension in either A or B");
+                }
+                int itLen = outDims[0]; // (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<byte> retStorage = new ILDenseStorage<byte>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    byte* ap;
+                   
+                    byte* bp;
+                   
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            if (dim == 0) {
+                                bp = (byte*)range.Item3;
+                                cp = (byte*)range.Item4; 
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (byte*)range.Item2;
+                                    int l = itLen; 
+                                    while (l > 10) {
+                                        cp[0] =  saturateByte (ap[0]  + (double) bp[0]);
+                                        cp[1] =  saturateByte (ap[1]  + (double) bp[1]);
+                                        cp[2] =  saturateByte (ap[2]  + (double) bp[2]);
+                                        cp[3] =  saturateByte (ap[3]  + (double) bp[3]);
+                                        cp[4] =  saturateByte (ap[4]  + (double) bp[4]);
+                                        cp[5] =  saturateByte (ap[5]  + (double) bp[5]);
+                                        cp[6] =  saturateByte (ap[6]  + (double) bp[6]);
+                                        cp[7] =  saturateByte (ap[7]  + (double) bp[7]);
+                                        cp[8] =  saturateByte (ap[8]  + (double) bp[8]);
+                                        cp[9] =  saturateByte (ap[9]  + (double) bp[9]);
+                                        cp[10] =  saturateByte (ap[10]  + (double) bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =  saturateByte (*ap++  + (double) *bp++);
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                ap = (byte*)range.Item2;
+                                bp = (byte*)range.Item3;
+                                cp = (byte*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   byte val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateByte (val  + (double) bp[0]);
+                                        cp[1] =  saturateByte (val  + (double) bp[1]);
+                                        cp[2] =  saturateByte (val  + (double) bp[2]);
+                                        cp[3] =  saturateByte (val  + (double) bp[3]);
+                                        cp[4] =  saturateByte (val  + (double) bp[4]);
+                                        cp[5] =  saturateByte (val  + (double) bp[5]);
+                                        cp[6] =  saturateByte (val  + (double) bp[6]);
+                                        cp[7] =  saturateByte (val  + (double) bp[7]);
+                                        cp[8] =  saturateByte (val  + (double) bp[8]);
+                                        cp[9] =  saturateByte (val  + (double) bp[9]);
+                                        cp[10] =  saturateByte (val  + (double) bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11; 
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =  saturateByte (val  + (double) *bp++);
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            if (dim == 0) {
+                                cp = (byte*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (byte*)range.Item2;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateByte (ap[0]  + (double) cp[0]);
+                                        cp[1] =  saturateByte (ap[1]  + (double) cp[1]);
+                                        cp[2] =  saturateByte (ap[2]  + (double) cp[2]);
+                                        cp[3] =  saturateByte (ap[3]  + (double) cp[3]);
+                                        cp[4] =  saturateByte (ap[4]  + (double) cp[4]);
+                                        cp[5] =  saturateByte (ap[5]  + (double) cp[5]);
+                                        cp[6] =  saturateByte (ap[6]  + (double) cp[6]);
+                                        cp[7] =  saturateByte (ap[7]  + (double) cp[7]);
+                                        cp[8] =  saturateByte (ap[8]  + (double) cp[8]);
+                                        cp[9] =  saturateByte (ap[9]  + (double) cp[9]);
+                                        cp[10] =  saturateByte (ap[10]  + (double) cp[10]);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateByte (*ap++  + (double) *cp);
+                                        cp++; 
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                cp = (byte*)range.Item4;
+                                ap = (byte*)range.Item2;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    byte val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateByte (val  + (double) cp[0]);
+                                        cp[1] =  saturateByte (val  + (double) cp[1]);
+                                        cp[2] =  saturateByte (val  + (double) cp[2]);
+                                        cp[3] =  saturateByte (val  + (double) cp[3]);
+                                        cp[4] =  saturateByte (val  + (double) cp[4]);
+                                        cp[5] =  saturateByte (val  + (double) cp[5]);
+                                        cp[6] =  saturateByte (val  + (double) cp[6]);
+                                        cp[7] =  saturateByte (val  + (double) cp[7]);
+                                        cp[8] =  saturateByte (val  + (double) cp[8]);
+                                        cp[9] =  saturateByte (val  + (double) cp[9]);
+                                        cp[10] =  saturateByte (val  + (double) cp[10]);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateByte (val  + (double) *cp);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            if (dim == 0) {
+                                ap = (byte*)range.Item2;
+                                cp = (byte*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (byte*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateByte (ap[0]  + (double) bp[0]);
+                                        cp[1] =  saturateByte (ap[1]  + (double) bp[1]);
+                                        cp[2] =  saturateByte (ap[2]  + (double) bp[2]);
+                                        cp[3] =  saturateByte (ap[3]  + (double) bp[3]);
+                                        cp[4] =  saturateByte (ap[4]  + (double) bp[4]);
+                                        cp[5] =  saturateByte (ap[5]  + (double) bp[5]);
+                                        cp[6] =  saturateByte (ap[6]  + (double) bp[6]);
+                                        cp[7] =  saturateByte (ap[7]  + (double) bp[7]);
+                                        cp[8] =  saturateByte (ap[8]  + (double) bp[8]);
+                                        cp[9] =  saturateByte (ap[9]  + (double) bp[9]);
+                                        cp[10] =  saturateByte (ap[10]  + (double) bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateByte (*ap  + (double) *bp);
+                                        ap++;
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                ap = (byte*)range.Item2;
+                                bp = (byte*)range.Item3;
+                                cp = (byte*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   byte val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateByte (ap[0]  + (double) val);
+                                        cp[1] =  saturateByte (ap[1]  + (double) val);
+                                        cp[2] =  saturateByte (ap[2]  + (double) val);
+                                        cp[3] =  saturateByte (ap[3]  + (double) val);
+                                        cp[4] =  saturateByte (ap[4]  + (double) val);
+                                        cp[5] =  saturateByte (ap[5]  + (double) val);
+                                        cp[6] =  saturateByte (ap[6]  + (double) val);
+                                        cp[7] =  saturateByte (ap[7]  + (double) val);
+                                        cp[8] =  saturateByte (ap[8]  + (double) val);
+                                        cp[9] =  saturateByte (ap[9]  + (double) val);
+                                        cp[10] =  saturateByte (ap[10]  + (double) val);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateByte (*ap  + (double) val);
+                                        ap++;
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            if (dim == 0) {
+                                cp = (byte*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (byte*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateByte (cp[0]  + (double) bp[0]);
+                                        cp[1] =  saturateByte (cp[1]  + (double) bp[1]);
+                                        cp[2] =  saturateByte (cp[2]  + (double) bp[2]);
+                                        cp[3] =  saturateByte (cp[3]  + (double) bp[3]);
+                                        cp[4] =  saturateByte (cp[4]  + (double) bp[4]);
+                                        cp[5] =  saturateByte (cp[5]  + (double) bp[5]);
+                                        cp[6] =  saturateByte (cp[6]  + (double) bp[6]);
+                                        cp[7] =  saturateByte (cp[7]  + (double) bp[7]);
+                                        cp[8] =  saturateByte (cp[8]  + (double) bp[8]);
+                                        cp[9] =  saturateByte (cp[9]  + (double) bp[9]);
+                                        cp[10] =  saturateByte (cp[10]  + (double) bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateByte (*cp  + (double) *bp);
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                bp = (byte*)range.Item3;
+                                cp = (byte*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    byte val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateByte (cp[0]  + (double) val);
+                                        cp[1] =  saturateByte (cp[1]  + (double) val);
+                                        cp[2] =  saturateByte (cp[2]  + (double) val);
+                                        cp[3] =  saturateByte (cp[3]  + (double) val);
+                                        cp[4] =  saturateByte (cp[4]  + (double) val);
+                                        cp[5] =  saturateByte (cp[5]  + (double) val);
+                                        cp[6] =  saturateByte (cp[6]  + (double) val);
+                                        cp[7] =  saturateByte (cp[7]  + (double) val);
+                                        cp[8] =  saturateByte (cp[8]  + (double) val);
+                                        cp[9] =  saturateByte (cp[9]  + (double) val);
+                                        cp[10] =  saturateByte (cp[10]  + (double) val);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l --> 0) {
+                                        *cp =  saturateByte (*cp  + (double) val);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outDims.NumberOfElements >= Settings.s_minParallelElement1Count
+                    && outDims[1] > 1) {
+                        if (outDims[1] > workItemCount) {
+                        workItemLength = outDims[1] / workItemCount;
+                    } else {
+                        workItemLength = outDims[1] / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outDims[1];
+                    workItemCount = 1;
+                }
+
+                fixed ( byte* arrAP = arrA)
+                fixed ( byte* arrBP = arrB)
+                fixed ( byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, IntPtr, IntPtr, IntPtr> range = new Tuple<int, IntPtr, IntPtr, IntPtr>
+                               (workItemLength
+                               , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                               , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                               , (IntPtr)(retArrP + i * outDims[0] * workItemLength)); 
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, IntPtr, IntPtr, IntPtr>
+                                (outDims[1] - i * workItemLength
+                                , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                                , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                                , (IntPtr)(retArrP + i * outDims[0] * workItemLength)));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<byte>(retStorage);
+            //}  // no scopes here! it disables implace operations
+        }
+
+
+#endregion HYCALPER AUTO GENERATED CODE
+   }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/DivideElem.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/DivideElem.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/DivideElem.cs	(revision 9102)
@@ -0,0 +1,5102 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using ILNumerics;
+using ILNumerics.Misc;
+using ILNumerics.Storage;
+using ILNumerics.Native;
+using ILNumerics.Exceptions;
+
+
+
+namespace ILNumerics {
+
+    public partial class ILMath {         
+         
+
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>Divide elements</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Array with elementwise division of A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<Int64>  divide(ILInArray<Int64> A, ILInArray<Int64> B) {
+            using (ILScope.Enter(A,B)) {
+                int outLen; 
+                BinOpItMode mode; 
+                Int64 [] retArr;
+                Int64 [] arrA = A.GetArrayForRead();
+                Int64[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size; 
+                    if (B.IsScalar) {
+                       
+                        return new  ILRetArray<Int64> (new  Int64 [1]{ saturateInt64 (A.GetValue(0)  / (double) B.GetValue(0))}, A.Size);
+                    } else if (B.IsEmpty) {
+                        return  ILRetArray<Int64>.empty(outDims); 
+                    } else {
+                        outLen = outDims.NumberOfElements; 
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< Int64 > (outLen);
+                            mode = BinOpItMode.SAN; 
+                        } else {
+                            mode = BinOpItMode.SAI; 
+                        }
+                    }
+                } else {
+                    outDims = A.Size; 
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return  ILRetArray<Int64>.empty(A.Size);  
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< Int64 > (outLen);
+                            mode = BinOpItMode.ASN; 
+                        } else {
+                            mode = BinOpItMode.ASI; 
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  divideEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (A.TryGetStorage4InplaceOp(out retArr)) 
+                            mode  = BinOpItMode.AAIA; 
+                        else if (B.TryGetStorage4InplaceOp(out retArr)) 
+                            mode = BinOpItMode.AAIB; 
+                        else {
+                            retArr = ILMemoryPool.Pool.New< Int64 > (outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<Int64> retStorage = new ILDenseStorage<Int64>(retArr, outDims);
+                int i = 0, workerCount = 1; 
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    Int64* cp = (Int64*)range.Item5 + range.Item1;
+                    Int64 scalar;
+                    int j = range.Item2; 
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           Int64* bp = ((Int64*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                                cp[0] =  saturateInt64 (cp[0]  / (double) bp[0]);
+                                cp[1] =  saturateInt64 (cp[1]  / (double) bp[1]);
+                                cp[2] =  saturateInt64 (cp[2]  / (double) bp[2]);
+                                cp[3] =  saturateInt64 (cp[3]  / (double) bp[3]);
+                                cp[4] =  saturateInt64 (cp[4]  / (double) bp[4]);
+                                cp[5] =  saturateInt64 (cp[5]  / (double) bp[5]);
+                                cp[6] =  saturateInt64 (cp[6]  / (double) bp[6]);
+                                cp[7] =  saturateInt64 (cp[7]  / (double) bp[7]);
+                                cp[8] =  saturateInt64 (cp[8]  / (double) bp[8]);
+                                cp[9] =  saturateInt64 (cp[9]  / (double) bp[9]);
+                                cp[10] =  saturateInt64 (cp[10]  / (double) bp[10]);
+                                cp[11] =  saturateInt64 (cp[11]  / (double) bp[11]);
+                                cp[12] =  saturateInt64 (cp[12]  / (double) bp[12]);
+                                cp[13] =  saturateInt64 (cp[13]  / (double) bp[13]);
+                                cp[14] =  saturateInt64 (cp[14]  / (double) bp[14]);
+                                cp[15] =  saturateInt64 (cp[15]  / (double) bp[15]);
+                                cp[16] =  saturateInt64 (cp[16]  / (double) bp[16]);
+                                cp[17] =  saturateInt64 (cp[17]  / (double) bp[17]);
+                                cp[18] =  saturateInt64 (cp[18]  / (double) bp[18]);
+                                cp[19] =  saturateInt64 (cp[19]  / (double) bp[19]);
+                                cp[20] =  saturateInt64 (cp[20]  / (double) bp[20]);
+                                cp += 21; bp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt64 (*cp  / (double) *bp);
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           Int64* ap = ((Int64*)range.Item3 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt64 (ap[0]  / (double) cp[0]);
+                                cp[1] =  saturateInt64 (ap[1]  / (double) cp[1]);
+                                cp[2] =  saturateInt64 (ap[2]  / (double) cp[2]);
+                                cp[3] =  saturateInt64 (ap[3]  / (double) cp[3]);
+                                cp[4] =  saturateInt64 (ap[4]  / (double) cp[4]);
+                                cp[5] =  saturateInt64 (ap[5]  / (double) cp[5]);
+                                cp[6] =  saturateInt64 (ap[6]  / (double) cp[6]);
+                                cp[7] =  saturateInt64 (ap[7]  / (double) cp[7]);
+                                cp[8] =  saturateInt64 (ap[8]  / (double) cp[8]);
+                                cp[9] =  saturateInt64 (ap[9]  / (double) cp[9]);
+                                cp[10] =  saturateInt64 (ap[10]  / (double) cp[10]);
+                                cp[11] =  saturateInt64 (ap[11]  / (double) cp[11]);
+                                cp[12] =  saturateInt64 (ap[12]  / (double) cp[12]);
+                                cp[13] =  saturateInt64 (ap[13]  / (double) cp[13]);
+                                cp[14] =  saturateInt64 (ap[14]  / (double) cp[14]);
+                                cp[15] =  saturateInt64 (ap[15]  / (double) cp[15]);
+                                cp[16] =  saturateInt64 (ap[16]  / (double) cp[16]);
+                                cp[17] =  saturateInt64 (ap[17]  / (double) cp[17]);
+                                cp[18] =  saturateInt64 (ap[18]  / (double) cp[18]);
+                                cp[19] =  saturateInt64 (ap[19]  / (double) cp[19]);
+                                cp[20] =  saturateInt64 (ap[20]  / (double) cp[20]);
+                                ap += 21; cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt64 (*ap  / (double) *cp);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((Int64*)range.Item3 + range.Item1);
+                            bp = ((Int64*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt64 (ap[0]  / (double) bp[0]);
+                                cp[1] =  saturateInt64 (ap[1]  / (double) bp[1]);
+                                cp[2] =  saturateInt64 (ap[2]  / (double) bp[2]);
+                                cp[3] =  saturateInt64 (ap[3]  / (double) bp[3]);
+                                cp[4] =  saturateInt64 (ap[4]  / (double) bp[4]);
+                                cp[5] =  saturateInt64 (ap[5]  / (double) bp[5]);
+                                cp[6] =  saturateInt64 (ap[6]  / (double) bp[6]);
+                                cp[7] =  saturateInt64 (ap[7]  / (double) bp[7]);
+                                cp[8] =  saturateInt64 (ap[8]  / (double) bp[8]);
+                                cp[9] =  saturateInt64 (ap[9]  / (double) bp[9]);
+                                cp[10] =  saturateInt64 (ap[10]  / (double) bp[10]);
+                                cp[11] =  saturateInt64 (ap[11]  / (double) bp[11]);
+                                cp[12] =  saturateInt64 (ap[12]  / (double) bp[12]);
+                                cp[13] =  saturateInt64 (ap[13]  / (double) bp[13]);
+                                cp[14] =  saturateInt64 (ap[14]  / (double) bp[14]);
+                                cp[15] =  saturateInt64 (ap[15]  / (double) bp[15]);
+                                cp[16] =  saturateInt64 (ap[16]  / (double) bp[16]);
+                                cp[17] =  saturateInt64 (ap[17]  / (double) bp[17]);
+                                cp[18] =  saturateInt64 (ap[18]  / (double) bp[18]);
+                                cp[19] =  saturateInt64 (ap[19]  / (double) bp[19]);
+                                cp[20] =  saturateInt64 (ap[20]  / (double) bp[20]);
+                                ap+=21; bp+=21; cp+=21; j-=21;
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt64 (*ap  / (double) *bp);
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((Int64*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt64 (cp[0]  / (double) scalar);
+                                cp[1] =  saturateInt64 (cp[1]  / (double) scalar);
+                                cp[2] =  saturateInt64 (cp[2]  / (double) scalar);
+                                cp[3] =  saturateInt64 (cp[3]  / (double) scalar);
+                                cp[4] =  saturateInt64 (cp[4]  / (double) scalar);
+                                cp[5] =  saturateInt64 (cp[5]  / (double) scalar);
+                                cp[6] =  saturateInt64 (cp[6]  / (double) scalar);
+                                cp[7] =  saturateInt64 (cp[7]  / (double) scalar);
+                                cp[8] =  saturateInt64 (cp[8]  / (double) scalar);
+                                cp[9] =  saturateInt64 (cp[9]  / (double) scalar);
+                                cp[10] =  saturateInt64 (cp[10]  / (double) scalar);
+                                cp[11] =  saturateInt64 (cp[11]  / (double) scalar);
+                                cp[12] =  saturateInt64 (cp[12]  / (double) scalar);
+                                cp[13] =  saturateInt64 (cp[13]  / (double) scalar);
+                                cp[14] =  saturateInt64 (cp[14]  / (double) scalar);
+                                cp[15] =  saturateInt64 (cp[15]  / (double) scalar);
+                                cp[16] =  saturateInt64 (cp[16]  / (double) scalar);
+                                cp[17] =  saturateInt64 (cp[17]  / (double) scalar);
+                                cp[18] =  saturateInt64 (cp[18]  / (double) scalar);
+                                cp[19] =  saturateInt64 (cp[19]  / (double) scalar);
+                                cp[20] =  saturateInt64 (cp[20]  / (double) scalar);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt64 (*cp  / (double) scalar);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((Int64*)range.Item3 + range.Item1);
+                            scalar = *((Int64*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt64 (ap[0]  / (double) scalar);
+                                cp[1] =  saturateInt64 (ap[1]  / (double) scalar);
+                                cp[2] =  saturateInt64 (ap[2]  / (double) scalar);
+                                cp[3] =  saturateInt64 (ap[3]  / (double) scalar);
+                                cp[4] =  saturateInt64 (ap[4]  / (double) scalar);
+                                cp[5] =  saturateInt64 (ap[5]  / (double) scalar);
+                                cp[6] =  saturateInt64 (ap[6]  / (double) scalar);
+                                cp[7] =  saturateInt64 (ap[7]  / (double) scalar);
+                                cp[8] =  saturateInt64 (ap[8]  / (double) scalar);
+                                cp[9] =  saturateInt64 (ap[9]  / (double) scalar);
+                                cp[10] =  saturateInt64 (ap[10]  / (double) scalar);
+                                cp[11] =  saturateInt64 (ap[11]  / (double) scalar);
+                                cp[12] =  saturateInt64 (ap[12]  / (double) scalar);
+                                cp[13] =  saturateInt64 (ap[13]  / (double) scalar);
+                                cp[14] =  saturateInt64 (ap[14]  / (double) scalar);
+                                cp[15] =  saturateInt64 (ap[15]  / (double) scalar);
+                                cp[16] =  saturateInt64 (ap[16]  / (double) scalar);
+                                cp[17] =  saturateInt64 (ap[17]  / (double) scalar);
+                                cp[18] =  saturateInt64 (ap[18]  / (double) scalar);
+                                cp[19] =  saturateInt64 (ap[19]  / (double) scalar);
+                                cp[20] =  saturateInt64 (ap[20]  / (double) scalar);
+                                ap+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt64 (*ap  / (double) scalar);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((Int64*)range.Item3);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt64 (scalar  / (double) cp[0]);
+                                cp[1] =  saturateInt64 (scalar  / (double) cp[1]);
+                                cp[2] =  saturateInt64 (scalar  / (double) cp[2]);
+                                cp[3] =  saturateInt64 (scalar  / (double) cp[3]);
+                                cp[4] =  saturateInt64 (scalar  / (double) cp[4]);
+                                cp[5] =  saturateInt64 (scalar  / (double) cp[5]);
+                                cp[6] =  saturateInt64 (scalar  / (double) cp[6]);
+                                cp[7] =  saturateInt64 (scalar  / (double) cp[7]);
+                                cp[8] =  saturateInt64 (scalar  / (double) cp[8]);
+                                cp[9] =  saturateInt64 (scalar  / (double) cp[9]);
+                                cp[10] =  saturateInt64 (scalar  / (double) cp[10]);
+                                cp[11] =  saturateInt64 (scalar  / (double) cp[11]);
+                                cp[12] =  saturateInt64 (scalar  / (double) cp[12]);
+                                cp[13] =  saturateInt64 (scalar  / (double) cp[13]);
+                                cp[14] =  saturateInt64 (scalar  / (double) cp[14]);
+                                cp[15] =  saturateInt64 (scalar  / (double) cp[15]);
+                                cp[16] =  saturateInt64 (scalar  / (double) cp[16]);
+                                cp[17] =  saturateInt64 (scalar  / (double) cp[17]);
+                                cp[18] =  saturateInt64 (scalar  / (double) cp[18]);
+                                cp[19] =  saturateInt64 (scalar  / (double) cp[19]);
+                                cp[20] =  saturateInt64 (scalar  / (double) cp[20]);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt64 (scalar  / (double) *cp);
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((Int64*)range.Item3);
+                            bp = ((Int64*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt64 (scalar  / (double) bp[0]);
+                                cp[1] =  saturateInt64 (scalar  / (double) bp[1]);
+                                cp[2] =  saturateInt64 (scalar  / (double) bp[2]);
+                                cp[3] =  saturateInt64 (scalar  / (double) bp[3]);
+                                cp[4] =  saturateInt64 (scalar  / (double) bp[4]);
+                                cp[5] =  saturateInt64 (scalar  / (double) bp[5]);
+                                cp[6] =  saturateInt64 (scalar  / (double) bp[6]);
+                                cp[7] =  saturateInt64 (scalar  / (double) bp[7]);
+                                cp[8] =  saturateInt64 (scalar  / (double) bp[8]);
+                                cp[9] =  saturateInt64 (scalar  / (double) bp[9]);
+                                cp[10] =  saturateInt64 (scalar  / (double) bp[10]);
+                                cp[11] =  saturateInt64 (scalar  / (double) bp[11]);
+                                cp[12] =  saturateInt64 (scalar  / (double) bp[12]);
+                                cp[13] =  saturateInt64 (scalar  / (double) bp[13]);
+                                cp[14] =  saturateInt64 (scalar  / (double) bp[14]);
+                                cp[15] =  saturateInt64 (scalar  / (double) bp[15]);
+                                cp[16] =  saturateInt64 (scalar  / (double) bp[16]);
+                                cp[17] =  saturateInt64 (scalar  / (double) bp[17]);
+                                cp[18] =  saturateInt64 (scalar  / (double) bp[18]);
+                                cp[19] =  saturateInt64 (scalar  / (double) bp[19]);
+                                cp[20] =  saturateInt64 (scalar  / (double) bp[20]);
+                                bp+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt64 (scalar  / (double) *bp);
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work 
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                
+                fixed ( Int64* arrAP = arrA)
+                fixed ( Int64* arrBP = arrB)
+                fixed ( Int64* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range 
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new  ILRetArray< Int64>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<Int64>  divideEx(ILInArray<Int64> A, ILInArray<Int64> B) {
+            //using (ILScope.Enter(A, B)) { we cannot start a new scope here, since this would prevent A and B to be used implace if applicable
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<Int64>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<Int64>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<Int64>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                dim = -(dim - 1);  // 0 -> 1, 1 -> 0
+                #endregion
+
+                #region parameter preparation
+               
+                Int64[] retArr;
+               
+                Int64[] arrA = A.GetArrayForRead();
+               
+                Int64[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int workItemMultiplierLenA;
+                int workItemMultiplierLenB;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<Int64>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    workItemMultiplierLenB = outDims[0]; 
+                    workItemMultiplierLenA = dim;  // 0 for column, 1 for row vector
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<Int64>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    workItemMultiplierLenB = dim;  // 0 for column, 1 for row vector
+                    workItemMultiplierLenA = outDims[0]; 
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one singleton dimension in either A or B");
+                }
+                int itLen = outDims[0]; // (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<Int64> retStorage = new ILDenseStorage<Int64>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    Int64* ap;
+                   
+                    Int64* bp;
+                   
+                    Int64* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            if (dim == 0) {
+                                bp = (Int64*)range.Item3;
+                                cp = (Int64*)range.Item4; 
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (Int64*)range.Item2;
+                                    int l = itLen; 
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt64 (ap[0]  / (double) bp[0]);
+                                        cp[1] =  saturateInt64 (ap[1]  / (double) bp[1]);
+                                        cp[2] =  saturateInt64 (ap[2]  / (double) bp[2]);
+                                        cp[3] =  saturateInt64 (ap[3]  / (double) bp[3]);
+                                        cp[4] =  saturateInt64 (ap[4]  / (double) bp[4]);
+                                        cp[5] =  saturateInt64 (ap[5]  / (double) bp[5]);
+                                        cp[6] =  saturateInt64 (ap[6]  / (double) bp[6]);
+                                        cp[7] =  saturateInt64 (ap[7]  / (double) bp[7]);
+                                        cp[8] =  saturateInt64 (ap[8]  / (double) bp[8]);
+                                        cp[9] =  saturateInt64 (ap[9]  / (double) bp[9]);
+                                        cp[10] =  saturateInt64 (ap[10]  / (double) bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =  saturateInt64 (*ap++  / (double) *bp++);
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                ap = (Int64*)range.Item2;
+                                bp = (Int64*)range.Item3;
+                                cp = (Int64*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   Int64 val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt64 (val  / (double) bp[0]);
+                                        cp[1] =  saturateInt64 (val  / (double) bp[1]);
+                                        cp[2] =  saturateInt64 (val  / (double) bp[2]);
+                                        cp[3] =  saturateInt64 (val  / (double) bp[3]);
+                                        cp[4] =  saturateInt64 (val  / (double) bp[4]);
+                                        cp[5] =  saturateInt64 (val  / (double) bp[5]);
+                                        cp[6] =  saturateInt64 (val  / (double) bp[6]);
+                                        cp[7] =  saturateInt64 (val  / (double) bp[7]);
+                                        cp[8] =  saturateInt64 (val  / (double) bp[8]);
+                                        cp[9] =  saturateInt64 (val  / (double) bp[9]);
+                                        cp[10] =  saturateInt64 (val  / (double) bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11; 
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =  saturateInt64 (val  / (double) *bp++);
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            if (dim == 0) {
+                                cp = (Int64*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (Int64*)range.Item2;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt64 (ap[0]  / (double) cp[0]);
+                                        cp[1] =  saturateInt64 (ap[1]  / (double) cp[1]);
+                                        cp[2] =  saturateInt64 (ap[2]  / (double) cp[2]);
+                                        cp[3] =  saturateInt64 (ap[3]  / (double) cp[3]);
+                                        cp[4] =  saturateInt64 (ap[4]  / (double) cp[4]);
+                                        cp[5] =  saturateInt64 (ap[5]  / (double) cp[5]);
+                                        cp[6] =  saturateInt64 (ap[6]  / (double) cp[6]);
+                                        cp[7] =  saturateInt64 (ap[7]  / (double) cp[7]);
+                                        cp[8] =  saturateInt64 (ap[8]  / (double) cp[8]);
+                                        cp[9] =  saturateInt64 (ap[9]  / (double) cp[9]);
+                                        cp[10] =  saturateInt64 (ap[10]  / (double) cp[10]);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt64 (*ap++  / (double) *cp);
+                                        cp++; 
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                cp = (Int64*)range.Item4;
+                                ap = (Int64*)range.Item2;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    Int64 val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt64 (val  / (double) cp[0]);
+                                        cp[1] =  saturateInt64 (val  / (double) cp[1]);
+                                        cp[2] =  saturateInt64 (val  / (double) cp[2]);
+                                        cp[3] =  saturateInt64 (val  / (double) cp[3]);
+                                        cp[4] =  saturateInt64 (val  / (double) cp[4]);
+                                        cp[5] =  saturateInt64 (val  / (double) cp[5]);
+                                        cp[6] =  saturateInt64 (val  / (double) cp[6]);
+                                        cp[7] =  saturateInt64 (val  / (double) cp[7]);
+                                        cp[8] =  saturateInt64 (val  / (double) cp[8]);
+                                        cp[9] =  saturateInt64 (val  / (double) cp[9]);
+                                        cp[10] =  saturateInt64 (val  / (double) cp[10]);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt64 (val  / (double) *cp);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            if (dim == 0) {
+                                ap = (Int64*)range.Item2;
+                                cp = (Int64*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (Int64*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt64 (ap[0]  / (double) bp[0]);
+                                        cp[1] =  saturateInt64 (ap[1]  / (double) bp[1]);
+                                        cp[2] =  saturateInt64 (ap[2]  / (double) bp[2]);
+                                        cp[3] =  saturateInt64 (ap[3]  / (double) bp[3]);
+                                        cp[4] =  saturateInt64 (ap[4]  / (double) bp[4]);
+                                        cp[5] =  saturateInt64 (ap[5]  / (double) bp[5]);
+                                        cp[6] =  saturateInt64 (ap[6]  / (double) bp[6]);
+                                        cp[7] =  saturateInt64 (ap[7]  / (double) bp[7]);
+                                        cp[8] =  saturateInt64 (ap[8]  / (double) bp[8]);
+                                        cp[9] =  saturateInt64 (ap[9]  / (double) bp[9]);
+                                        cp[10] =  saturateInt64 (ap[10]  / (double) bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt64 (*ap  / (double) *bp);
+                                        ap++;
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                ap = (Int64*)range.Item2;
+                                bp = (Int64*)range.Item3;
+                                cp = (Int64*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   Int64 val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt64 (ap[0]  / (double) val);
+                                        cp[1] =  saturateInt64 (ap[1]  / (double) val);
+                                        cp[2] =  saturateInt64 (ap[2]  / (double) val);
+                                        cp[3] =  saturateInt64 (ap[3]  / (double) val);
+                                        cp[4] =  saturateInt64 (ap[4]  / (double) val);
+                                        cp[5] =  saturateInt64 (ap[5]  / (double) val);
+                                        cp[6] =  saturateInt64 (ap[6]  / (double) val);
+                                        cp[7] =  saturateInt64 (ap[7]  / (double) val);
+                                        cp[8] =  saturateInt64 (ap[8]  / (double) val);
+                                        cp[9] =  saturateInt64 (ap[9]  / (double) val);
+                                        cp[10] =  saturateInt64 (ap[10]  / (double) val);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt64 (*ap  / (double) val);
+                                        ap++;
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            if (dim == 0) {
+                                cp = (Int64*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (Int64*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt64 (cp[0]  / (double) bp[0]);
+                                        cp[1] =  saturateInt64 (cp[1]  / (double) bp[1]);
+                                        cp[2] =  saturateInt64 (cp[2]  / (double) bp[2]);
+                                        cp[3] =  saturateInt64 (cp[3]  / (double) bp[3]);
+                                        cp[4] =  saturateInt64 (cp[4]  / (double) bp[4]);
+                                        cp[5] =  saturateInt64 (cp[5]  / (double) bp[5]);
+                                        cp[6] =  saturateInt64 (cp[6]  / (double) bp[6]);
+                                        cp[7] =  saturateInt64 (cp[7]  / (double) bp[7]);
+                                        cp[8] =  saturateInt64 (cp[8]  / (double) bp[8]);
+                                        cp[9] =  saturateInt64 (cp[9]  / (double) bp[9]);
+                                        cp[10] =  saturateInt64 (cp[10]  / (double) bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt64 (*cp  / (double) *bp);
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                bp = (Int64*)range.Item3;
+                                cp = (Int64*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    Int64 val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt64 (cp[0]  / (double) val);
+                                        cp[1] =  saturateInt64 (cp[1]  / (double) val);
+                                        cp[2] =  saturateInt64 (cp[2]  / (double) val);
+                                        cp[3] =  saturateInt64 (cp[3]  / (double) val);
+                                        cp[4] =  saturateInt64 (cp[4]  / (double) val);
+                                        cp[5] =  saturateInt64 (cp[5]  / (double) val);
+                                        cp[6] =  saturateInt64 (cp[6]  / (double) val);
+                                        cp[7] =  saturateInt64 (cp[7]  / (double) val);
+                                        cp[8] =  saturateInt64 (cp[8]  / (double) val);
+                                        cp[9] =  saturateInt64 (cp[9]  / (double) val);
+                                        cp[10] =  saturateInt64 (cp[10]  / (double) val);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l --> 0) {
+                                        *cp =  saturateInt64 (*cp  / (double) val);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outDims.NumberOfElements >= Settings.s_minParallelElement1Count
+                    && outDims[1] > 1) {
+                        if (outDims[1] > workItemCount) {
+                        workItemLength = outDims[1] / workItemCount;
+                    } else {
+                        workItemLength = outDims[1] / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outDims[1];
+                    workItemCount = 1;
+                }
+
+                fixed ( Int64* arrAP = arrA)
+                fixed ( Int64* arrBP = arrB)
+                fixed ( Int64* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, IntPtr, IntPtr, IntPtr> range = new Tuple<int, IntPtr, IntPtr, IntPtr>
+                               (workItemLength
+                               , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                               , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                               , (IntPtr)(retArrP + i * outDims[0] * workItemLength)); 
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, IntPtr, IntPtr, IntPtr>
+                                (outDims[1] - i * workItemLength
+                                , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                                , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                                , (IntPtr)(retArrP + i * outDims[0] * workItemLength)));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<Int64>(retStorage);
+            //}  // no scopes here! it disables implace operations
+        }
+
+        /// <summary>Divide elements</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Array with elementwise division of A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<Int32>  divide(ILInArray<Int32> A, ILInArray<Int32> B) {
+            using (ILScope.Enter(A,B)) {
+                int outLen; 
+                BinOpItMode mode; 
+                Int32 [] retArr;
+                Int32 [] arrA = A.GetArrayForRead();
+                Int32[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size; 
+                    if (B.IsScalar) {
+                       
+                        return new  ILRetArray<Int32> (new  Int32 [1]{ saturateInt32 (A.GetValue(0)  / (double) B.GetValue(0))}, A.Size);
+                    } else if (B.IsEmpty) {
+                        return  ILRetArray<Int32>.empty(outDims); 
+                    } else {
+                        outLen = outDims.NumberOfElements; 
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< Int32 > (outLen);
+                            mode = BinOpItMode.SAN; 
+                        } else {
+                            mode = BinOpItMode.SAI; 
+                        }
+                    }
+                } else {
+                    outDims = A.Size; 
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return  ILRetArray<Int32>.empty(A.Size);  
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< Int32 > (outLen);
+                            mode = BinOpItMode.ASN; 
+                        } else {
+                            mode = BinOpItMode.ASI; 
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  divideEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (A.TryGetStorage4InplaceOp(out retArr)) 
+                            mode  = BinOpItMode.AAIA; 
+                        else if (B.TryGetStorage4InplaceOp(out retArr)) 
+                            mode = BinOpItMode.AAIB; 
+                        else {
+                            retArr = ILMemoryPool.Pool.New< Int32 > (outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<Int32> retStorage = new ILDenseStorage<Int32>(retArr, outDims);
+                int i = 0, workerCount = 1; 
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    Int32* cp = (Int32*)range.Item5 + range.Item1;
+                    Int32 scalar;
+                    int j = range.Item2; 
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           Int32* bp = ((Int32*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                                cp[0] =  saturateInt32 (cp[0]  / (double) bp[0]);
+                                cp[1] =  saturateInt32 (cp[1]  / (double) bp[1]);
+                                cp[2] =  saturateInt32 (cp[2]  / (double) bp[2]);
+                                cp[3] =  saturateInt32 (cp[3]  / (double) bp[3]);
+                                cp[4] =  saturateInt32 (cp[4]  / (double) bp[4]);
+                                cp[5] =  saturateInt32 (cp[5]  / (double) bp[5]);
+                                cp[6] =  saturateInt32 (cp[6]  / (double) bp[6]);
+                                cp[7] =  saturateInt32 (cp[7]  / (double) bp[7]);
+                                cp[8] =  saturateInt32 (cp[8]  / (double) bp[8]);
+                                cp[9] =  saturateInt32 (cp[9]  / (double) bp[9]);
+                                cp[10] =  saturateInt32 (cp[10]  / (double) bp[10]);
+                                cp[11] =  saturateInt32 (cp[11]  / (double) bp[11]);
+                                cp[12] =  saturateInt32 (cp[12]  / (double) bp[12]);
+                                cp[13] =  saturateInt32 (cp[13]  / (double) bp[13]);
+                                cp[14] =  saturateInt32 (cp[14]  / (double) bp[14]);
+                                cp[15] =  saturateInt32 (cp[15]  / (double) bp[15]);
+                                cp[16] =  saturateInt32 (cp[16]  / (double) bp[16]);
+                                cp[17] =  saturateInt32 (cp[17]  / (double) bp[17]);
+                                cp[18] =  saturateInt32 (cp[18]  / (double) bp[18]);
+                                cp[19] =  saturateInt32 (cp[19]  / (double) bp[19]);
+                                cp[20] =  saturateInt32 (cp[20]  / (double) bp[20]);
+                                cp += 21; bp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt32 (*cp  / (double) *bp);
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           Int32* ap = ((Int32*)range.Item3 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt32 (ap[0]  / (double) cp[0]);
+                                cp[1] =  saturateInt32 (ap[1]  / (double) cp[1]);
+                                cp[2] =  saturateInt32 (ap[2]  / (double) cp[2]);
+                                cp[3] =  saturateInt32 (ap[3]  / (double) cp[3]);
+                                cp[4] =  saturateInt32 (ap[4]  / (double) cp[4]);
+                                cp[5] =  saturateInt32 (ap[5]  / (double) cp[5]);
+                                cp[6] =  saturateInt32 (ap[6]  / (double) cp[6]);
+                                cp[7] =  saturateInt32 (ap[7]  / (double) cp[7]);
+                                cp[8] =  saturateInt32 (ap[8]  / (double) cp[8]);
+                                cp[9] =  saturateInt32 (ap[9]  / (double) cp[9]);
+                                cp[10] =  saturateInt32 (ap[10]  / (double) cp[10]);
+                                cp[11] =  saturateInt32 (ap[11]  / (double) cp[11]);
+                                cp[12] =  saturateInt32 (ap[12]  / (double) cp[12]);
+                                cp[13] =  saturateInt32 (ap[13]  / (double) cp[13]);
+                                cp[14] =  saturateInt32 (ap[14]  / (double) cp[14]);
+                                cp[15] =  saturateInt32 (ap[15]  / (double) cp[15]);
+                                cp[16] =  saturateInt32 (ap[16]  / (double) cp[16]);
+                                cp[17] =  saturateInt32 (ap[17]  / (double) cp[17]);
+                                cp[18] =  saturateInt32 (ap[18]  / (double) cp[18]);
+                                cp[19] =  saturateInt32 (ap[19]  / (double) cp[19]);
+                                cp[20] =  saturateInt32 (ap[20]  / (double) cp[20]);
+                                ap += 21; cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt32 (*ap  / (double) *cp);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((Int32*)range.Item3 + range.Item1);
+                            bp = ((Int32*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt32 (ap[0]  / (double) bp[0]);
+                                cp[1] =  saturateInt32 (ap[1]  / (double) bp[1]);
+                                cp[2] =  saturateInt32 (ap[2]  / (double) bp[2]);
+                                cp[3] =  saturateInt32 (ap[3]  / (double) bp[3]);
+                                cp[4] =  saturateInt32 (ap[4]  / (double) bp[4]);
+                                cp[5] =  saturateInt32 (ap[5]  / (double) bp[5]);
+                                cp[6] =  saturateInt32 (ap[6]  / (double) bp[6]);
+                                cp[7] =  saturateInt32 (ap[7]  / (double) bp[7]);
+                                cp[8] =  saturateInt32 (ap[8]  / (double) bp[8]);
+                                cp[9] =  saturateInt32 (ap[9]  / (double) bp[9]);
+                                cp[10] =  saturateInt32 (ap[10]  / (double) bp[10]);
+                                cp[11] =  saturateInt32 (ap[11]  / (double) bp[11]);
+                                cp[12] =  saturateInt32 (ap[12]  / (double) bp[12]);
+                                cp[13] =  saturateInt32 (ap[13]  / (double) bp[13]);
+                                cp[14] =  saturateInt32 (ap[14]  / (double) bp[14]);
+                                cp[15] =  saturateInt32 (ap[15]  / (double) bp[15]);
+                                cp[16] =  saturateInt32 (ap[16]  / (double) bp[16]);
+                                cp[17] =  saturateInt32 (ap[17]  / (double) bp[17]);
+                                cp[18] =  saturateInt32 (ap[18]  / (double) bp[18]);
+                                cp[19] =  saturateInt32 (ap[19]  / (double) bp[19]);
+                                cp[20] =  saturateInt32 (ap[20]  / (double) bp[20]);
+                                ap+=21; bp+=21; cp+=21; j-=21;
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt32 (*ap  / (double) *bp);
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((Int32*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt32 (cp[0]  / (double) scalar);
+                                cp[1] =  saturateInt32 (cp[1]  / (double) scalar);
+                                cp[2] =  saturateInt32 (cp[2]  / (double) scalar);
+                                cp[3] =  saturateInt32 (cp[3]  / (double) scalar);
+                                cp[4] =  saturateInt32 (cp[4]  / (double) scalar);
+                                cp[5] =  saturateInt32 (cp[5]  / (double) scalar);
+                                cp[6] =  saturateInt32 (cp[6]  / (double) scalar);
+                                cp[7] =  saturateInt32 (cp[7]  / (double) scalar);
+                                cp[8] =  saturateInt32 (cp[8]  / (double) scalar);
+                                cp[9] =  saturateInt32 (cp[9]  / (double) scalar);
+                                cp[10] =  saturateInt32 (cp[10]  / (double) scalar);
+                                cp[11] =  saturateInt32 (cp[11]  / (double) scalar);
+                                cp[12] =  saturateInt32 (cp[12]  / (double) scalar);
+                                cp[13] =  saturateInt32 (cp[13]  / (double) scalar);
+                                cp[14] =  saturateInt32 (cp[14]  / (double) scalar);
+                                cp[15] =  saturateInt32 (cp[15]  / (double) scalar);
+                                cp[16] =  saturateInt32 (cp[16]  / (double) scalar);
+                                cp[17] =  saturateInt32 (cp[17]  / (double) scalar);
+                                cp[18] =  saturateInt32 (cp[18]  / (double) scalar);
+                                cp[19] =  saturateInt32 (cp[19]  / (double) scalar);
+                                cp[20] =  saturateInt32 (cp[20]  / (double) scalar);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt32 (*cp  / (double) scalar);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((Int32*)range.Item3 + range.Item1);
+                            scalar = *((Int32*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt32 (ap[0]  / (double) scalar);
+                                cp[1] =  saturateInt32 (ap[1]  / (double) scalar);
+                                cp[2] =  saturateInt32 (ap[2]  / (double) scalar);
+                                cp[3] =  saturateInt32 (ap[3]  / (double) scalar);
+                                cp[4] =  saturateInt32 (ap[4]  / (double) scalar);
+                                cp[5] =  saturateInt32 (ap[5]  / (double) scalar);
+                                cp[6] =  saturateInt32 (ap[6]  / (double) scalar);
+                                cp[7] =  saturateInt32 (ap[7]  / (double) scalar);
+                                cp[8] =  saturateInt32 (ap[8]  / (double) scalar);
+                                cp[9] =  saturateInt32 (ap[9]  / (double) scalar);
+                                cp[10] =  saturateInt32 (ap[10]  / (double) scalar);
+                                cp[11] =  saturateInt32 (ap[11]  / (double) scalar);
+                                cp[12] =  saturateInt32 (ap[12]  / (double) scalar);
+                                cp[13] =  saturateInt32 (ap[13]  / (double) scalar);
+                                cp[14] =  saturateInt32 (ap[14]  / (double) scalar);
+                                cp[15] =  saturateInt32 (ap[15]  / (double) scalar);
+                                cp[16] =  saturateInt32 (ap[16]  / (double) scalar);
+                                cp[17] =  saturateInt32 (ap[17]  / (double) scalar);
+                                cp[18] =  saturateInt32 (ap[18]  / (double) scalar);
+                                cp[19] =  saturateInt32 (ap[19]  / (double) scalar);
+                                cp[20] =  saturateInt32 (ap[20]  / (double) scalar);
+                                ap+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt32 (*ap  / (double) scalar);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((Int32*)range.Item3);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt32 (scalar  / (double) cp[0]);
+                                cp[1] =  saturateInt32 (scalar  / (double) cp[1]);
+                                cp[2] =  saturateInt32 (scalar  / (double) cp[2]);
+                                cp[3] =  saturateInt32 (scalar  / (double) cp[3]);
+                                cp[4] =  saturateInt32 (scalar  / (double) cp[4]);
+                                cp[5] =  saturateInt32 (scalar  / (double) cp[5]);
+                                cp[6] =  saturateInt32 (scalar  / (double) cp[6]);
+                                cp[7] =  saturateInt32 (scalar  / (double) cp[7]);
+                                cp[8] =  saturateInt32 (scalar  / (double) cp[8]);
+                                cp[9] =  saturateInt32 (scalar  / (double) cp[9]);
+                                cp[10] =  saturateInt32 (scalar  / (double) cp[10]);
+                                cp[11] =  saturateInt32 (scalar  / (double) cp[11]);
+                                cp[12] =  saturateInt32 (scalar  / (double) cp[12]);
+                                cp[13] =  saturateInt32 (scalar  / (double) cp[13]);
+                                cp[14] =  saturateInt32 (scalar  / (double) cp[14]);
+                                cp[15] =  saturateInt32 (scalar  / (double) cp[15]);
+                                cp[16] =  saturateInt32 (scalar  / (double) cp[16]);
+                                cp[17] =  saturateInt32 (scalar  / (double) cp[17]);
+                                cp[18] =  saturateInt32 (scalar  / (double) cp[18]);
+                                cp[19] =  saturateInt32 (scalar  / (double) cp[19]);
+                                cp[20] =  saturateInt32 (scalar  / (double) cp[20]);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt32 (scalar  / (double) *cp);
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((Int32*)range.Item3);
+                            bp = ((Int32*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt32 (scalar  / (double) bp[0]);
+                                cp[1] =  saturateInt32 (scalar  / (double) bp[1]);
+                                cp[2] =  saturateInt32 (scalar  / (double) bp[2]);
+                                cp[3] =  saturateInt32 (scalar  / (double) bp[3]);
+                                cp[4] =  saturateInt32 (scalar  / (double) bp[4]);
+                                cp[5] =  saturateInt32 (scalar  / (double) bp[5]);
+                                cp[6] =  saturateInt32 (scalar  / (double) bp[6]);
+                                cp[7] =  saturateInt32 (scalar  / (double) bp[7]);
+                                cp[8] =  saturateInt32 (scalar  / (double) bp[8]);
+                                cp[9] =  saturateInt32 (scalar  / (double) bp[9]);
+                                cp[10] =  saturateInt32 (scalar  / (double) bp[10]);
+                                cp[11] =  saturateInt32 (scalar  / (double) bp[11]);
+                                cp[12] =  saturateInt32 (scalar  / (double) bp[12]);
+                                cp[13] =  saturateInt32 (scalar  / (double) bp[13]);
+                                cp[14] =  saturateInt32 (scalar  / (double) bp[14]);
+                                cp[15] =  saturateInt32 (scalar  / (double) bp[15]);
+                                cp[16] =  saturateInt32 (scalar  / (double) bp[16]);
+                                cp[17] =  saturateInt32 (scalar  / (double) bp[17]);
+                                cp[18] =  saturateInt32 (scalar  / (double) bp[18]);
+                                cp[19] =  saturateInt32 (scalar  / (double) bp[19]);
+                                cp[20] =  saturateInt32 (scalar  / (double) bp[20]);
+                                bp+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt32 (scalar  / (double) *bp);
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work 
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                
+                fixed ( Int32* arrAP = arrA)
+                fixed ( Int32* arrBP = arrB)
+                fixed ( Int32* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range 
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new  ILRetArray< Int32>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<Int32>  divideEx(ILInArray<Int32> A, ILInArray<Int32> B) {
+            //using (ILScope.Enter(A, B)) { we cannot start a new scope here, since this would prevent A and B to be used implace if applicable
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<Int32>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<Int32>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<Int32>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                dim = -(dim - 1);  // 0 -> 1, 1 -> 0
+                #endregion
+
+                #region parameter preparation
+               
+                Int32[] retArr;
+               
+                Int32[] arrA = A.GetArrayForRead();
+               
+                Int32[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int workItemMultiplierLenA;
+                int workItemMultiplierLenB;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<Int32>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    workItemMultiplierLenB = outDims[0]; 
+                    workItemMultiplierLenA = dim;  // 0 for column, 1 for row vector
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<Int32>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    workItemMultiplierLenB = dim;  // 0 for column, 1 for row vector
+                    workItemMultiplierLenA = outDims[0]; 
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one singleton dimension in either A or B");
+                }
+                int itLen = outDims[0]; // (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<Int32> retStorage = new ILDenseStorage<Int32>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    Int32* ap;
+                   
+                    Int32* bp;
+                   
+                    Int32* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            if (dim == 0) {
+                                bp = (Int32*)range.Item3;
+                                cp = (Int32*)range.Item4; 
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (Int32*)range.Item2;
+                                    int l = itLen; 
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt32 (ap[0]  / (double) bp[0]);
+                                        cp[1] =  saturateInt32 (ap[1]  / (double) bp[1]);
+                                        cp[2] =  saturateInt32 (ap[2]  / (double) bp[2]);
+                                        cp[3] =  saturateInt32 (ap[3]  / (double) bp[3]);
+                                        cp[4] =  saturateInt32 (ap[4]  / (double) bp[4]);
+                                        cp[5] =  saturateInt32 (ap[5]  / (double) bp[5]);
+                                        cp[6] =  saturateInt32 (ap[6]  / (double) bp[6]);
+                                        cp[7] =  saturateInt32 (ap[7]  / (double) bp[7]);
+                                        cp[8] =  saturateInt32 (ap[8]  / (double) bp[8]);
+                                        cp[9] =  saturateInt32 (ap[9]  / (double) bp[9]);
+                                        cp[10] =  saturateInt32 (ap[10]  / (double) bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =  saturateInt32 (*ap++  / (double) *bp++);
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                ap = (Int32*)range.Item2;
+                                bp = (Int32*)range.Item3;
+                                cp = (Int32*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   Int32 val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt32 (val  / (double) bp[0]);
+                                        cp[1] =  saturateInt32 (val  / (double) bp[1]);
+                                        cp[2] =  saturateInt32 (val  / (double) bp[2]);
+                                        cp[3] =  saturateInt32 (val  / (double) bp[3]);
+                                        cp[4] =  saturateInt32 (val  / (double) bp[4]);
+                                        cp[5] =  saturateInt32 (val  / (double) bp[5]);
+                                        cp[6] =  saturateInt32 (val  / (double) bp[6]);
+                                        cp[7] =  saturateInt32 (val  / (double) bp[7]);
+                                        cp[8] =  saturateInt32 (val  / (double) bp[8]);
+                                        cp[9] =  saturateInt32 (val  / (double) bp[9]);
+                                        cp[10] =  saturateInt32 (val  / (double) bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11; 
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =  saturateInt32 (val  / (double) *bp++);
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            if (dim == 0) {
+                                cp = (Int32*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (Int32*)range.Item2;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt32 (ap[0]  / (double) cp[0]);
+                                        cp[1] =  saturateInt32 (ap[1]  / (double) cp[1]);
+                                        cp[2] =  saturateInt32 (ap[2]  / (double) cp[2]);
+                                        cp[3] =  saturateInt32 (ap[3]  / (double) cp[3]);
+                                        cp[4] =  saturateInt32 (ap[4]  / (double) cp[4]);
+                                        cp[5] =  saturateInt32 (ap[5]  / (double) cp[5]);
+                                        cp[6] =  saturateInt32 (ap[6]  / (double) cp[6]);
+                                        cp[7] =  saturateInt32 (ap[7]  / (double) cp[7]);
+                                        cp[8] =  saturateInt32 (ap[8]  / (double) cp[8]);
+                                        cp[9] =  saturateInt32 (ap[9]  / (double) cp[9]);
+                                        cp[10] =  saturateInt32 (ap[10]  / (double) cp[10]);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt32 (*ap++  / (double) *cp);
+                                        cp++; 
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                cp = (Int32*)range.Item4;
+                                ap = (Int32*)range.Item2;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    Int32 val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt32 (val  / (double) cp[0]);
+                                        cp[1] =  saturateInt32 (val  / (double) cp[1]);
+                                        cp[2] =  saturateInt32 (val  / (double) cp[2]);
+                                        cp[3] =  saturateInt32 (val  / (double) cp[3]);
+                                        cp[4] =  saturateInt32 (val  / (double) cp[4]);
+                                        cp[5] =  saturateInt32 (val  / (double) cp[5]);
+                                        cp[6] =  saturateInt32 (val  / (double) cp[6]);
+                                        cp[7] =  saturateInt32 (val  / (double) cp[7]);
+                                        cp[8] =  saturateInt32 (val  / (double) cp[8]);
+                                        cp[9] =  saturateInt32 (val  / (double) cp[9]);
+                                        cp[10] =  saturateInt32 (val  / (double) cp[10]);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt32 (val  / (double) *cp);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            if (dim == 0) {
+                                ap = (Int32*)range.Item2;
+                                cp = (Int32*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (Int32*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt32 (ap[0]  / (double) bp[0]);
+                                        cp[1] =  saturateInt32 (ap[1]  / (double) bp[1]);
+                                        cp[2] =  saturateInt32 (ap[2]  / (double) bp[2]);
+                                        cp[3] =  saturateInt32 (ap[3]  / (double) bp[3]);
+                                        cp[4] =  saturateInt32 (ap[4]  / (double) bp[4]);
+                                        cp[5] =  saturateInt32 (ap[5]  / (double) bp[5]);
+                                        cp[6] =  saturateInt32 (ap[6]  / (double) bp[6]);
+                                        cp[7] =  saturateInt32 (ap[7]  / (double) bp[7]);
+                                        cp[8] =  saturateInt32 (ap[8]  / (double) bp[8]);
+                                        cp[9] =  saturateInt32 (ap[9]  / (double) bp[9]);
+                                        cp[10] =  saturateInt32 (ap[10]  / (double) bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt32 (*ap  / (double) *bp);
+                                        ap++;
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                ap = (Int32*)range.Item2;
+                                bp = (Int32*)range.Item3;
+                                cp = (Int32*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   Int32 val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt32 (ap[0]  / (double) val);
+                                        cp[1] =  saturateInt32 (ap[1]  / (double) val);
+                                        cp[2] =  saturateInt32 (ap[2]  / (double) val);
+                                        cp[3] =  saturateInt32 (ap[3]  / (double) val);
+                                        cp[4] =  saturateInt32 (ap[4]  / (double) val);
+                                        cp[5] =  saturateInt32 (ap[5]  / (double) val);
+                                        cp[6] =  saturateInt32 (ap[6]  / (double) val);
+                                        cp[7] =  saturateInt32 (ap[7]  / (double) val);
+                                        cp[8] =  saturateInt32 (ap[8]  / (double) val);
+                                        cp[9] =  saturateInt32 (ap[9]  / (double) val);
+                                        cp[10] =  saturateInt32 (ap[10]  / (double) val);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt32 (*ap  / (double) val);
+                                        ap++;
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            if (dim == 0) {
+                                cp = (Int32*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (Int32*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt32 (cp[0]  / (double) bp[0]);
+                                        cp[1] =  saturateInt32 (cp[1]  / (double) bp[1]);
+                                        cp[2] =  saturateInt32 (cp[2]  / (double) bp[2]);
+                                        cp[3] =  saturateInt32 (cp[3]  / (double) bp[3]);
+                                        cp[4] =  saturateInt32 (cp[4]  / (double) bp[4]);
+                                        cp[5] =  saturateInt32 (cp[5]  / (double) bp[5]);
+                                        cp[6] =  saturateInt32 (cp[6]  / (double) bp[6]);
+                                        cp[7] =  saturateInt32 (cp[7]  / (double) bp[7]);
+                                        cp[8] =  saturateInt32 (cp[8]  / (double) bp[8]);
+                                        cp[9] =  saturateInt32 (cp[9]  / (double) bp[9]);
+                                        cp[10] =  saturateInt32 (cp[10]  / (double) bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt32 (*cp  / (double) *bp);
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                bp = (Int32*)range.Item3;
+                                cp = (Int32*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    Int32 val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt32 (cp[0]  / (double) val);
+                                        cp[1] =  saturateInt32 (cp[1]  / (double) val);
+                                        cp[2] =  saturateInt32 (cp[2]  / (double) val);
+                                        cp[3] =  saturateInt32 (cp[3]  / (double) val);
+                                        cp[4] =  saturateInt32 (cp[4]  / (double) val);
+                                        cp[5] =  saturateInt32 (cp[5]  / (double) val);
+                                        cp[6] =  saturateInt32 (cp[6]  / (double) val);
+                                        cp[7] =  saturateInt32 (cp[7]  / (double) val);
+                                        cp[8] =  saturateInt32 (cp[8]  / (double) val);
+                                        cp[9] =  saturateInt32 (cp[9]  / (double) val);
+                                        cp[10] =  saturateInt32 (cp[10]  / (double) val);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l --> 0) {
+                                        *cp =  saturateInt32 (*cp  / (double) val);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outDims.NumberOfElements >= Settings.s_minParallelElement1Count
+                    && outDims[1] > 1) {
+                        if (outDims[1] > workItemCount) {
+                        workItemLength = outDims[1] / workItemCount;
+                    } else {
+                        workItemLength = outDims[1] / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outDims[1];
+                    workItemCount = 1;
+                }
+
+                fixed ( Int32* arrAP = arrA)
+                fixed ( Int32* arrBP = arrB)
+                fixed ( Int32* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, IntPtr, IntPtr, IntPtr> range = new Tuple<int, IntPtr, IntPtr, IntPtr>
+                               (workItemLength
+                               , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                               , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                               , (IntPtr)(retArrP + i * outDims[0] * workItemLength)); 
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, IntPtr, IntPtr, IntPtr>
+                                (outDims[1] - i * workItemLength
+                                , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                                , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                                , (IntPtr)(retArrP + i * outDims[0] * workItemLength)));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<Int32>(retStorage);
+            //}  // no scopes here! it disables implace operations
+        }
+
+        /// <summary>Divide elements</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Array with elementwise division of A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<float>  divide(ILInArray<float> A, ILInArray<float> B) {
+            using (ILScope.Enter(A,B)) {
+                int outLen; 
+                BinOpItMode mode; 
+                float [] retArr;
+                float [] arrA = A.GetArrayForRead();
+                float[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size; 
+                    if (B.IsScalar) {
+                       
+                        return new  ILRetArray<float> (new  float [1]{  (A.GetValue(0)  / B.GetValue(0))}, A.Size);
+                    } else if (B.IsEmpty) {
+                        return  ILRetArray<float>.empty(outDims); 
+                    } else {
+                        outLen = outDims.NumberOfElements; 
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< float > (outLen);
+                            mode = BinOpItMode.SAN; 
+                        } else {
+                            mode = BinOpItMode.SAI; 
+                        }
+                    }
+                } else {
+                    outDims = A.Size; 
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return  ILRetArray<float>.empty(A.Size);  
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< float > (outLen);
+                            mode = BinOpItMode.ASN; 
+                        } else {
+                            mode = BinOpItMode.ASI; 
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  divideEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (A.TryGetStorage4InplaceOp(out retArr)) 
+                            mode  = BinOpItMode.AAIA; 
+                        else if (B.TryGetStorage4InplaceOp(out retArr)) 
+                            mode = BinOpItMode.AAIB; 
+                        else {
+                            retArr = ILMemoryPool.Pool.New< float > (outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<float> retStorage = new ILDenseStorage<float>(retArr, outDims);
+                int i = 0, workerCount = 1; 
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    float* cp = (float*)range.Item5 + range.Item1;
+                    float scalar;
+                    int j = range.Item2; 
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           float* bp = ((float*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                                cp[0] =   (cp[0]  / bp[0]);
+                                cp[1] =   (cp[1]  / bp[1]);
+                                cp[2] =   (cp[2]  / bp[2]);
+                                cp[3] =   (cp[3]  / bp[3]);
+                                cp[4] =   (cp[4]  / bp[4]);
+                                cp[5] =   (cp[5]  / bp[5]);
+                                cp[6] =   (cp[6]  / bp[6]);
+                                cp[7] =   (cp[7]  / bp[7]);
+                                cp[8] =   (cp[8]  / bp[8]);
+                                cp[9] =   (cp[9]  / bp[9]);
+                                cp[10] =   (cp[10]  / bp[10]);
+                                cp[11] =   (cp[11]  / bp[11]);
+                                cp[12] =   (cp[12]  / bp[12]);
+                                cp[13] =   (cp[13]  / bp[13]);
+                                cp[14] =   (cp[14]  / bp[14]);
+                                cp[15] =   (cp[15]  / bp[15]);
+                                cp[16] =   (cp[16]  / bp[16]);
+                                cp[17] =   (cp[17]  / bp[17]);
+                                cp[18] =   (cp[18]  / bp[18]);
+                                cp[19] =   (cp[19]  / bp[19]);
+                                cp[20] =   (cp[20]  / bp[20]);
+                                cp += 21; bp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*cp  / *bp);
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           float* ap = ((float*)range.Item3 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  / cp[0]);
+                                cp[1] =   (ap[1]  / cp[1]);
+                                cp[2] =   (ap[2]  / cp[2]);
+                                cp[3] =   (ap[3]  / cp[3]);
+                                cp[4] =   (ap[4]  / cp[4]);
+                                cp[5] =   (ap[5]  / cp[5]);
+                                cp[6] =   (ap[6]  / cp[6]);
+                                cp[7] =   (ap[7]  / cp[7]);
+                                cp[8] =   (ap[8]  / cp[8]);
+                                cp[9] =   (ap[9]  / cp[9]);
+                                cp[10] =   (ap[10]  / cp[10]);
+                                cp[11] =   (ap[11]  / cp[11]);
+                                cp[12] =   (ap[12]  / cp[12]);
+                                cp[13] =   (ap[13]  / cp[13]);
+                                cp[14] =   (ap[14]  / cp[14]);
+                                cp[15] =   (ap[15]  / cp[15]);
+                                cp[16] =   (ap[16]  / cp[16]);
+                                cp[17] =   (ap[17]  / cp[17]);
+                                cp[18] =   (ap[18]  / cp[18]);
+                                cp[19] =   (ap[19]  / cp[19]);
+                                cp[20] =   (ap[20]  / cp[20]);
+                                ap += 21; cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  / *cp);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((float*)range.Item3 + range.Item1);
+                            bp = ((float*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  / bp[0]);
+                                cp[1] =   (ap[1]  / bp[1]);
+                                cp[2] =   (ap[2]  / bp[2]);
+                                cp[3] =   (ap[3]  / bp[3]);
+                                cp[4] =   (ap[4]  / bp[4]);
+                                cp[5] =   (ap[5]  / bp[5]);
+                                cp[6] =   (ap[6]  / bp[6]);
+                                cp[7] =   (ap[7]  / bp[7]);
+                                cp[8] =   (ap[8]  / bp[8]);
+                                cp[9] =   (ap[9]  / bp[9]);
+                                cp[10] =   (ap[10]  / bp[10]);
+                                cp[11] =   (ap[11]  / bp[11]);
+                                cp[12] =   (ap[12]  / bp[12]);
+                                cp[13] =   (ap[13]  / bp[13]);
+                                cp[14] =   (ap[14]  / bp[14]);
+                                cp[15] =   (ap[15]  / bp[15]);
+                                cp[16] =   (ap[16]  / bp[16]);
+                                cp[17] =   (ap[17]  / bp[17]);
+                                cp[18] =   (ap[18]  / bp[18]);
+                                cp[19] =   (ap[19]  / bp[19]);
+                                cp[20] =   (ap[20]  / bp[20]);
+                                ap+=21; bp+=21; cp+=21; j-=21;
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  / *bp);
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((float*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =   (cp[0]  / scalar);
+                                cp[1] =   (cp[1]  / scalar);
+                                cp[2] =   (cp[2]  / scalar);
+                                cp[3] =   (cp[3]  / scalar);
+                                cp[4] =   (cp[4]  / scalar);
+                                cp[5] =   (cp[5]  / scalar);
+                                cp[6] =   (cp[6]  / scalar);
+                                cp[7] =   (cp[7]  / scalar);
+                                cp[8] =   (cp[8]  / scalar);
+                                cp[9] =   (cp[9]  / scalar);
+                                cp[10] =   (cp[10]  / scalar);
+                                cp[11] =   (cp[11]  / scalar);
+                                cp[12] =   (cp[12]  / scalar);
+                                cp[13] =   (cp[13]  / scalar);
+                                cp[14] =   (cp[14]  / scalar);
+                                cp[15] =   (cp[15]  / scalar);
+                                cp[16] =   (cp[16]  / scalar);
+                                cp[17] =   (cp[17]  / scalar);
+                                cp[18] =   (cp[18]  / scalar);
+                                cp[19] =   (cp[19]  / scalar);
+                                cp[20] =   (cp[20]  / scalar);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*cp  / scalar);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((float*)range.Item3 + range.Item1);
+                            scalar = *((float*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  / scalar);
+                                cp[1] =   (ap[1]  / scalar);
+                                cp[2] =   (ap[2]  / scalar);
+                                cp[3] =   (ap[3]  / scalar);
+                                cp[4] =   (ap[4]  / scalar);
+                                cp[5] =   (ap[5]  / scalar);
+                                cp[6] =   (ap[6]  / scalar);
+                                cp[7] =   (ap[7]  / scalar);
+                                cp[8] =   (ap[8]  / scalar);
+                                cp[9] =   (ap[9]  / scalar);
+                                cp[10] =   (ap[10]  / scalar);
+                                cp[11] =   (ap[11]  / scalar);
+                                cp[12] =   (ap[12]  / scalar);
+                                cp[13] =   (ap[13]  / scalar);
+                                cp[14] =   (ap[14]  / scalar);
+                                cp[15] =   (ap[15]  / scalar);
+                                cp[16] =   (ap[16]  / scalar);
+                                cp[17] =   (ap[17]  / scalar);
+                                cp[18] =   (ap[18]  / scalar);
+                                cp[19] =   (ap[19]  / scalar);
+                                cp[20] =   (ap[20]  / scalar);
+                                ap+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  / scalar);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((float*)range.Item3);
+                            while (j > 20) {
+                               
+                                cp[0] =   (scalar  / cp[0]);
+                                cp[1] =   (scalar  / cp[1]);
+                                cp[2] =   (scalar  / cp[2]);
+                                cp[3] =   (scalar  / cp[3]);
+                                cp[4] =   (scalar  / cp[4]);
+                                cp[5] =   (scalar  / cp[5]);
+                                cp[6] =   (scalar  / cp[6]);
+                                cp[7] =   (scalar  / cp[7]);
+                                cp[8] =   (scalar  / cp[8]);
+                                cp[9] =   (scalar  / cp[9]);
+                                cp[10] =   (scalar  / cp[10]);
+                                cp[11] =   (scalar  / cp[11]);
+                                cp[12] =   (scalar  / cp[12]);
+                                cp[13] =   (scalar  / cp[13]);
+                                cp[14] =   (scalar  / cp[14]);
+                                cp[15] =   (scalar  / cp[15]);
+                                cp[16] =   (scalar  / cp[16]);
+                                cp[17] =   (scalar  / cp[17]);
+                                cp[18] =   (scalar  / cp[18]);
+                                cp[19] =   (scalar  / cp[19]);
+                                cp[20] =   (scalar  / cp[20]);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (scalar  / *cp);
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((float*)range.Item3);
+                            bp = ((float*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (scalar  / bp[0]);
+                                cp[1] =   (scalar  / bp[1]);
+                                cp[2] =   (scalar  / bp[2]);
+                                cp[3] =   (scalar  / bp[3]);
+                                cp[4] =   (scalar  / bp[4]);
+                                cp[5] =   (scalar  / bp[5]);
+                                cp[6] =   (scalar  / bp[6]);
+                                cp[7] =   (scalar  / bp[7]);
+                                cp[8] =   (scalar  / bp[8]);
+                                cp[9] =   (scalar  / bp[9]);
+                                cp[10] =   (scalar  / bp[10]);
+                                cp[11] =   (scalar  / bp[11]);
+                                cp[12] =   (scalar  / bp[12]);
+                                cp[13] =   (scalar  / bp[13]);
+                                cp[14] =   (scalar  / bp[14]);
+                                cp[15] =   (scalar  / bp[15]);
+                                cp[16] =   (scalar  / bp[16]);
+                                cp[17] =   (scalar  / bp[17]);
+                                cp[18] =   (scalar  / bp[18]);
+                                cp[19] =   (scalar  / bp[19]);
+                                cp[20] =   (scalar  / bp[20]);
+                                bp+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (scalar  / *bp);
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work 
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                
+                fixed ( float* arrAP = arrA)
+                fixed ( float* arrBP = arrB)
+                fixed ( float* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range 
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new  ILRetArray< float>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<float>  divideEx(ILInArray<float> A, ILInArray<float> B) {
+            //using (ILScope.Enter(A, B)) { we cannot start a new scope here, since this would prevent A and B to be used implace if applicable
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<float>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<float>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<float>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                dim = -(dim - 1);  // 0 -> 1, 1 -> 0
+                #endregion
+
+                #region parameter preparation
+               
+                float[] retArr;
+               
+                float[] arrA = A.GetArrayForRead();
+               
+                float[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int workItemMultiplierLenA;
+                int workItemMultiplierLenB;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<float>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    workItemMultiplierLenB = outDims[0]; 
+                    workItemMultiplierLenA = dim;  // 0 for column, 1 for row vector
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<float>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    workItemMultiplierLenB = dim;  // 0 for column, 1 for row vector
+                    workItemMultiplierLenA = outDims[0]; 
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one singleton dimension in either A or B");
+                }
+                int itLen = outDims[0]; // (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<float> retStorage = new ILDenseStorage<float>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    float* ap;
+                   
+                    float* bp;
+                   
+                    float* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            if (dim == 0) {
+                                bp = (float*)range.Item3;
+                                cp = (float*)range.Item4; 
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (float*)range.Item2;
+                                    int l = itLen; 
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  / bp[0]);
+                                        cp[1] =   (ap[1]  / bp[1]);
+                                        cp[2] =   (ap[2]  / bp[2]);
+                                        cp[3] =   (ap[3]  / bp[3]);
+                                        cp[4] =   (ap[4]  / bp[4]);
+                                        cp[5] =   (ap[5]  / bp[5]);
+                                        cp[6] =   (ap[6]  / bp[6]);
+                                        cp[7] =   (ap[7]  / bp[7]);
+                                        cp[8] =   (ap[8]  / bp[8]);
+                                        cp[9] =   (ap[9]  / bp[9]);
+                                        cp[10] =   (ap[10]  / bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =   (*ap++  / *bp++);
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                ap = (float*)range.Item2;
+                                bp = (float*)range.Item3;
+                                cp = (float*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   float val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (val  / bp[0]);
+                                        cp[1] =   (val  / bp[1]);
+                                        cp[2] =   (val  / bp[2]);
+                                        cp[3] =   (val  / bp[3]);
+                                        cp[4] =   (val  / bp[4]);
+                                        cp[5] =   (val  / bp[5]);
+                                        cp[6] =   (val  / bp[6]);
+                                        cp[7] =   (val  / bp[7]);
+                                        cp[8] =   (val  / bp[8]);
+                                        cp[9] =   (val  / bp[9]);
+                                        cp[10] =   (val  / bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11; 
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =   (val  / *bp++);
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            if (dim == 0) {
+                                cp = (float*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (float*)range.Item2;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  / cp[0]);
+                                        cp[1] =   (ap[1]  / cp[1]);
+                                        cp[2] =   (ap[2]  / cp[2]);
+                                        cp[3] =   (ap[3]  / cp[3]);
+                                        cp[4] =   (ap[4]  / cp[4]);
+                                        cp[5] =   (ap[5]  / cp[5]);
+                                        cp[6] =   (ap[6]  / cp[6]);
+                                        cp[7] =   (ap[7]  / cp[7]);
+                                        cp[8] =   (ap[8]  / cp[8]);
+                                        cp[9] =   (ap[9]  / cp[9]);
+                                        cp[10] =   (ap[10]  / cp[10]);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap++  / *cp);
+                                        cp++; 
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                cp = (float*)range.Item4;
+                                ap = (float*)range.Item2;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    float val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (val  / cp[0]);
+                                        cp[1] =   (val  / cp[1]);
+                                        cp[2] =   (val  / cp[2]);
+                                        cp[3] =   (val  / cp[3]);
+                                        cp[4] =   (val  / cp[4]);
+                                        cp[5] =   (val  / cp[5]);
+                                        cp[6] =   (val  / cp[6]);
+                                        cp[7] =   (val  / cp[7]);
+                                        cp[8] =   (val  / cp[8]);
+                                        cp[9] =   (val  / cp[9]);
+                                        cp[10] =   (val  / cp[10]);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (val  / *cp);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            if (dim == 0) {
+                                ap = (float*)range.Item2;
+                                cp = (float*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (float*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  / bp[0]);
+                                        cp[1] =   (ap[1]  / bp[1]);
+                                        cp[2] =   (ap[2]  / bp[2]);
+                                        cp[3] =   (ap[3]  / bp[3]);
+                                        cp[4] =   (ap[4]  / bp[4]);
+                                        cp[5] =   (ap[5]  / bp[5]);
+                                        cp[6] =   (ap[6]  / bp[6]);
+                                        cp[7] =   (ap[7]  / bp[7]);
+                                        cp[8] =   (ap[8]  / bp[8]);
+                                        cp[9] =   (ap[9]  / bp[9]);
+                                        cp[10] =   (ap[10]  / bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap  / *bp);
+                                        ap++;
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                ap = (float*)range.Item2;
+                                bp = (float*)range.Item3;
+                                cp = (float*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   float val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  / val);
+                                        cp[1] =   (ap[1]  / val);
+                                        cp[2] =   (ap[2]  / val);
+                                        cp[3] =   (ap[3]  / val);
+                                        cp[4] =   (ap[4]  / val);
+                                        cp[5] =   (ap[5]  / val);
+                                        cp[6] =   (ap[6]  / val);
+                                        cp[7] =   (ap[7]  / val);
+                                        cp[8] =   (ap[8]  / val);
+                                        cp[9] =   (ap[9]  / val);
+                                        cp[10] =   (ap[10]  / val);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap  / val);
+                                        ap++;
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            if (dim == 0) {
+                                cp = (float*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (float*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (cp[0]  / bp[0]);
+                                        cp[1] =   (cp[1]  / bp[1]);
+                                        cp[2] =   (cp[2]  / bp[2]);
+                                        cp[3] =   (cp[3]  / bp[3]);
+                                        cp[4] =   (cp[4]  / bp[4]);
+                                        cp[5] =   (cp[5]  / bp[5]);
+                                        cp[6] =   (cp[6]  / bp[6]);
+                                        cp[7] =   (cp[7]  / bp[7]);
+                                        cp[8] =   (cp[8]  / bp[8]);
+                                        cp[9] =   (cp[9]  / bp[9]);
+                                        cp[10] =   (cp[10]  / bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*cp  / *bp);
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                bp = (float*)range.Item3;
+                                cp = (float*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    float val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (cp[0]  / val);
+                                        cp[1] =   (cp[1]  / val);
+                                        cp[2] =   (cp[2]  / val);
+                                        cp[3] =   (cp[3]  / val);
+                                        cp[4] =   (cp[4]  / val);
+                                        cp[5] =   (cp[5]  / val);
+                                        cp[6] =   (cp[6]  / val);
+                                        cp[7] =   (cp[7]  / val);
+                                        cp[8] =   (cp[8]  / val);
+                                        cp[9] =   (cp[9]  / val);
+                                        cp[10] =   (cp[10]  / val);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l --> 0) {
+                                        *cp =   (*cp  / val);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outDims.NumberOfElements >= Settings.s_minParallelElement1Count
+                    && outDims[1] > 1) {
+                        if (outDims[1] > workItemCount) {
+                        workItemLength = outDims[1] / workItemCount;
+                    } else {
+                        workItemLength = outDims[1] / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outDims[1];
+                    workItemCount = 1;
+                }
+
+                fixed ( float* arrAP = arrA)
+                fixed ( float* arrBP = arrB)
+                fixed ( float* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, IntPtr, IntPtr, IntPtr> range = new Tuple<int, IntPtr, IntPtr, IntPtr>
+                               (workItemLength
+                               , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                               , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                               , (IntPtr)(retArrP + i * outDims[0] * workItemLength)); 
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, IntPtr, IntPtr, IntPtr>
+                                (outDims[1] - i * workItemLength
+                                , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                                , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                                , (IntPtr)(retArrP + i * outDims[0] * workItemLength)));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<float>(retStorage);
+            //}  // no scopes here! it disables implace operations
+        }
+
+        /// <summary>Divide elements</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Array with elementwise division of A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<fcomplex>  divide(ILInArray<fcomplex> A, ILInArray<fcomplex> B) {
+            using (ILScope.Enter(A,B)) {
+                int outLen; 
+                BinOpItMode mode; 
+                fcomplex [] retArr;
+                fcomplex [] arrA = A.GetArrayForRead();
+                fcomplex[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size; 
+                    if (B.IsScalar) {
+                       
+                        return new  ILRetArray<fcomplex> (new  fcomplex [1]{  (A.GetValue(0)  / B.GetValue(0))}, A.Size);
+                    } else if (B.IsEmpty) {
+                        return  ILRetArray<fcomplex>.empty(outDims); 
+                    } else {
+                        outLen = outDims.NumberOfElements; 
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< fcomplex > (outLen);
+                            mode = BinOpItMode.SAN; 
+                        } else {
+                            mode = BinOpItMode.SAI; 
+                        }
+                    }
+                } else {
+                    outDims = A.Size; 
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return  ILRetArray<fcomplex>.empty(A.Size);  
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< fcomplex > (outLen);
+                            mode = BinOpItMode.ASN; 
+                        } else {
+                            mode = BinOpItMode.ASI; 
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  divideEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (A.TryGetStorage4InplaceOp(out retArr)) 
+                            mode  = BinOpItMode.AAIA; 
+                        else if (B.TryGetStorage4InplaceOp(out retArr)) 
+                            mode = BinOpItMode.AAIB; 
+                        else {
+                            retArr = ILMemoryPool.Pool.New< fcomplex > (outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<fcomplex> retStorage = new ILDenseStorage<fcomplex>(retArr, outDims);
+                int i = 0, workerCount = 1; 
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    fcomplex* cp = (fcomplex*)range.Item5 + range.Item1;
+                    fcomplex scalar;
+                    int j = range.Item2; 
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           fcomplex* bp = ((fcomplex*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                                cp[0] =   (cp[0]  / bp[0]);
+                                cp[1] =   (cp[1]  / bp[1]);
+                                cp[2] =   (cp[2]  / bp[2]);
+                                cp[3] =   (cp[3]  / bp[3]);
+                                cp[4] =   (cp[4]  / bp[4]);
+                                cp[5] =   (cp[5]  / bp[5]);
+                                cp[6] =   (cp[6]  / bp[6]);
+                                cp[7] =   (cp[7]  / bp[7]);
+                                cp[8] =   (cp[8]  / bp[8]);
+                                cp[9] =   (cp[9]  / bp[9]);
+                                cp[10] =   (cp[10]  / bp[10]);
+                                cp[11] =   (cp[11]  / bp[11]);
+                                cp[12] =   (cp[12]  / bp[12]);
+                                cp[13] =   (cp[13]  / bp[13]);
+                                cp[14] =   (cp[14]  / bp[14]);
+                                cp[15] =   (cp[15]  / bp[15]);
+                                cp[16] =   (cp[16]  / bp[16]);
+                                cp[17] =   (cp[17]  / bp[17]);
+                                cp[18] =   (cp[18]  / bp[18]);
+                                cp[19] =   (cp[19]  / bp[19]);
+                                cp[20] =   (cp[20]  / bp[20]);
+                                cp += 21; bp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*cp  / *bp);
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           fcomplex* ap = ((fcomplex*)range.Item3 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  / cp[0]);
+                                cp[1] =   (ap[1]  / cp[1]);
+                                cp[2] =   (ap[2]  / cp[2]);
+                                cp[3] =   (ap[3]  / cp[3]);
+                                cp[4] =   (ap[4]  / cp[4]);
+                                cp[5] =   (ap[5]  / cp[5]);
+                                cp[6] =   (ap[6]  / cp[6]);
+                                cp[7] =   (ap[7]  / cp[7]);
+                                cp[8] =   (ap[8]  / cp[8]);
+                                cp[9] =   (ap[9]  / cp[9]);
+                                cp[10] =   (ap[10]  / cp[10]);
+                                cp[11] =   (ap[11]  / cp[11]);
+                                cp[12] =   (ap[12]  / cp[12]);
+                                cp[13] =   (ap[13]  / cp[13]);
+                                cp[14] =   (ap[14]  / cp[14]);
+                                cp[15] =   (ap[15]  / cp[15]);
+                                cp[16] =   (ap[16]  / cp[16]);
+                                cp[17] =   (ap[17]  / cp[17]);
+                                cp[18] =   (ap[18]  / cp[18]);
+                                cp[19] =   (ap[19]  / cp[19]);
+                                cp[20] =   (ap[20]  / cp[20]);
+                                ap += 21; cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  / *cp);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((fcomplex*)range.Item3 + range.Item1);
+                            bp = ((fcomplex*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  / bp[0]);
+                                cp[1] =   (ap[1]  / bp[1]);
+                                cp[2] =   (ap[2]  / bp[2]);
+                                cp[3] =   (ap[3]  / bp[3]);
+                                cp[4] =   (ap[4]  / bp[4]);
+                                cp[5] =   (ap[5]  / bp[5]);
+                                cp[6] =   (ap[6]  / bp[6]);
+                                cp[7] =   (ap[7]  / bp[7]);
+                                cp[8] =   (ap[8]  / bp[8]);
+                                cp[9] =   (ap[9]  / bp[9]);
+                                cp[10] =   (ap[10]  / bp[10]);
+                                cp[11] =   (ap[11]  / bp[11]);
+                                cp[12] =   (ap[12]  / bp[12]);
+                                cp[13] =   (ap[13]  / bp[13]);
+                                cp[14] =   (ap[14]  / bp[14]);
+                                cp[15] =   (ap[15]  / bp[15]);
+                                cp[16] =   (ap[16]  / bp[16]);
+                                cp[17] =   (ap[17]  / bp[17]);
+                                cp[18] =   (ap[18]  / bp[18]);
+                                cp[19] =   (ap[19]  / bp[19]);
+                                cp[20] =   (ap[20]  / bp[20]);
+                                ap+=21; bp+=21; cp+=21; j-=21;
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  / *bp);
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((fcomplex*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =   (cp[0]  / scalar);
+                                cp[1] =   (cp[1]  / scalar);
+                                cp[2] =   (cp[2]  / scalar);
+                                cp[3] =   (cp[3]  / scalar);
+                                cp[4] =   (cp[4]  / scalar);
+                                cp[5] =   (cp[5]  / scalar);
+                                cp[6] =   (cp[6]  / scalar);
+                                cp[7] =   (cp[7]  / scalar);
+                                cp[8] =   (cp[8]  / scalar);
+                                cp[9] =   (cp[9]  / scalar);
+                                cp[10] =   (cp[10]  / scalar);
+                                cp[11] =   (cp[11]  / scalar);
+                                cp[12] =   (cp[12]  / scalar);
+                                cp[13] =   (cp[13]  / scalar);
+                                cp[14] =   (cp[14]  / scalar);
+                                cp[15] =   (cp[15]  / scalar);
+                                cp[16] =   (cp[16]  / scalar);
+                                cp[17] =   (cp[17]  / scalar);
+                                cp[18] =   (cp[18]  / scalar);
+                                cp[19] =   (cp[19]  / scalar);
+                                cp[20] =   (cp[20]  / scalar);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*cp  / scalar);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((fcomplex*)range.Item3 + range.Item1);
+                            scalar = *((fcomplex*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  / scalar);
+                                cp[1] =   (ap[1]  / scalar);
+                                cp[2] =   (ap[2]  / scalar);
+                                cp[3] =   (ap[3]  / scalar);
+                                cp[4] =   (ap[4]  / scalar);
+                                cp[5] =   (ap[5]  / scalar);
+                                cp[6] =   (ap[6]  / scalar);
+                                cp[7] =   (ap[7]  / scalar);
+                                cp[8] =   (ap[8]  / scalar);
+                                cp[9] =   (ap[9]  / scalar);
+                                cp[10] =   (ap[10]  / scalar);
+                                cp[11] =   (ap[11]  / scalar);
+                                cp[12] =   (ap[12]  / scalar);
+                                cp[13] =   (ap[13]  / scalar);
+                                cp[14] =   (ap[14]  / scalar);
+                                cp[15] =   (ap[15]  / scalar);
+                                cp[16] =   (ap[16]  / scalar);
+                                cp[17] =   (ap[17]  / scalar);
+                                cp[18] =   (ap[18]  / scalar);
+                                cp[19] =   (ap[19]  / scalar);
+                                cp[20] =   (ap[20]  / scalar);
+                                ap+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  / scalar);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((fcomplex*)range.Item3);
+                            while (j > 20) {
+                               
+                                cp[0] =   (scalar  / cp[0]);
+                                cp[1] =   (scalar  / cp[1]);
+                                cp[2] =   (scalar  / cp[2]);
+                                cp[3] =   (scalar  / cp[3]);
+                                cp[4] =   (scalar  / cp[4]);
+                                cp[5] =   (scalar  / cp[5]);
+                                cp[6] =   (scalar  / cp[6]);
+                                cp[7] =   (scalar  / cp[7]);
+                                cp[8] =   (scalar  / cp[8]);
+                                cp[9] =   (scalar  / cp[9]);
+                                cp[10] =   (scalar  / cp[10]);
+                                cp[11] =   (scalar  / cp[11]);
+                                cp[12] =   (scalar  / cp[12]);
+                                cp[13] =   (scalar  / cp[13]);
+                                cp[14] =   (scalar  / cp[14]);
+                                cp[15] =   (scalar  / cp[15]);
+                                cp[16] =   (scalar  / cp[16]);
+                                cp[17] =   (scalar  / cp[17]);
+                                cp[18] =   (scalar  / cp[18]);
+                                cp[19] =   (scalar  / cp[19]);
+                                cp[20] =   (scalar  / cp[20]);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (scalar  / *cp);
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((fcomplex*)range.Item3);
+                            bp = ((fcomplex*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (scalar  / bp[0]);
+                                cp[1] =   (scalar  / bp[1]);
+                                cp[2] =   (scalar  / bp[2]);
+                                cp[3] =   (scalar  / bp[3]);
+                                cp[4] =   (scalar  / bp[4]);
+                                cp[5] =   (scalar  / bp[5]);
+                                cp[6] =   (scalar  / bp[6]);
+                                cp[7] =   (scalar  / bp[7]);
+                                cp[8] =   (scalar  / bp[8]);
+                                cp[9] =   (scalar  / bp[9]);
+                                cp[10] =   (scalar  / bp[10]);
+                                cp[11] =   (scalar  / bp[11]);
+                                cp[12] =   (scalar  / bp[12]);
+                                cp[13] =   (scalar  / bp[13]);
+                                cp[14] =   (scalar  / bp[14]);
+                                cp[15] =   (scalar  / bp[15]);
+                                cp[16] =   (scalar  / bp[16]);
+                                cp[17] =   (scalar  / bp[17]);
+                                cp[18] =   (scalar  / bp[18]);
+                                cp[19] =   (scalar  / bp[19]);
+                                cp[20] =   (scalar  / bp[20]);
+                                bp+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (scalar  / *bp);
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work 
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                
+                fixed ( fcomplex* arrAP = arrA)
+                fixed ( fcomplex* arrBP = arrB)
+                fixed ( fcomplex* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range 
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new  ILRetArray< fcomplex>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<fcomplex>  divideEx(ILInArray<fcomplex> A, ILInArray<fcomplex> B) {
+            //using (ILScope.Enter(A, B)) { we cannot start a new scope here, since this would prevent A and B to be used implace if applicable
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<fcomplex>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<fcomplex>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<fcomplex>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                dim = -(dim - 1);  // 0 -> 1, 1 -> 0
+                #endregion
+
+                #region parameter preparation
+               
+                fcomplex[] retArr;
+               
+                fcomplex[] arrA = A.GetArrayForRead();
+               
+                fcomplex[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int workItemMultiplierLenA;
+                int workItemMultiplierLenB;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<fcomplex>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    workItemMultiplierLenB = outDims[0]; 
+                    workItemMultiplierLenA = dim;  // 0 for column, 1 for row vector
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<fcomplex>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    workItemMultiplierLenB = dim;  // 0 for column, 1 for row vector
+                    workItemMultiplierLenA = outDims[0]; 
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one singleton dimension in either A or B");
+                }
+                int itLen = outDims[0]; // (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<fcomplex> retStorage = new ILDenseStorage<fcomplex>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    fcomplex* ap;
+                   
+                    fcomplex* bp;
+                   
+                    fcomplex* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            if (dim == 0) {
+                                bp = (fcomplex*)range.Item3;
+                                cp = (fcomplex*)range.Item4; 
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (fcomplex*)range.Item2;
+                                    int l = itLen; 
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  / bp[0]);
+                                        cp[1] =   (ap[1]  / bp[1]);
+                                        cp[2] =   (ap[2]  / bp[2]);
+                                        cp[3] =   (ap[3]  / bp[3]);
+                                        cp[4] =   (ap[4]  / bp[4]);
+                                        cp[5] =   (ap[5]  / bp[5]);
+                                        cp[6] =   (ap[6]  / bp[6]);
+                                        cp[7] =   (ap[7]  / bp[7]);
+                                        cp[8] =   (ap[8]  / bp[8]);
+                                        cp[9] =   (ap[9]  / bp[9]);
+                                        cp[10] =   (ap[10]  / bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =   (*ap++  / *bp++);
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                ap = (fcomplex*)range.Item2;
+                                bp = (fcomplex*)range.Item3;
+                                cp = (fcomplex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   fcomplex val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (val  / bp[0]);
+                                        cp[1] =   (val  / bp[1]);
+                                        cp[2] =   (val  / bp[2]);
+                                        cp[3] =   (val  / bp[3]);
+                                        cp[4] =   (val  / bp[4]);
+                                        cp[5] =   (val  / bp[5]);
+                                        cp[6] =   (val  / bp[6]);
+                                        cp[7] =   (val  / bp[7]);
+                                        cp[8] =   (val  / bp[8]);
+                                        cp[9] =   (val  / bp[9]);
+                                        cp[10] =   (val  / bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11; 
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =   (val  / *bp++);
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            if (dim == 0) {
+                                cp = (fcomplex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (fcomplex*)range.Item2;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  / cp[0]);
+                                        cp[1] =   (ap[1]  / cp[1]);
+                                        cp[2] =   (ap[2]  / cp[2]);
+                                        cp[3] =   (ap[3]  / cp[3]);
+                                        cp[4] =   (ap[4]  / cp[4]);
+                                        cp[5] =   (ap[5]  / cp[5]);
+                                        cp[6] =   (ap[6]  / cp[6]);
+                                        cp[7] =   (ap[7]  / cp[7]);
+                                        cp[8] =   (ap[8]  / cp[8]);
+                                        cp[9] =   (ap[9]  / cp[9]);
+                                        cp[10] =   (ap[10]  / cp[10]);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap++  / *cp);
+                                        cp++; 
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                cp = (fcomplex*)range.Item4;
+                                ap = (fcomplex*)range.Item2;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    fcomplex val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (val  / cp[0]);
+                                        cp[1] =   (val  / cp[1]);
+                                        cp[2] =   (val  / cp[2]);
+                                        cp[3] =   (val  / cp[3]);
+                                        cp[4] =   (val  / cp[4]);
+                                        cp[5] =   (val  / cp[5]);
+                                        cp[6] =   (val  / cp[6]);
+                                        cp[7] =   (val  / cp[7]);
+                                        cp[8] =   (val  / cp[8]);
+                                        cp[9] =   (val  / cp[9]);
+                                        cp[10] =   (val  / cp[10]);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (val  / *cp);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            if (dim == 0) {
+                                ap = (fcomplex*)range.Item2;
+                                cp = (fcomplex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (fcomplex*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  / bp[0]);
+                                        cp[1] =   (ap[1]  / bp[1]);
+                                        cp[2] =   (ap[2]  / bp[2]);
+                                        cp[3] =   (ap[3]  / bp[3]);
+                                        cp[4] =   (ap[4]  / bp[4]);
+                                        cp[5] =   (ap[5]  / bp[5]);
+                                        cp[6] =   (ap[6]  / bp[6]);
+                                        cp[7] =   (ap[7]  / bp[7]);
+                                        cp[8] =   (ap[8]  / bp[8]);
+                                        cp[9] =   (ap[9]  / bp[9]);
+                                        cp[10] =   (ap[10]  / bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap  / *bp);
+                                        ap++;
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                ap = (fcomplex*)range.Item2;
+                                bp = (fcomplex*)range.Item3;
+                                cp = (fcomplex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   fcomplex val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  / val);
+                                        cp[1] =   (ap[1]  / val);
+                                        cp[2] =   (ap[2]  / val);
+                                        cp[3] =   (ap[3]  / val);
+                                        cp[4] =   (ap[4]  / val);
+                                        cp[5] =   (ap[5]  / val);
+                                        cp[6] =   (ap[6]  / val);
+                                        cp[7] =   (ap[7]  / val);
+                                        cp[8] =   (ap[8]  / val);
+                                        cp[9] =   (ap[9]  / val);
+                                        cp[10] =   (ap[10]  / val);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap  / val);
+                                        ap++;
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            if (dim == 0) {
+                                cp = (fcomplex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (fcomplex*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (cp[0]  / bp[0]);
+                                        cp[1] =   (cp[1]  / bp[1]);
+                                        cp[2] =   (cp[2]  / bp[2]);
+                                        cp[3] =   (cp[3]  / bp[3]);
+                                        cp[4] =   (cp[4]  / bp[4]);
+                                        cp[5] =   (cp[5]  / bp[5]);
+                                        cp[6] =   (cp[6]  / bp[6]);
+                                        cp[7] =   (cp[7]  / bp[7]);
+                                        cp[8] =   (cp[8]  / bp[8]);
+                                        cp[9] =   (cp[9]  / bp[9]);
+                                        cp[10] =   (cp[10]  / bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*cp  / *bp);
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                bp = (fcomplex*)range.Item3;
+                                cp = (fcomplex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    fcomplex val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (cp[0]  / val);
+                                        cp[1] =   (cp[1]  / val);
+                                        cp[2] =   (cp[2]  / val);
+                                        cp[3] =   (cp[3]  / val);
+                                        cp[4] =   (cp[4]  / val);
+                                        cp[5] =   (cp[5]  / val);
+                                        cp[6] =   (cp[6]  / val);
+                                        cp[7] =   (cp[7]  / val);
+                                        cp[8] =   (cp[8]  / val);
+                                        cp[9] =   (cp[9]  / val);
+                                        cp[10] =   (cp[10]  / val);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l --> 0) {
+                                        *cp =   (*cp  / val);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outDims.NumberOfElements >= Settings.s_minParallelElement1Count
+                    && outDims[1] > 1) {
+                        if (outDims[1] > workItemCount) {
+                        workItemLength = outDims[1] / workItemCount;
+                    } else {
+                        workItemLength = outDims[1] / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outDims[1];
+                    workItemCount = 1;
+                }
+
+                fixed ( fcomplex* arrAP = arrA)
+                fixed ( fcomplex* arrBP = arrB)
+                fixed ( fcomplex* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, IntPtr, IntPtr, IntPtr> range = new Tuple<int, IntPtr, IntPtr, IntPtr>
+                               (workItemLength
+                               , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                               , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                               , (IntPtr)(retArrP + i * outDims[0] * workItemLength)); 
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, IntPtr, IntPtr, IntPtr>
+                                (outDims[1] - i * workItemLength
+                                , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                                , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                                , (IntPtr)(retArrP + i * outDims[0] * workItemLength)));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<fcomplex>(retStorage);
+            //}  // no scopes here! it disables implace operations
+        }
+
+        /// <summary>Divide elements</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Array with elementwise division of A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<complex>  divide(ILInArray<complex> A, ILInArray<complex> B) {
+            using (ILScope.Enter(A,B)) {
+                int outLen; 
+                BinOpItMode mode; 
+                complex [] retArr;
+                complex [] arrA = A.GetArrayForRead();
+                complex[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size; 
+                    if (B.IsScalar) {
+                       
+                        return new  ILRetArray<complex> (new  complex [1]{  (A.GetValue(0)  / B.GetValue(0))}, A.Size);
+                    } else if (B.IsEmpty) {
+                        return  ILRetArray<complex>.empty(outDims); 
+                    } else {
+                        outLen = outDims.NumberOfElements; 
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< complex > (outLen);
+                            mode = BinOpItMode.SAN; 
+                        } else {
+                            mode = BinOpItMode.SAI; 
+                        }
+                    }
+                } else {
+                    outDims = A.Size; 
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return  ILRetArray<complex>.empty(A.Size);  
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< complex > (outLen);
+                            mode = BinOpItMode.ASN; 
+                        } else {
+                            mode = BinOpItMode.ASI; 
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  divideEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (A.TryGetStorage4InplaceOp(out retArr)) 
+                            mode  = BinOpItMode.AAIA; 
+                        else if (B.TryGetStorage4InplaceOp(out retArr)) 
+                            mode = BinOpItMode.AAIB; 
+                        else {
+                            retArr = ILMemoryPool.Pool.New< complex > (outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<complex> retStorage = new ILDenseStorage<complex>(retArr, outDims);
+                int i = 0, workerCount = 1; 
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    complex* cp = (complex*)range.Item5 + range.Item1;
+                    complex scalar;
+                    int j = range.Item2; 
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           complex* bp = ((complex*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                                cp[0] =   (cp[0]  / bp[0]);
+                                cp[1] =   (cp[1]  / bp[1]);
+                                cp[2] =   (cp[2]  / bp[2]);
+                                cp[3] =   (cp[3]  / bp[3]);
+                                cp[4] =   (cp[4]  / bp[4]);
+                                cp[5] =   (cp[5]  / bp[5]);
+                                cp[6] =   (cp[6]  / bp[6]);
+                                cp[7] =   (cp[7]  / bp[7]);
+                                cp[8] =   (cp[8]  / bp[8]);
+                                cp[9] =   (cp[9]  / bp[9]);
+                                cp[10] =   (cp[10]  / bp[10]);
+                                cp[11] =   (cp[11]  / bp[11]);
+                                cp[12] =   (cp[12]  / bp[12]);
+                                cp[13] =   (cp[13]  / bp[13]);
+                                cp[14] =   (cp[14]  / bp[14]);
+                                cp[15] =   (cp[15]  / bp[15]);
+                                cp[16] =   (cp[16]  / bp[16]);
+                                cp[17] =   (cp[17]  / bp[17]);
+                                cp[18] =   (cp[18]  / bp[18]);
+                                cp[19] =   (cp[19]  / bp[19]);
+                                cp[20] =   (cp[20]  / bp[20]);
+                                cp += 21; bp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*cp  / *bp);
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           complex* ap = ((complex*)range.Item3 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  / cp[0]);
+                                cp[1] =   (ap[1]  / cp[1]);
+                                cp[2] =   (ap[2]  / cp[2]);
+                                cp[3] =   (ap[3]  / cp[3]);
+                                cp[4] =   (ap[4]  / cp[4]);
+                                cp[5] =   (ap[5]  / cp[5]);
+                                cp[6] =   (ap[6]  / cp[6]);
+                                cp[7] =   (ap[7]  / cp[7]);
+                                cp[8] =   (ap[8]  / cp[8]);
+                                cp[9] =   (ap[9]  / cp[9]);
+                                cp[10] =   (ap[10]  / cp[10]);
+                                cp[11] =   (ap[11]  / cp[11]);
+                                cp[12] =   (ap[12]  / cp[12]);
+                                cp[13] =   (ap[13]  / cp[13]);
+                                cp[14] =   (ap[14]  / cp[14]);
+                                cp[15] =   (ap[15]  / cp[15]);
+                                cp[16] =   (ap[16]  / cp[16]);
+                                cp[17] =   (ap[17]  / cp[17]);
+                                cp[18] =   (ap[18]  / cp[18]);
+                                cp[19] =   (ap[19]  / cp[19]);
+                                cp[20] =   (ap[20]  / cp[20]);
+                                ap += 21; cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  / *cp);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((complex*)range.Item3 + range.Item1);
+                            bp = ((complex*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  / bp[0]);
+                                cp[1] =   (ap[1]  / bp[1]);
+                                cp[2] =   (ap[2]  / bp[2]);
+                                cp[3] =   (ap[3]  / bp[3]);
+                                cp[4] =   (ap[4]  / bp[4]);
+                                cp[5] =   (ap[5]  / bp[5]);
+                                cp[6] =   (ap[6]  / bp[6]);
+                                cp[7] =   (ap[7]  / bp[7]);
+                                cp[8] =   (ap[8]  / bp[8]);
+                                cp[9] =   (ap[9]  / bp[9]);
+                                cp[10] =   (ap[10]  / bp[10]);
+                                cp[11] =   (ap[11]  / bp[11]);
+                                cp[12] =   (ap[12]  / bp[12]);
+                                cp[13] =   (ap[13]  / bp[13]);
+                                cp[14] =   (ap[14]  / bp[14]);
+                                cp[15] =   (ap[15]  / bp[15]);
+                                cp[16] =   (ap[16]  / bp[16]);
+                                cp[17] =   (ap[17]  / bp[17]);
+                                cp[18] =   (ap[18]  / bp[18]);
+                                cp[19] =   (ap[19]  / bp[19]);
+                                cp[20] =   (ap[20]  / bp[20]);
+                                ap+=21; bp+=21; cp+=21; j-=21;
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  / *bp);
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((complex*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =   (cp[0]  / scalar);
+                                cp[1] =   (cp[1]  / scalar);
+                                cp[2] =   (cp[2]  / scalar);
+                                cp[3] =   (cp[3]  / scalar);
+                                cp[4] =   (cp[4]  / scalar);
+                                cp[5] =   (cp[5]  / scalar);
+                                cp[6] =   (cp[6]  / scalar);
+                                cp[7] =   (cp[7]  / scalar);
+                                cp[8] =   (cp[8]  / scalar);
+                                cp[9] =   (cp[9]  / scalar);
+                                cp[10] =   (cp[10]  / scalar);
+                                cp[11] =   (cp[11]  / scalar);
+                                cp[12] =   (cp[12]  / scalar);
+                                cp[13] =   (cp[13]  / scalar);
+                                cp[14] =   (cp[14]  / scalar);
+                                cp[15] =   (cp[15]  / scalar);
+                                cp[16] =   (cp[16]  / scalar);
+                                cp[17] =   (cp[17]  / scalar);
+                                cp[18] =   (cp[18]  / scalar);
+                                cp[19] =   (cp[19]  / scalar);
+                                cp[20] =   (cp[20]  / scalar);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*cp  / scalar);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((complex*)range.Item3 + range.Item1);
+                            scalar = *((complex*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  / scalar);
+                                cp[1] =   (ap[1]  / scalar);
+                                cp[2] =   (ap[2]  / scalar);
+                                cp[3] =   (ap[3]  / scalar);
+                                cp[4] =   (ap[4]  / scalar);
+                                cp[5] =   (ap[5]  / scalar);
+                                cp[6] =   (ap[6]  / scalar);
+                                cp[7] =   (ap[7]  / scalar);
+                                cp[8] =   (ap[8]  / scalar);
+                                cp[9] =   (ap[9]  / scalar);
+                                cp[10] =   (ap[10]  / scalar);
+                                cp[11] =   (ap[11]  / scalar);
+                                cp[12] =   (ap[12]  / scalar);
+                                cp[13] =   (ap[13]  / scalar);
+                                cp[14] =   (ap[14]  / scalar);
+                                cp[15] =   (ap[15]  / scalar);
+                                cp[16] =   (ap[16]  / scalar);
+                                cp[17] =   (ap[17]  / scalar);
+                                cp[18] =   (ap[18]  / scalar);
+                                cp[19] =   (ap[19]  / scalar);
+                                cp[20] =   (ap[20]  / scalar);
+                                ap+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  / scalar);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((complex*)range.Item3);
+                            while (j > 20) {
+                               
+                                cp[0] =   (scalar  / cp[0]);
+                                cp[1] =   (scalar  / cp[1]);
+                                cp[2] =   (scalar  / cp[2]);
+                                cp[3] =   (scalar  / cp[3]);
+                                cp[4] =   (scalar  / cp[4]);
+                                cp[5] =   (scalar  / cp[5]);
+                                cp[6] =   (scalar  / cp[6]);
+                                cp[7] =   (scalar  / cp[7]);
+                                cp[8] =   (scalar  / cp[8]);
+                                cp[9] =   (scalar  / cp[9]);
+                                cp[10] =   (scalar  / cp[10]);
+                                cp[11] =   (scalar  / cp[11]);
+                                cp[12] =   (scalar  / cp[12]);
+                                cp[13] =   (scalar  / cp[13]);
+                                cp[14] =   (scalar  / cp[14]);
+                                cp[15] =   (scalar  / cp[15]);
+                                cp[16] =   (scalar  / cp[16]);
+                                cp[17] =   (scalar  / cp[17]);
+                                cp[18] =   (scalar  / cp[18]);
+                                cp[19] =   (scalar  / cp[19]);
+                                cp[20] =   (scalar  / cp[20]);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (scalar  / *cp);
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((complex*)range.Item3);
+                            bp = ((complex*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (scalar  / bp[0]);
+                                cp[1] =   (scalar  / bp[1]);
+                                cp[2] =   (scalar  / bp[2]);
+                                cp[3] =   (scalar  / bp[3]);
+                                cp[4] =   (scalar  / bp[4]);
+                                cp[5] =   (scalar  / bp[5]);
+                                cp[6] =   (scalar  / bp[6]);
+                                cp[7] =   (scalar  / bp[7]);
+                                cp[8] =   (scalar  / bp[8]);
+                                cp[9] =   (scalar  / bp[9]);
+                                cp[10] =   (scalar  / bp[10]);
+                                cp[11] =   (scalar  / bp[11]);
+                                cp[12] =   (scalar  / bp[12]);
+                                cp[13] =   (scalar  / bp[13]);
+                                cp[14] =   (scalar  / bp[14]);
+                                cp[15] =   (scalar  / bp[15]);
+                                cp[16] =   (scalar  / bp[16]);
+                                cp[17] =   (scalar  / bp[17]);
+                                cp[18] =   (scalar  / bp[18]);
+                                cp[19] =   (scalar  / bp[19]);
+                                cp[20] =   (scalar  / bp[20]);
+                                bp+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (scalar  / *bp);
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work 
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                
+                fixed ( complex* arrAP = arrA)
+                fixed ( complex* arrBP = arrB)
+                fixed ( complex* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range 
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new  ILRetArray< complex>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<complex>  divideEx(ILInArray<complex> A, ILInArray<complex> B) {
+            //using (ILScope.Enter(A, B)) { we cannot start a new scope here, since this would prevent A and B to be used implace if applicable
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<complex>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<complex>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<complex>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                dim = -(dim - 1);  // 0 -> 1, 1 -> 0
+                #endregion
+
+                #region parameter preparation
+               
+                complex[] retArr;
+               
+                complex[] arrA = A.GetArrayForRead();
+               
+                complex[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int workItemMultiplierLenA;
+                int workItemMultiplierLenB;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<complex>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    workItemMultiplierLenB = outDims[0]; 
+                    workItemMultiplierLenA = dim;  // 0 for column, 1 for row vector
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<complex>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    workItemMultiplierLenB = dim;  // 0 for column, 1 for row vector
+                    workItemMultiplierLenA = outDims[0]; 
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one singleton dimension in either A or B");
+                }
+                int itLen = outDims[0]; // (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<complex> retStorage = new ILDenseStorage<complex>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    complex* ap;
+                   
+                    complex* bp;
+                   
+                    complex* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            if (dim == 0) {
+                                bp = (complex*)range.Item3;
+                                cp = (complex*)range.Item4; 
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (complex*)range.Item2;
+                                    int l = itLen; 
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  / bp[0]);
+                                        cp[1] =   (ap[1]  / bp[1]);
+                                        cp[2] =   (ap[2]  / bp[2]);
+                                        cp[3] =   (ap[3]  / bp[3]);
+                                        cp[4] =   (ap[4]  / bp[4]);
+                                        cp[5] =   (ap[5]  / bp[5]);
+                                        cp[6] =   (ap[6]  / bp[6]);
+                                        cp[7] =   (ap[7]  / bp[7]);
+                                        cp[8] =   (ap[8]  / bp[8]);
+                                        cp[9] =   (ap[9]  / bp[9]);
+                                        cp[10] =   (ap[10]  / bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =   (*ap++  / *bp++);
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                ap = (complex*)range.Item2;
+                                bp = (complex*)range.Item3;
+                                cp = (complex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   complex val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (val  / bp[0]);
+                                        cp[1] =   (val  / bp[1]);
+                                        cp[2] =   (val  / bp[2]);
+                                        cp[3] =   (val  / bp[3]);
+                                        cp[4] =   (val  / bp[4]);
+                                        cp[5] =   (val  / bp[5]);
+                                        cp[6] =   (val  / bp[6]);
+                                        cp[7] =   (val  / bp[7]);
+                                        cp[8] =   (val  / bp[8]);
+                                        cp[9] =   (val  / bp[9]);
+                                        cp[10] =   (val  / bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11; 
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =   (val  / *bp++);
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            if (dim == 0) {
+                                cp = (complex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (complex*)range.Item2;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  / cp[0]);
+                                        cp[1] =   (ap[1]  / cp[1]);
+                                        cp[2] =   (ap[2]  / cp[2]);
+                                        cp[3] =   (ap[3]  / cp[3]);
+                                        cp[4] =   (ap[4]  / cp[4]);
+                                        cp[5] =   (ap[5]  / cp[5]);
+                                        cp[6] =   (ap[6]  / cp[6]);
+                                        cp[7] =   (ap[7]  / cp[7]);
+                                        cp[8] =   (ap[8]  / cp[8]);
+                                        cp[9] =   (ap[9]  / cp[9]);
+                                        cp[10] =   (ap[10]  / cp[10]);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap++  / *cp);
+                                        cp++; 
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                cp = (complex*)range.Item4;
+                                ap = (complex*)range.Item2;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    complex val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (val  / cp[0]);
+                                        cp[1] =   (val  / cp[1]);
+                                        cp[2] =   (val  / cp[2]);
+                                        cp[3] =   (val  / cp[3]);
+                                        cp[4] =   (val  / cp[4]);
+                                        cp[5] =   (val  / cp[5]);
+                                        cp[6] =   (val  / cp[6]);
+                                        cp[7] =   (val  / cp[7]);
+                                        cp[8] =   (val  / cp[8]);
+                                        cp[9] =   (val  / cp[9]);
+                                        cp[10] =   (val  / cp[10]);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (val  / *cp);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            if (dim == 0) {
+                                ap = (complex*)range.Item2;
+                                cp = (complex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (complex*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  / bp[0]);
+                                        cp[1] =   (ap[1]  / bp[1]);
+                                        cp[2] =   (ap[2]  / bp[2]);
+                                        cp[3] =   (ap[3]  / bp[3]);
+                                        cp[4] =   (ap[4]  / bp[4]);
+                                        cp[5] =   (ap[5]  / bp[5]);
+                                        cp[6] =   (ap[6]  / bp[6]);
+                                        cp[7] =   (ap[7]  / bp[7]);
+                                        cp[8] =   (ap[8]  / bp[8]);
+                                        cp[9] =   (ap[9]  / bp[9]);
+                                        cp[10] =   (ap[10]  / bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap  / *bp);
+                                        ap++;
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                ap = (complex*)range.Item2;
+                                bp = (complex*)range.Item3;
+                                cp = (complex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   complex val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  / val);
+                                        cp[1] =   (ap[1]  / val);
+                                        cp[2] =   (ap[2]  / val);
+                                        cp[3] =   (ap[3]  / val);
+                                        cp[4] =   (ap[4]  / val);
+                                        cp[5] =   (ap[5]  / val);
+                                        cp[6] =   (ap[6]  / val);
+                                        cp[7] =   (ap[7]  / val);
+                                        cp[8] =   (ap[8]  / val);
+                                        cp[9] =   (ap[9]  / val);
+                                        cp[10] =   (ap[10]  / val);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap  / val);
+                                        ap++;
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            if (dim == 0) {
+                                cp = (complex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (complex*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (cp[0]  / bp[0]);
+                                        cp[1] =   (cp[1]  / bp[1]);
+                                        cp[2] =   (cp[2]  / bp[2]);
+                                        cp[3] =   (cp[3]  / bp[3]);
+                                        cp[4] =   (cp[4]  / bp[4]);
+                                        cp[5] =   (cp[5]  / bp[5]);
+                                        cp[6] =   (cp[6]  / bp[6]);
+                                        cp[7] =   (cp[7]  / bp[7]);
+                                        cp[8] =   (cp[8]  / bp[8]);
+                                        cp[9] =   (cp[9]  / bp[9]);
+                                        cp[10] =   (cp[10]  / bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*cp  / *bp);
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                bp = (complex*)range.Item3;
+                                cp = (complex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    complex val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (cp[0]  / val);
+                                        cp[1] =   (cp[1]  / val);
+                                        cp[2] =   (cp[2]  / val);
+                                        cp[3] =   (cp[3]  / val);
+                                        cp[4] =   (cp[4]  / val);
+                                        cp[5] =   (cp[5]  / val);
+                                        cp[6] =   (cp[6]  / val);
+                                        cp[7] =   (cp[7]  / val);
+                                        cp[8] =   (cp[8]  / val);
+                                        cp[9] =   (cp[9]  / val);
+                                        cp[10] =   (cp[10]  / val);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l --> 0) {
+                                        *cp =   (*cp  / val);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outDims.NumberOfElements >= Settings.s_minParallelElement1Count
+                    && outDims[1] > 1) {
+                        if (outDims[1] > workItemCount) {
+                        workItemLength = outDims[1] / workItemCount;
+                    } else {
+                        workItemLength = outDims[1] / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outDims[1];
+                    workItemCount = 1;
+                }
+
+                fixed ( complex* arrAP = arrA)
+                fixed ( complex* arrBP = arrB)
+                fixed ( complex* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, IntPtr, IntPtr, IntPtr> range = new Tuple<int, IntPtr, IntPtr, IntPtr>
+                               (workItemLength
+                               , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                               , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                               , (IntPtr)(retArrP + i * outDims[0] * workItemLength)); 
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, IntPtr, IntPtr, IntPtr>
+                                (outDims[1] - i * workItemLength
+                                , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                                , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                                , (IntPtr)(retArrP + i * outDims[0] * workItemLength)));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<complex>(retStorage);
+            //}  // no scopes here! it disables implace operations
+        }
+
+        /// <summary>Divide elements</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Array with elementwise division of A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<byte>  divide(ILInArray<byte> A, ILInArray<byte> B) {
+            using (ILScope.Enter(A,B)) {
+                int outLen; 
+                BinOpItMode mode; 
+                byte [] retArr;
+                byte [] arrA = A.GetArrayForRead();
+                byte[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size; 
+                    if (B.IsScalar) {
+                       
+                        return new  ILRetArray<byte> (new  byte [1]{ saturateByte (A.GetValue(0)  / (double) B.GetValue(0))}, A.Size);
+                    } else if (B.IsEmpty) {
+                        return  ILRetArray<byte>.empty(outDims); 
+                    } else {
+                        outLen = outDims.NumberOfElements; 
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< byte > (outLen);
+                            mode = BinOpItMode.SAN; 
+                        } else {
+                            mode = BinOpItMode.SAI; 
+                        }
+                    }
+                } else {
+                    outDims = A.Size; 
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return  ILRetArray<byte>.empty(A.Size);  
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< byte > (outLen);
+                            mode = BinOpItMode.ASN; 
+                        } else {
+                            mode = BinOpItMode.ASI; 
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  divideEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (A.TryGetStorage4InplaceOp(out retArr)) 
+                            mode  = BinOpItMode.AAIA; 
+                        else if (B.TryGetStorage4InplaceOp(out retArr)) 
+                            mode = BinOpItMode.AAIB; 
+                        else {
+                            retArr = ILMemoryPool.Pool.New< byte > (outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<byte> retStorage = new ILDenseStorage<byte>(retArr, outDims);
+                int i = 0, workerCount = 1; 
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cp = (byte*)range.Item5 + range.Item1;
+                    byte scalar;
+                    int j = range.Item2; 
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           byte* bp = ((byte*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                                cp[0] =  saturateByte (cp[0]  / (double) bp[0]);
+                                cp[1] =  saturateByte (cp[1]  / (double) bp[1]);
+                                cp[2] =  saturateByte (cp[2]  / (double) bp[2]);
+                                cp[3] =  saturateByte (cp[3]  / (double) bp[3]);
+                                cp[4] =  saturateByte (cp[4]  / (double) bp[4]);
+                                cp[5] =  saturateByte (cp[5]  / (double) bp[5]);
+                                cp[6] =  saturateByte (cp[6]  / (double) bp[6]);
+                                cp[7] =  saturateByte (cp[7]  / (double) bp[7]);
+                                cp[8] =  saturateByte (cp[8]  / (double) bp[8]);
+                                cp[9] =  saturateByte (cp[9]  / (double) bp[9]);
+                                cp[10] =  saturateByte (cp[10]  / (double) bp[10]);
+                                cp[11] =  saturateByte (cp[11]  / (double) bp[11]);
+                                cp[12] =  saturateByte (cp[12]  / (double) bp[12]);
+                                cp[13] =  saturateByte (cp[13]  / (double) bp[13]);
+                                cp[14] =  saturateByte (cp[14]  / (double) bp[14]);
+                                cp[15] =  saturateByte (cp[15]  / (double) bp[15]);
+                                cp[16] =  saturateByte (cp[16]  / (double) bp[16]);
+                                cp[17] =  saturateByte (cp[17]  / (double) bp[17]);
+                                cp[18] =  saturateByte (cp[18]  / (double) bp[18]);
+                                cp[19] =  saturateByte (cp[19]  / (double) bp[19]);
+                                cp[20] =  saturateByte (cp[20]  / (double) bp[20]);
+                                cp += 21; bp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateByte (*cp  / (double) *bp);
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           byte* ap = ((byte*)range.Item3 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateByte (ap[0]  / (double) cp[0]);
+                                cp[1] =  saturateByte (ap[1]  / (double) cp[1]);
+                                cp[2] =  saturateByte (ap[2]  / (double) cp[2]);
+                                cp[3] =  saturateByte (ap[3]  / (double) cp[3]);
+                                cp[4] =  saturateByte (ap[4]  / (double) cp[4]);
+                                cp[5] =  saturateByte (ap[5]  / (double) cp[5]);
+                                cp[6] =  saturateByte (ap[6]  / (double) cp[6]);
+                                cp[7] =  saturateByte (ap[7]  / (double) cp[7]);
+                                cp[8] =  saturateByte (ap[8]  / (double) cp[8]);
+                                cp[9] =  saturateByte (ap[9]  / (double) cp[9]);
+                                cp[10] =  saturateByte (ap[10]  / (double) cp[10]);
+                                cp[11] =  saturateByte (ap[11]  / (double) cp[11]);
+                                cp[12] =  saturateByte (ap[12]  / (double) cp[12]);
+                                cp[13] =  saturateByte (ap[13]  / (double) cp[13]);
+                                cp[14] =  saturateByte (ap[14]  / (double) cp[14]);
+                                cp[15] =  saturateByte (ap[15]  / (double) cp[15]);
+                                cp[16] =  saturateByte (ap[16]  / (double) cp[16]);
+                                cp[17] =  saturateByte (ap[17]  / (double) cp[17]);
+                                cp[18] =  saturateByte (ap[18]  / (double) cp[18]);
+                                cp[19] =  saturateByte (ap[19]  / (double) cp[19]);
+                                cp[20] =  saturateByte (ap[20]  / (double) cp[20]);
+                                ap += 21; cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateByte (*ap  / (double) *cp);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((byte*)range.Item3 + range.Item1);
+                            bp = ((byte*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateByte (ap[0]  / (double) bp[0]);
+                                cp[1] =  saturateByte (ap[1]  / (double) bp[1]);
+                                cp[2] =  saturateByte (ap[2]  / (double) bp[2]);
+                                cp[3] =  saturateByte (ap[3]  / (double) bp[3]);
+                                cp[4] =  saturateByte (ap[4]  / (double) bp[4]);
+                                cp[5] =  saturateByte (ap[5]  / (double) bp[5]);
+                                cp[6] =  saturateByte (ap[6]  / (double) bp[6]);
+                                cp[7] =  saturateByte (ap[7]  / (double) bp[7]);
+                                cp[8] =  saturateByte (ap[8]  / (double) bp[8]);
+                                cp[9] =  saturateByte (ap[9]  / (double) bp[9]);
+                                cp[10] =  saturateByte (ap[10]  / (double) bp[10]);
+                                cp[11] =  saturateByte (ap[11]  / (double) bp[11]);
+                                cp[12] =  saturateByte (ap[12]  / (double) bp[12]);
+                                cp[13] =  saturateByte (ap[13]  / (double) bp[13]);
+                                cp[14] =  saturateByte (ap[14]  / (double) bp[14]);
+                                cp[15] =  saturateByte (ap[15]  / (double) bp[15]);
+                                cp[16] =  saturateByte (ap[16]  / (double) bp[16]);
+                                cp[17] =  saturateByte (ap[17]  / (double) bp[17]);
+                                cp[18] =  saturateByte (ap[18]  / (double) bp[18]);
+                                cp[19] =  saturateByte (ap[19]  / (double) bp[19]);
+                                cp[20] =  saturateByte (ap[20]  / (double) bp[20]);
+                                ap+=21; bp+=21; cp+=21; j-=21;
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateByte (*ap  / (double) *bp);
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((byte*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateByte (cp[0]  / (double) scalar);
+                                cp[1] =  saturateByte (cp[1]  / (double) scalar);
+                                cp[2] =  saturateByte (cp[2]  / (double) scalar);
+                                cp[3] =  saturateByte (cp[3]  / (double) scalar);
+                                cp[4] =  saturateByte (cp[4]  / (double) scalar);
+                                cp[5] =  saturateByte (cp[5]  / (double) scalar);
+                                cp[6] =  saturateByte (cp[6]  / (double) scalar);
+                                cp[7] =  saturateByte (cp[7]  / (double) scalar);
+                                cp[8] =  saturateByte (cp[8]  / (double) scalar);
+                                cp[9] =  saturateByte (cp[9]  / (double) scalar);
+                                cp[10] =  saturateByte (cp[10]  / (double) scalar);
+                                cp[11] =  saturateByte (cp[11]  / (double) scalar);
+                                cp[12] =  saturateByte (cp[12]  / (double) scalar);
+                                cp[13] =  saturateByte (cp[13]  / (double) scalar);
+                                cp[14] =  saturateByte (cp[14]  / (double) scalar);
+                                cp[15] =  saturateByte (cp[15]  / (double) scalar);
+                                cp[16] =  saturateByte (cp[16]  / (double) scalar);
+                                cp[17] =  saturateByte (cp[17]  / (double) scalar);
+                                cp[18] =  saturateByte (cp[18]  / (double) scalar);
+                                cp[19] =  saturateByte (cp[19]  / (double) scalar);
+                                cp[20] =  saturateByte (cp[20]  / (double) scalar);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateByte (*cp  / (double) scalar);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((byte*)range.Item3 + range.Item1);
+                            scalar = *((byte*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateByte (ap[0]  / (double) scalar);
+                                cp[1] =  saturateByte (ap[1]  / (double) scalar);
+                                cp[2] =  saturateByte (ap[2]  / (double) scalar);
+                                cp[3] =  saturateByte (ap[3]  / (double) scalar);
+                                cp[4] =  saturateByte (ap[4]  / (double) scalar);
+                                cp[5] =  saturateByte (ap[5]  / (double) scalar);
+                                cp[6] =  saturateByte (ap[6]  / (double) scalar);
+                                cp[7] =  saturateByte (ap[7]  / (double) scalar);
+                                cp[8] =  saturateByte (ap[8]  / (double) scalar);
+                                cp[9] =  saturateByte (ap[9]  / (double) scalar);
+                                cp[10] =  saturateByte (ap[10]  / (double) scalar);
+                                cp[11] =  saturateByte (ap[11]  / (double) scalar);
+                                cp[12] =  saturateByte (ap[12]  / (double) scalar);
+                                cp[13] =  saturateByte (ap[13]  / (double) scalar);
+                                cp[14] =  saturateByte (ap[14]  / (double) scalar);
+                                cp[15] =  saturateByte (ap[15]  / (double) scalar);
+                                cp[16] =  saturateByte (ap[16]  / (double) scalar);
+                                cp[17] =  saturateByte (ap[17]  / (double) scalar);
+                                cp[18] =  saturateByte (ap[18]  / (double) scalar);
+                                cp[19] =  saturateByte (ap[19]  / (double) scalar);
+                                cp[20] =  saturateByte (ap[20]  / (double) scalar);
+                                ap+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateByte (*ap  / (double) scalar);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((byte*)range.Item3);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateByte (scalar  / (double) cp[0]);
+                                cp[1] =  saturateByte (scalar  / (double) cp[1]);
+                                cp[2] =  saturateByte (scalar  / (double) cp[2]);
+                                cp[3] =  saturateByte (scalar  / (double) cp[3]);
+                                cp[4] =  saturateByte (scalar  / (double) cp[4]);
+                                cp[5] =  saturateByte (scalar  / (double) cp[5]);
+                                cp[6] =  saturateByte (scalar  / (double) cp[6]);
+                                cp[7] =  saturateByte (scalar  / (double) cp[7]);
+                                cp[8] =  saturateByte (scalar  / (double) cp[8]);
+                                cp[9] =  saturateByte (scalar  / (double) cp[9]);
+                                cp[10] =  saturateByte (scalar  / (double) cp[10]);
+                                cp[11] =  saturateByte (scalar  / (double) cp[11]);
+                                cp[12] =  saturateByte (scalar  / (double) cp[12]);
+                                cp[13] =  saturateByte (scalar  / (double) cp[13]);
+                                cp[14] =  saturateByte (scalar  / (double) cp[14]);
+                                cp[15] =  saturateByte (scalar  / (double) cp[15]);
+                                cp[16] =  saturateByte (scalar  / (double) cp[16]);
+                                cp[17] =  saturateByte (scalar  / (double) cp[17]);
+                                cp[18] =  saturateByte (scalar  / (double) cp[18]);
+                                cp[19] =  saturateByte (scalar  / (double) cp[19]);
+                                cp[20] =  saturateByte (scalar  / (double) cp[20]);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateByte (scalar  / (double) *cp);
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((byte*)range.Item3);
+                            bp = ((byte*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateByte (scalar  / (double) bp[0]);
+                                cp[1] =  saturateByte (scalar  / (double) bp[1]);
+                                cp[2] =  saturateByte (scalar  / (double) bp[2]);
+                                cp[3] =  saturateByte (scalar  / (double) bp[3]);
+                                cp[4] =  saturateByte (scalar  / (double) bp[4]);
+                                cp[5] =  saturateByte (scalar  / (double) bp[5]);
+                                cp[6] =  saturateByte (scalar  / (double) bp[6]);
+                                cp[7] =  saturateByte (scalar  / (double) bp[7]);
+                                cp[8] =  saturateByte (scalar  / (double) bp[8]);
+                                cp[9] =  saturateByte (scalar  / (double) bp[9]);
+                                cp[10] =  saturateByte (scalar  / (double) bp[10]);
+                                cp[11] =  saturateByte (scalar  / (double) bp[11]);
+                                cp[12] =  saturateByte (scalar  / (double) bp[12]);
+                                cp[13] =  saturateByte (scalar  / (double) bp[13]);
+                                cp[14] =  saturateByte (scalar  / (double) bp[14]);
+                                cp[15] =  saturateByte (scalar  / (double) bp[15]);
+                                cp[16] =  saturateByte (scalar  / (double) bp[16]);
+                                cp[17] =  saturateByte (scalar  / (double) bp[17]);
+                                cp[18] =  saturateByte (scalar  / (double) bp[18]);
+                                cp[19] =  saturateByte (scalar  / (double) bp[19]);
+                                cp[20] =  saturateByte (scalar  / (double) bp[20]);
+                                bp+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateByte (scalar  / (double) *bp);
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work 
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                
+                fixed ( byte* arrAP = arrA)
+                fixed ( byte* arrBP = arrB)
+                fixed ( byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range 
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new  ILRetArray< byte>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<byte>  divideEx(ILInArray<byte> A, ILInArray<byte> B) {
+            //using (ILScope.Enter(A, B)) { we cannot start a new scope here, since this would prevent A and B to be used implace if applicable
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<byte>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<byte>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<byte>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                dim = -(dim - 1);  // 0 -> 1, 1 -> 0
+                #endregion
+
+                #region parameter preparation
+               
+                byte[] retArr;
+               
+                byte[] arrA = A.GetArrayForRead();
+               
+                byte[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int workItemMultiplierLenA;
+                int workItemMultiplierLenB;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    workItemMultiplierLenB = outDims[0]; 
+                    workItemMultiplierLenA = dim;  // 0 for column, 1 for row vector
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    workItemMultiplierLenB = dim;  // 0 for column, 1 for row vector
+                    workItemMultiplierLenA = outDims[0]; 
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one singleton dimension in either A or B");
+                }
+                int itLen = outDims[0]; // (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<byte> retStorage = new ILDenseStorage<byte>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    byte* ap;
+                   
+                    byte* bp;
+                   
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            if (dim == 0) {
+                                bp = (byte*)range.Item3;
+                                cp = (byte*)range.Item4; 
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (byte*)range.Item2;
+                                    int l = itLen; 
+                                    while (l > 10) {
+                                        cp[0] =  saturateByte (ap[0]  / (double) bp[0]);
+                                        cp[1] =  saturateByte (ap[1]  / (double) bp[1]);
+                                        cp[2] =  saturateByte (ap[2]  / (double) bp[2]);
+                                        cp[3] =  saturateByte (ap[3]  / (double) bp[3]);
+                                        cp[4] =  saturateByte (ap[4]  / (double) bp[4]);
+                                        cp[5] =  saturateByte (ap[5]  / (double) bp[5]);
+                                        cp[6] =  saturateByte (ap[6]  / (double) bp[6]);
+                                        cp[7] =  saturateByte (ap[7]  / (double) bp[7]);
+                                        cp[8] =  saturateByte (ap[8]  / (double) bp[8]);
+                                        cp[9] =  saturateByte (ap[9]  / (double) bp[9]);
+                                        cp[10] =  saturateByte (ap[10]  / (double) bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =  saturateByte (*ap++  / (double) *bp++);
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                ap = (byte*)range.Item2;
+                                bp = (byte*)range.Item3;
+                                cp = (byte*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   byte val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateByte (val  / (double) bp[0]);
+                                        cp[1] =  saturateByte (val  / (double) bp[1]);
+                                        cp[2] =  saturateByte (val  / (double) bp[2]);
+                                        cp[3] =  saturateByte (val  / (double) bp[3]);
+                                        cp[4] =  saturateByte (val  / (double) bp[4]);
+                                        cp[5] =  saturateByte (val  / (double) bp[5]);
+                                        cp[6] =  saturateByte (val  / (double) bp[6]);
+                                        cp[7] =  saturateByte (val  / (double) bp[7]);
+                                        cp[8] =  saturateByte (val  / (double) bp[8]);
+                                        cp[9] =  saturateByte (val  / (double) bp[9]);
+                                        cp[10] =  saturateByte (val  / (double) bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11; 
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =  saturateByte (val  / (double) *bp++);
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            if (dim == 0) {
+                                cp = (byte*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (byte*)range.Item2;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateByte (ap[0]  / (double) cp[0]);
+                                        cp[1] =  saturateByte (ap[1]  / (double) cp[1]);
+                                        cp[2] =  saturateByte (ap[2]  / (double) cp[2]);
+                                        cp[3] =  saturateByte (ap[3]  / (double) cp[3]);
+                                        cp[4] =  saturateByte (ap[4]  / (double) cp[4]);
+                                        cp[5] =  saturateByte (ap[5]  / (double) cp[5]);
+                                        cp[6] =  saturateByte (ap[6]  / (double) cp[6]);
+                                        cp[7] =  saturateByte (ap[7]  / (double) cp[7]);
+                                        cp[8] =  saturateByte (ap[8]  / (double) cp[8]);
+                                        cp[9] =  saturateByte (ap[9]  / (double) cp[9]);
+                                        cp[10] =  saturateByte (ap[10]  / (double) cp[10]);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateByte (*ap++  / (double) *cp);
+                                        cp++; 
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                cp = (byte*)range.Item4;
+                                ap = (byte*)range.Item2;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    byte val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateByte (val  / (double) cp[0]);
+                                        cp[1] =  saturateByte (val  / (double) cp[1]);
+                                        cp[2] =  saturateByte (val  / (double) cp[2]);
+                                        cp[3] =  saturateByte (val  / (double) cp[3]);
+                                        cp[4] =  saturateByte (val  / (double) cp[4]);
+                                        cp[5] =  saturateByte (val  / (double) cp[5]);
+                                        cp[6] =  saturateByte (val  / (double) cp[6]);
+                                        cp[7] =  saturateByte (val  / (double) cp[7]);
+                                        cp[8] =  saturateByte (val  / (double) cp[8]);
+                                        cp[9] =  saturateByte (val  / (double) cp[9]);
+                                        cp[10] =  saturateByte (val  / (double) cp[10]);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateByte (val  / (double) *cp);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            if (dim == 0) {
+                                ap = (byte*)range.Item2;
+                                cp = (byte*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (byte*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateByte (ap[0]  / (double) bp[0]);
+                                        cp[1] =  saturateByte (ap[1]  / (double) bp[1]);
+                                        cp[2] =  saturateByte (ap[2]  / (double) bp[2]);
+                                        cp[3] =  saturateByte (ap[3]  / (double) bp[3]);
+                                        cp[4] =  saturateByte (ap[4]  / (double) bp[4]);
+                                        cp[5] =  saturateByte (ap[5]  / (double) bp[5]);
+                                        cp[6] =  saturateByte (ap[6]  / (double) bp[6]);
+                                        cp[7] =  saturateByte (ap[7]  / (double) bp[7]);
+                                        cp[8] =  saturateByte (ap[8]  / (double) bp[8]);
+                                        cp[9] =  saturateByte (ap[9]  / (double) bp[9]);
+                                        cp[10] =  saturateByte (ap[10]  / (double) bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateByte (*ap  / (double) *bp);
+                                        ap++;
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                ap = (byte*)range.Item2;
+                                bp = (byte*)range.Item3;
+                                cp = (byte*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   byte val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateByte (ap[0]  / (double) val);
+                                        cp[1] =  saturateByte (ap[1]  / (double) val);
+                                        cp[2] =  saturateByte (ap[2]  / (double) val);
+                                        cp[3] =  saturateByte (ap[3]  / (double) val);
+                                        cp[4] =  saturateByte (ap[4]  / (double) val);
+                                        cp[5] =  saturateByte (ap[5]  / (double) val);
+                                        cp[6] =  saturateByte (ap[6]  / (double) val);
+                                        cp[7] =  saturateByte (ap[7]  / (double) val);
+                                        cp[8] =  saturateByte (ap[8]  / (double) val);
+                                        cp[9] =  saturateByte (ap[9]  / (double) val);
+                                        cp[10] =  saturateByte (ap[10]  / (double) val);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateByte (*ap  / (double) val);
+                                        ap++;
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            if (dim == 0) {
+                                cp = (byte*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (byte*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateByte (cp[0]  / (double) bp[0]);
+                                        cp[1] =  saturateByte (cp[1]  / (double) bp[1]);
+                                        cp[2] =  saturateByte (cp[2]  / (double) bp[2]);
+                                        cp[3] =  saturateByte (cp[3]  / (double) bp[3]);
+                                        cp[4] =  saturateByte (cp[4]  / (double) bp[4]);
+                                        cp[5] =  saturateByte (cp[5]  / (double) bp[5]);
+                                        cp[6] =  saturateByte (cp[6]  / (double) bp[6]);
+                                        cp[7] =  saturateByte (cp[7]  / (double) bp[7]);
+                                        cp[8] =  saturateByte (cp[8]  / (double) bp[8]);
+                                        cp[9] =  saturateByte (cp[9]  / (double) bp[9]);
+                                        cp[10] =  saturateByte (cp[10]  / (double) bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateByte (*cp  / (double) *bp);
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                bp = (byte*)range.Item3;
+                                cp = (byte*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    byte val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateByte (cp[0]  / (double) val);
+                                        cp[1] =  saturateByte (cp[1]  / (double) val);
+                                        cp[2] =  saturateByte (cp[2]  / (double) val);
+                                        cp[3] =  saturateByte (cp[3]  / (double) val);
+                                        cp[4] =  saturateByte (cp[4]  / (double) val);
+                                        cp[5] =  saturateByte (cp[5]  / (double) val);
+                                        cp[6] =  saturateByte (cp[6]  / (double) val);
+                                        cp[7] =  saturateByte (cp[7]  / (double) val);
+                                        cp[8] =  saturateByte (cp[8]  / (double) val);
+                                        cp[9] =  saturateByte (cp[9]  / (double) val);
+                                        cp[10] =  saturateByte (cp[10]  / (double) val);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l --> 0) {
+                                        *cp =  saturateByte (*cp  / (double) val);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outDims.NumberOfElements >= Settings.s_minParallelElement1Count
+                    && outDims[1] > 1) {
+                        if (outDims[1] > workItemCount) {
+                        workItemLength = outDims[1] / workItemCount;
+                    } else {
+                        workItemLength = outDims[1] / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outDims[1];
+                    workItemCount = 1;
+                }
+
+                fixed ( byte* arrAP = arrA)
+                fixed ( byte* arrBP = arrB)
+                fixed ( byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, IntPtr, IntPtr, IntPtr> range = new Tuple<int, IntPtr, IntPtr, IntPtr>
+                               (workItemLength
+                               , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                               , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                               , (IntPtr)(retArrP + i * outDims[0] * workItemLength)); 
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, IntPtr, IntPtr, IntPtr>
+                                (outDims[1] - i * workItemLength
+                                , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                                , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                                , (IntPtr)(retArrP + i * outDims[0] * workItemLength)));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<byte>(retStorage);
+            //}  // no scopes here! it disables implace operations
+        }
+
+        /// <summary>Divide elements</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Array with elementwise division of A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<double>  divide(ILInArray<double> A, ILInArray<double> B) {
+            using (ILScope.Enter(A,B)) {
+                int outLen; 
+                BinOpItMode mode; 
+                double [] retArr;
+                double [] arrA = A.GetArrayForRead();
+                double[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size; 
+                    if (B.IsScalar) {
+                       
+                        return new  ILRetArray<double> (new  double [1]{  (A.GetValue(0)  / B.GetValue(0))}, A.Size);
+                    } else if (B.IsEmpty) {
+                        return  ILRetArray<double>.empty(outDims); 
+                    } else {
+                        outLen = outDims.NumberOfElements; 
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< double > (outLen);
+                            mode = BinOpItMode.SAN; 
+                        } else {
+                            mode = BinOpItMode.SAI; 
+                        }
+                    }
+                } else {
+                    outDims = A.Size; 
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return  ILRetArray<double>.empty(A.Size);  
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< double > (outLen);
+                            mode = BinOpItMode.ASN; 
+                        } else {
+                            mode = BinOpItMode.ASI; 
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  divideEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (A.TryGetStorage4InplaceOp(out retArr)) 
+                            mode  = BinOpItMode.AAIA; 
+                        else if (B.TryGetStorage4InplaceOp(out retArr)) 
+                            mode = BinOpItMode.AAIB; 
+                        else {
+                            retArr = ILMemoryPool.Pool.New< double > (outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<double> retStorage = new ILDenseStorage<double>(retArr, outDims);
+                int i = 0, workerCount = 1; 
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    double* cp = (double*)range.Item5 + range.Item1;
+                    double scalar;
+                    int j = range.Item2; 
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           double* bp = ((double*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                                cp[0] =   (cp[0]  / bp[0]);
+                                cp[1] =   (cp[1]  / bp[1]);
+                                cp[2] =   (cp[2]  / bp[2]);
+                                cp[3] =   (cp[3]  / bp[3]);
+                                cp[4] =   (cp[4]  / bp[4]);
+                                cp[5] =   (cp[5]  / bp[5]);
+                                cp[6] =   (cp[6]  / bp[6]);
+                                cp[7] =   (cp[7]  / bp[7]);
+                                cp[8] =   (cp[8]  / bp[8]);
+                                cp[9] =   (cp[9]  / bp[9]);
+                                cp[10] =   (cp[10]  / bp[10]);
+                                cp[11] =   (cp[11]  / bp[11]);
+                                cp[12] =   (cp[12]  / bp[12]);
+                                cp[13] =   (cp[13]  / bp[13]);
+                                cp[14] =   (cp[14]  / bp[14]);
+                                cp[15] =   (cp[15]  / bp[15]);
+                                cp[16] =   (cp[16]  / bp[16]);
+                                cp[17] =   (cp[17]  / bp[17]);
+                                cp[18] =   (cp[18]  / bp[18]);
+                                cp[19] =   (cp[19]  / bp[19]);
+                                cp[20] =   (cp[20]  / bp[20]);
+                                cp += 21; bp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*cp  / *bp);
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           double* ap = ((double*)range.Item3 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  / cp[0]);
+                                cp[1] =   (ap[1]  / cp[1]);
+                                cp[2] =   (ap[2]  / cp[2]);
+                                cp[3] =   (ap[3]  / cp[3]);
+                                cp[4] =   (ap[4]  / cp[4]);
+                                cp[5] =   (ap[5]  / cp[5]);
+                                cp[6] =   (ap[6]  / cp[6]);
+                                cp[7] =   (ap[7]  / cp[7]);
+                                cp[8] =   (ap[8]  / cp[8]);
+                                cp[9] =   (ap[9]  / cp[9]);
+                                cp[10] =   (ap[10]  / cp[10]);
+                                cp[11] =   (ap[11]  / cp[11]);
+                                cp[12] =   (ap[12]  / cp[12]);
+                                cp[13] =   (ap[13]  / cp[13]);
+                                cp[14] =   (ap[14]  / cp[14]);
+                                cp[15] =   (ap[15]  / cp[15]);
+                                cp[16] =   (ap[16]  / cp[16]);
+                                cp[17] =   (ap[17]  / cp[17]);
+                                cp[18] =   (ap[18]  / cp[18]);
+                                cp[19] =   (ap[19]  / cp[19]);
+                                cp[20] =   (ap[20]  / cp[20]);
+                                ap += 21; cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  / *cp);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((double*)range.Item3 + range.Item1);
+                            bp = ((double*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  / bp[0]);
+                                cp[1] =   (ap[1]  / bp[1]);
+                                cp[2] =   (ap[2]  / bp[2]);
+                                cp[3] =   (ap[3]  / bp[3]);
+                                cp[4] =   (ap[4]  / bp[4]);
+                                cp[5] =   (ap[5]  / bp[5]);
+                                cp[6] =   (ap[6]  / bp[6]);
+                                cp[7] =   (ap[7]  / bp[7]);
+                                cp[8] =   (ap[8]  / bp[8]);
+                                cp[9] =   (ap[9]  / bp[9]);
+                                cp[10] =   (ap[10]  / bp[10]);
+                                cp[11] =   (ap[11]  / bp[11]);
+                                cp[12] =   (ap[12]  / bp[12]);
+                                cp[13] =   (ap[13]  / bp[13]);
+                                cp[14] =   (ap[14]  / bp[14]);
+                                cp[15] =   (ap[15]  / bp[15]);
+                                cp[16] =   (ap[16]  / bp[16]);
+                                cp[17] =   (ap[17]  / bp[17]);
+                                cp[18] =   (ap[18]  / bp[18]);
+                                cp[19] =   (ap[19]  / bp[19]);
+                                cp[20] =   (ap[20]  / bp[20]);
+                                ap+=21; bp+=21; cp+=21; j-=21;
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  / *bp);
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((double*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =   (cp[0]  / scalar);
+                                cp[1] =   (cp[1]  / scalar);
+                                cp[2] =   (cp[2]  / scalar);
+                                cp[3] =   (cp[3]  / scalar);
+                                cp[4] =   (cp[4]  / scalar);
+                                cp[5] =   (cp[5]  / scalar);
+                                cp[6] =   (cp[6]  / scalar);
+                                cp[7] =   (cp[7]  / scalar);
+                                cp[8] =   (cp[8]  / scalar);
+                                cp[9] =   (cp[9]  / scalar);
+                                cp[10] =   (cp[10]  / scalar);
+                                cp[11] =   (cp[11]  / scalar);
+                                cp[12] =   (cp[12]  / scalar);
+                                cp[13] =   (cp[13]  / scalar);
+                                cp[14] =   (cp[14]  / scalar);
+                                cp[15] =   (cp[15]  / scalar);
+                                cp[16] =   (cp[16]  / scalar);
+                                cp[17] =   (cp[17]  / scalar);
+                                cp[18] =   (cp[18]  / scalar);
+                                cp[19] =   (cp[19]  / scalar);
+                                cp[20] =   (cp[20]  / scalar);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*cp  / scalar);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((double*)range.Item3 + range.Item1);
+                            scalar = *((double*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  / scalar);
+                                cp[1] =   (ap[1]  / scalar);
+                                cp[2] =   (ap[2]  / scalar);
+                                cp[3] =   (ap[3]  / scalar);
+                                cp[4] =   (ap[4]  / scalar);
+                                cp[5] =   (ap[5]  / scalar);
+                                cp[6] =   (ap[6]  / scalar);
+                                cp[7] =   (ap[7]  / scalar);
+                                cp[8] =   (ap[8]  / scalar);
+                                cp[9] =   (ap[9]  / scalar);
+                                cp[10] =   (ap[10]  / scalar);
+                                cp[11] =   (ap[11]  / scalar);
+                                cp[12] =   (ap[12]  / scalar);
+                                cp[13] =   (ap[13]  / scalar);
+                                cp[14] =   (ap[14]  / scalar);
+                                cp[15] =   (ap[15]  / scalar);
+                                cp[16] =   (ap[16]  / scalar);
+                                cp[17] =   (ap[17]  / scalar);
+                                cp[18] =   (ap[18]  / scalar);
+                                cp[19] =   (ap[19]  / scalar);
+                                cp[20] =   (ap[20]  / scalar);
+                                ap+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  / scalar);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((double*)range.Item3);
+                            while (j > 20) {
+                               
+                                cp[0] =   (scalar  / cp[0]);
+                                cp[1] =   (scalar  / cp[1]);
+                                cp[2] =   (scalar  / cp[2]);
+                                cp[3] =   (scalar  / cp[3]);
+                                cp[4] =   (scalar  / cp[4]);
+                                cp[5] =   (scalar  / cp[5]);
+                                cp[6] =   (scalar  / cp[6]);
+                                cp[7] =   (scalar  / cp[7]);
+                                cp[8] =   (scalar  / cp[8]);
+                                cp[9] =   (scalar  / cp[9]);
+                                cp[10] =   (scalar  / cp[10]);
+                                cp[11] =   (scalar  / cp[11]);
+                                cp[12] =   (scalar  / cp[12]);
+                                cp[13] =   (scalar  / cp[13]);
+                                cp[14] =   (scalar  / cp[14]);
+                                cp[15] =   (scalar  / cp[15]);
+                                cp[16] =   (scalar  / cp[16]);
+                                cp[17] =   (scalar  / cp[17]);
+                                cp[18] =   (scalar  / cp[18]);
+                                cp[19] =   (scalar  / cp[19]);
+                                cp[20] =   (scalar  / cp[20]);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (scalar  / *cp);
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((double*)range.Item3);
+                            bp = ((double*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (scalar  / bp[0]);
+                                cp[1] =   (scalar  / bp[1]);
+                                cp[2] =   (scalar  / bp[2]);
+                                cp[3] =   (scalar  / bp[3]);
+                                cp[4] =   (scalar  / bp[4]);
+                                cp[5] =   (scalar  / bp[5]);
+                                cp[6] =   (scalar  / bp[6]);
+                                cp[7] =   (scalar  / bp[7]);
+                                cp[8] =   (scalar  / bp[8]);
+                                cp[9] =   (scalar  / bp[9]);
+                                cp[10] =   (scalar  / bp[10]);
+                                cp[11] =   (scalar  / bp[11]);
+                                cp[12] =   (scalar  / bp[12]);
+                                cp[13] =   (scalar  / bp[13]);
+                                cp[14] =   (scalar  / bp[14]);
+                                cp[15] =   (scalar  / bp[15]);
+                                cp[16] =   (scalar  / bp[16]);
+                                cp[17] =   (scalar  / bp[17]);
+                                cp[18] =   (scalar  / bp[18]);
+                                cp[19] =   (scalar  / bp[19]);
+                                cp[20] =   (scalar  / bp[20]);
+                                bp+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (scalar  / *bp);
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work 
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                
+                fixed ( double* arrAP = arrA)
+                fixed ( double* arrBP = arrB)
+                fixed ( double* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range 
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new  ILRetArray< double>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<double>  divideEx(ILInArray<double> A, ILInArray<double> B) {
+            //using (ILScope.Enter(A, B)) { we cannot start a new scope here, since this would prevent A and B to be used implace if applicable
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<double>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<double>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<double>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                dim = -(dim - 1);  // 0 -> 1, 1 -> 0
+                #endregion
+
+                #region parameter preparation
+               
+                double[] retArr;
+               
+                double[] arrA = A.GetArrayForRead();
+               
+                double[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int workItemMultiplierLenA;
+                int workItemMultiplierLenB;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<double>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    workItemMultiplierLenB = outDims[0]; 
+                    workItemMultiplierLenA = dim;  // 0 for column, 1 for row vector
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<double>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    workItemMultiplierLenB = dim;  // 0 for column, 1 for row vector
+                    workItemMultiplierLenA = outDims[0]; 
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one singleton dimension in either A or B");
+                }
+                int itLen = outDims[0]; // (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<double> retStorage = new ILDenseStorage<double>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    double* ap;
+                   
+                    double* bp;
+                   
+                    double* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            if (dim == 0) {
+                                bp = (double*)range.Item3;
+                                cp = (double*)range.Item4; 
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (double*)range.Item2;
+                                    int l = itLen; 
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  / bp[0]);
+                                        cp[1] =   (ap[1]  / bp[1]);
+                                        cp[2] =   (ap[2]  / bp[2]);
+                                        cp[3] =   (ap[3]  / bp[3]);
+                                        cp[4] =   (ap[4]  / bp[4]);
+                                        cp[5] =   (ap[5]  / bp[5]);
+                                        cp[6] =   (ap[6]  / bp[6]);
+                                        cp[7] =   (ap[7]  / bp[7]);
+                                        cp[8] =   (ap[8]  / bp[8]);
+                                        cp[9] =   (ap[9]  / bp[9]);
+                                        cp[10] =   (ap[10]  / bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =   (*ap++  / *bp++);
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                ap = (double*)range.Item2;
+                                bp = (double*)range.Item3;
+                                cp = (double*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   double val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (val  / bp[0]);
+                                        cp[1] =   (val  / bp[1]);
+                                        cp[2] =   (val  / bp[2]);
+                                        cp[3] =   (val  / bp[3]);
+                                        cp[4] =   (val  / bp[4]);
+                                        cp[5] =   (val  / bp[5]);
+                                        cp[6] =   (val  / bp[6]);
+                                        cp[7] =   (val  / bp[7]);
+                                        cp[8] =   (val  / bp[8]);
+                                        cp[9] =   (val  / bp[9]);
+                                        cp[10] =   (val  / bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11; 
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =   (val  / *bp++);
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            if (dim == 0) {
+                                cp = (double*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (double*)range.Item2;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  / cp[0]);
+                                        cp[1] =   (ap[1]  / cp[1]);
+                                        cp[2] =   (ap[2]  / cp[2]);
+                                        cp[3] =   (ap[3]  / cp[3]);
+                                        cp[4] =   (ap[4]  / cp[4]);
+                                        cp[5] =   (ap[5]  / cp[5]);
+                                        cp[6] =   (ap[6]  / cp[6]);
+                                        cp[7] =   (ap[7]  / cp[7]);
+                                        cp[8] =   (ap[8]  / cp[8]);
+                                        cp[9] =   (ap[9]  / cp[9]);
+                                        cp[10] =   (ap[10]  / cp[10]);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap++  / *cp);
+                                        cp++; 
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                cp = (double*)range.Item4;
+                                ap = (double*)range.Item2;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    double val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (val  / cp[0]);
+                                        cp[1] =   (val  / cp[1]);
+                                        cp[2] =   (val  / cp[2]);
+                                        cp[3] =   (val  / cp[3]);
+                                        cp[4] =   (val  / cp[4]);
+                                        cp[5] =   (val  / cp[5]);
+                                        cp[6] =   (val  / cp[6]);
+                                        cp[7] =   (val  / cp[7]);
+                                        cp[8] =   (val  / cp[8]);
+                                        cp[9] =   (val  / cp[9]);
+                                        cp[10] =   (val  / cp[10]);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (val  / *cp);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            if (dim == 0) {
+                                ap = (double*)range.Item2;
+                                cp = (double*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (double*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  / bp[0]);
+                                        cp[1] =   (ap[1]  / bp[1]);
+                                        cp[2] =   (ap[2]  / bp[2]);
+                                        cp[3] =   (ap[3]  / bp[3]);
+                                        cp[4] =   (ap[4]  / bp[4]);
+                                        cp[5] =   (ap[5]  / bp[5]);
+                                        cp[6] =   (ap[6]  / bp[6]);
+                                        cp[7] =   (ap[7]  / bp[7]);
+                                        cp[8] =   (ap[8]  / bp[8]);
+                                        cp[9] =   (ap[9]  / bp[9]);
+                                        cp[10] =   (ap[10]  / bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap  / *bp);
+                                        ap++;
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                ap = (double*)range.Item2;
+                                bp = (double*)range.Item3;
+                                cp = (double*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   double val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  / val);
+                                        cp[1] =   (ap[1]  / val);
+                                        cp[2] =   (ap[2]  / val);
+                                        cp[3] =   (ap[3]  / val);
+                                        cp[4] =   (ap[4]  / val);
+                                        cp[5] =   (ap[5]  / val);
+                                        cp[6] =   (ap[6]  / val);
+                                        cp[7] =   (ap[7]  / val);
+                                        cp[8] =   (ap[8]  / val);
+                                        cp[9] =   (ap[9]  / val);
+                                        cp[10] =   (ap[10]  / val);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap  / val);
+                                        ap++;
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            if (dim == 0) {
+                                cp = (double*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (double*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (cp[0]  / bp[0]);
+                                        cp[1] =   (cp[1]  / bp[1]);
+                                        cp[2] =   (cp[2]  / bp[2]);
+                                        cp[3] =   (cp[3]  / bp[3]);
+                                        cp[4] =   (cp[4]  / bp[4]);
+                                        cp[5] =   (cp[5]  / bp[5]);
+                                        cp[6] =   (cp[6]  / bp[6]);
+                                        cp[7] =   (cp[7]  / bp[7]);
+                                        cp[8] =   (cp[8]  / bp[8]);
+                                        cp[9] =   (cp[9]  / bp[9]);
+                                        cp[10] =   (cp[10]  / bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*cp  / *bp);
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                bp = (double*)range.Item3;
+                                cp = (double*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    double val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (cp[0]  / val);
+                                        cp[1] =   (cp[1]  / val);
+                                        cp[2] =   (cp[2]  / val);
+                                        cp[3] =   (cp[3]  / val);
+                                        cp[4] =   (cp[4]  / val);
+                                        cp[5] =   (cp[5]  / val);
+                                        cp[6] =   (cp[6]  / val);
+                                        cp[7] =   (cp[7]  / val);
+                                        cp[8] =   (cp[8]  / val);
+                                        cp[9] =   (cp[9]  / val);
+                                        cp[10] =   (cp[10]  / val);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l --> 0) {
+                                        *cp =   (*cp  / val);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outDims.NumberOfElements >= Settings.s_minParallelElement1Count
+                    && outDims[1] > 1) {
+                        if (outDims[1] > workItemCount) {
+                        workItemLength = outDims[1] / workItemCount;
+                    } else {
+                        workItemLength = outDims[1] / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outDims[1];
+                    workItemCount = 1;
+                }
+
+                fixed ( double* arrAP = arrA)
+                fixed ( double* arrBP = arrB)
+                fixed ( double* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, IntPtr, IntPtr, IntPtr> range = new Tuple<int, IntPtr, IntPtr, IntPtr>
+                               (workItemLength
+                               , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                               , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                               , (IntPtr)(retArrP + i * outDims[0] * workItemLength)); 
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, IntPtr, IntPtr, IntPtr>
+                                (outDims[1] - i * workItemLength
+                                , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                                , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                                , (IntPtr)(retArrP + i * outDims[0] * workItemLength)));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<double>(retStorage);
+            //}  // no scopes here! it disables implace operations
+        }
+
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/Find.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/Find.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/Find.cs	(revision 9102)
@@ -0,0 +1,1275 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions;
+
+
+
+namespace ILNumerics {
+    public partial class ILMath {
+       
+
+        /// <summary>
+        /// Find nonzero elements in A
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="limit">[Optional] Number of elements to search for. If this value is <![CDATA[< 0]]> the function 
+        /// will return at most 'limit' nonzero elements from the end of the array ordered by ascending index.
+        /// Set to 0 to search full array (default).</param>
+        /// <param name="C">[Optional] If not null, the function will return the row indices of nonzero elements 
+        /// as main return value. C will therefore hold the column indices of those elements. If A
+        /// has more than 2 dimensions, the column indices will go along the 2nd dimension.</param>
+        /// <param name="V">[Optional] If not null on entrance, V will hold a copy of the values of nonzero elements returned.</param>
+        /// <returns>Vector containing (sequential) indices of nonzero elements in A. If C was 
+        /// not null, return value will contain row indices of nonzero elements. </returns>
+        /// <remarks>The return type of the index vectors is always 'double'. The return type 
+        /// of the element vector 'V' depends on the type of input array A. V and C may be null on 
+        /// entrance, indicating their information is not needed. If V is not null (e.g. 'empty()') C must be 
+        /// not null also. Any initial data of V or C will be lost.</remarks>
+        public static ILRetArray<double> find(ILInArray< double> A, int limit = 0,
+                      ILOutArray<double> C = null, ILOutArray< double> V = null) {
+            using (ILScope.Enter(A)) {
+                bool create_row_columns = !Object.Equals(C, null);
+                bool return_values = !Object.Equals(V, null);
+                ILArray<double> ret = empty();
+                ILSize inDim = A.Size;
+                if (inDim.NumberOfElements == 1) {
+                    #region SCALAR
+                    // scalar -> return copy
+                    
+                    if (A.GetValue(0, 0) != 0.0) {
+                        if (create_row_columns) {
+                            C.a = zeros<double>(ILSize.Scalar1_1);
+                        }
+                        if (return_values) {
+                            V.a = A.C;
+                        }
+                        return zeros<double>(1, 1);
+                    } else {
+                        if (create_row_columns) {
+                            C.a = empty<double>(ILSize.Empty00);
+                        }
+                        if (return_values) {
+                            V.a = empty<double>(ILSize.Empty00);
+                        }
+                        return empty<double>(ILSize.Empty00);
+                    }
+                    #endregion SCALAR
+                }
+                long nrElements = inDim.NumberOfElements;
+                
+
+                if (limit != 0) {
+                    int lim = Math.Abs(limit);
+                    if (lim < nrElements)
+                        nrElements = lim;
+                }
+                double[] indices = ILMemoryPool.Pool.New<double>(nrElements); // init return array with most elements for non logical inarray -> shorten afterwards 
+                int foundIdx = 0;
+                // physical -> pointer arithmetic
+                if (limit >= 0) {
+                    unsafe {
+                        fixed (double* pIndices = indices)
+                        fixed ( double* pX = A.GetArrayForRead()) {
+                            
+                            double* lastElement = pX + inDim.NumberOfElements;
+                            
+                            double* tmpIn = pX;
+                            double* pI = pIndices;
+                            double* pFoundLast = pI + indices.Length;
+                            while (tmpIn < lastElement && pI < pFoundLast) {
+                                
+                                if (*tmpIn != 0.0)
+                                    *pI++ = (double)(tmpIn - pX);
+                                tmpIn++;
+                            }
+                            foundIdx = (int)(pI - pIndices);
+                        }
+                    }
+                } else {
+                    // search backwards 
+                    unsafe {
+                        fixed (double* pIndices = indices)
+                        fixed ( double* pX = A.GetArrayForRead()) {
+                            
+                            double* lastElementX = pX;
+                            
+                            double* tmpIn = pX + inDim.NumberOfElements;
+                            double* pI = pIndices + indices.Length;
+                            while (tmpIn > lastElementX && pI > pIndices) {
+                                tmpIn--;
+                                
+                                if (*tmpIn != 0.0)
+                                    *(--pI) = (double)(tmpIn - pX);
+                            }
+                            foundIdx = (int)(pIndices + indices.Length - pI);
+                        }
+                    }
+                }
+                if (foundIdx == 0) {
+                    return empty();
+                }
+                // transform to row / columns; extract values if needed
+                int leadDimLen = inDim[0];
+                if (create_row_columns) {
+                    #region RETURN ROWS / COLUMNS /VALUES
+                    C.a = new ILRetArray<double>(ILMemoryPool.Pool.New<double>(foundIdx), foundIdx, 1);
+                    ret.a = new ILRetArray<double>(ILMemoryPool.Pool.New<double>(foundIdx), foundIdx, 1);
+                    if (return_values) {
+                        V.a = new ILRetArray< double>(ILMemoryPool.Pool.New<  double>(foundIdx), foundIdx, 1);
+                        // copy values, transform to row/columns
+                        unsafe {
+                            fixed (double* pIndices = indices,
+                                   pRows = ret.GetArrayForWrite(), pCols = C.GetArrayForWrite())
+                            fixed ( double* pValues = V.GetArrayForWrite(), pInput = A.GetArrayForRead()) {
+                                double* pI = (limit >= 0) ?
+                                        pIndices : (pIndices + indices.Length - foundIdx);
+                                double* pLastIndex = pI + foundIdx;
+                                double* pR = pRows;
+                                double* pC = pCols;
+                                
+                                double* pV = pValues;
+                                
+                                double* pX = pInput;
+                                while (pI < pLastIndex) {
+                                    *pR++ = *(pI) % leadDimLen;
+                                    *pC++ = (int)*(pI) / leadDimLen;
+                                    *pV++ = *(pInput + (int)*pI++);
+                                }
+                            }
+                        }
+                    } else {
+                        // just return row / columns 
+                        unsafe {
+                            fixed (double* pIndices = indices,
+                                   pRows = ret.GetArrayForWrite(), pCols = C.GetArrayForWrite())
+                            fixed ( double* pInput = A.GetArrayForRead()) {
+                                double* pI = (limit >= 0) ?
+                                        pIndices : (pIndices + indices.Length - foundIdx);
+                                double* pLastIndex = pI + foundIdx;
+                                double* pR = pRows;
+                                double* pC = pCols;
+                                while (pI < pLastIndex) {
+                                    *pR++ = *(pI) % leadDimLen;
+                                    *pC++ = (int)(*(pI++) / leadDimLen);
+                                }
+                            }
+                        }
+                    }
+                    #endregion RETURN ROWS / COLUMNS
+                } else {
+                    #region RETURN INDICES ONLY
+                    if (foundIdx != indices.Length) {
+                        ret.a = new ILRetArray<double>(ILMemoryPool.Pool.New<double>(foundIdx), foundIdx, 1);
+                        unsafe {
+                            fixed (double* pIndices = indices, pRows = ret.GetArrayForWrite()) {
+                                double* pI = (limit >= 0) ?
+                                        pIndices : (pIndices + indices.Length - foundIdx);
+                                double* pLastIndex = pI + foundIdx;
+                                double* pR = pRows;
+                                while (pI < pLastIndex) {
+                                    *pR++ = *pI++;
+                                }
+                            }
+                        }
+                    } else {
+                        ret.a = new ILRetArray<double>(indices, foundIdx, 1);
+                    }
+                    #endregion RETURN INDICES ONLY
+                }
+                return ret;
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// Find nonzero elements in A
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="limit">[Optional] Number of elements to search for. If this value is <![CDATA[< 0]]> the function 
+        /// will return at most 'limit' nonzero elements from the end of the array ordered by ascending index.
+        /// Set to 0 to search full array (default).</param>
+        /// <param name="C">[Optional] If not null, the function will return the row indices of nonzero elements 
+        /// as main return value. C will therefore hold the column indices of those elements. If A
+        /// has more than 2 dimensions, the column indices will go along the 2nd dimension.</param>
+        /// <param name="V">[Optional] If not null on entrance, V will hold a copy of the values of nonzero elements returned.</param>
+        /// <returns>Vector containing (sequential) indices of nonzero elements in A. If C was 
+        /// not null, return value will contain row indices of nonzero elements. </returns>
+        /// <remarks>The return type of the index vectors is always 'double'. The return type 
+        /// of the element vector 'V' depends on the type of input array A. V and C may be null on 
+        /// entrance, indicating their information is not needed. If V is not null (e.g. 'empty()') C must be 
+        /// not null also. Any initial data of V or C will be lost.</remarks>
+        public static ILRetArray<double> find(ILInArray< Int64> A, int limit = 0,
+                      ILOutArray<double> C = null, ILOutArray< Int64> V = null) {
+            using (ILScope.Enter(A)) {
+                bool create_row_columns = !Object.Equals(C, null);
+                bool return_values = !Object.Equals(V, null);
+                ILArray<double> ret = empty();
+                ILSize inDim = A.Size;
+                if (inDim.NumberOfElements == 1) {
+                    #region SCALAR
+                    // scalar -> return copy
+                    if (A.GetValue(0,0) != 0) {
+                        if (create_row_columns) {
+                            C.a = zeros<double>(ILSize.Scalar1_1);
+                        }
+                        if (return_values) {
+                            V.a = A.C;
+                        }
+                        return zeros<double>(1, 1);
+                    } else {
+                        if (create_row_columns) {
+                            C.a = empty<double>(ILSize.Empty00);
+                        }
+                        if (return_values) {
+                            V.a = empty<Int64>(ILSize.Empty00);
+                        }
+                        return empty<double>(ILSize.Empty00);
+                    }
+                    #endregion SCALAR
+                }
+                long nrElements = inDim.NumberOfElements;
+                
+                if (limit != 0) {
+                    int lim = Math.Abs(limit);
+                    if (lim < nrElements)
+                        nrElements = lim;
+                }
+                double[] indices = ILMemoryPool.Pool.New<double>(nrElements); // init return array with most elements for non logical inarray -> shorten afterwards 
+                int foundIdx = 0;
+                // physical -> pointer arithmetic
+                if (limit >= 0) {
+                    unsafe {
+                        fixed (double* pIndices = indices)
+                        fixed ( Int64* pX = A.GetArrayForRead()) {
+                           
+                            Int64* lastElement = pX + inDim.NumberOfElements;
+                           
+                            Int64* tmpIn = pX;
+                            double* pI = pIndices;
+                            double* pFoundLast = pI + indices.Length;
+                            while (tmpIn < lastElement && pI < pFoundLast) {
+                                if (*tmpIn != 0)
+                                    *pI++ = (double)(tmpIn - pX);
+                                tmpIn++;
+                            }
+                            foundIdx = (int)(pI - pIndices);
+                        }
+                    }
+                } else {
+                    // search backwards 
+                    unsafe {
+                        fixed (double* pIndices = indices)
+                        fixed ( Int64* pX = A.GetArrayForRead()) {
+                           
+                            Int64* lastElementX = pX;
+                           
+                            Int64* tmpIn = pX + inDim.NumberOfElements;
+                            double* pI = pIndices + indices.Length;
+                            while (tmpIn > lastElementX && pI > pIndices) {
+                                tmpIn--;
+                                if (*tmpIn != 0)
+                                    *(--pI) = (double)(tmpIn - pX);
+                            }
+                            foundIdx = (int)(pIndices + indices.Length - pI);
+                        }
+                    }
+                }
+                if (foundIdx == 0) {
+                    return empty();
+                }
+                // transform to row / columns; extract values if needed
+                int leadDimLen = inDim[0];
+                if (create_row_columns) {
+                    #region RETURN ROWS / COLUMNS /VALUES
+                    C.a = new ILRetArray<double>(ILMemoryPool.Pool.New<double>(foundIdx), foundIdx, 1);
+                    ret.a = new ILRetArray<double>(ILMemoryPool.Pool.New<double>(foundIdx), foundIdx, 1);
+                    if (return_values) {
+                        V.a = new ILRetArray< Int64>(ILMemoryPool.Pool.New<  Int64>(foundIdx), foundIdx, 1);
+                        // copy values, transform to row/columns
+                        unsafe {
+                            fixed (double* pIndices = indices,
+                                   pRows = ret.GetArrayForWrite(), pCols = C.GetArrayForWrite())
+                            fixed ( Int64* pValues = V.GetArrayForWrite(), pInput = A.GetArrayForRead()) {
+                                double* pI = (limit >= 0) ?
+                                        pIndices : (pIndices + indices.Length - foundIdx);
+                                double* pLastIndex = pI + foundIdx;
+                                double* pR = pRows;
+                                double* pC = pCols;
+                               
+                                Int64* pV = pValues;
+                               
+                                Int64* pX = pInput;
+                                while (pI < pLastIndex) {
+                                    *pR++ = *(pI) % leadDimLen;
+                                    *pC++ = (int)*(pI) / leadDimLen;
+                                    *pV++ = *(pInput + (int)*pI++);
+                                }
+                            }
+                        }
+                    } else {
+                        // just return row / columns 
+                        unsafe {
+                            fixed (double* pIndices = indices,
+                                   pRows = ret.GetArrayForWrite(), pCols = C.GetArrayForWrite())
+                            fixed ( Int64* pInput = A.GetArrayForRead()) {
+                                double* pI = (limit >= 0) ?
+                                        pIndices : (pIndices + indices.Length - foundIdx);
+                                double* pLastIndex = pI + foundIdx;
+                                double* pR = pRows;
+                                double* pC = pCols;
+                                while (pI < pLastIndex) {
+                                    *pR++ = *(pI) % leadDimLen;
+                                    *pC++ = (int)(*(pI++) / leadDimLen);
+                                }
+                            }
+                        }
+                    }
+                    #endregion RETURN ROWS / COLUMNS
+                } else {
+                    #region RETURN INDICES ONLY
+                    if (foundIdx != indices.Length) {
+                        ret.a = new ILRetArray<double>(ILMemoryPool.Pool.New<double>(foundIdx), foundIdx, 1);
+                        unsafe {
+                            fixed (double* pIndices = indices, pRows = ret.GetArrayForWrite()) {
+                                double* pI = (limit >= 0) ?
+                                        pIndices : (pIndices + indices.Length - foundIdx);
+                                double* pLastIndex = pI + foundIdx;
+                                double* pR = pRows;
+                                while (pI < pLastIndex) {
+                                    *pR++ = *pI++;
+                                }
+                            }
+                        }
+                    } else {
+                        ret.a = new ILRetArray<double>(indices, foundIdx, 1);
+                    }
+                    #endregion RETURN INDICES ONLY
+                }
+                return ret;
+            }
+        }
+        /// <summary>
+        /// Find nonzero elements in A
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="limit">[Optional] Number of elements to search for. If this value is <![CDATA[< 0]]> the function 
+        /// will return at most 'limit' nonzero elements from the end of the array ordered by ascending index.
+        /// Set to 0 to search full array (default).</param>
+        /// <param name="C">[Optional] If not null, the function will return the row indices of nonzero elements 
+        /// as main return value. C will therefore hold the column indices of those elements. If A
+        /// has more than 2 dimensions, the column indices will go along the 2nd dimension.</param>
+        /// <param name="V">[Optional] If not null on entrance, V will hold a copy of the values of nonzero elements returned.</param>
+        /// <returns>Vector containing (sequential) indices of nonzero elements in A. If C was 
+        /// not null, return value will contain row indices of nonzero elements. </returns>
+        /// <remarks>The return type of the index vectors is always 'double'. The return type 
+        /// of the element vector 'V' depends on the type of input array A. V and C may be null on 
+        /// entrance, indicating their information is not needed. If V is not null (e.g. 'empty()') C must be 
+        /// not null also. Any initial data of V or C will be lost.</remarks>
+        public static ILRetArray<double> find(ILInArray< Int32> A, int limit = 0,
+                      ILOutArray<double> C = null, ILOutArray< Int32> V = null) {
+            using (ILScope.Enter(A)) {
+                bool create_row_columns = !Object.Equals(C, null);
+                bool return_values = !Object.Equals(V, null);
+                ILArray<double> ret = empty();
+                ILSize inDim = A.Size;
+                if (inDim.NumberOfElements == 1) {
+                    #region SCALAR
+                    // scalar -> return copy
+                    if (A.GetValue(0,0) != 0) {
+                        if (create_row_columns) {
+                            C.a = zeros<double>(ILSize.Scalar1_1);
+                        }
+                        if (return_values) {
+                            V.a = A.C;
+                        }
+                        return zeros<double>(1, 1);
+                    } else {
+                        if (create_row_columns) {
+                            C.a = empty<double>(ILSize.Empty00);
+                        }
+                        if (return_values) {
+                            V.a = empty<Int32>(ILSize.Empty00);
+                        }
+                        return empty<double>(ILSize.Empty00);
+                    }
+                    #endregion SCALAR
+                }
+                long nrElements = inDim.NumberOfElements;
+                
+                if (limit != 0) {
+                    int lim = Math.Abs(limit);
+                    if (lim < nrElements)
+                        nrElements = lim;
+                }
+                double[] indices = ILMemoryPool.Pool.New<double>(nrElements); // init return array with most elements for non logical inarray -> shorten afterwards 
+                int foundIdx = 0;
+                // physical -> pointer arithmetic
+                if (limit >= 0) {
+                    unsafe {
+                        fixed (double* pIndices = indices)
+                        fixed ( Int32* pX = A.GetArrayForRead()) {
+                           
+                            Int32* lastElement = pX + inDim.NumberOfElements;
+                           
+                            Int32* tmpIn = pX;
+                            double* pI = pIndices;
+                            double* pFoundLast = pI + indices.Length;
+                            while (tmpIn < lastElement && pI < pFoundLast) {
+                                if (*tmpIn != 0)
+                                    *pI++ = (double)(tmpIn - pX);
+                                tmpIn++;
+                            }
+                            foundIdx = (int)(pI - pIndices);
+                        }
+                    }
+                } else {
+                    // search backwards 
+                    unsafe {
+                        fixed (double* pIndices = indices)
+                        fixed ( Int32* pX = A.GetArrayForRead()) {
+                           
+                            Int32* lastElementX = pX;
+                           
+                            Int32* tmpIn = pX + inDim.NumberOfElements;
+                            double* pI = pIndices + indices.Length;
+                            while (tmpIn > lastElementX && pI > pIndices) {
+                                tmpIn--;
+                                if (*tmpIn != 0)
+                                    *(--pI) = (double)(tmpIn - pX);
+                            }
+                            foundIdx = (int)(pIndices + indices.Length - pI);
+                        }
+                    }
+                }
+                if (foundIdx == 0) {
+                    return empty();
+                }
+                // transform to row / columns; extract values if needed
+                int leadDimLen = inDim[0];
+                if (create_row_columns) {
+                    #region RETURN ROWS / COLUMNS /VALUES
+                    C.a = new ILRetArray<double>(ILMemoryPool.Pool.New<double>(foundIdx), foundIdx, 1);
+                    ret.a = new ILRetArray<double>(ILMemoryPool.Pool.New<double>(foundIdx), foundIdx, 1);
+                    if (return_values) {
+                        V.a = new ILRetArray< Int32>(ILMemoryPool.Pool.New<  Int32>(foundIdx), foundIdx, 1);
+                        // copy values, transform to row/columns
+                        unsafe {
+                            fixed (double* pIndices = indices,
+                                   pRows = ret.GetArrayForWrite(), pCols = C.GetArrayForWrite())
+                            fixed ( Int32* pValues = V.GetArrayForWrite(), pInput = A.GetArrayForRead()) {
+                                double* pI = (limit >= 0) ?
+                                        pIndices : (pIndices + indices.Length - foundIdx);
+                                double* pLastIndex = pI + foundIdx;
+                                double* pR = pRows;
+                                double* pC = pCols;
+                               
+                                Int32* pV = pValues;
+                               
+                                Int32* pX = pInput;
+                                while (pI < pLastIndex) {
+                                    *pR++ = *(pI) % leadDimLen;
+                                    *pC++ = (int)*(pI) / leadDimLen;
+                                    *pV++ = *(pInput + (int)*pI++);
+                                }
+                            }
+                        }
+                    } else {
+                        // just return row / columns 
+                        unsafe {
+                            fixed (double* pIndices = indices,
+                                   pRows = ret.GetArrayForWrite(), pCols = C.GetArrayForWrite())
+                            fixed ( Int32* pInput = A.GetArrayForRead()) {
+                                double* pI = (limit >= 0) ?
+                                        pIndices : (pIndices + indices.Length - foundIdx);
+                                double* pLastIndex = pI + foundIdx;
+                                double* pR = pRows;
+                                double* pC = pCols;
+                                while (pI < pLastIndex) {
+                                    *pR++ = *(pI) % leadDimLen;
+                                    *pC++ = (int)(*(pI++) / leadDimLen);
+                                }
+                            }
+                        }
+                    }
+                    #endregion RETURN ROWS / COLUMNS
+                } else {
+                    #region RETURN INDICES ONLY
+                    if (foundIdx != indices.Length) {
+                        ret.a = new ILRetArray<double>(ILMemoryPool.Pool.New<double>(foundIdx), foundIdx, 1);
+                        unsafe {
+                            fixed (double* pIndices = indices, pRows = ret.GetArrayForWrite()) {
+                                double* pI = (limit >= 0) ?
+                                        pIndices : (pIndices + indices.Length - foundIdx);
+                                double* pLastIndex = pI + foundIdx;
+                                double* pR = pRows;
+                                while (pI < pLastIndex) {
+                                    *pR++ = *pI++;
+                                }
+                            }
+                        }
+                    } else {
+                        ret.a = new ILRetArray<double>(indices, foundIdx, 1);
+                    }
+                    #endregion RETURN INDICES ONLY
+                }
+                return ret;
+            }
+        }
+        /// <summary>
+        /// Find nonzero elements in A
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="limit">[Optional] Number of elements to search for. If this value is <![CDATA[< 0]]> the function 
+        /// will return at most 'limit' nonzero elements from the end of the array ordered by ascending index.
+        /// Set to 0 to search full array (default).</param>
+        /// <param name="C">[Optional] If not null, the function will return the row indices of nonzero elements 
+        /// as main return value. C will therefore hold the column indices of those elements. If A
+        /// has more than 2 dimensions, the column indices will go along the 2nd dimension.</param>
+        /// <param name="V">[Optional] If not null on entrance, V will hold a copy of the values of nonzero elements returned.</param>
+        /// <returns>Vector containing (sequential) indices of nonzero elements in A. If C was 
+        /// not null, return value will contain row indices of nonzero elements. </returns>
+        /// <remarks>The return type of the index vectors is always 'double'. The return type 
+        /// of the element vector 'V' depends on the type of input array A. V and C may be null on 
+        /// entrance, indicating their information is not needed. If V is not null (e.g. 'empty()') C must be 
+        /// not null also. Any initial data of V or C will be lost.</remarks>
+        public static ILRetArray<double> find(ILInArray< float> A, int limit = 0,
+                      ILOutArray<double> C = null, ILOutArray< float> V = null) {
+            using (ILScope.Enter(A)) {
+                bool create_row_columns = !Object.Equals(C, null);
+                bool return_values = !Object.Equals(V, null);
+                ILArray<double> ret = empty();
+                ILSize inDim = A.Size;
+                if (inDim.NumberOfElements == 1) {
+                    #region SCALAR
+                    // scalar -> return copy
+                    if (A.GetValue(0,0) != 0.0) {
+                        if (create_row_columns) {
+                            C.a = zeros<double>(ILSize.Scalar1_1);
+                        }
+                        if (return_values) {
+                            V.a = A.C;
+                        }
+                        return zeros<double>(1, 1);
+                    } else {
+                        if (create_row_columns) {
+                            C.a = empty<double>(ILSize.Empty00);
+                        }
+                        if (return_values) {
+                            V.a = empty<float>(ILSize.Empty00);
+                        }
+                        return empty<double>(ILSize.Empty00);
+                    }
+                    #endregion SCALAR
+                }
+                long nrElements = inDim.NumberOfElements;
+                
+                if (limit != 0) {
+                    int lim = Math.Abs(limit);
+                    if (lim < nrElements)
+                        nrElements = lim;
+                }
+                double[] indices = ILMemoryPool.Pool.New<double>(nrElements); // init return array with most elements for non logical inarray -> shorten afterwards 
+                int foundIdx = 0;
+                // physical -> pointer arithmetic
+                if (limit >= 0) {
+                    unsafe {
+                        fixed (double* pIndices = indices)
+                        fixed ( float* pX = A.GetArrayForRead()) {
+                           
+                            float* lastElement = pX + inDim.NumberOfElements;
+                           
+                            float* tmpIn = pX;
+                            double* pI = pIndices;
+                            double* pFoundLast = pI + indices.Length;
+                            while (tmpIn < lastElement && pI < pFoundLast) {
+                                if (*tmpIn != 0.0f)
+                                    *pI++ = (double)(tmpIn - pX);
+                                tmpIn++;
+                            }
+                            foundIdx = (int)(pI - pIndices);
+                        }
+                    }
+                } else {
+                    // search backwards 
+                    unsafe {
+                        fixed (double* pIndices = indices)
+                        fixed ( float* pX = A.GetArrayForRead()) {
+                           
+                            float* lastElementX = pX;
+                           
+                            float* tmpIn = pX + inDim.NumberOfElements;
+                            double* pI = pIndices + indices.Length;
+                            while (tmpIn > lastElementX && pI > pIndices) {
+                                tmpIn--;
+                                if (*tmpIn != 0.0f)
+                                    *(--pI) = (double)(tmpIn - pX);
+                            }
+                            foundIdx = (int)(pIndices + indices.Length - pI);
+                        }
+                    }
+                }
+                if (foundIdx == 0) {
+                    return empty();
+                }
+                // transform to row / columns; extract values if needed
+                int leadDimLen = inDim[0];
+                if (create_row_columns) {
+                    #region RETURN ROWS / COLUMNS /VALUES
+                    C.a = new ILRetArray<double>(ILMemoryPool.Pool.New<double>(foundIdx), foundIdx, 1);
+                    ret.a = new ILRetArray<double>(ILMemoryPool.Pool.New<double>(foundIdx), foundIdx, 1);
+                    if (return_values) {
+                        V.a = new ILRetArray< float>(ILMemoryPool.Pool.New<  float>(foundIdx), foundIdx, 1);
+                        // copy values, transform to row/columns
+                        unsafe {
+                            fixed (double* pIndices = indices,
+                                   pRows = ret.GetArrayForWrite(), pCols = C.GetArrayForWrite())
+                            fixed ( float* pValues = V.GetArrayForWrite(), pInput = A.GetArrayForRead()) {
+                                double* pI = (limit >= 0) ?
+                                        pIndices : (pIndices + indices.Length - foundIdx);
+                                double* pLastIndex = pI + foundIdx;
+                                double* pR = pRows;
+                                double* pC = pCols;
+                               
+                                float* pV = pValues;
+                               
+                                float* pX = pInput;
+                                while (pI < pLastIndex) {
+                                    *pR++ = *(pI) % leadDimLen;
+                                    *pC++ = (int)*(pI) / leadDimLen;
+                                    *pV++ = *(pInput + (int)*pI++);
+                                }
+                            }
+                        }
+                    } else {
+                        // just return row / columns 
+                        unsafe {
+                            fixed (double* pIndices = indices,
+                                   pRows = ret.GetArrayForWrite(), pCols = C.GetArrayForWrite())
+                            fixed ( float* pInput = A.GetArrayForRead()) {
+                                double* pI = (limit >= 0) ?
+                                        pIndices : (pIndices + indices.Length - foundIdx);
+                                double* pLastIndex = pI + foundIdx;
+                                double* pR = pRows;
+                                double* pC = pCols;
+                                while (pI < pLastIndex) {
+                                    *pR++ = *(pI) % leadDimLen;
+                                    *pC++ = (int)(*(pI++) / leadDimLen);
+                                }
+                            }
+                        }
+                    }
+                    #endregion RETURN ROWS / COLUMNS
+                } else {
+                    #region RETURN INDICES ONLY
+                    if (foundIdx != indices.Length) {
+                        ret.a = new ILRetArray<double>(ILMemoryPool.Pool.New<double>(foundIdx), foundIdx, 1);
+                        unsafe {
+                            fixed (double* pIndices = indices, pRows = ret.GetArrayForWrite()) {
+                                double* pI = (limit >= 0) ?
+                                        pIndices : (pIndices + indices.Length - foundIdx);
+                                double* pLastIndex = pI + foundIdx;
+                                double* pR = pRows;
+                                while (pI < pLastIndex) {
+                                    *pR++ = *pI++;
+                                }
+                            }
+                        }
+                    } else {
+                        ret.a = new ILRetArray<double>(indices, foundIdx, 1);
+                    }
+                    #endregion RETURN INDICES ONLY
+                }
+                return ret;
+            }
+        }
+        /// <summary>
+        /// Find nonzero elements in A
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="limit">[Optional] Number of elements to search for. If this value is <![CDATA[< 0]]> the function 
+        /// will return at most 'limit' nonzero elements from the end of the array ordered by ascending index.
+        /// Set to 0 to search full array (default).</param>
+        /// <param name="C">[Optional] If not null, the function will return the row indices of nonzero elements 
+        /// as main return value. C will therefore hold the column indices of those elements. If A
+        /// has more than 2 dimensions, the column indices will go along the 2nd dimension.</param>
+        /// <param name="V">[Optional] If not null on entrance, V will hold a copy of the values of nonzero elements returned.</param>
+        /// <returns>Vector containing (sequential) indices of nonzero elements in A. If C was 
+        /// not null, return value will contain row indices of nonzero elements. </returns>
+        /// <remarks>The return type of the index vectors is always 'double'. The return type 
+        /// of the element vector 'V' depends on the type of input array A. V and C may be null on 
+        /// entrance, indicating their information is not needed. If V is not null (e.g. 'empty()') C must be 
+        /// not null also. Any initial data of V or C will be lost.</remarks>
+        public static ILRetArray<double> find(ILInArray< fcomplex> A, int limit = 0,
+                      ILOutArray<double> C = null, ILOutArray< fcomplex> V = null) {
+            using (ILScope.Enter(A)) {
+                bool create_row_columns = !Object.Equals(C, null);
+                bool return_values = !Object.Equals(V, null);
+                ILArray<double> ret = empty();
+                ILSize inDim = A.Size;
+                if (inDim.NumberOfElements == 1) {
+                    #region SCALAR
+                    // scalar -> return copy
+                    if (A.GetValue(0,0).real != 0.0 || A.GetValue(0,0).imag != 0.0) {
+                        if (create_row_columns) {
+                            C.a = zeros<double>(ILSize.Scalar1_1);
+                        }
+                        if (return_values) {
+                            V.a = A.C;
+                        }
+                        return zeros<double>(1, 1);
+                    } else {
+                        if (create_row_columns) {
+                            C.a = empty<double>(ILSize.Empty00);
+                        }
+                        if (return_values) {
+                            V.a = empty<fcomplex>(ILSize.Empty00);
+                        }
+                        return empty<double>(ILSize.Empty00);
+                    }
+                    #endregion SCALAR
+                }
+                long nrElements = inDim.NumberOfElements;
+                
+                if (limit != 0) {
+                    int lim = Math.Abs(limit);
+                    if (lim < nrElements)
+                        nrElements = lim;
+                }
+                double[] indices = ILMemoryPool.Pool.New<double>(nrElements); // init return array with most elements for non logical inarray -> shorten afterwards 
+                int foundIdx = 0;
+                // physical -> pointer arithmetic
+                if (limit >= 0) {
+                    unsafe {
+                        fixed (double* pIndices = indices)
+                        fixed ( fcomplex* pX = A.GetArrayForRead()) {
+                           
+                            fcomplex* lastElement = pX + inDim.NumberOfElements;
+                           
+                            fcomplex* tmpIn = pX;
+                            double* pI = pIndices;
+                            double* pFoundLast = pI + indices.Length;
+                            while (tmpIn < lastElement && pI < pFoundLast) {
+                                if ((*tmpIn).real != 0.0 || (*tmpIn).imag != 0.0)
+                                    *pI++ = (double)(tmpIn - pX);
+                                tmpIn++;
+                            }
+                            foundIdx = (int)(pI - pIndices);
+                        }
+                    }
+                } else {
+                    // search backwards 
+                    unsafe {
+                        fixed (double* pIndices = indices)
+                        fixed ( fcomplex* pX = A.GetArrayForRead()) {
+                           
+                            fcomplex* lastElementX = pX;
+                           
+                            fcomplex* tmpIn = pX + inDim.NumberOfElements;
+                            double* pI = pIndices + indices.Length;
+                            while (tmpIn > lastElementX && pI > pIndices) {
+                                tmpIn--;
+                                if ((*tmpIn).real != 0.0 || (*tmpIn).imag != 0.0)
+                                    *(--pI) = (double)(tmpIn - pX);
+                            }
+                            foundIdx = (int)(pIndices + indices.Length - pI);
+                        }
+                    }
+                }
+                if (foundIdx == 0) {
+                    return empty();
+                }
+                // transform to row / columns; extract values if needed
+                int leadDimLen = inDim[0];
+                if (create_row_columns) {
+                    #region RETURN ROWS / COLUMNS /VALUES
+                    C.a = new ILRetArray<double>(ILMemoryPool.Pool.New<double>(foundIdx), foundIdx, 1);
+                    ret.a = new ILRetArray<double>(ILMemoryPool.Pool.New<double>(foundIdx), foundIdx, 1);
+                    if (return_values) {
+                        V.a = new ILRetArray< fcomplex>(ILMemoryPool.Pool.New<  fcomplex>(foundIdx), foundIdx, 1);
+                        // copy values, transform to row/columns
+                        unsafe {
+                            fixed (double* pIndices = indices,
+                                   pRows = ret.GetArrayForWrite(), pCols = C.GetArrayForWrite())
+                            fixed ( fcomplex* pValues = V.GetArrayForWrite(), pInput = A.GetArrayForRead()) {
+                                double* pI = (limit >= 0) ?
+                                        pIndices : (pIndices + indices.Length - foundIdx);
+                                double* pLastIndex = pI + foundIdx;
+                                double* pR = pRows;
+                                double* pC = pCols;
+                               
+                                fcomplex* pV = pValues;
+                               
+                                fcomplex* pX = pInput;
+                                while (pI < pLastIndex) {
+                                    *pR++ = *(pI) % leadDimLen;
+                                    *pC++ = (int)*(pI) / leadDimLen;
+                                    *pV++ = *(pInput + (int)*pI++);
+                                }
+                            }
+                        }
+                    } else {
+                        // just return row / columns 
+                        unsafe {
+                            fixed (double* pIndices = indices,
+                                   pRows = ret.GetArrayForWrite(), pCols = C.GetArrayForWrite())
+                            fixed ( fcomplex* pInput = A.GetArrayForRead()) {
+                                double* pI = (limit >= 0) ?
+                                        pIndices : (pIndices + indices.Length - foundIdx);
+                                double* pLastIndex = pI + foundIdx;
+                                double* pR = pRows;
+                                double* pC = pCols;
+                                while (pI < pLastIndex) {
+                                    *pR++ = *(pI) % leadDimLen;
+                                    *pC++ = (int)(*(pI++) / leadDimLen);
+                                }
+                            }
+                        }
+                    }
+                    #endregion RETURN ROWS / COLUMNS
+                } else {
+                    #region RETURN INDICES ONLY
+                    if (foundIdx != indices.Length) {
+                        ret.a = new ILRetArray<double>(ILMemoryPool.Pool.New<double>(foundIdx), foundIdx, 1);
+                        unsafe {
+                            fixed (double* pIndices = indices, pRows = ret.GetArrayForWrite()) {
+                                double* pI = (limit >= 0) ?
+                                        pIndices : (pIndices + indices.Length - foundIdx);
+                                double* pLastIndex = pI + foundIdx;
+                                double* pR = pRows;
+                                while (pI < pLastIndex) {
+                                    *pR++ = *pI++;
+                                }
+                            }
+                        }
+                    } else {
+                        ret.a = new ILRetArray<double>(indices, foundIdx, 1);
+                    }
+                    #endregion RETURN INDICES ONLY
+                }
+                return ret;
+            }
+        }
+        /// <summary>
+        /// Find nonzero elements in A
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="limit">[Optional] Number of elements to search for. If this value is <![CDATA[< 0]]> the function 
+        /// will return at most 'limit' nonzero elements from the end of the array ordered by ascending index.
+        /// Set to 0 to search full array (default).</param>
+        /// <param name="C">[Optional] If not null, the function will return the row indices of nonzero elements 
+        /// as main return value. C will therefore hold the column indices of those elements. If A
+        /// has more than 2 dimensions, the column indices will go along the 2nd dimension.</param>
+        /// <param name="V">[Optional] If not null on entrance, V will hold a copy of the values of nonzero elements returned.</param>
+        /// <returns>Vector containing (sequential) indices of nonzero elements in A. If C was 
+        /// not null, return value will contain row indices of nonzero elements. </returns>
+        /// <remarks>The return type of the index vectors is always 'double'. The return type 
+        /// of the element vector 'V' depends on the type of input array A. V and C may be null on 
+        /// entrance, indicating their information is not needed. If V is not null (e.g. 'empty()') C must be 
+        /// not null also. Any initial data of V or C will be lost.</remarks>
+        public static ILRetArray<double> find(ILInArray< complex> A, int limit = 0,
+                      ILOutArray<double> C = null, ILOutArray< complex> V = null) {
+            using (ILScope.Enter(A)) {
+                bool create_row_columns = !Object.Equals(C, null);
+                bool return_values = !Object.Equals(V, null);
+                ILArray<double> ret = empty();
+                ILSize inDim = A.Size;
+                if (inDim.NumberOfElements == 1) {
+                    #region SCALAR
+                    // scalar -> return copy
+                    if (A.GetValue(0,0).real != 0.0 || A.GetValue(0,0).imag != 0.0) {
+                        if (create_row_columns) {
+                            C.a = zeros<double>(ILSize.Scalar1_1);
+                        }
+                        if (return_values) {
+                            V.a = A.C;
+                        }
+                        return zeros<double>(1, 1);
+                    } else {
+                        if (create_row_columns) {
+                            C.a = empty<double>(ILSize.Empty00);
+                        }
+                        if (return_values) {
+                            V.a = empty<complex>(ILSize.Empty00);
+                        }
+                        return empty<double>(ILSize.Empty00);
+                    }
+                    #endregion SCALAR
+                }
+                long nrElements = inDim.NumberOfElements;
+                
+                if (limit != 0) {
+                    int lim = Math.Abs(limit);
+                    if (lim < nrElements)
+                        nrElements = lim;
+                }
+                double[] indices = ILMemoryPool.Pool.New<double>(nrElements); // init return array with most elements for non logical inarray -> shorten afterwards 
+                int foundIdx = 0;
+                // physical -> pointer arithmetic
+                if (limit >= 0) {
+                    unsafe {
+                        fixed (double* pIndices = indices)
+                        fixed ( complex* pX = A.GetArrayForRead()) {
+                           
+                            complex* lastElement = pX + inDim.NumberOfElements;
+                           
+                            complex* tmpIn = pX;
+                            double* pI = pIndices;
+                            double* pFoundLast = pI + indices.Length;
+                            while (tmpIn < lastElement && pI < pFoundLast) {
+                                if ((*tmpIn).real != 0.0 || (*tmpIn).imag != 0.0)
+                                    *pI++ = (double)(tmpIn - pX);
+                                tmpIn++;
+                            }
+                            foundIdx = (int)(pI - pIndices);
+                        }
+                    }
+                } else {
+                    // search backwards 
+                    unsafe {
+                        fixed (double* pIndices = indices)
+                        fixed ( complex* pX = A.GetArrayForRead()) {
+                           
+                            complex* lastElementX = pX;
+                           
+                            complex* tmpIn = pX + inDim.NumberOfElements;
+                            double* pI = pIndices + indices.Length;
+                            while (tmpIn > lastElementX && pI > pIndices) {
+                                tmpIn--;
+                                if ((*tmpIn).real != 0.0 || (*tmpIn).imag != 0.0)
+                                    *(--pI) = (double)(tmpIn - pX);
+                            }
+                            foundIdx = (int)(pIndices + indices.Length - pI);
+                        }
+                    }
+                }
+                if (foundIdx == 0) {
+                    return empty();
+                }
+                // transform to row / columns; extract values if needed
+                int leadDimLen = inDim[0];
+                if (create_row_columns) {
+                    #region RETURN ROWS / COLUMNS /VALUES
+                    C.a = new ILRetArray<double>(ILMemoryPool.Pool.New<double>(foundIdx), foundIdx, 1);
+                    ret.a = new ILRetArray<double>(ILMemoryPool.Pool.New<double>(foundIdx), foundIdx, 1);
+                    if (return_values) {
+                        V.a = new ILRetArray< complex>(ILMemoryPool.Pool.New<  complex>(foundIdx), foundIdx, 1);
+                        // copy values, transform to row/columns
+                        unsafe {
+                            fixed (double* pIndices = indices,
+                                   pRows = ret.GetArrayForWrite(), pCols = C.GetArrayForWrite())
+                            fixed ( complex* pValues = V.GetArrayForWrite(), pInput = A.GetArrayForRead()) {
+                                double* pI = (limit >= 0) ?
+                                        pIndices : (pIndices + indices.Length - foundIdx);
+                                double* pLastIndex = pI + foundIdx;
+                                double* pR = pRows;
+                                double* pC = pCols;
+                               
+                                complex* pV = pValues;
+                               
+                                complex* pX = pInput;
+                                while (pI < pLastIndex) {
+                                    *pR++ = *(pI) % leadDimLen;
+                                    *pC++ = (int)*(pI) / leadDimLen;
+                                    *pV++ = *(pInput + (int)*pI++);
+                                }
+                            }
+                        }
+                    } else {
+                        // just return row / columns 
+                        unsafe {
+                            fixed (double* pIndices = indices,
+                                   pRows = ret.GetArrayForWrite(), pCols = C.GetArrayForWrite())
+                            fixed ( complex* pInput = A.GetArrayForRead()) {
+                                double* pI = (limit >= 0) ?
+                                        pIndices : (pIndices + indices.Length - foundIdx);
+                                double* pLastIndex = pI + foundIdx;
+                                double* pR = pRows;
+                                double* pC = pCols;
+                                while (pI < pLastIndex) {
+                                    *pR++ = *(pI) % leadDimLen;
+                                    *pC++ = (int)(*(pI++) / leadDimLen);
+                                }
+                            }
+                        }
+                    }
+                    #endregion RETURN ROWS / COLUMNS
+                } else {
+                    #region RETURN INDICES ONLY
+                    if (foundIdx != indices.Length) {
+                        ret.a = new ILRetArray<double>(ILMemoryPool.Pool.New<double>(foundIdx), foundIdx, 1);
+                        unsafe {
+                            fixed (double* pIndices = indices, pRows = ret.GetArrayForWrite()) {
+                                double* pI = (limit >= 0) ?
+                                        pIndices : (pIndices + indices.Length - foundIdx);
+                                double* pLastIndex = pI + foundIdx;
+                                double* pR = pRows;
+                                while (pI < pLastIndex) {
+                                    *pR++ = *pI++;
+                                }
+                            }
+                        }
+                    } else {
+                        ret.a = new ILRetArray<double>(indices, foundIdx, 1);
+                    }
+                    #endregion RETURN INDICES ONLY
+                }
+                return ret;
+            }
+        }
+        /// <summary>
+        /// Find nonzero elements in A
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="limit">[Optional] Number of elements to search for. If this value is <![CDATA[< 0]]> the function 
+        /// will return at most 'limit' nonzero elements from the end of the array ordered by ascending index.
+        /// Set to 0 to search full array (default).</param>
+        /// <param name="C">[Optional] If not null, the function will return the row indices of nonzero elements 
+        /// as main return value. C will therefore hold the column indices of those elements. If A
+        /// has more than 2 dimensions, the column indices will go along the 2nd dimension.</param>
+        /// <param name="V">[Optional] If not null on entrance, V will hold a copy of the values of nonzero elements returned.</param>
+        /// <returns>Vector containing (sequential) indices of nonzero elements in A. If C was 
+        /// not null, return value will contain row indices of nonzero elements. </returns>
+        /// <remarks>The return type of the index vectors is always 'double'. The return type 
+        /// of the element vector 'V' depends on the type of input array A. V and C may be null on 
+        /// entrance, indicating their information is not needed. If V is not null (e.g. 'empty()') C must be 
+        /// not null also. Any initial data of V or C will be lost.</remarks>
+        public static ILRetArray<double> find(ILInArray< byte> A, int limit = 0,
+                      ILOutArray<double> C = null, ILOutArray< byte> V = null) {
+            using (ILScope.Enter(A)) {
+                bool create_row_columns = !Object.Equals(C, null);
+                bool return_values = !Object.Equals(V, null);
+                ILArray<double> ret = empty();
+                ILSize inDim = A.Size;
+                if (inDim.NumberOfElements == 1) {
+                    #region SCALAR
+                    // scalar -> return copy
+                    if (A.GetValue(0,0) != 0) {
+                        if (create_row_columns) {
+                            C.a = zeros<double>(ILSize.Scalar1_1);
+                        }
+                        if (return_values) {
+                            V.a = A.C;
+                        }
+                        return zeros<double>(1, 1);
+                    } else {
+                        if (create_row_columns) {
+                            C.a = empty<double>(ILSize.Empty00);
+                        }
+                        if (return_values) {
+                            V.a = empty<byte>(ILSize.Empty00);
+                        }
+                        return empty<double>(ILSize.Empty00);
+                    }
+                    #endregion SCALAR
+                }
+                long nrElements = inDim.NumberOfElements;
+                
+                if (limit != 0) {
+                    int lim = Math.Abs(limit);
+                    if (lim < nrElements)
+                        nrElements = lim;
+                }
+                double[] indices = ILMemoryPool.Pool.New<double>(nrElements); // init return array with most elements for non logical inarray -> shorten afterwards 
+                int foundIdx = 0;
+                // physical -> pointer arithmetic
+                if (limit >= 0) {
+                    unsafe {
+                        fixed (double* pIndices = indices)
+                        fixed ( byte* pX = A.GetArrayForRead()) {
+                           
+                            byte* lastElement = pX + inDim.NumberOfElements;
+                           
+                            byte* tmpIn = pX;
+                            double* pI = pIndices;
+                            double* pFoundLast = pI + indices.Length;
+                            while (tmpIn < lastElement && pI < pFoundLast) {
+                                if (*tmpIn != 0)
+                                    *pI++ = (double)(tmpIn - pX);
+                                tmpIn++;
+                            }
+                            foundIdx = (int)(pI - pIndices);
+                        }
+                    }
+                } else {
+                    // search backwards 
+                    unsafe {
+                        fixed (double* pIndices = indices)
+                        fixed ( byte* pX = A.GetArrayForRead()) {
+                           
+                            byte* lastElementX = pX;
+                           
+                            byte* tmpIn = pX + inDim.NumberOfElements;
+                            double* pI = pIndices + indices.Length;
+                            while (tmpIn > lastElementX && pI > pIndices) {
+                                tmpIn--;
+                                if (*tmpIn != 0)
+                                    *(--pI) = (double)(tmpIn - pX);
+                            }
+                            foundIdx = (int)(pIndices + indices.Length - pI);
+                        }
+                    }
+                }
+                if (foundIdx == 0) {
+                    return empty();
+                }
+                // transform to row / columns; extract values if needed
+                int leadDimLen = inDim[0];
+                if (create_row_columns) {
+                    #region RETURN ROWS / COLUMNS /VALUES
+                    C.a = new ILRetArray<double>(ILMemoryPool.Pool.New<double>(foundIdx), foundIdx, 1);
+                    ret.a = new ILRetArray<double>(ILMemoryPool.Pool.New<double>(foundIdx), foundIdx, 1);
+                    if (return_values) {
+                        V.a = new ILRetArray< byte>(ILMemoryPool.Pool.New<  byte>(foundIdx), foundIdx, 1);
+                        // copy values, transform to row/columns
+                        unsafe {
+                            fixed (double* pIndices = indices,
+                                   pRows = ret.GetArrayForWrite(), pCols = C.GetArrayForWrite())
+                            fixed ( byte* pValues = V.GetArrayForWrite(), pInput = A.GetArrayForRead()) {
+                                double* pI = (limit >= 0) ?
+                                        pIndices : (pIndices + indices.Length - foundIdx);
+                                double* pLastIndex = pI + foundIdx;
+                                double* pR = pRows;
+                                double* pC = pCols;
+                               
+                                byte* pV = pValues;
+                               
+                                byte* pX = pInput;
+                                while (pI < pLastIndex) {
+                                    *pR++ = *(pI) % leadDimLen;
+                                    *pC++ = (int)*(pI) / leadDimLen;
+                                    *pV++ = *(pInput + (int)*pI++);
+                                }
+                            }
+                        }
+                    } else {
+                        // just return row / columns 
+                        unsafe {
+                            fixed (double* pIndices = indices,
+                                   pRows = ret.GetArrayForWrite(), pCols = C.GetArrayForWrite())
+                            fixed ( byte* pInput = A.GetArrayForRead()) {
+                                double* pI = (limit >= 0) ?
+                                        pIndices : (pIndices + indices.Length - foundIdx);
+                                double* pLastIndex = pI + foundIdx;
+                                double* pR = pRows;
+                                double* pC = pCols;
+                                while (pI < pLastIndex) {
+                                    *pR++ = *(pI) % leadDimLen;
+                                    *pC++ = (int)(*(pI++) / leadDimLen);
+                                }
+                            }
+                        }
+                    }
+                    #endregion RETURN ROWS / COLUMNS
+                } else {
+                    #region RETURN INDICES ONLY
+                    if (foundIdx != indices.Length) {
+                        ret.a = new ILRetArray<double>(ILMemoryPool.Pool.New<double>(foundIdx), foundIdx, 1);
+                        unsafe {
+                            fixed (double* pIndices = indices, pRows = ret.GetArrayForWrite()) {
+                                double* pI = (limit >= 0) ?
+                                        pIndices : (pIndices + indices.Length - foundIdx);
+                                double* pLastIndex = pI + foundIdx;
+                                double* pR = pRows;
+                                while (pI < pLastIndex) {
+                                    *pR++ = *pI++;
+                                }
+                            }
+                        }
+                    } else {
+                        ret.a = new ILRetArray<double>(indices, foundIdx, 1);
+                    }
+                    #endregion RETURN INDICES ONLY
+                }
+                return ret;
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+        #region logicals 
+        /// <summary>
+        /// Find nonzero elements in A
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="limit">Number of elements to search for. If this value is <![CDATA[< 0]]> the function 
+        /// will return at most 'limit' nonzero elements from the end of the array ordered by ascending index.
+        /// Set to 0 to search full array (default).</param>
+        /// <param name="C">If not null, the function will return the row indices of nonzero elements 
+        /// as main return value. C will therefore hold the column indices of those elements. If A
+        /// has more than 2 dimensions, the column indices will go along the 2nd dimension.</param>
+        /// <param name="V">If not null on entrance, V will hold a copy of the values of nonzero elements returned.</param>
+        /// <returns>Vector containing (sequential) indices of nonzero elements in A. If C was 
+        /// not null, return value will contain row indices of nonzero elements. </returns>
+        /// <remarks>The return type of the index vectors is always 'double'. The return type 
+        /// of the element vector 'V' depends on the type of input array A. V and C may be null on 
+        /// entrance, indicating their information is not needed. If V is not null (e.g. 'empty()') C must be 
+        /// not null also. Any initial data of V or C will be lost.</remarks>
+        public static ILRetArray<double> find(ILInLogical A, int limit,
+                        ILOutArray<double> C, ILOutLogical V) {
+            using (ILScope.Enter(A)) {
+                if (isnullorempty(A)) {
+                    if (!isnull(V)) {
+                        V.a = new ILLogical(ILSize.Empty00);
+                    }
+                    return empty();
+                }
+                ILArray<byte> tmpA = new ILArray<byte>(A.Storage);
+                ILArray<byte> tmpV = null;
+                if (!isnull(V)) {
+                    tmpV = new ILArray<byte>(V.Storage);
+                }
+                ILArray<double> ret = find(tmpA, limit, C, tmpV);
+                if (!isnull(tmpV)) {
+                    V.a = new ILLogical(new ILLogicalStorage( tmpV.Storage.GetDataArray(), tmpV.S));
+                }
+                return ret; 
+            }
+        }
+
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/Horzcat.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/Horzcat.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/Horzcat.cs	(revision 9102)
@@ -0,0 +1,162 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions;
+
+
+
+namespace ILNumerics {
+    public partial class ILMath {
+
+
+        /// <summary>
+        /// Horizontal array concatenation 
+        /// </summary>
+        /// <param name="arrays">Arrays to be concatenated with each other. All
+        /// arrays must be of the same inner type. The dimensions of all arrays 
+        /// must match - except for the second dimension (index 1).</param>
+        /// <returns>Larger array having all arrays in 'arrays' placed next to each other.
+        /// </returns>
+        public static ILRetArray<double> horzcat(params ILInArray<double>[] arrays) {
+            return horzcat<double>(arrays); 
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// Horizontal array concatenation 
+        /// </summary>
+        /// <param name="arrays">Arrays to be concatenated with each other. All
+        /// arrays must be of the same inner type. The dimensions of all arrays 
+        /// must match - except for the second dimension (index 1).</param>
+        /// <returns>Larger array having all arrays in 'arrays' placed next to each other.
+        /// </returns>
+        public static ILRetArray<fcomplex> horzcat(params ILInArray<fcomplex>[] arrays) {
+            return horzcat<fcomplex>(arrays); 
+        }
+        /// <summary>
+        /// Horizontal array concatenation 
+        /// </summary>
+        /// <param name="arrays">Arrays to be concatenated with each other. All
+        /// arrays must be of the same inner type. The dimensions of all arrays 
+        /// must match - except for the second dimension (index 1).</param>
+        /// <returns>Larger array having all arrays in 'arrays' placed next to each other.
+        /// </returns>
+        public static ILRetArray<complex> horzcat(params ILInArray<complex>[] arrays) {
+            return horzcat<complex>(arrays); 
+        }
+        /// <summary>
+        /// Horizontal array concatenation 
+        /// </summary>
+        /// <param name="arrays">Arrays to be concatenated with each other. All
+        /// arrays must be of the same inner type. The dimensions of all arrays 
+        /// must match - except for the second dimension (index 1).</param>
+        /// <returns>Larger array having all arrays in 'arrays' placed next to each other.
+        /// </returns>
+        public static ILRetArray<byte> horzcat(params ILInArray<byte>[] arrays) {
+            return horzcat<byte>(arrays); 
+        }
+        /// <summary>
+        /// Horizontal array concatenation 
+        /// </summary>
+        /// <param name="arrays">Arrays to be concatenated with each other. All
+        /// arrays must be of the same inner type. The dimensions of all arrays 
+        /// must match - except for the second dimension (index 1).</param>
+        /// <returns>Larger array having all arrays in 'arrays' placed next to each other.
+        /// </returns>
+        public static ILRetArray<Int64> horzcat(params ILInArray<Int64>[] arrays) {
+            return horzcat<Int64>(arrays); 
+        }
+        /// <summary>
+        /// Horizontal array concatenation 
+        /// </summary>
+        /// <param name="arrays">Arrays to be concatenated with each other. All
+        /// arrays must be of the same inner type. The dimensions of all arrays 
+        /// must match - except for the second dimension (index 1).</param>
+        /// <returns>Larger array having all arrays in 'arrays' placed next to each other.
+        /// </returns>
+        public static ILRetArray<Int32> horzcat(params ILInArray<Int32>[] arrays) {
+            return horzcat<Int32>(arrays); 
+        }
+        /// <summary>
+        /// Horizontal array concatenation 
+        /// </summary>
+        /// <param name="arrays">Arrays to be concatenated with each other. All
+        /// arrays must be of the same inner type. The dimensions of all arrays 
+        /// must match - except for the second dimension (index 1).</param>
+        /// <returns>Larger array having all arrays in 'arrays' placed next to each other.
+        /// </returns>
+        public static ILRetArray<float> horzcat(params ILInArray<float>[] arrays) {
+            return horzcat<float>(arrays); 
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// Horizontal array concatenation 
+        /// </summary>
+        /// <param name="arrays">Arrays to be concatenated with each other. All
+        /// arrays must be of the same inner type. The dimensions of all arrays 
+        /// must match - except for the second dimension (index 1).</param>
+        /// <returns>Larger array having all arrays in 'arrays' placed next to each other.
+        /// </returns>
+        public static ILRetArray<T> horzcat<T>(params ILInArray<T>[] arrays) {
+            using (ILScope.Enter(arrays)) {
+                if (arrays == null)
+                    throw new ILArgumentException("input argument must not be null!");
+                if (arrays.Length == 0 || object.Equals(arrays[0], null))
+                    return ILRetArray<T>.empty(ILSize.Empty00);
+                if (arrays.Length == 1)
+                    return arrays[0].C;
+                ILDenseStorage<T> ret = arrays[0].Storage.Concat(arrays[1].Storage, 1);
+                for (int i = 2; i < arrays.Length; i++) {
+                    ILDenseStorage<T> tmp = ret.Concat(arrays[i].Storage, 1);
+                    ret.Dispose();
+                    ret = tmp;
+                }
+                return new ILRetArray<T>(ret);
+            }
+        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/Invert.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/Invert.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/Invert.cs	(revision 9102)
@@ -0,0 +1,392 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using ILNumerics;
+using ILNumerics.Misc;
+using ILNumerics.Storage;
+using ILNumerics.Native;
+using ILNumerics.Exceptions;
+
+/////   this is a template for unary - inplace functions 
+
+
+
+namespace ILNumerics {
+
+    public partial class ILMath {         
+         
+
+        /// <summary>
+        /// Invert elements of A, return result into predefined output array
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="outArray">Predefined array for results</param>
+        public static void  invert(ILInArray<double> A, ILOutArray<double> outArray) {
+            using (ILScope.Enter(A)) {
+                ILSize inDim = A.Size;
+                if (object.Equals(outArray,null))
+                    throw new ILArgumentException("output parameter 'outArray' must not be null but reference existing array");
+
+                bool inplace = true; 
+                int outLen = A.S.NumberOfElements; 
+                ILSize outDims = A.S; 
+                 double[] retArr = outArray.GetArrayForWrite(); 
+                 double[] aArr = A.GetArrayForRead();
+                if (outArray.S.NumberOfElements != outLen 
+                    && !A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILNumerics.ILMemoryPool.Pool.New<double>(outLen); 
+                    inplace = false; 
+                }
+                unsafe {
+                    fixed ( double* inA2 =retArr)
+                    fixed ( double* inA1 = aArr) {
+                        
+                        double* pInA1 = inA1;
+                        
+                        double* pInA2 = inA2;
+                        
+                        double* outEnd = inA2 + outLen;
+                        if (!inplace) {
+                            while (pInA2 < outEnd) {  //HC11
+                                
+                                *pInA2++ =  /*dummy*/ (*pInA1++ /*HC:HCoperation*/ * (-1.0)/*dummy*/);
+                            }
+                        } else {
+                            while (pInA2 < outEnd) {  //HC11
+                                *pInA2 =  /*dummy*/ (*pInA2 /*HC:HCoperation*/ * (-1.0)/*dummy*/);
+                                pInA2++; 
+                            }
+                        }
+                    }
+                }
+                outArray.a = new ILRetArray< double>(new ILDenseStorage< double>(retArr, outDims)); 
+                return;
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// Invert elements of A, return result into predefined output array
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="outArray">Predefined array for results</param>
+        public static void  invert(ILInArray<byte> A, ILOutArray<byte> outArray) {
+            using (ILScope.Enter(A)) {
+                ILSize inDim = A.Size;
+                if (object.Equals(outArray,null))
+                    throw new ILArgumentException("output parameter 'outArray' must not be null but reference existing array");
+
+                bool inplace = true; 
+                int outLen = A.S.NumberOfElements; 
+                ILSize outDims = A.S; 
+                byte[] retArr = outArray.GetArrayForWrite(); 
+                byte[] aArr = A.GetArrayForRead();
+                if (outArray.S.NumberOfElements != outLen 
+                    && !A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILNumerics.ILMemoryPool.Pool.New<byte>(outLen); 
+                    inplace = false; 
+                }
+                unsafe {
+                    fixed ( byte* inA2 =retArr)
+                    fixed ( byte* inA1 = aArr) {
+                       
+                        byte* pInA1 = inA1;
+                       
+                        byte* pInA2 = inA2;
+                       
+                        byte* outEnd = inA2 + outLen;
+                        if (!inplace) {
+                            while (pInA2 < outEnd) {  //HC11
+                               
+                                *pInA2++ =  (byte) (*pInA1++ /*HC:*/ *(-1)/*dummy*/);
+                            }
+                        } else {
+                            while (pInA2 < outEnd) {  //HC11
+                                *pInA2 =  (byte) (*pInA2 /*HC:*/ *(-1)/*dummy*/);
+                                pInA2++; 
+                            }
+                        }
+                    }
+                }
+                outArray.a = new ILRetArray< byte>(new ILDenseStorage< byte>(retArr, outDims)); 
+                return;
+            }
+        }
+        /// <summary>
+        /// Invert elements of A, return result into predefined output array
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="outArray">Predefined array for results</param>
+        public static void  invert(ILInArray<Int64> A, ILOutArray<Int64> outArray) {
+            using (ILScope.Enter(A)) {
+                ILSize inDim = A.Size;
+                if (object.Equals(outArray,null))
+                    throw new ILArgumentException("output parameter 'outArray' must not be null but reference existing array");
+
+                bool inplace = true; 
+                int outLen = A.S.NumberOfElements; 
+                ILSize outDims = A.S; 
+                Int64[] retArr = outArray.GetArrayForWrite(); 
+                Int64[] aArr = A.GetArrayForRead();
+                if (outArray.S.NumberOfElements != outLen 
+                    && !A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILNumerics.ILMemoryPool.Pool.New<Int64>(outLen); 
+                    inplace = false; 
+                }
+                unsafe {
+                    fixed ( Int64* inA2 =retArr)
+                    fixed ( Int64* inA1 = aArr) {
+                       
+                        Int64* pInA1 = inA1;
+                       
+                        Int64* pInA2 = inA2;
+                       
+                        Int64* outEnd = inA2 + outLen;
+                        if (!inplace) {
+                            while (pInA2 < outEnd) {  //HC11
+                               
+                                *pInA2++ =   (*pInA1++ /*HC:*/ *(-1)/*dummy*/);
+                            }
+                        } else {
+                            while (pInA2 < outEnd) {  //HC11
+                                *pInA2 =   (*pInA2 /*HC:*/ *(-1)/*dummy*/);
+                                pInA2++; 
+                            }
+                        }
+                    }
+                }
+                outArray.a = new ILRetArray< Int64>(new ILDenseStorage< Int64>(retArr, outDims)); 
+                return;
+            }
+        }
+        /// <summary>
+        /// Invert elements of A, return result into predefined output array
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="outArray">Predefined array for results</param>
+        public static void  invert(ILInArray<Int32> A, ILOutArray<Int32> outArray) {
+            using (ILScope.Enter(A)) {
+                ILSize inDim = A.Size;
+                if (object.Equals(outArray,null))
+                    throw new ILArgumentException("output parameter 'outArray' must not be null but reference existing array");
+
+                bool inplace = true; 
+                int outLen = A.S.NumberOfElements; 
+                ILSize outDims = A.S; 
+                Int32[] retArr = outArray.GetArrayForWrite(); 
+                Int32[] aArr = A.GetArrayForRead();
+                if (outArray.S.NumberOfElements != outLen 
+                    && !A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILNumerics.ILMemoryPool.Pool.New<Int32>(outLen); 
+                    inplace = false; 
+                }
+                unsafe {
+                    fixed ( Int32* inA2 =retArr)
+                    fixed ( Int32* inA1 = aArr) {
+                       
+                        Int32* pInA1 = inA1;
+                       
+                        Int32* pInA2 = inA2;
+                       
+                        Int32* outEnd = inA2 + outLen;
+                        if (!inplace) {
+                            while (pInA2 < outEnd) {  //HC11
+                               
+                                *pInA2++ =   (*pInA1++ /*HC:*/ *(-1)/*dummy*/);
+                            }
+                        } else {
+                            while (pInA2 < outEnd) {  //HC11
+                                *pInA2 =   (*pInA2 /*HC:*/ *(-1)/*dummy*/);
+                                pInA2++; 
+                            }
+                        }
+                    }
+                }
+                outArray.a = new ILRetArray< Int32>(new ILDenseStorage< Int32>(retArr, outDims)); 
+                return;
+            }
+        }
+        /// <summary>
+        /// Invert elements of A, return result into predefined output array
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="outArray">Predefined array for results</param>
+        public static void  invert(ILInArray<float> A, ILOutArray<float> outArray) {
+            using (ILScope.Enter(A)) {
+                ILSize inDim = A.Size;
+                if (object.Equals(outArray,null))
+                    throw new ILArgumentException("output parameter 'outArray' must not be null but reference existing array");
+
+                bool inplace = true; 
+                int outLen = A.S.NumberOfElements; 
+                ILSize outDims = A.S; 
+                float[] retArr = outArray.GetArrayForWrite(); 
+                float[] aArr = A.GetArrayForRead();
+                if (outArray.S.NumberOfElements != outLen 
+                    && !A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILNumerics.ILMemoryPool.Pool.New<float>(outLen); 
+                    inplace = false; 
+                }
+                unsafe {
+                    fixed ( float* inA2 =retArr)
+                    fixed ( float* inA1 = aArr) {
+                       
+                        float* pInA1 = inA1;
+                       
+                        float* pInA2 = inA2;
+                       
+                        float* outEnd = inA2 + outLen;
+                        if (!inplace) {
+                            while (pInA2 < outEnd) {  //HC11
+                               
+                                *pInA2++ =   (*pInA1++ /*HC:*/ *(-1.0f)/*dummy*/);
+                            }
+                        } else {
+                            while (pInA2 < outEnd) {  //HC11
+                                *pInA2 =   (*pInA2 /*HC:*/ *(-1.0f)/*dummy*/);
+                                pInA2++; 
+                            }
+                        }
+                    }
+                }
+                outArray.a = new ILRetArray< float>(new ILDenseStorage< float>(retArr, outDims)); 
+                return;
+            }
+        }
+        /// <summary>
+        /// Invert elements of A, return result into predefined output array
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="outArray">Predefined array for results</param>
+        public static void  invert(ILInArray<fcomplex> A, ILOutArray<fcomplex> outArray) {
+            using (ILScope.Enter(A)) {
+                ILSize inDim = A.Size;
+                if (object.Equals(outArray,null))
+                    throw new ILArgumentException("output parameter 'outArray' must not be null but reference existing array");
+
+                bool inplace = true; 
+                int outLen = A.S.NumberOfElements; 
+                ILSize outDims = A.S; 
+                fcomplex[] retArr = outArray.GetArrayForWrite(); 
+                fcomplex[] aArr = A.GetArrayForRead();
+                if (outArray.S.NumberOfElements != outLen 
+                    && !A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILNumerics.ILMemoryPool.Pool.New<fcomplex>(outLen); 
+                    inplace = false; 
+                }
+                unsafe {
+                    fixed ( fcomplex* inA2 =retArr)
+                    fixed ( fcomplex* inA1 = aArr) {
+                       
+                        fcomplex* pInA1 = inA1;
+                       
+                        fcomplex* pInA2 = inA2;
+                       
+                        fcomplex* outEnd = inA2 + outLen;
+                        if (!inplace) {
+                            while (pInA2 < outEnd) {  //HC11
+                               
+                                *pInA2++ =   (*pInA1++ /*HC:*/ *(-1.0f)/*dummy*/);
+                            }
+                        } else {
+                            while (pInA2 < outEnd) {  //HC11
+                                *pInA2 =   (*pInA2 /*HC:*/ *(-1.0f)/*dummy*/);
+                                pInA2++; 
+                            }
+                        }
+                    }
+                }
+                outArray.a = new ILRetArray< fcomplex>(new ILDenseStorage< fcomplex>(retArr, outDims)); 
+                return;
+            }
+        }
+        /// <summary>
+        /// Invert elements of A, return result into predefined output array
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="outArray">Predefined array for results</param>
+        public static void  invert(ILInArray<complex> A, ILOutArray<complex> outArray) {
+            using (ILScope.Enter(A)) {
+                ILSize inDim = A.Size;
+                if (object.Equals(outArray,null))
+                    throw new ILArgumentException("output parameter 'outArray' must not be null but reference existing array");
+
+                bool inplace = true; 
+                int outLen = A.S.NumberOfElements; 
+                ILSize outDims = A.S; 
+                complex[] retArr = outArray.GetArrayForWrite(); 
+                complex[] aArr = A.GetArrayForRead();
+                if (outArray.S.NumberOfElements != outLen 
+                    && !A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILNumerics.ILMemoryPool.Pool.New<complex>(outLen); 
+                    inplace = false; 
+                }
+                unsafe {
+                    fixed ( complex* inA2 =retArr)
+                    fixed ( complex* inA1 = aArr) {
+                       
+                        complex* pInA1 = inA1;
+                       
+                        complex* pInA2 = inA2;
+                       
+                        complex* outEnd = inA2 + outLen;
+                        if (!inplace) {
+                            while (pInA2 < outEnd) {  //HC11
+                               
+                                *pInA2++ =   (*pInA1++ /*HC:*/ *(-1.0)/*dummy*/);
+                            }
+                        } else {
+                            while (pInA2 < outEnd) {  //HC11
+                                *pInA2 =   (*pInA2 /*HC:*/ *(-1.0)/*dummy*/);
+                                pInA2++; 
+                            }
+                        }
+                    }
+                }
+                outArray.a = new ILRetArray< complex>(new ILDenseStorage< complex>(retArr, outDims)); 
+                return;
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/ManMatMult.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/ManMatMult.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/ManMatMult.cs	(revision 9102)
@@ -0,0 +1,325 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using ILNumerics.Misc; 
+
+namespace ILNumerics {
+
+    public partial class ILMath {
+        #region managed mult 
+        unsafe public static void MMultBlockedThreaded(double[] A, double[] B, double[] C, int m, int n, int k, int kc) {
+
+            // block parameters
+            int mc = 512;
+            int mr = 4;
+            int nr = 4;
+
+            double[] CAux = ILMemoryPool.Pool.New<double>(mc + ALIGN / sizeof(double));
+            double[] Bpack1 = ILMemoryPool.Pool.New<double>(kc * (n) + ALIGN / sizeof(double));
+            double[] Apack1 = ILMemoryPool.Pool.New<double>(kc * mc + ALIGN / sizeof(double));
+            double[] Bpack2 = ILMemoryPool.Pool.New<double>(kc * (n) + ALIGN / sizeof(double));
+            double[] Apack2 = ILMemoryPool.Pool.New<double>(kc * mc + ALIGN / sizeof(double));
+            fixed (double* pAArr = A)
+            fixed (double* pBArr = B)
+            fixed (double* pCArr = C)
+            fixed (double* pBpack1 = Bpack1)
+            fixed (double* pApack1 = Apack1)
+            fixed (double* pBpack2 = Bpack2)
+            fixed (double* pApack2 = Apack2) {
+
+                int workerCount = 1;
+                Action<object> func = data => {
+                    MatMultArguments args = (MatMultArguments)data; 
+                    inner_k_loop_managed(m, n, k, kc, mc, mr, nr,
+                                 (double*)args.pArr, (double*)args.pBrr, (double*)args.pCrr, (double*)args.pBPack, (double*)args.pAPack, 
+                                 args.n_start, args.n_end, args.m_start, args.m_end);
+                    //inner_k_loop(args.Item1, args.Item2, args.Item3, args.Item4, args.Item5, args.Item6, args.Item7,
+                    //             args.Rest.Item1, args.Rest.Item2, args.Rest.Item3, args.Rest.Item4, args.Rest.Item5,
+                    //             args.Rest.Item6, args.Rest.Item7);
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                MatMultArguments args4Thread; // = new MatMultArguments();
+                args4Thread.pArr = (IntPtr)pAArr;
+                args4Thread.pBrr = (IntPtr)pBArr;
+                args4Thread.pCrr = (IntPtr)pCArr;
+                args4Thread.pAPack = (IntPtr)pApack1;
+                args4Thread.pBPack = (IntPtr)pBpack1;
+                args4Thread.n_start = 0;
+                args4Thread.n_end = (int)(n / 2);
+                args4Thread.m_start = 0;
+                args4Thread.m_end = m;
+                ILNumerics.Misc.ILThreadPool.QueueUserWorkItem(0, func, args4Thread);
+
+                //inner_k_loop(m, n, k, kc, mc, mr, nr, (IntPtr)pAArr, (IntPtr)pBArr, (IntPtr)pCArr, (IntPtr)pBpack2, (IntPtr)pApack2, n / 2, n);
+                inner_k_loop_managed(m, n, k, kc, mc, mr, nr, pAArr, pBArr, pCArr, pBpack2, pApack2, (int)(n / 2), n, 0, m);
+                ILThreadPool.Wait4Workers(ref workerCount);
+
+            }
+        }
+        unsafe public static void MMultBlocked(double[] A, double[] B, double[] C, int m, int n, int k, int kc) {
+
+            // block parameters
+            int mc = 512;
+            int mr = 4;
+            int nr = 4;
+
+            double[] CAux = ILMemoryPool.Pool.New<double>(mc + ALIGN / sizeof(double));
+            double[] Bpack1 = ILMemoryPool.Pool.New<double>(kc * (n) + ALIGN / sizeof(double));
+            double[] Apack1 = ILMemoryPool.Pool.New<double>(kc * mc + ALIGN / sizeof(double));
+            double[] Bpack2 = ILMemoryPool.Pool.New<double>(kc * (n) + ALIGN / sizeof(double));
+            double[] Apack2 = ILMemoryPool.Pool.New<double>(kc * mc + ALIGN / sizeof(double));
+            fixed (double* pAArr = A)
+            fixed (double* pBArr = B)
+            fixed (double* pCArr = C)
+            fixed (double* pBpack1 = Bpack1)
+            fixed (double* pApack1 = Apack1)
+            fixed (double* pBpack2 = Bpack2)
+            fixed (double* pApack2 = Apack2) {
+
+                inner_k_loop_managed(m, n, k, kc, mc, mr, nr, pAArr, pBArr, pCArr, pBpack2, pApack2, 0, n, 0, m);
+
+            }
+        }
+
+        unsafe private static void inner_k_loop_managed(int m, int n, int k, int kc, int mc, int mr, int nr,
+                                            double* pAArr, double* pBArr, double* pCArr, double* pBpack, double* pApack,
+                                            int n_start, int n_end, int m_start, int m_end) {
+
+            double* pApackTmp = (double*)((byte*)pApack + (ALIGN - ((uint)pApack % ALIGN)));
+            double* pBpackTmp = (double*)((byte*)pBpack + (ALIGN - ((uint)pBpack % ALIGN)));
+            double* pCArrTmp, pBArrTmp, pAArrTmp;
+
+            int n_len = n_end - n_start;
+            for (int ki = 0; ki < k; ki += kc) {
+                if (k - ki < kc) kc = k - ki;
+
+                #region pack B
+                pBpackTmp = pBpack;
+                for (int nb = 0; nb < n_len; nb++) {
+                    pBArrTmp = pBArr + ki + k * (nb + n_start);
+                    int c = 0;
+                    for (; c < kc - 8; c += 8) {
+                        pBpackTmp[0] = pBArrTmp[0];
+                        pBpackTmp[1] = pBArrTmp[1];
+                        pBpackTmp[2] = pBArrTmp[2];
+                        pBpackTmp[3] = pBArrTmp[3];
+                        pBpackTmp[4] = pBArrTmp[4];
+                        pBpackTmp[5] = pBArrTmp[5];
+                        pBpackTmp[6] = pBArrTmp[6];
+                        pBpackTmp[7] = pBArrTmp[7];
+                        pBpackTmp += 8; pBArrTmp += 8;
+                    }
+                    for (; c < kc; c++) {
+                        *pBpackTmp++ = *pBArrTmp++;
+                    }
+                }
+                //pack(BArr, Bpack, r, 0, kc, n, k);
+                #endregion
+
+                int mcc = mc;
+                int m_len = m_end - m_start; 
+                for (int ai = 0; ai < m_len; ai += mcc) {
+                    if (m_len - ai < mcc) mcc = m_len - ai;
+
+                    #region pack A
+                    for (int ca = 0; ca < kc; ca++) {
+                        pApackTmp = pApack + ca;
+                        pAArrTmp = pAArr + ai + m * (m_start + ki + ca);
+                        int ra = 0;
+                        for (; ra < mcc - 8; ra += 8) {
+                            pApackTmp[(ra) * kc] = pAArrTmp[0];
+                            pApackTmp[(ra + 1) * kc] = pAArrTmp[1];
+                            pApackTmp[(ra + 2) * kc] = pAArrTmp[2];
+                            pApackTmp[(ra + 3) * kc] = pAArrTmp[3];
+                            pApackTmp[(ra + 4) * kc] = pAArrTmp[4];
+                            pApackTmp[(ra + 5) * kc] = pAArrTmp[5];
+                            pApackTmp[(ra + 6) * kc] = pAArrTmp[6];
+                            pApackTmp[(ra + 7) * kc] = pAArrTmp[7];
+                            pAArrTmp += 8;
+                        }
+                        for (; ra < mcc; ra++) {
+                            pApackTmp[ra * kc] = *pAArrTmp++;
+                        }
+                    }
+                    #endregion
+
+                    #region subblocked
+                    int nrLen = nr;
+                    for (int nri = 0; nri < n_len; nri += nrLen) {
+                        if (n_len - nri < nrLen) nrLen = n_len - nri;
+                        int mrLen = mr;
+                        for (int mri = 0; mri < mcc; mri += mrLen) {
+                            if (mcc - mri < mrLen) mrLen = mcc - mri;
+
+                            // prefetch CAux 
+
+
+                            if (false && mrLen == 4 && nrLen == 4) {
+
+                            } else {
+                                for (int nii = 0; nii < nrLen; nii++) {
+                                    pCArrTmp = pCArr + ai + mri + (nri + nii + n_start) * m;
+                                    //for (int mii = 0; mii < mrLen; mii++) {
+                                    //    pCAux[mii] = pCArrTmp[mii];
+                                    //}
+                                    for (int mii = 0; mii < mrLen; mii++) {
+                                        pApackTmp = pApack + (mri + mii) * kc; // <-- transposed packed!
+                                        pBpackTmp = pBpack + (nri + nii) * kc;
+                                        double sum = 0;
+                                        int jj = 0;
+                                        for (; jj < kc - 8; jj += 8) {
+                                            sum += pApackTmp[0] * pBpackTmp[0]
+                                                + pApackTmp[1] * pBpackTmp[1]
+                                                + pApackTmp[2] * pBpackTmp[2]
+                                                + pApackTmp[3] * pBpackTmp[3]
+                                                + pApackTmp[4] * pBpackTmp[4]
+                                                + pApackTmp[5] * pBpackTmp[5]
+                                                + pApackTmp[6] * pBpackTmp[6]
+                                                + pApackTmp[7] * pBpackTmp[7];
+                                            pApackTmp += 8;
+                                            pBpackTmp += 8;
+                                        }
+                                        for (; jj < kc; jj++) {
+                                            sum += *pApackTmp++ * *pBpackTmp++;
+                                        }
+                                        //CAux[ra] = sum;
+                                        pCArrTmp[mii] += sum;
+                                    }
+                                    //for (int mii = 0; mii < mrLen; mii++) {
+                                    //    pCArrTmp[mii] = pCAux[mii];
+                                    //}
+
+                                }
+
+                            }
+                        }
+
+                    }
+                    #endregion
+
+                    #region standard mmult
+                    //for (int bj = 0; bj < n_len; bj++) {
+                    //    pCArrTmp = pCArr + m_start + ai + (bj + n_start) * m;
+                    //    for (int ra = 0; ra < mcc; ra++) {
+                    //        pApackTmp = pApack + ra * kc;
+                    //        pBpackTmp = pBpack + bj * kc;
+                    //        double sum = 0;
+                    //        int jj = 0;
+                    //        for (; jj < kc - 24; jj += 24) {
+                    //            sum += pApackTmp[0] * pBpackTmp[0]
+                    //                + pApackTmp[1] * pBpackTmp[1]
+                    //                + pApackTmp[2] * pBpackTmp[2]
+                    //                + pApackTmp[3] * pBpackTmp[3]
+                    //                + pApackTmp[4] * pBpackTmp[4]
+                    //                + pApackTmp[5] * pBpackTmp[5]
+                    //                + pApackTmp[6] * pBpackTmp[6]
+                    //                + pApackTmp[7] * pBpackTmp[7]
+                    //                + pApackTmp[8] * pBpackTmp[8]
+                    //                + pApackTmp[9] * pBpackTmp[9]
+                    //                + pApackTmp[10] * pBpackTmp[10]
+                    //                + pApackTmp[11] * pBpackTmp[11]
+                    //                + pApackTmp[12] * pBpackTmp[12]
+                    //                + pApackTmp[13] * pBpackTmp[13]
+                    //                + pApackTmp[14] * pBpackTmp[14]
+                    //                + pApackTmp[15] * pBpackTmp[15]
+                    //                + pApackTmp[16] * pBpackTmp[16]
+                    //                + pApackTmp[17] * pBpackTmp[17]
+                    //                + pApackTmp[18] * pBpackTmp[18]
+                    //                + pApackTmp[19] * pBpackTmp[19]
+                    //                + pApackTmp[20] * pBpackTmp[20]
+                    //                + pApackTmp[21] * pBpackTmp[21]
+                    //                + pApackTmp[22] * pBpackTmp[22]
+                    //                + pApackTmp[23] * pBpackTmp[23];
+                    //            pApackTmp += 24; pBpackTmp += 24; 
+                    //        }
+                    //        for (; jj < kc; jj++) {
+                    //            sum += *pApackTmp++ * *pBpackTmp++;
+                    //        }
+                    //        pCArrTmp[ra] += sum;
+                    //    }
+                    //}
+                    #endregion
+                    #region unblocked fast mult  (NOT CORRECT! would require A to be NOT transposed!)
+                    //double* pYA, pXA, pZA;
+                    //for (int i = 0; i < n; i++) {
+                    //    pYA = pBpack + kc * i;
+                    //    pXA = pApack;
+                    //    for (int kcl = 0; kcl < kc; kcl++) {
+                    //        double r = *pYA++;
+                    //        //double r = Y[k + N * i];
+                    //        pZA = pCArr + ai + m * i;
+                    //        int j = 0;
+                    //        for (; j < mcc - 16; j += 16) {
+                    //            //double c0 = pZA[0], c1 = pZA[1], c2 = pZA[2], c3 = pZA[3], c4 = pZA[4], c5 = pZA[5], c6 = pZA[6], c7 = pZA[7];
+                    //            pZA[0] += r * pXA[0];
+                    //            pZA[1] += r * pXA[1];
+                    //            pZA[2] += r * pXA[2];
+                    //            pZA[3] += r * pXA[3];
+                    //            pZA[4] += r * pXA[4];
+                    //            pZA[5] += r * pXA[5];
+                    //            pZA[6] += r * pXA[6];
+                    //            pZA[7] += r * pXA[7];
+                    //            pZA[8] += r * pXA[8];
+                    //            pZA[9] += r * pXA[9];
+                    //            pZA[10] += r * pXA[10];
+                    //            pZA[11] += r * pXA[11];
+                    //            pZA[12] += r * pXA[12];
+                    //            pZA[13] += r * pXA[13];
+                    //            pZA[14] += r * pXA[14];
+                    //            pZA[15] += r * pXA[15];
+                    //            pZA += 16; pXA += 16;
+                    //        }
+                    //        while (j++ < mcc) {
+                    //            *pZA++ += *pXA++ * r;
+                    //            //Z[j + N * i] += X[j + N * k] * r;
+                    //        }
+                    //    }
+                    //}
+                    #endregion
+                }
+            }
+        }
+
+        #endregion
+}
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/Max.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/Max.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/Max.cs	(revision 9102)
@@ -0,0 +1,4731 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions;
+
+
+
+namespace ILNumerics {
+
+    public partial class ILMath {
+    
+       
+
+
+        /// <summary>
+        /// Maximum values along specified dimension
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="I">[Optional] If not null I will hold on return the indices into dim of  
+        /// the values found. If, on entering the function, I is null, those indices 
+        /// will not be computed and I will be ignored.</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns>Array of same inner type and size as A, except for dimension 
+        /// 'dim' which will be reduced to length 1.</returns>
+        public static  ILRetArray<double>  max(ILInArray<double> A, ILOutArray<double> I = null, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (A.IsEmpty) {
+                    if (!object.Equals(I, null))
+                        I.a = empty<double>(ILSize.Empty00);
+                    return new  ILRetArray<double>(A.Size); 
+                }
+                if (dim >= A.Size.NumberOfDimensions || A.Size[dim] == 1) {
+                    // scalar or sum over singleton -> return copy
+                    if (!object.Equals(I, null))
+                        I.a = zeros<double>(A.S);
+                    return new ILRetArray<double>(A.C.Storage);
+                }
+                int[] newDims = A.Size.ToIntArray();
+                int leadDimLen = A.Size[dim];
+                int newLength = A.Size.NumberOfElements / leadDimLen;
+                newDims[dim] = 1;
+                
+                double[] retArr = ILMemoryPool.Pool.New< double>(newLength);
+                #region HYCALPER GLOBAL_INIT
+
+                
+                double result;
+                
+                double curval;
+                double[] indices = null;
+                bool createIndices = false;
+                if (!Object.Equals(I, null)) {
+                    indices = ILMemoryPool.Pool.New<double>(newLength);
+                    createIndices = true;
+                }
+                #endregion HYCALPER GLOBAL_INIT
+                #region HYCALPER INIT_COMPLEX
+
+                #endregion HYCALPER INIT_COMPLEX
+
+                // physical -> pointer arithmetic
+                if (dim == 0) {
+                    #region physical along 1st leading dimension
+                    unsafe {
+                        fixed ( double* pOutArr = retArr)
+                        fixed ( double* pInArr = A.GetArrayForRead())
+                        fixed (double* pIndices = indices) {
+                            
+                            double* lastElement;
+                            
+                            double* tmpOut = pOutArr;
+                            
+                            double* tmpIn = pInArr;
+                            if (createIndices) {
+                                double* tmpInd = pIndices;
+                                for (int h = newLength; h-- > 0; ) {
+
+                                    lastElement = tmpIn + leadDimLen;
+
+                                    result = *tmpIn;
+                                    while 
+#pragma warning disable
+                                    (
+                                        
+                                         double.IsNaN(result)
+                                        && ++tmpIn < lastElement) 
+#pragma warning restore
+                                    {
+                                        result = *tmpIn;
+                                        *tmpInd += 1;
+                                    }
+
+
+                                    #region HYCALPER TAKERESULT
+
+                                    #endregion HYCALPER TAKERESULT
+                                    while (tmpIn < lastElement) {
+                                        curval = *tmpIn;
+
+                                        if (curval > result) {
+                                            result = curval;
+
+                                            *tmpInd = (double)(tmpIn - (lastElement - leadDimLen));
+                                        }
+                                        tmpIn++;
+                                    }
+                                    *(tmpOut++) = ( double)result;
+                                    tmpInd++;
+                                }
+                            } else {   // no indices
+                                double* tmpInd = pIndices;
+                                for (int h = newLength; h-- > 0; ) {
+                                    lastElement = tmpIn + leadDimLen;
+
+                                    result = *tmpIn;
+                                    while 
+#pragma warning disable
+                                        (
+                                        
+                                         double.IsNaN(result)
+                                        && ++tmpIn < lastElement) 
+#pragma warning restore
+                                        {
+                                        result = *tmpIn;
+                                    }
+
+                                    #region HYCALPER TAKERESULT
+
+                                    #endregion HYCALPER TAKERESULT
+                                    while (tmpIn < lastElement) {
+                                        curval = *tmpIn++;
+
+                                        if (curval > result) {
+                                            result = curval;
+
+                                        }
+                                    }
+
+                                    *(tmpOut++) = ( double)result;
+
+                                }
+                            }
+                        }
+                    }
+                    #endregion physical along 1st leading dimension
+                } else {
+                    #region physical along abitrary dimension
+                    // sum along abitrary dimension 
+                    unsafe {
+                        fixed ( double* pOutArr = retArr)
+                        fixed ( double* pInArr = A.GetArrayForRead())
+                        fixed (double* pIndices = indices) {
+                            
+                            double* lastElementOut = newLength + pOutArr - 1;
+                            int inLength = A.Size.NumberOfElements - 1;
+                            
+                            double* lastElementIn = pInArr + inLength;
+                            int inc = A.Size.SequentialIndexDistance(dim);
+                            
+                            double* tmpOut = pOutArr;
+                            int outLength = newLength - 1;
+                            
+                            double* leadEnd;
+                            
+                            double* tmpIn = pInArr;
+                            if (createIndices) {
+                                double* tmpInd = pIndices;
+                                for (int h = newLength; h-- > 0; ) {
+                                    leadEnd = tmpIn + leadDimLen * inc;
+
+                                    result = *tmpIn;
+                                    while 
+#pragma warning disable
+                                        (
+                                        
+                                         double.IsNaN(result)
+                                        && (tmpIn += inc) < leadEnd)
+#pragma warning restore                 
+                                    {
+                                        result = *tmpIn;
+                                        *tmpInd += 1;
+                                    }
+
+                                    #region HYCALPER TAKERESULT
+
+                                    #endregion HYCALPER TAKERESULT
+                                    while (tmpIn < leadEnd) {
+                                        curval = *tmpIn;
+
+                                        if (curval > result) {
+                                            result = curval;
+
+                                            *tmpInd = (double)(leadDimLen - (leadEnd - tmpIn) / inc);
+                                        }
+                                        tmpIn += inc;
+                                    }
+
+                                    *(tmpOut) = ( double)result;
+
+                                    tmpOut += inc;
+                                    tmpInd += inc;
+                                    if (tmpOut > lastElementOut) {
+                                        tmpOut -= outLength;
+                                        tmpInd -= outLength;
+                                    }
+                                    if (tmpIn > lastElementIn)
+                                        tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                                }
+                            } else {  // no indices
+                                for (int h = newLength; h-- > 0; ) {
+                                    leadEnd = tmpIn + leadDimLen * inc;
+
+                                    result = *tmpIn;
+                                    while
+#pragma warning disable
+                                    (
+                                        
+                                         double.IsNaN(result)
+                                        && (tmpIn += inc) < leadEnd)
+#pragma warning restore
+                                    {
+                                        result = *tmpIn;
+                                    }
+
+                                    #region HYCALPER TAKERESULT
+
+                                    #endregion HYCALPER TAKERESULT
+                                    while (tmpIn < leadEnd) {
+                                        curval = *tmpIn;
+
+                                        if (curval > result) {
+                                            result = curval;
+
+                                        }
+                                        tmpIn += inc;
+                                    }
+
+                                    *(tmpOut) = ( double)result;
+
+                                    tmpOut += inc;
+                                    if (tmpOut > lastElementOut) {
+                                        tmpOut -= outLength;
+                                    }
+                                    if (tmpIn > lastElementIn)
+                                        tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                                }
+                            }
+                        }
+                    }
+                    #endregion
+                }
+                if (createIndices) {
+                    I.a = array<double>(indices, newDims);
+                }
+                return new ILRetArray<double>(retArr, newDims);
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// Maximum values along specified dimension
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="I">[Optional] If not null I will hold on return the indices into dim of  
+        /// the values found. If, on entering the function, I is null, those indices 
+        /// will not be computed and I will be ignored.</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns>Array of same inner type and size as A, except for dimension 
+        /// 'dim' which will be reduced to length 1.</returns>
+        public static  ILRetArray<Int64>  max(ILInArray<Int64> A, ILOutArray<double> I = null, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (A.IsEmpty) {
+                    if (!object.Equals(I, null))
+                        I.a = empty<double>(ILSize.Empty00);
+                    return new  ILRetArray<Int64>(A.Size); 
+                }
+                if (dim >= A.Size.NumberOfDimensions || A.Size[dim] == 1) {
+                    // scalar or sum over singleton -> return copy
+                    if (!object.Equals(I, null))
+                        I.a = zeros<double>(A.S);
+                    return new ILRetArray<Int64>(A.C.Storage);
+                }
+                int[] newDims = A.Size.ToIntArray();
+                int leadDimLen = A.Size[dim];
+                int newLength = A.Size.NumberOfElements / leadDimLen;
+                newDims[dim] = 1;
+               
+                Int64[] retArr = ILMemoryPool.Pool.New< Int64>(newLength);
+                #region HYCALPER GLOBAL_INIT
+
+               
+                Int64 result;
+               
+                Int64 curval;
+                double[] indices = null;
+                bool createIndices = false;
+                if (!Object.Equals(I, null)) {
+                    indices = ILMemoryPool.Pool.New<double>(newLength);
+                    createIndices = true;
+                }
+                #endregion HYCALPER GLOBAL_INIT
+                
+
+                // physical -> pointer arithmetic
+                if (dim == 0) {
+                    #region physical along 1st leading dimension
+                    unsafe {
+                        fixed ( Int64* pOutArr = retArr)
+                        fixed ( Int64* pInArr = A.GetArrayForRead())
+                        fixed (double* pIndices = indices) {
+                           
+                            Int64* lastElement;
+                           
+                            Int64* tmpOut = pOutArr;
+                           
+                            Int64* tmpIn = pInArr;
+                            if (createIndices) {
+                                double* tmpInd = pIndices;
+                                for (int h = newLength; h-- > 0; ) {
+
+                                    lastElement = tmpIn + leadDimLen;
+
+                                    result = *tmpIn;
+                                    while 
+#pragma warning disable
+                                    (
+                                        false
+                                        && ++tmpIn < lastElement) 
+#pragma warning restore
+                                    {
+                                        result = *tmpIn;
+                                        *tmpInd += 1;
+                                    }
+
+
+                                    
+                                    while (tmpIn < lastElement) {
+                                        curval = *tmpIn;
+                                        if (curval > result) {
+                                                result = curval;
+                                            
+                                            *tmpInd = (double)(tmpIn - (lastElement - leadDimLen));
+                                        }
+                                        tmpIn++;
+                                    }
+                                    *(tmpOut++) = ( Int64)result;
+                                    tmpInd++;
+                                }
+                            } else {   // no indices
+                                double* tmpInd = pIndices;
+                                for (int h = newLength; h-- > 0; ) {
+                                    lastElement = tmpIn + leadDimLen;
+
+                                    result = *tmpIn;
+                                    while 
+#pragma warning disable
+                                        (
+                                        false
+                                        && ++tmpIn < lastElement) 
+#pragma warning restore
+                                        {
+                                        result = *tmpIn;
+                                    }
+
+                                    
+                                    while (tmpIn < lastElement) {
+                                        curval = *tmpIn++;
+                                        if (curval > result) {
+                                                result = curval;
+                                            
+                                        }
+                                    }
+
+                                    *(tmpOut++) = ( Int64)result;
+
+                                }
+                            }
+                        }
+                    }
+                    #endregion physical along 1st leading dimension
+                } else {
+                    #region physical along abitrary dimension
+                    // sum along abitrary dimension 
+                    unsafe {
+                        fixed ( Int64* pOutArr = retArr)
+                        fixed ( Int64* pInArr = A.GetArrayForRead())
+                        fixed (double* pIndices = indices) {
+                           
+                            Int64* lastElementOut = newLength + pOutArr - 1;
+                            int inLength = A.Size.NumberOfElements - 1;
+                           
+                            Int64* lastElementIn = pInArr + inLength;
+                            int inc = A.Size.SequentialIndexDistance(dim);
+                           
+                            Int64* tmpOut = pOutArr;
+                            int outLength = newLength - 1;
+                           
+                            Int64* leadEnd;
+                           
+                            Int64* tmpIn = pInArr;
+                            if (createIndices) {
+                                double* tmpInd = pIndices;
+                                for (int h = newLength; h-- > 0; ) {
+                                    leadEnd = tmpIn + leadDimLen * inc;
+
+                                    result = *tmpIn;
+                                    while 
+#pragma warning disable
+                                        (
+                                        false
+                                        && (tmpIn += inc) < leadEnd)
+#pragma warning restore                 
+                                    {
+                                        result = *tmpIn;
+                                        *tmpInd += 1;
+                                    }
+
+                                    
+                                    while (tmpIn < leadEnd) {
+                                        curval = *tmpIn;
+                                        if (curval > result) {
+                                                result = curval;
+                                            
+                                            *tmpInd = (double)(leadDimLen - (leadEnd - tmpIn) / inc);
+                                        }
+                                        tmpIn += inc;
+                                    }
+
+                                    *(tmpOut) = ( Int64)result;
+
+                                    tmpOut += inc;
+                                    tmpInd += inc;
+                                    if (tmpOut > lastElementOut) {
+                                        tmpOut -= outLength;
+                                        tmpInd -= outLength;
+                                    }
+                                    if (tmpIn > lastElementIn)
+                                        tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                                }
+                            } else {  // no indices
+                                for (int h = newLength; h-- > 0; ) {
+                                    leadEnd = tmpIn + leadDimLen * inc;
+
+                                    result = *tmpIn;
+                                    while
+#pragma warning disable
+                                    (
+                                        false
+                                        && (tmpIn += inc) < leadEnd)
+#pragma warning restore
+                                    {
+                                        result = *tmpIn;
+                                    }
+
+                                    
+                                    while (tmpIn < leadEnd) {
+                                        curval = *tmpIn;
+                                        if (curval > result) {
+                                                result = curval;
+                                            
+                                        }
+                                        tmpIn += inc;
+                                    }
+
+                                    *(tmpOut) = ( Int64)result;
+
+                                    tmpOut += inc;
+                                    if (tmpOut > lastElementOut) {
+                                        tmpOut -= outLength;
+                                    }
+                                    if (tmpIn > lastElementIn)
+                                        tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                                }
+                            }
+                        }
+                    }
+                    #endregion
+                }
+                if (createIndices) {
+                    I.a = array<double>(indices, newDims);
+                }
+                return new ILRetArray<Int64>(retArr, newDims);
+            }
+        }
+        /// <summary>
+        /// Maximum values along specified dimension
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="I">[Optional] If not null I will hold on return the indices into dim of  
+        /// the values found. If, on entering the function, I is null, those indices 
+        /// will not be computed and I will be ignored.</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns>Array of same inner type and size as A, except for dimension 
+        /// 'dim' which will be reduced to length 1.</returns>
+        public static  ILRetArray<Int32>  max(ILInArray<Int32> A, ILOutArray<double> I = null, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (A.IsEmpty) {
+                    if (!object.Equals(I, null))
+                        I.a = empty<double>(ILSize.Empty00);
+                    return new  ILRetArray<Int32>(A.Size); 
+                }
+                if (dim >= A.Size.NumberOfDimensions || A.Size[dim] == 1) {
+                    // scalar or sum over singleton -> return copy
+                    if (!object.Equals(I, null))
+                        I.a = zeros<double>(A.S);
+                    return new ILRetArray<Int32>(A.C.Storage);
+                }
+                int[] newDims = A.Size.ToIntArray();
+                int leadDimLen = A.Size[dim];
+                int newLength = A.Size.NumberOfElements / leadDimLen;
+                newDims[dim] = 1;
+               
+                Int32[] retArr = ILMemoryPool.Pool.New< Int32>(newLength);
+                #region HYCALPER GLOBAL_INIT
+
+               
+                Int32 result;
+               
+                Int32 curval;
+                double[] indices = null;
+                bool createIndices = false;
+                if (!Object.Equals(I, null)) {
+                    indices = ILMemoryPool.Pool.New<double>(newLength);
+                    createIndices = true;
+                }
+                #endregion HYCALPER GLOBAL_INIT
+                
+
+                // physical -> pointer arithmetic
+                if (dim == 0) {
+                    #region physical along 1st leading dimension
+                    unsafe {
+                        fixed ( Int32* pOutArr = retArr)
+                        fixed ( Int32* pInArr = A.GetArrayForRead())
+                        fixed (double* pIndices = indices) {
+                           
+                            Int32* lastElement;
+                           
+                            Int32* tmpOut = pOutArr;
+                           
+                            Int32* tmpIn = pInArr;
+                            if (createIndices) {
+                                double* tmpInd = pIndices;
+                                for (int h = newLength; h-- > 0; ) {
+
+                                    lastElement = tmpIn + leadDimLen;
+
+                                    result = *tmpIn;
+                                    while 
+#pragma warning disable
+                                    (
+                                        false
+                                        && ++tmpIn < lastElement) 
+#pragma warning restore
+                                    {
+                                        result = *tmpIn;
+                                        *tmpInd += 1;
+                                    }
+
+
+                                    
+                                    while (tmpIn < lastElement) {
+                                        curval = *tmpIn;
+                                        if (curval > result) {
+                                                result = curval;
+                                            
+                                            *tmpInd = (double)(tmpIn - (lastElement - leadDimLen));
+                                        }
+                                        tmpIn++;
+                                    }
+                                    *(tmpOut++) = ( Int32)result;
+                                    tmpInd++;
+                                }
+                            } else {   // no indices
+                                double* tmpInd = pIndices;
+                                for (int h = newLength; h-- > 0; ) {
+                                    lastElement = tmpIn + leadDimLen;
+
+                                    result = *tmpIn;
+                                    while 
+#pragma warning disable
+                                        (
+                                        false
+                                        && ++tmpIn < lastElement) 
+#pragma warning restore
+                                        {
+                                        result = *tmpIn;
+                                    }
+
+                                    
+                                    while (tmpIn < lastElement) {
+                                        curval = *tmpIn++;
+                                        if (curval > result) {
+                                                result = curval;
+                                            
+                                        }
+                                    }
+
+                                    *(tmpOut++) = ( Int32)result;
+
+                                }
+                            }
+                        }
+                    }
+                    #endregion physical along 1st leading dimension
+                } else {
+                    #region physical along abitrary dimension
+                    // sum along abitrary dimension 
+                    unsafe {
+                        fixed ( Int32* pOutArr = retArr)
+                        fixed ( Int32* pInArr = A.GetArrayForRead())
+                        fixed (double* pIndices = indices) {
+                           
+                            Int32* lastElementOut = newLength + pOutArr - 1;
+                            int inLength = A.Size.NumberOfElements - 1;
+                           
+                            Int32* lastElementIn = pInArr + inLength;
+                            int inc = A.Size.SequentialIndexDistance(dim);
+                           
+                            Int32* tmpOut = pOutArr;
+                            int outLength = newLength - 1;
+                           
+                            Int32* leadEnd;
+                           
+                            Int32* tmpIn = pInArr;
+                            if (createIndices) {
+                                double* tmpInd = pIndices;
+                                for (int h = newLength; h-- > 0; ) {
+                                    leadEnd = tmpIn + leadDimLen * inc;
+
+                                    result = *tmpIn;
+                                    while 
+#pragma warning disable
+                                        (
+                                        false
+                                        && (tmpIn += inc) < leadEnd)
+#pragma warning restore                 
+                                    {
+                                        result = *tmpIn;
+                                        *tmpInd += 1;
+                                    }
+
+                                    
+                                    while (tmpIn < leadEnd) {
+                                        curval = *tmpIn;
+                                        if (curval > result) {
+                                                result = curval;
+                                            
+                                            *tmpInd = (double)(leadDimLen - (leadEnd - tmpIn) / inc);
+                                        }
+                                        tmpIn += inc;
+                                    }
+
+                                    *(tmpOut) = ( Int32)result;
+
+                                    tmpOut += inc;
+                                    tmpInd += inc;
+                                    if (tmpOut > lastElementOut) {
+                                        tmpOut -= outLength;
+                                        tmpInd -= outLength;
+                                    }
+                                    if (tmpIn > lastElementIn)
+                                        tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                                }
+                            } else {  // no indices
+                                for (int h = newLength; h-- > 0; ) {
+                                    leadEnd = tmpIn + leadDimLen * inc;
+
+                                    result = *tmpIn;
+                                    while
+#pragma warning disable
+                                    (
+                                        false
+                                        && (tmpIn += inc) < leadEnd)
+#pragma warning restore
+                                    {
+                                        result = *tmpIn;
+                                    }
+
+                                    
+                                    while (tmpIn < leadEnd) {
+                                        curval = *tmpIn;
+                                        if (curval > result) {
+                                                result = curval;
+                                            
+                                        }
+                                        tmpIn += inc;
+                                    }
+
+                                    *(tmpOut) = ( Int32)result;
+
+                                    tmpOut += inc;
+                                    if (tmpOut > lastElementOut) {
+                                        tmpOut -= outLength;
+                                    }
+                                    if (tmpIn > lastElementIn)
+                                        tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                                }
+                            }
+                        }
+                    }
+                    #endregion
+                }
+                if (createIndices) {
+                    I.a = array<double>(indices, newDims);
+                }
+                return new ILRetArray<Int32>(retArr, newDims);
+            }
+        }
+        /// <summary>
+        /// Maximum values along specified dimension
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="I">[Optional] If not null I will hold on return the indices into dim of  
+        /// the values found. If, on entering the function, I is null, those indices 
+        /// will not be computed and I will be ignored.</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns>Array of same inner type and size as A, except for dimension 
+        /// 'dim' which will be reduced to length 1.</returns>
+        public static  ILRetLogical  max(ILInArray<byte> A, ILOutArray<double> I = null, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (A.IsEmpty) {
+                    if (!object.Equals(I, null))
+                        I.a = empty<double>(ILSize.Empty00);
+                    return new  ILRetLogical(A.Size); 
+                }
+                if (dim >= A.Size.NumberOfDimensions || A.Size[dim] == 1) {
+                    // scalar or sum over singleton -> return copy
+                    if (!object.Equals(I, null))
+                        I.a = zeros<double>(A.S);
+                    return new ILRetLogical(A.C.Storage);
+                }
+                int[] newDims = A.Size.ToIntArray();
+                int leadDimLen = A.Size[dim];
+                int newLength = A.Size.NumberOfElements / leadDimLen;
+                newDims[dim] = 1;
+               
+                byte[] retArr = ILMemoryPool.Pool.New< byte>(newLength);
+                #region HYCALPER GLOBAL_INIT
+
+               
+                byte result;
+               
+                byte curval;
+                double[] indices = null;
+                bool createIndices = false;
+                if (!Object.Equals(I, null)) {
+                    indices = ILMemoryPool.Pool.New<double>(newLength);
+                    createIndices = true;
+                }
+                #endregion HYCALPER GLOBAL_INIT
+                
+
+                // physical -> pointer arithmetic
+                if (dim == 0) {
+                    #region physical along 1st leading dimension
+                    unsafe {
+                        fixed ( byte* pOutArr = retArr)
+                        fixed ( byte* pInArr = A.GetArrayForRead())
+                        fixed (double* pIndices = indices) {
+                           
+                            byte* lastElement;
+                           
+                            byte* tmpOut = pOutArr;
+                           
+                            byte* tmpIn = pInArr;
+                            if (createIndices) {
+                                double* tmpInd = pIndices;
+                                for (int h = newLength; h-- > 0; ) {
+
+                                    lastElement = tmpIn + leadDimLen;
+
+                                    result = *tmpIn;
+                                    while 
+#pragma warning disable
+                                    (
+                                        false
+                                        && ++tmpIn < lastElement) 
+#pragma warning restore
+                                    {
+                                        result = *tmpIn;
+                                        *tmpInd += 1;
+                                    }
+
+
+                                    
+                                    while (tmpIn < lastElement) {
+                                        curval = *tmpIn;
+                                        if (curval > result) {
+                                                result = curval;
+                                            
+                                            *tmpInd = (double)(tmpIn - (lastElement - leadDimLen));
+                                        }
+                                        tmpIn++;
+                                    }
+                                    *(tmpOut++) = ( byte)result;
+                                    tmpInd++;
+                                }
+                            } else {   // no indices
+                                double* tmpInd = pIndices;
+                                for (int h = newLength; h-- > 0; ) {
+                                    lastElement = tmpIn + leadDimLen;
+
+                                    result = *tmpIn;
+                                    while 
+#pragma warning disable
+                                        (
+                                        false
+                                        && ++tmpIn < lastElement) 
+#pragma warning restore
+                                        {
+                                        result = *tmpIn;
+                                    }
+
+                                    
+                                    while (tmpIn < lastElement) {
+                                        curval = *tmpIn++;
+                                        if (curval > result) {
+                                                result = curval;
+                                            
+                                        }
+                                    }
+
+                                    *(tmpOut++) = ( byte)result;
+
+                                }
+                            }
+                        }
+                    }
+                    #endregion physical along 1st leading dimension
+                } else {
+                    #region physical along abitrary dimension
+                    // sum along abitrary dimension 
+                    unsafe {
+                        fixed ( byte* pOutArr = retArr)
+                        fixed ( byte* pInArr = A.GetArrayForRead())
+                        fixed (double* pIndices = indices) {
+                           
+                            byte* lastElementOut = newLength + pOutArr - 1;
+                            int inLength = A.Size.NumberOfElements - 1;
+                           
+                            byte* lastElementIn = pInArr + inLength;
+                            int inc = A.Size.SequentialIndexDistance(dim);
+                           
+                            byte* tmpOut = pOutArr;
+                            int outLength = newLength - 1;
+                           
+                            byte* leadEnd;
+                           
+                            byte* tmpIn = pInArr;
+                            if (createIndices) {
+                                double* tmpInd = pIndices;
+                                for (int h = newLength; h-- > 0; ) {
+                                    leadEnd = tmpIn + leadDimLen * inc;
+
+                                    result = *tmpIn;
+                                    while 
+#pragma warning disable
+                                        (
+                                        false
+                                        && (tmpIn += inc) < leadEnd)
+#pragma warning restore                 
+                                    {
+                                        result = *tmpIn;
+                                        *tmpInd += 1;
+                                    }
+
+                                    
+                                    while (tmpIn < leadEnd) {
+                                        curval = *tmpIn;
+                                        if (curval > result) {
+                                                result = curval;
+                                            
+                                            *tmpInd = (double)(leadDimLen - (leadEnd - tmpIn) / inc);
+                                        }
+                                        tmpIn += inc;
+                                    }
+
+                                    *(tmpOut) = ( byte)result;
+
+                                    tmpOut += inc;
+                                    tmpInd += inc;
+                                    if (tmpOut > lastElementOut) {
+                                        tmpOut -= outLength;
+                                        tmpInd -= outLength;
+                                    }
+                                    if (tmpIn > lastElementIn)
+                                        tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                                }
+                            } else {  // no indices
+                                for (int h = newLength; h-- > 0; ) {
+                                    leadEnd = tmpIn + leadDimLen * inc;
+
+                                    result = *tmpIn;
+                                    while
+#pragma warning disable
+                                    (
+                                        false
+                                        && (tmpIn += inc) < leadEnd)
+#pragma warning restore
+                                    {
+                                        result = *tmpIn;
+                                    }
+
+                                    
+                                    while (tmpIn < leadEnd) {
+                                        curval = *tmpIn;
+                                        if (curval > result) {
+                                                result = curval;
+                                            
+                                        }
+                                        tmpIn += inc;
+                                    }
+
+                                    *(tmpOut) = ( byte)result;
+
+                                    tmpOut += inc;
+                                    if (tmpOut > lastElementOut) {
+                                        tmpOut -= outLength;
+                                    }
+                                    if (tmpIn > lastElementIn)
+                                        tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                                }
+                            }
+                        }
+                    }
+                    #endregion
+                }
+                if (createIndices) {
+                    I.a = array<double>(indices, newDims);
+                }
+                return new ILRetLogical(retArr, newDims);
+            }
+        }
+        /// <summary>
+        /// Maximum values along specified dimension
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="I">[Optional] If not null I will hold on return the indices into dim of  
+        /// the values found. If, on entering the function, I is null, those indices 
+        /// will not be computed and I will be ignored.</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns>Array of same inner type and size as A, except for dimension 
+        /// 'dim' which will be reduced to length 1.</returns>
+        public static  ILRetArray<fcomplex>  max(ILInArray<fcomplex> A, ILOutArray<double> I = null, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (A.IsEmpty) {
+                    if (!object.Equals(I, null))
+                        I.a = empty<double>(ILSize.Empty00);
+                    return new  ILRetArray<fcomplex>(A.Size); 
+                }
+                if (dim >= A.Size.NumberOfDimensions || A.Size[dim] == 1) {
+                    // scalar or sum over singleton -> return copy
+                    if (!object.Equals(I, null))
+                        I.a = zeros<double>(A.S);
+                    return new ILRetArray<fcomplex>(A.C.Storage);
+                }
+                int[] newDims = A.Size.ToIntArray();
+                int leadDimLen = A.Size[dim];
+                int newLength = A.Size.NumberOfElements / leadDimLen;
+                newDims[dim] = 1;
+               
+                fcomplex[] retArr = ILMemoryPool.Pool.New< fcomplex>(newLength);
+                #region HYCALPER GLOBAL_INIT
+
+               
+                fcomplex result;
+               
+                fcomplex curval;
+                double[] indices = null;
+                bool createIndices = false;
+                if (!Object.Equals(I, null)) {
+                    indices = ILMemoryPool.Pool.New<double>(newLength);
+                    createIndices = true;
+                }
+                #endregion HYCALPER GLOBAL_INIT
+                float curabsval; float curabsmaxval; 
+
+                // physical -> pointer arithmetic
+                if (dim == 0) {
+                    #region physical along 1st leading dimension
+                    unsafe {
+                        fixed ( fcomplex* pOutArr = retArr)
+                        fixed ( fcomplex* pInArr = A.GetArrayForRead())
+                        fixed (double* pIndices = indices) {
+                           
+                            fcomplex* lastElement;
+                           
+                            fcomplex* tmpOut = pOutArr;
+                           
+                            fcomplex* tmpIn = pInArr;
+                            if (createIndices) {
+                                double* tmpInd = pIndices;
+                                for (int h = newLength; h-- > 0; ) {
+
+                                    lastElement = tmpIn + leadDimLen;
+
+                                    result = *tmpIn;
+                                    while 
+#pragma warning disable
+                                    (
+                                        fcomplex.IsNaN(result)
+                                        && ++tmpIn < lastElement) 
+#pragma warning restore
+                                    {
+                                        result = *tmpIn;
+                                        *tmpInd += 1;
+                                    }
+
+
+                                    curabsmaxval = fcomplex.Abs(result);
+                                    while (tmpIn < lastElement) {
+                                        curval = *tmpIn;
+                                        curabsval = fcomplex.Abs(curval);
+                                            if (curabsval > curabsmaxval) {
+                                                curabsmaxval = curabsval;
+                                                result = curval;
+                                            
+                                            *tmpInd = (double)(tmpIn - (lastElement - leadDimLen));
+                                        }
+                                        tmpIn++;
+                                    }
+                                    *(tmpOut++) = ( fcomplex)result;
+                                    tmpInd++;
+                                }
+                            } else {   // no indices
+                                double* tmpInd = pIndices;
+                                for (int h = newLength; h-- > 0; ) {
+                                    lastElement = tmpIn + leadDimLen;
+
+                                    result = *tmpIn;
+                                    while 
+#pragma warning disable
+                                        (
+                                        fcomplex.IsNaN(result)
+                                        && ++tmpIn < lastElement) 
+#pragma warning restore
+                                        {
+                                        result = *tmpIn;
+                                    }
+
+                                    curabsmaxval = fcomplex.Abs(result);
+                                    while (tmpIn < lastElement) {
+                                        curval = *tmpIn++;
+                                        curabsval = fcomplex.Abs(curval);
+                                            if (curabsval > curabsmaxval) {
+                                                curabsmaxval = curabsval;
+                                                result = curval;
+                                            
+                                        }
+                                    }
+
+                                    *(tmpOut++) = ( fcomplex)result;
+
+                                }
+                            }
+                        }
+                    }
+                    #endregion physical along 1st leading dimension
+                } else {
+                    #region physical along abitrary dimension
+                    // sum along abitrary dimension 
+                    unsafe {
+                        fixed ( fcomplex* pOutArr = retArr)
+                        fixed ( fcomplex* pInArr = A.GetArrayForRead())
+                        fixed (double* pIndices = indices) {
+                           
+                            fcomplex* lastElementOut = newLength + pOutArr - 1;
+                            int inLength = A.Size.NumberOfElements - 1;
+                           
+                            fcomplex* lastElementIn = pInArr + inLength;
+                            int inc = A.Size.SequentialIndexDistance(dim);
+                           
+                            fcomplex* tmpOut = pOutArr;
+                            int outLength = newLength - 1;
+                           
+                            fcomplex* leadEnd;
+                           
+                            fcomplex* tmpIn = pInArr;
+                            if (createIndices) {
+                                double* tmpInd = pIndices;
+                                for (int h = newLength; h-- > 0; ) {
+                                    leadEnd = tmpIn + leadDimLen * inc;
+
+                                    result = *tmpIn;
+                                    while 
+#pragma warning disable
+                                        (
+                                        fcomplex.IsNaN(result)
+                                        && (tmpIn += inc) < leadEnd)
+#pragma warning restore                 
+                                    {
+                                        result = *tmpIn;
+                                        *tmpInd += 1;
+                                    }
+
+                                    curabsmaxval = fcomplex.Abs(result);
+                                    while (tmpIn < leadEnd) {
+                                        curval = *tmpIn;
+                                        curabsval = fcomplex.Abs(curval);
+                                            if (curabsval > curabsmaxval) {
+                                                curabsmaxval = curabsval;
+                                                result = curval;
+                                            
+                                            *tmpInd = (double)(leadDimLen - (leadEnd - tmpIn) / inc);
+                                        }
+                                        tmpIn += inc;
+                                    }
+
+                                    *(tmpOut) = ( fcomplex)result;
+
+                                    tmpOut += inc;
+                                    tmpInd += inc;
+                                    if (tmpOut > lastElementOut) {
+                                        tmpOut -= outLength;
+                                        tmpInd -= outLength;
+                                    }
+                                    if (tmpIn > lastElementIn)
+                                        tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                                }
+                            } else {  // no indices
+                                for (int h = newLength; h-- > 0; ) {
+                                    leadEnd = tmpIn + leadDimLen * inc;
+
+                                    result = *tmpIn;
+                                    while
+#pragma warning disable
+                                    (
+                                        fcomplex.IsNaN(result)
+                                        && (tmpIn += inc) < leadEnd)
+#pragma warning restore
+                                    {
+                                        result = *tmpIn;
+                                    }
+
+                                    curabsmaxval = fcomplex.Abs(result);
+                                    while (tmpIn < leadEnd) {
+                                        curval = *tmpIn;
+                                        curabsval = fcomplex.Abs(curval);
+                                            if (curabsval > curabsmaxval) {
+                                                curabsmaxval = curabsval;
+                                                result = curval;
+                                            
+                                        }
+                                        tmpIn += inc;
+                                    }
+
+                                    *(tmpOut) = ( fcomplex)result;
+
+                                    tmpOut += inc;
+                                    if (tmpOut > lastElementOut) {
+                                        tmpOut -= outLength;
+                                    }
+                                    if (tmpIn > lastElementIn)
+                                        tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                                }
+                            }
+                        }
+                    }
+                    #endregion
+                }
+                if (createIndices) {
+                    I.a = array<double>(indices, newDims);
+                }
+                return new ILRetArray<fcomplex>(retArr, newDims);
+            }
+        }
+        /// <summary>
+        /// Maximum values along specified dimension
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="I">[Optional] If not null I will hold on return the indices into dim of  
+        /// the values found. If, on entering the function, I is null, those indices 
+        /// will not be computed and I will be ignored.</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns>Array of same inner type and size as A, except for dimension 
+        /// 'dim' which will be reduced to length 1.</returns>
+        public static  ILRetArray<float>  max(ILInArray<float> A, ILOutArray<double> I = null, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (A.IsEmpty) {
+                    if (!object.Equals(I, null))
+                        I.a = empty<double>(ILSize.Empty00);
+                    return new  ILRetArray<float>(A.Size); 
+                }
+                if (dim >= A.Size.NumberOfDimensions || A.Size[dim] == 1) {
+                    // scalar or sum over singleton -> return copy
+                    if (!object.Equals(I, null))
+                        I.a = zeros<double>(A.S);
+                    return new ILRetArray<float>(A.C.Storage);
+                }
+                int[] newDims = A.Size.ToIntArray();
+                int leadDimLen = A.Size[dim];
+                int newLength = A.Size.NumberOfElements / leadDimLen;
+                newDims[dim] = 1;
+               
+                float[] retArr = ILMemoryPool.Pool.New< float>(newLength);
+                #region HYCALPER GLOBAL_INIT
+
+               
+                float result;
+               
+                float curval;
+                double[] indices = null;
+                bool createIndices = false;
+                if (!Object.Equals(I, null)) {
+                    indices = ILMemoryPool.Pool.New<double>(newLength);
+                    createIndices = true;
+                }
+                #endregion HYCALPER GLOBAL_INIT
+                
+
+                // physical -> pointer arithmetic
+                if (dim == 0) {
+                    #region physical along 1st leading dimension
+                    unsafe {
+                        fixed ( float* pOutArr = retArr)
+                        fixed ( float* pInArr = A.GetArrayForRead())
+                        fixed (double* pIndices = indices) {
+                           
+                            float* lastElement;
+                           
+                            float* tmpOut = pOutArr;
+                           
+                            float* tmpIn = pInArr;
+                            if (createIndices) {
+                                double* tmpInd = pIndices;
+                                for (int h = newLength; h-- > 0; ) {
+
+                                    lastElement = tmpIn + leadDimLen;
+
+                                    result = *tmpIn;
+                                    while 
+#pragma warning disable
+                                    (
+                                        float.IsNaN(result)
+                                        && ++tmpIn < lastElement) 
+#pragma warning restore
+                                    {
+                                        result = *tmpIn;
+                                        *tmpInd += 1;
+                                    }
+
+
+                                    
+                                    while (tmpIn < lastElement) {
+                                        curval = *tmpIn;
+                                        if (curval > result) {
+                                                result = curval;
+                                            
+                                            *tmpInd = (double)(tmpIn - (lastElement - leadDimLen));
+                                        }
+                                        tmpIn++;
+                                    }
+                                    *(tmpOut++) = ( float)result;
+                                    tmpInd++;
+                                }
+                            } else {   // no indices
+                                double* tmpInd = pIndices;
+                                for (int h = newLength; h-- > 0; ) {
+                                    lastElement = tmpIn + leadDimLen;
+
+                                    result = *tmpIn;
+                                    while 
+#pragma warning disable
+                                        (
+                                        float.IsNaN(result)
+                                        && ++tmpIn < lastElement) 
+#pragma warning restore
+                                        {
+                                        result = *tmpIn;
+                                    }
+
+                                    
+                                    while (tmpIn < lastElement) {
+                                        curval = *tmpIn++;
+                                        if (curval > result) {
+                                                result = curval;
+                                            
+                                        }
+                                    }
+
+                                    *(tmpOut++) = ( float)result;
+
+                                }
+                            }
+                        }
+                    }
+                    #endregion physical along 1st leading dimension
+                } else {
+                    #region physical along abitrary dimension
+                    // sum along abitrary dimension 
+                    unsafe {
+                        fixed ( float* pOutArr = retArr)
+                        fixed ( float* pInArr = A.GetArrayForRead())
+                        fixed (double* pIndices = indices) {
+                           
+                            float* lastElementOut = newLength + pOutArr - 1;
+                            int inLength = A.Size.NumberOfElements - 1;
+                           
+                            float* lastElementIn = pInArr + inLength;
+                            int inc = A.Size.SequentialIndexDistance(dim);
+                           
+                            float* tmpOut = pOutArr;
+                            int outLength = newLength - 1;
+                           
+                            float* leadEnd;
+                           
+                            float* tmpIn = pInArr;
+                            if (createIndices) {
+                                double* tmpInd = pIndices;
+                                for (int h = newLength; h-- > 0; ) {
+                                    leadEnd = tmpIn + leadDimLen * inc;
+
+                                    result = *tmpIn;
+                                    while 
+#pragma warning disable
+                                        (
+                                        float.IsNaN(result)
+                                        && (tmpIn += inc) < leadEnd)
+#pragma warning restore                 
+                                    {
+                                        result = *tmpIn;
+                                        *tmpInd += 1;
+                                    }
+
+                                    
+                                    while (tmpIn < leadEnd) {
+                                        curval = *tmpIn;
+                                        if (curval > result) {
+                                                result = curval;
+                                            
+                                            *tmpInd = (double)(leadDimLen - (leadEnd - tmpIn) / inc);
+                                        }
+                                        tmpIn += inc;
+                                    }
+
+                                    *(tmpOut) = ( float)result;
+
+                                    tmpOut += inc;
+                                    tmpInd += inc;
+                                    if (tmpOut > lastElementOut) {
+                                        tmpOut -= outLength;
+                                        tmpInd -= outLength;
+                                    }
+                                    if (tmpIn > lastElementIn)
+                                        tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                                }
+                            } else {  // no indices
+                                for (int h = newLength; h-- > 0; ) {
+                                    leadEnd = tmpIn + leadDimLen * inc;
+
+                                    result = *tmpIn;
+                                    while
+#pragma warning disable
+                                    (
+                                        float.IsNaN(result)
+                                        && (tmpIn += inc) < leadEnd)
+#pragma warning restore
+                                    {
+                                        result = *tmpIn;
+                                    }
+
+                                    
+                                    while (tmpIn < leadEnd) {
+                                        curval = *tmpIn;
+                                        if (curval > result) {
+                                                result = curval;
+                                            
+                                        }
+                                        tmpIn += inc;
+                                    }
+
+                                    *(tmpOut) = ( float)result;
+
+                                    tmpOut += inc;
+                                    if (tmpOut > lastElementOut) {
+                                        tmpOut -= outLength;
+                                    }
+                                    if (tmpIn > lastElementIn)
+                                        tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                                }
+                            }
+                        }
+                    }
+                    #endregion
+                }
+                if (createIndices) {
+                    I.a = array<double>(indices, newDims);
+                }
+                return new ILRetArray<float>(retArr, newDims);
+            }
+        }
+        /// <summary>
+        /// Maximum values along specified dimension
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="I">[Optional] If not null I will hold on return the indices into dim of  
+        /// the values found. If, on entering the function, I is null, those indices 
+        /// will not be computed and I will be ignored.</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns>Array of same inner type and size as A, except for dimension 
+        /// 'dim' which will be reduced to length 1.</returns>
+        public static  ILRetArray<complex>  max(ILInArray<complex> A, ILOutArray<double> I = null, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (A.IsEmpty) {
+                    if (!object.Equals(I, null))
+                        I.a = empty<double>(ILSize.Empty00);
+                    return new  ILRetArray<complex>(A.Size); 
+                }
+                if (dim >= A.Size.NumberOfDimensions || A.Size[dim] == 1) {
+                    // scalar or sum over singleton -> return copy
+                    if (!object.Equals(I, null))
+                        I.a = zeros<double>(A.S);
+                    return new ILRetArray<complex>(A.C.Storage);
+                }
+                int[] newDims = A.Size.ToIntArray();
+                int leadDimLen = A.Size[dim];
+                int newLength = A.Size.NumberOfElements / leadDimLen;
+                newDims[dim] = 1;
+               
+                complex[] retArr = ILMemoryPool.Pool.New< complex>(newLength);
+                #region HYCALPER GLOBAL_INIT
+
+               
+                complex result;
+               
+                complex curval;
+                double[] indices = null;
+                bool createIndices = false;
+                if (!Object.Equals(I, null)) {
+                    indices = ILMemoryPool.Pool.New<double>(newLength);
+                    createIndices = true;
+                }
+                #endregion HYCALPER GLOBAL_INIT
+                double curabsval; double curabsmaxval; 
+
+                // physical -> pointer arithmetic
+                if (dim == 0) {
+                    #region physical along 1st leading dimension
+                    unsafe {
+                        fixed ( complex* pOutArr = retArr)
+                        fixed ( complex* pInArr = A.GetArrayForRead())
+                        fixed (double* pIndices = indices) {
+                           
+                            complex* lastElement;
+                           
+                            complex* tmpOut = pOutArr;
+                           
+                            complex* tmpIn = pInArr;
+                            if (createIndices) {
+                                double* tmpInd = pIndices;
+                                for (int h = newLength; h-- > 0; ) {
+
+                                    lastElement = tmpIn + leadDimLen;
+
+                                    result = *tmpIn;
+                                    while 
+#pragma warning disable
+                                    (
+                                        complex.IsNaN(result)
+                                        && ++tmpIn < lastElement) 
+#pragma warning restore
+                                    {
+                                        result = *tmpIn;
+                                        *tmpInd += 1;
+                                    }
+
+
+                                    curabsmaxval = complex.Abs(result);
+                                    while (tmpIn < lastElement) {
+                                        curval = *tmpIn;
+                                        curabsval = complex.Abs(curval);
+                                            if (curabsval > curabsmaxval) {
+                                                curabsmaxval = curabsval;
+                                                result = curval;
+                                            
+                                            *tmpInd = (double)(tmpIn - (lastElement - leadDimLen));
+                                        }
+                                        tmpIn++;
+                                    }
+                                    *(tmpOut++) = ( complex)result;
+                                    tmpInd++;
+                                }
+                            } else {   // no indices
+                                double* tmpInd = pIndices;
+                                for (int h = newLength; h-- > 0; ) {
+                                    lastElement = tmpIn + leadDimLen;
+
+                                    result = *tmpIn;
+                                    while 
+#pragma warning disable
+                                        (
+                                        complex.IsNaN(result)
+                                        && ++tmpIn < lastElement) 
+#pragma warning restore
+                                        {
+                                        result = *tmpIn;
+                                    }
+
+                                    curabsmaxval = complex.Abs(result);
+                                    while (tmpIn < lastElement) {
+                                        curval = *tmpIn++;
+                                        curabsval = complex.Abs(curval);
+                                            if (curabsval > curabsmaxval) {
+                                                curabsmaxval = curabsval;
+                                                result = curval;
+                                            
+                                        }
+                                    }
+
+                                    *(tmpOut++) = ( complex)result;
+
+                                }
+                            }
+                        }
+                    }
+                    #endregion physical along 1st leading dimension
+                } else {
+                    #region physical along abitrary dimension
+                    // sum along abitrary dimension 
+                    unsafe {
+                        fixed ( complex* pOutArr = retArr)
+                        fixed ( complex* pInArr = A.GetArrayForRead())
+                        fixed (double* pIndices = indices) {
+                           
+                            complex* lastElementOut = newLength + pOutArr - 1;
+                            int inLength = A.Size.NumberOfElements - 1;
+                           
+                            complex* lastElementIn = pInArr + inLength;
+                            int inc = A.Size.SequentialIndexDistance(dim);
+                           
+                            complex* tmpOut = pOutArr;
+                            int outLength = newLength - 1;
+                           
+                            complex* leadEnd;
+                           
+                            complex* tmpIn = pInArr;
+                            if (createIndices) {
+                                double* tmpInd = pIndices;
+                                for (int h = newLength; h-- > 0; ) {
+                                    leadEnd = tmpIn + leadDimLen * inc;
+
+                                    result = *tmpIn;
+                                    while 
+#pragma warning disable
+                                        (
+                                        complex.IsNaN(result)
+                                        && (tmpIn += inc) < leadEnd)
+#pragma warning restore                 
+                                    {
+                                        result = *tmpIn;
+                                        *tmpInd += 1;
+                                    }
+
+                                    curabsmaxval = complex.Abs(result);
+                                    while (tmpIn < leadEnd) {
+                                        curval = *tmpIn;
+                                        curabsval = complex.Abs(curval);
+                                            if (curabsval > curabsmaxval) {
+                                                curabsmaxval = curabsval;
+                                                result = curval;
+                                            
+                                            *tmpInd = (double)(leadDimLen - (leadEnd - tmpIn) / inc);
+                                        }
+                                        tmpIn += inc;
+                                    }
+
+                                    *(tmpOut) = ( complex)result;
+
+                                    tmpOut += inc;
+                                    tmpInd += inc;
+                                    if (tmpOut > lastElementOut) {
+                                        tmpOut -= outLength;
+                                        tmpInd -= outLength;
+                                    }
+                                    if (tmpIn > lastElementIn)
+                                        tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                                }
+                            } else {  // no indices
+                                for (int h = newLength; h-- > 0; ) {
+                                    leadEnd = tmpIn + leadDimLen * inc;
+
+                                    result = *tmpIn;
+                                    while
+#pragma warning disable
+                                    (
+                                        complex.IsNaN(result)
+                                        && (tmpIn += inc) < leadEnd)
+#pragma warning restore
+                                    {
+                                        result = *tmpIn;
+                                    }
+
+                                    curabsmaxval = complex.Abs(result);
+                                    while (tmpIn < leadEnd) {
+                                        curval = *tmpIn;
+                                        curabsval = complex.Abs(curval);
+                                            if (curabsval > curabsmaxval) {
+                                                curabsmaxval = curabsval;
+                                                result = curval;
+                                            
+                                        }
+                                        tmpIn += inc;
+                                    }
+
+                                    *(tmpOut) = ( complex)result;
+
+                                    tmpOut += inc;
+                                    if (tmpOut > lastElementOut) {
+                                        tmpOut -= outLength;
+                                    }
+                                    if (tmpIn > lastElementIn)
+                                        tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                                }
+                            }
+                        }
+                    }
+                    #endregion
+                }
+                if (createIndices) {
+                    I.a = array<double>(indices, newDims);
+                }
+                return new ILRetArray<complex>(retArr, newDims);
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+
+        
+        /// <summary>Maximum of A and B elementwise</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Array with the maximum elements of A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<double>  max(ILInArray<double> A, ILInArray<double> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                 double[] retArr;
+                 double[] arrA = A.GetArrayForRead();
+                 double[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size;
+                    if (B.IsScalar) {
+                        return array<double>(new double[1] { (A.GetValue(0) > B.GetValue(0)) ? A.GetValue(0) : B.GetValue(0) });
+                    } else if (B.IsEmpty) {
+                        return ILRetArray<double>.empty(outDims);
+                    } else {
+                        outLen = outDims.NumberOfElements;
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< double>(outLen);
+                            mode = BinOpItMode.SAN;
+                        } else {
+                            mode = BinOpItMode.SAI;
+                        }
+                    }
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return ILRetArray<double>.empty(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New<double>(outLen);
+                            mode = BinOpItMode.ASN;
+                        } else {
+                            mode = BinOpItMode.ASI;
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  maxEx(A, B);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        if (A.TryGetStorage4InplaceOp(out retArr))
+                            mode = BinOpItMode.AAIA;
+                        else if (B.TryGetStorage4InplaceOp(out retArr))
+                            mode = BinOpItMode.AAIB;
+                        else {
+                            retArr = ILMemoryPool.Pool.New<double>(outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<double> retStorage = new ILDenseStorage<double>(retArr, outDims);
+                int i = 0, workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    
+                    double* cp = (double*)range.Item5 + range.Item1;
+                    
+                    double scalar;
+                    int j = range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                            
+                            double* bp = ((double*)range.Item4 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (cp[0]  > bp[0]) ? cp[0] : bp[0];
+                                cp[1] = (cp[1]  > bp[1]) ? cp[1] : bp[1];
+                                cp[2] = (cp[2]  > bp[2]) ? cp[2] : bp[2];
+                                cp[3] = (cp[3]  > bp[3]) ? cp[3] : bp[3];
+                                cp[4] = (cp[4]  > bp[4]) ? cp[4] : bp[4];
+                                cp[5] = (cp[5]  > bp[5]) ? cp[5] : bp[5];
+                                cp[6] = (cp[6]  > bp[6]) ? cp[6] : bp[6];
+                                cp[7] = (cp[7]  > bp[7]) ? cp[7] : bp[7];
+                                cp += 8; bp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*cp  > *bp) ? *cp : *bp;
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                            
+                            double* ap = ((double*)range.Item3 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (ap[0]  > cp[0]) ? ap[0] : cp[0];
+                                cp[1] = (ap[1]  > cp[1]) ? ap[1] : cp[1];
+                                cp[2] = (ap[2]  > cp[2]) ? ap[2] : cp[2];
+                                cp[3] = (ap[3]  > cp[3]) ? ap[3] : cp[3];
+                                cp[4] = (ap[4]  > cp[4]) ? ap[4] : cp[4];
+                                cp[5] = (ap[5]  > cp[5]) ? ap[5] : cp[5];
+                                cp[6] = (ap[6]  > cp[6]) ? ap[6] : cp[6];
+                                cp[7] = (ap[7]  > cp[7]) ? ap[7] : cp[7];
+                                ap += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*ap  > *cp) ? *ap : *cp;
+                                ap++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((double*)range.Item3 + range.Item1);
+                            bp = ((double*)range.Item4 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (ap[0]  > bp[0]) ? ap[0] : bp[0];
+                                cp[1] = (ap[1]  > bp[1]) ? ap[1] : bp[1];
+                                cp[2] = (ap[2]  > bp[2]) ? ap[2] : bp[2];
+                                cp[3] = (ap[3]  > bp[3]) ? ap[3] : bp[3];
+                                cp[4] = (ap[4]  > bp[4]) ? ap[4] : bp[4];
+                                cp[5] = (ap[5]  > bp[5]) ? ap[5] : bp[5];
+                                cp[6] = (ap[6]  > bp[6]) ? ap[6] : bp[6];
+                                cp[7] = (ap[7]  > bp[7]) ? ap[7] : bp[7];
+                                ap += 8; bp += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*ap  > *bp) ? *ap : *bp;
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((double*)range.Item4);
+                            while (j > 7) {
+                                cp[0] = (cp[0]  > scalar) ? cp[0] : scalar;
+                                cp[1] = (cp[1]  > scalar) ? cp[1] : scalar;
+                                cp[2] = (cp[2]  > scalar) ? cp[2] : scalar;
+                                cp[3] = (cp[3]  > scalar) ? cp[3] : scalar;
+                                cp[4] = (cp[4]  > scalar) ? cp[4] : scalar;
+                                cp[5] = (cp[5]  > scalar) ? cp[5] : scalar;
+                                cp[6] = (cp[6]  > scalar) ? cp[6] : scalar;
+                                cp[7] = (cp[7]  > scalar) ? cp[7] : scalar;
+                                cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*cp  > scalar) ? *cp : scalar;
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((double*)range.Item3 + range.Item1);
+                            scalar = *((double*)range.Item4);
+                            while (j > 7) {
+                                cp[0] = (ap[0]  > scalar) ? ap[0] : scalar;
+                                cp[1] = (ap[1]  > scalar) ? ap[1] : scalar;
+                                cp[2] = (ap[2]  > scalar) ? ap[2] : scalar;
+                                cp[3] = (ap[3]  > scalar) ? ap[3] : scalar;
+                                cp[4] = (ap[4]  > scalar) ? ap[4] : scalar;
+                                cp[5] = (ap[5]  > scalar) ? ap[5] : scalar;
+                                cp[6] = (ap[6]  > scalar) ? ap[6] : scalar;
+                                cp[7] = (ap[7]  > scalar) ? ap[7] : scalar;
+                                ap += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*ap  > scalar) ? *ap : scalar;
+                                ap++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((double*)range.Item3);
+                            while (j > 7) {
+                                cp[0] = (scalar  > cp[0]) ? scalar : cp[0];
+                                cp[1] = (scalar  > cp[1]) ? scalar : cp[1];
+                                cp[2] = (scalar  > cp[2]) ? scalar : cp[2];
+                                cp[3] = (scalar  > cp[3]) ? scalar : cp[3];
+                                cp[4] = (scalar  > cp[4]) ? scalar : cp[4];
+                                cp[5] = (scalar  > cp[5]) ? scalar : cp[5];
+                                cp[6] = (scalar  > cp[6]) ? scalar : cp[6];
+                                cp[7] = (scalar  > cp[7]) ? scalar : cp[7];
+                                cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (scalar  > *cp) ? scalar : *cp;
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((double*)range.Item3);
+                            bp = ((double*)range.Item4 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (scalar  > bp[0]) ? scalar : bp[0];
+                                cp[1] = (scalar  > bp[1]) ? scalar : bp[1];
+                                cp[2] = (scalar  > bp[2]) ? scalar : bp[2];
+                                cp[3] = (scalar  > bp[3]) ? scalar : bp[3];
+                                cp[4] = (scalar  > bp[4]) ? scalar : bp[4];
+                                cp[5] = (scalar  > bp[5]) ? scalar : bp[5];
+                                cp[6] = (scalar  > bp[6]) ? scalar : bp[6];
+                                cp[7] = (scalar  > bp[7]) ? scalar : bp[7];
+                                bp += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (scalar  > *bp) ? scalar : *bp;
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+
+                fixed (double* arrAP = arrA)
+                fixed (double* arrBP = arrB)
+                fixed (double* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new ILRetArray<double>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<double>  maxEx(ILInArray<double> A, ILInArray<double> B) {
+            using (ILScope.Enter(A, B)) {
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<double>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<double>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<double>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+
+                
+                double[] retArr;
+
+                
+                double[] arrA = A.GetArrayForRead();
+
+                
+                double[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<double>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<double>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<double> retStorage = new ILDenseStorage<double>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+
+                    
+                    double* ap;
+
+                    
+                    double* bp;
+
+                    
+                    double* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (double*)range.Item3;
+                                bp = (double*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (double*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap  > *bp) ? *ap : *bp;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (double*)range.Item3;
+                                cp = (double*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap  > *cp) ? *ap : *cp;
+                                    ap++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (double*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (double*)range.Item4;
+                                cp = (double*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap  > *bp) ? *ap : *bp;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            for (int s = 0; s < range.Item2; s++) {
+                                bp = (double*)range.Item4;
+                                cp = (double*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*cp  > *bp) ? *cp : *bp;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed (double* arrAP = arrA)
+                fixed (double* arrBP = arrB)
+                fixed (double* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<double>(retStorage);
+            }
+        }
+
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+       
+        /// <summary>Maximum of A and B elementwise</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Array with the maximum elements of A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<Int64>  max(ILInArray<Int64> A, ILInArray<Int64> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                Int64[] retArr;
+                Int64[] arrA = A.GetArrayForRead();
+                Int64[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size;
+                    if (B.IsScalar) {
+                        return array<Int64>(new Int64[1] { (A.GetValue(0) > B.GetValue(0)) ? A.GetValue(0) : B.GetValue(0) });
+                    } else if (B.IsEmpty) {
+                        return ILRetArray<Int64>.empty(outDims);
+                    } else {
+                        outLen = outDims.NumberOfElements;
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< Int64>(outLen);
+                            mode = BinOpItMode.SAN;
+                        } else {
+                            mode = BinOpItMode.SAI;
+                        }
+                    }
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return ILRetArray<Int64>.empty(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New<Int64>(outLen);
+                            mode = BinOpItMode.ASN;
+                        } else {
+                            mode = BinOpItMode.ASI;
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  maxEx(A, B);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        if (A.TryGetStorage4InplaceOp(out retArr))
+                            mode = BinOpItMode.AAIA;
+                        else if (B.TryGetStorage4InplaceOp(out retArr))
+                            mode = BinOpItMode.AAIB;
+                        else {
+                            retArr = ILMemoryPool.Pool.New<Int64>(outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<Int64> retStorage = new ILDenseStorage<Int64>(retArr, outDims);
+                int i = 0, workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                   
+                    Int64* cp = (Int64*)range.Item5 + range.Item1;
+                   
+                    Int64 scalar;
+                    int j = range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           
+                            Int64* bp = ((Int64*)range.Item4 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (cp[0]  > bp[0]) ? cp[0] : bp[0];
+                                cp[1] = (cp[1]  > bp[1]) ? cp[1] : bp[1];
+                                cp[2] = (cp[2]  > bp[2]) ? cp[2] : bp[2];
+                                cp[3] = (cp[3]  > bp[3]) ? cp[3] : bp[3];
+                                cp[4] = (cp[4]  > bp[4]) ? cp[4] : bp[4];
+                                cp[5] = (cp[5]  > bp[5]) ? cp[5] : bp[5];
+                                cp[6] = (cp[6]  > bp[6]) ? cp[6] : bp[6];
+                                cp[7] = (cp[7]  > bp[7]) ? cp[7] : bp[7];
+                                cp += 8; bp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*cp  > *bp) ? *cp : *bp;
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           
+                            Int64* ap = ((Int64*)range.Item3 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (ap[0]  > cp[0]) ? ap[0] : cp[0];
+                                cp[1] = (ap[1]  > cp[1]) ? ap[1] : cp[1];
+                                cp[2] = (ap[2]  > cp[2]) ? ap[2] : cp[2];
+                                cp[3] = (ap[3]  > cp[3]) ? ap[3] : cp[3];
+                                cp[4] = (ap[4]  > cp[4]) ? ap[4] : cp[4];
+                                cp[5] = (ap[5]  > cp[5]) ? ap[5] : cp[5];
+                                cp[6] = (ap[6]  > cp[6]) ? ap[6] : cp[6];
+                                cp[7] = (ap[7]  > cp[7]) ? ap[7] : cp[7];
+                                ap += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*ap  > *cp) ? *ap : *cp;
+                                ap++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((Int64*)range.Item3 + range.Item1);
+                            bp = ((Int64*)range.Item4 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (ap[0]  > bp[0]) ? ap[0] : bp[0];
+                                cp[1] = (ap[1]  > bp[1]) ? ap[1] : bp[1];
+                                cp[2] = (ap[2]  > bp[2]) ? ap[2] : bp[2];
+                                cp[3] = (ap[3]  > bp[3]) ? ap[3] : bp[3];
+                                cp[4] = (ap[4]  > bp[4]) ? ap[4] : bp[4];
+                                cp[5] = (ap[5]  > bp[5]) ? ap[5] : bp[5];
+                                cp[6] = (ap[6]  > bp[6]) ? ap[6] : bp[6];
+                                cp[7] = (ap[7]  > bp[7]) ? ap[7] : bp[7];
+                                ap += 8; bp += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*ap  > *bp) ? *ap : *bp;
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((Int64*)range.Item4);
+                            while (j > 7) {
+                                cp[0] = (cp[0]  > scalar) ? cp[0] : scalar;
+                                cp[1] = (cp[1]  > scalar) ? cp[1] : scalar;
+                                cp[2] = (cp[2]  > scalar) ? cp[2] : scalar;
+                                cp[3] = (cp[3]  > scalar) ? cp[3] : scalar;
+                                cp[4] = (cp[4]  > scalar) ? cp[4] : scalar;
+                                cp[5] = (cp[5]  > scalar) ? cp[5] : scalar;
+                                cp[6] = (cp[6]  > scalar) ? cp[6] : scalar;
+                                cp[7] = (cp[7]  > scalar) ? cp[7] : scalar;
+                                cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*cp  > scalar) ? *cp : scalar;
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((Int64*)range.Item3 + range.Item1);
+                            scalar = *((Int64*)range.Item4);
+                            while (j > 7) {
+                                cp[0] = (ap[0]  > scalar) ? ap[0] : scalar;
+                                cp[1] = (ap[1]  > scalar) ? ap[1] : scalar;
+                                cp[2] = (ap[2]  > scalar) ? ap[2] : scalar;
+                                cp[3] = (ap[3]  > scalar) ? ap[3] : scalar;
+                                cp[4] = (ap[4]  > scalar) ? ap[4] : scalar;
+                                cp[5] = (ap[5]  > scalar) ? ap[5] : scalar;
+                                cp[6] = (ap[6]  > scalar) ? ap[6] : scalar;
+                                cp[7] = (ap[7]  > scalar) ? ap[7] : scalar;
+                                ap += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*ap  > scalar) ? *ap : scalar;
+                                ap++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((Int64*)range.Item3);
+                            while (j > 7) {
+                                cp[0] = (scalar  > cp[0]) ? scalar : cp[0];
+                                cp[1] = (scalar  > cp[1]) ? scalar : cp[1];
+                                cp[2] = (scalar  > cp[2]) ? scalar : cp[2];
+                                cp[3] = (scalar  > cp[3]) ? scalar : cp[3];
+                                cp[4] = (scalar  > cp[4]) ? scalar : cp[4];
+                                cp[5] = (scalar  > cp[5]) ? scalar : cp[5];
+                                cp[6] = (scalar  > cp[6]) ? scalar : cp[6];
+                                cp[7] = (scalar  > cp[7]) ? scalar : cp[7];
+                                cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (scalar  > *cp) ? scalar : *cp;
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((Int64*)range.Item3);
+                            bp = ((Int64*)range.Item4 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (scalar  > bp[0]) ? scalar : bp[0];
+                                cp[1] = (scalar  > bp[1]) ? scalar : bp[1];
+                                cp[2] = (scalar  > bp[2]) ? scalar : bp[2];
+                                cp[3] = (scalar  > bp[3]) ? scalar : bp[3];
+                                cp[4] = (scalar  > bp[4]) ? scalar : bp[4];
+                                cp[5] = (scalar  > bp[5]) ? scalar : bp[5];
+                                cp[6] = (scalar  > bp[6]) ? scalar : bp[6];
+                                cp[7] = (scalar  > bp[7]) ? scalar : bp[7];
+                                bp += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (scalar  > *bp) ? scalar : *bp;
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+
+                fixed (Int64* arrAP = arrA)
+                fixed (Int64* arrBP = arrB)
+                fixed (Int64* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new ILRetArray<Int64>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<Int64>  maxEx(ILInArray<Int64> A, ILInArray<Int64> B) {
+            using (ILScope.Enter(A, B)) {
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<Int64>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<Int64>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<Int64>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+
+               
+                Int64[] retArr;
+
+               
+                Int64[] arrA = A.GetArrayForRead();
+
+               
+                Int64[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<Int64>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<Int64>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<Int64> retStorage = new ILDenseStorage<Int64>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+
+                   
+                    Int64* ap;
+
+                   
+                    Int64* bp;
+
+                   
+                    Int64* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (Int64*)range.Item3;
+                                bp = (Int64*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (Int64*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap  > *bp) ? *ap : *bp;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (Int64*)range.Item3;
+                                cp = (Int64*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap  > *cp) ? *ap : *cp;
+                                    ap++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (Int64*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (Int64*)range.Item4;
+                                cp = (Int64*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap  > *bp) ? *ap : *bp;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            for (int s = 0; s < range.Item2; s++) {
+                                bp = (Int64*)range.Item4;
+                                cp = (Int64*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*cp  > *bp) ? *cp : *bp;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed (Int64* arrAP = arrA)
+                fixed (Int64* arrBP = arrB)
+                fixed (Int64* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<Int64>(retStorage);
+            }
+        }
+
+
+       
+        /// <summary>Maximum of A and B elementwise</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Array with the maximum elements of A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<Int32>  max(ILInArray<Int32> A, ILInArray<Int32> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                Int32[] retArr;
+                Int32[] arrA = A.GetArrayForRead();
+                Int32[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size;
+                    if (B.IsScalar) {
+                        return array<Int32>(new Int32[1] { (A.GetValue(0) > B.GetValue(0)) ? A.GetValue(0) : B.GetValue(0) });
+                    } else if (B.IsEmpty) {
+                        return ILRetArray<Int32>.empty(outDims);
+                    } else {
+                        outLen = outDims.NumberOfElements;
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< Int32>(outLen);
+                            mode = BinOpItMode.SAN;
+                        } else {
+                            mode = BinOpItMode.SAI;
+                        }
+                    }
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return ILRetArray<Int32>.empty(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New<Int32>(outLen);
+                            mode = BinOpItMode.ASN;
+                        } else {
+                            mode = BinOpItMode.ASI;
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  maxEx(A, B);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        if (A.TryGetStorage4InplaceOp(out retArr))
+                            mode = BinOpItMode.AAIA;
+                        else if (B.TryGetStorage4InplaceOp(out retArr))
+                            mode = BinOpItMode.AAIB;
+                        else {
+                            retArr = ILMemoryPool.Pool.New<Int32>(outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<Int32> retStorage = new ILDenseStorage<Int32>(retArr, outDims);
+                int i = 0, workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                   
+                    Int32* cp = (Int32*)range.Item5 + range.Item1;
+                   
+                    Int32 scalar;
+                    int j = range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           
+                            Int32* bp = ((Int32*)range.Item4 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (cp[0]  > bp[0]) ? cp[0] : bp[0];
+                                cp[1] = (cp[1]  > bp[1]) ? cp[1] : bp[1];
+                                cp[2] = (cp[2]  > bp[2]) ? cp[2] : bp[2];
+                                cp[3] = (cp[3]  > bp[3]) ? cp[3] : bp[3];
+                                cp[4] = (cp[4]  > bp[4]) ? cp[4] : bp[4];
+                                cp[5] = (cp[5]  > bp[5]) ? cp[5] : bp[5];
+                                cp[6] = (cp[6]  > bp[6]) ? cp[6] : bp[6];
+                                cp[7] = (cp[7]  > bp[7]) ? cp[7] : bp[7];
+                                cp += 8; bp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*cp  > *bp) ? *cp : *bp;
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           
+                            Int32* ap = ((Int32*)range.Item3 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (ap[0]  > cp[0]) ? ap[0] : cp[0];
+                                cp[1] = (ap[1]  > cp[1]) ? ap[1] : cp[1];
+                                cp[2] = (ap[2]  > cp[2]) ? ap[2] : cp[2];
+                                cp[3] = (ap[3]  > cp[3]) ? ap[3] : cp[3];
+                                cp[4] = (ap[4]  > cp[4]) ? ap[4] : cp[4];
+                                cp[5] = (ap[5]  > cp[5]) ? ap[5] : cp[5];
+                                cp[6] = (ap[6]  > cp[6]) ? ap[6] : cp[6];
+                                cp[7] = (ap[7]  > cp[7]) ? ap[7] : cp[7];
+                                ap += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*ap  > *cp) ? *ap : *cp;
+                                ap++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((Int32*)range.Item3 + range.Item1);
+                            bp = ((Int32*)range.Item4 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (ap[0]  > bp[0]) ? ap[0] : bp[0];
+                                cp[1] = (ap[1]  > bp[1]) ? ap[1] : bp[1];
+                                cp[2] = (ap[2]  > bp[2]) ? ap[2] : bp[2];
+                                cp[3] = (ap[3]  > bp[3]) ? ap[3] : bp[3];
+                                cp[4] = (ap[4]  > bp[4]) ? ap[4] : bp[4];
+                                cp[5] = (ap[5]  > bp[5]) ? ap[5] : bp[5];
+                                cp[6] = (ap[6]  > bp[6]) ? ap[6] : bp[6];
+                                cp[7] = (ap[7]  > bp[7]) ? ap[7] : bp[7];
+                                ap += 8; bp += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*ap  > *bp) ? *ap : *bp;
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((Int32*)range.Item4);
+                            while (j > 7) {
+                                cp[0] = (cp[0]  > scalar) ? cp[0] : scalar;
+                                cp[1] = (cp[1]  > scalar) ? cp[1] : scalar;
+                                cp[2] = (cp[2]  > scalar) ? cp[2] : scalar;
+                                cp[3] = (cp[3]  > scalar) ? cp[3] : scalar;
+                                cp[4] = (cp[4]  > scalar) ? cp[4] : scalar;
+                                cp[5] = (cp[5]  > scalar) ? cp[5] : scalar;
+                                cp[6] = (cp[6]  > scalar) ? cp[6] : scalar;
+                                cp[7] = (cp[7]  > scalar) ? cp[7] : scalar;
+                                cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*cp  > scalar) ? *cp : scalar;
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((Int32*)range.Item3 + range.Item1);
+                            scalar = *((Int32*)range.Item4);
+                            while (j > 7) {
+                                cp[0] = (ap[0]  > scalar) ? ap[0] : scalar;
+                                cp[1] = (ap[1]  > scalar) ? ap[1] : scalar;
+                                cp[2] = (ap[2]  > scalar) ? ap[2] : scalar;
+                                cp[3] = (ap[3]  > scalar) ? ap[3] : scalar;
+                                cp[4] = (ap[4]  > scalar) ? ap[4] : scalar;
+                                cp[5] = (ap[5]  > scalar) ? ap[5] : scalar;
+                                cp[6] = (ap[6]  > scalar) ? ap[6] : scalar;
+                                cp[7] = (ap[7]  > scalar) ? ap[7] : scalar;
+                                ap += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*ap  > scalar) ? *ap : scalar;
+                                ap++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((Int32*)range.Item3);
+                            while (j > 7) {
+                                cp[0] = (scalar  > cp[0]) ? scalar : cp[0];
+                                cp[1] = (scalar  > cp[1]) ? scalar : cp[1];
+                                cp[2] = (scalar  > cp[2]) ? scalar : cp[2];
+                                cp[3] = (scalar  > cp[3]) ? scalar : cp[3];
+                                cp[4] = (scalar  > cp[4]) ? scalar : cp[4];
+                                cp[5] = (scalar  > cp[5]) ? scalar : cp[5];
+                                cp[6] = (scalar  > cp[6]) ? scalar : cp[6];
+                                cp[7] = (scalar  > cp[7]) ? scalar : cp[7];
+                                cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (scalar  > *cp) ? scalar : *cp;
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((Int32*)range.Item3);
+                            bp = ((Int32*)range.Item4 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (scalar  > bp[0]) ? scalar : bp[0];
+                                cp[1] = (scalar  > bp[1]) ? scalar : bp[1];
+                                cp[2] = (scalar  > bp[2]) ? scalar : bp[2];
+                                cp[3] = (scalar  > bp[3]) ? scalar : bp[3];
+                                cp[4] = (scalar  > bp[4]) ? scalar : bp[4];
+                                cp[5] = (scalar  > bp[5]) ? scalar : bp[5];
+                                cp[6] = (scalar  > bp[6]) ? scalar : bp[6];
+                                cp[7] = (scalar  > bp[7]) ? scalar : bp[7];
+                                bp += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (scalar  > *bp) ? scalar : *bp;
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+
+                fixed (Int32* arrAP = arrA)
+                fixed (Int32* arrBP = arrB)
+                fixed (Int32* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new ILRetArray<Int32>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<Int32>  maxEx(ILInArray<Int32> A, ILInArray<Int32> B) {
+            using (ILScope.Enter(A, B)) {
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<Int32>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<Int32>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<Int32>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+
+               
+                Int32[] retArr;
+
+               
+                Int32[] arrA = A.GetArrayForRead();
+
+               
+                Int32[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<Int32>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<Int32>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<Int32> retStorage = new ILDenseStorage<Int32>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+
+                   
+                    Int32* ap;
+
+                   
+                    Int32* bp;
+
+                   
+                    Int32* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (Int32*)range.Item3;
+                                bp = (Int32*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (Int32*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap  > *bp) ? *ap : *bp;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (Int32*)range.Item3;
+                                cp = (Int32*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap  > *cp) ? *ap : *cp;
+                                    ap++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (Int32*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (Int32*)range.Item4;
+                                cp = (Int32*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap  > *bp) ? *ap : *bp;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            for (int s = 0; s < range.Item2; s++) {
+                                bp = (Int32*)range.Item4;
+                                cp = (Int32*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*cp  > *bp) ? *cp : *bp;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed (Int32* arrAP = arrA)
+                fixed (Int32* arrBP = arrB)
+                fixed (Int32* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<Int32>(retStorage);
+            }
+        }
+
+
+       
+        /// <summary>Maximum of A and B elementwise</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Array with the maximum elements of A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<float>  max(ILInArray<float> A, ILInArray<float> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                float[] retArr;
+                float[] arrA = A.GetArrayForRead();
+                float[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size;
+                    if (B.IsScalar) {
+                        return array<float>(new float[1] { (A.GetValue(0) > B.GetValue(0)) ? A.GetValue(0) : B.GetValue(0) });
+                    } else if (B.IsEmpty) {
+                        return ILRetArray<float>.empty(outDims);
+                    } else {
+                        outLen = outDims.NumberOfElements;
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< float>(outLen);
+                            mode = BinOpItMode.SAN;
+                        } else {
+                            mode = BinOpItMode.SAI;
+                        }
+                    }
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return ILRetArray<float>.empty(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New<float>(outLen);
+                            mode = BinOpItMode.ASN;
+                        } else {
+                            mode = BinOpItMode.ASI;
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  maxEx(A, B);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        if (A.TryGetStorage4InplaceOp(out retArr))
+                            mode = BinOpItMode.AAIA;
+                        else if (B.TryGetStorage4InplaceOp(out retArr))
+                            mode = BinOpItMode.AAIB;
+                        else {
+                            retArr = ILMemoryPool.Pool.New<float>(outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<float> retStorage = new ILDenseStorage<float>(retArr, outDims);
+                int i = 0, workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                   
+                    float* cp = (float*)range.Item5 + range.Item1;
+                   
+                    float scalar;
+                    int j = range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           
+                            float* bp = ((float*)range.Item4 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (cp[0]  > bp[0]) ? cp[0] : bp[0];
+                                cp[1] = (cp[1]  > bp[1]) ? cp[1] : bp[1];
+                                cp[2] = (cp[2]  > bp[2]) ? cp[2] : bp[2];
+                                cp[3] = (cp[3]  > bp[3]) ? cp[3] : bp[3];
+                                cp[4] = (cp[4]  > bp[4]) ? cp[4] : bp[4];
+                                cp[5] = (cp[5]  > bp[5]) ? cp[5] : bp[5];
+                                cp[6] = (cp[6]  > bp[6]) ? cp[6] : bp[6];
+                                cp[7] = (cp[7]  > bp[7]) ? cp[7] : bp[7];
+                                cp += 8; bp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*cp  > *bp) ? *cp : *bp;
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           
+                            float* ap = ((float*)range.Item3 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (ap[0]  > cp[0]) ? ap[0] : cp[0];
+                                cp[1] = (ap[1]  > cp[1]) ? ap[1] : cp[1];
+                                cp[2] = (ap[2]  > cp[2]) ? ap[2] : cp[2];
+                                cp[3] = (ap[3]  > cp[3]) ? ap[3] : cp[3];
+                                cp[4] = (ap[4]  > cp[4]) ? ap[4] : cp[4];
+                                cp[5] = (ap[5]  > cp[5]) ? ap[5] : cp[5];
+                                cp[6] = (ap[6]  > cp[6]) ? ap[6] : cp[6];
+                                cp[7] = (ap[7]  > cp[7]) ? ap[7] : cp[7];
+                                ap += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*ap  > *cp) ? *ap : *cp;
+                                ap++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((float*)range.Item3 + range.Item1);
+                            bp = ((float*)range.Item4 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (ap[0]  > bp[0]) ? ap[0] : bp[0];
+                                cp[1] = (ap[1]  > bp[1]) ? ap[1] : bp[1];
+                                cp[2] = (ap[2]  > bp[2]) ? ap[2] : bp[2];
+                                cp[3] = (ap[3]  > bp[3]) ? ap[3] : bp[3];
+                                cp[4] = (ap[4]  > bp[4]) ? ap[4] : bp[4];
+                                cp[5] = (ap[5]  > bp[5]) ? ap[5] : bp[5];
+                                cp[6] = (ap[6]  > bp[6]) ? ap[6] : bp[6];
+                                cp[7] = (ap[7]  > bp[7]) ? ap[7] : bp[7];
+                                ap += 8; bp += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*ap  > *bp) ? *ap : *bp;
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((float*)range.Item4);
+                            while (j > 7) {
+                                cp[0] = (cp[0]  > scalar) ? cp[0] : scalar;
+                                cp[1] = (cp[1]  > scalar) ? cp[1] : scalar;
+                                cp[2] = (cp[2]  > scalar) ? cp[2] : scalar;
+                                cp[3] = (cp[3]  > scalar) ? cp[3] : scalar;
+                                cp[4] = (cp[4]  > scalar) ? cp[4] : scalar;
+                                cp[5] = (cp[5]  > scalar) ? cp[5] : scalar;
+                                cp[6] = (cp[6]  > scalar) ? cp[6] : scalar;
+                                cp[7] = (cp[7]  > scalar) ? cp[7] : scalar;
+                                cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*cp  > scalar) ? *cp : scalar;
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((float*)range.Item3 + range.Item1);
+                            scalar = *((float*)range.Item4);
+                            while (j > 7) {
+                                cp[0] = (ap[0]  > scalar) ? ap[0] : scalar;
+                                cp[1] = (ap[1]  > scalar) ? ap[1] : scalar;
+                                cp[2] = (ap[2]  > scalar) ? ap[2] : scalar;
+                                cp[3] = (ap[3]  > scalar) ? ap[3] : scalar;
+                                cp[4] = (ap[4]  > scalar) ? ap[4] : scalar;
+                                cp[5] = (ap[5]  > scalar) ? ap[5] : scalar;
+                                cp[6] = (ap[6]  > scalar) ? ap[6] : scalar;
+                                cp[7] = (ap[7]  > scalar) ? ap[7] : scalar;
+                                ap += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*ap  > scalar) ? *ap : scalar;
+                                ap++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((float*)range.Item3);
+                            while (j > 7) {
+                                cp[0] = (scalar  > cp[0]) ? scalar : cp[0];
+                                cp[1] = (scalar  > cp[1]) ? scalar : cp[1];
+                                cp[2] = (scalar  > cp[2]) ? scalar : cp[2];
+                                cp[3] = (scalar  > cp[3]) ? scalar : cp[3];
+                                cp[4] = (scalar  > cp[4]) ? scalar : cp[4];
+                                cp[5] = (scalar  > cp[5]) ? scalar : cp[5];
+                                cp[6] = (scalar  > cp[6]) ? scalar : cp[6];
+                                cp[7] = (scalar  > cp[7]) ? scalar : cp[7];
+                                cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (scalar  > *cp) ? scalar : *cp;
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((float*)range.Item3);
+                            bp = ((float*)range.Item4 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (scalar  > bp[0]) ? scalar : bp[0];
+                                cp[1] = (scalar  > bp[1]) ? scalar : bp[1];
+                                cp[2] = (scalar  > bp[2]) ? scalar : bp[2];
+                                cp[3] = (scalar  > bp[3]) ? scalar : bp[3];
+                                cp[4] = (scalar  > bp[4]) ? scalar : bp[4];
+                                cp[5] = (scalar  > bp[5]) ? scalar : bp[5];
+                                cp[6] = (scalar  > bp[6]) ? scalar : bp[6];
+                                cp[7] = (scalar  > bp[7]) ? scalar : bp[7];
+                                bp += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (scalar  > *bp) ? scalar : *bp;
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+
+                fixed (float* arrAP = arrA)
+                fixed (float* arrBP = arrB)
+                fixed (float* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new ILRetArray<float>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<float>  maxEx(ILInArray<float> A, ILInArray<float> B) {
+            using (ILScope.Enter(A, B)) {
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<float>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<float>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<float>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+
+               
+                float[] retArr;
+
+               
+                float[] arrA = A.GetArrayForRead();
+
+               
+                float[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<float>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<float>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<float> retStorage = new ILDenseStorage<float>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+
+                   
+                    float* ap;
+
+                   
+                    float* bp;
+
+                   
+                    float* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (float*)range.Item3;
+                                bp = (float*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (float*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap  > *bp) ? *ap : *bp;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (float*)range.Item3;
+                                cp = (float*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap  > *cp) ? *ap : *cp;
+                                    ap++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (float*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (float*)range.Item4;
+                                cp = (float*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap  > *bp) ? *ap : *bp;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            for (int s = 0; s < range.Item2; s++) {
+                                bp = (float*)range.Item4;
+                                cp = (float*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*cp  > *bp) ? *cp : *bp;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed (float* arrAP = arrA)
+                fixed (float* arrBP = arrB)
+                fixed (float* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<float>(retStorage);
+            }
+        }
+
+
+       
+        /// <summary>Maximum of A and B elementwise</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Array with the maximum elements of A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<fcomplex>  max(ILInArray<fcomplex> A, ILInArray<fcomplex> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                fcomplex[] retArr;
+                fcomplex[] arrA = A.GetArrayForRead();
+                fcomplex[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size;
+                    if (B.IsScalar) {
+                        return array<fcomplex>(new fcomplex[1] { (A.GetValue(0) > B.GetValue(0)) ? A.GetValue(0) : B.GetValue(0) });
+                    } else if (B.IsEmpty) {
+                        return ILRetArray<fcomplex>.empty(outDims);
+                    } else {
+                        outLen = outDims.NumberOfElements;
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< fcomplex>(outLen);
+                            mode = BinOpItMode.SAN;
+                        } else {
+                            mode = BinOpItMode.SAI;
+                        }
+                    }
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return ILRetArray<fcomplex>.empty(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New<fcomplex>(outLen);
+                            mode = BinOpItMode.ASN;
+                        } else {
+                            mode = BinOpItMode.ASI;
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  maxEx(A, B);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        if (A.TryGetStorage4InplaceOp(out retArr))
+                            mode = BinOpItMode.AAIA;
+                        else if (B.TryGetStorage4InplaceOp(out retArr))
+                            mode = BinOpItMode.AAIB;
+                        else {
+                            retArr = ILMemoryPool.Pool.New<fcomplex>(outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<fcomplex> retStorage = new ILDenseStorage<fcomplex>(retArr, outDims);
+                int i = 0, workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                   
+                    fcomplex* cp = (fcomplex*)range.Item5 + range.Item1;
+                   
+                    fcomplex scalar;
+                    int j = range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           
+                            fcomplex* bp = ((fcomplex*)range.Item4 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (cp[0]  > bp[0]) ? cp[0] : bp[0];
+                                cp[1] = (cp[1]  > bp[1]) ? cp[1] : bp[1];
+                                cp[2] = (cp[2]  > bp[2]) ? cp[2] : bp[2];
+                                cp[3] = (cp[3]  > bp[3]) ? cp[3] : bp[3];
+                                cp[4] = (cp[4]  > bp[4]) ? cp[4] : bp[4];
+                                cp[5] = (cp[5]  > bp[5]) ? cp[5] : bp[5];
+                                cp[6] = (cp[6]  > bp[6]) ? cp[6] : bp[6];
+                                cp[7] = (cp[7]  > bp[7]) ? cp[7] : bp[7];
+                                cp += 8; bp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*cp  > *bp) ? *cp : *bp;
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           
+                            fcomplex* ap = ((fcomplex*)range.Item3 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (ap[0]  > cp[0]) ? ap[0] : cp[0];
+                                cp[1] = (ap[1]  > cp[1]) ? ap[1] : cp[1];
+                                cp[2] = (ap[2]  > cp[2]) ? ap[2] : cp[2];
+                                cp[3] = (ap[3]  > cp[3]) ? ap[3] : cp[3];
+                                cp[4] = (ap[4]  > cp[4]) ? ap[4] : cp[4];
+                                cp[5] = (ap[5]  > cp[5]) ? ap[5] : cp[5];
+                                cp[6] = (ap[6]  > cp[6]) ? ap[6] : cp[6];
+                                cp[7] = (ap[7]  > cp[7]) ? ap[7] : cp[7];
+                                ap += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*ap  > *cp) ? *ap : *cp;
+                                ap++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((fcomplex*)range.Item3 + range.Item1);
+                            bp = ((fcomplex*)range.Item4 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (ap[0]  > bp[0]) ? ap[0] : bp[0];
+                                cp[1] = (ap[1]  > bp[1]) ? ap[1] : bp[1];
+                                cp[2] = (ap[2]  > bp[2]) ? ap[2] : bp[2];
+                                cp[3] = (ap[3]  > bp[3]) ? ap[3] : bp[3];
+                                cp[4] = (ap[4]  > bp[4]) ? ap[4] : bp[4];
+                                cp[5] = (ap[5]  > bp[5]) ? ap[5] : bp[5];
+                                cp[6] = (ap[6]  > bp[6]) ? ap[6] : bp[6];
+                                cp[7] = (ap[7]  > bp[7]) ? ap[7] : bp[7];
+                                ap += 8; bp += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*ap  > *bp) ? *ap : *bp;
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((fcomplex*)range.Item4);
+                            while (j > 7) {
+                                cp[0] = (cp[0]  > scalar) ? cp[0] : scalar;
+                                cp[1] = (cp[1]  > scalar) ? cp[1] : scalar;
+                                cp[2] = (cp[2]  > scalar) ? cp[2] : scalar;
+                                cp[3] = (cp[3]  > scalar) ? cp[3] : scalar;
+                                cp[4] = (cp[4]  > scalar) ? cp[4] : scalar;
+                                cp[5] = (cp[5]  > scalar) ? cp[5] : scalar;
+                                cp[6] = (cp[6]  > scalar) ? cp[6] : scalar;
+                                cp[7] = (cp[7]  > scalar) ? cp[7] : scalar;
+                                cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*cp  > scalar) ? *cp : scalar;
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((fcomplex*)range.Item3 + range.Item1);
+                            scalar = *((fcomplex*)range.Item4);
+                            while (j > 7) {
+                                cp[0] = (ap[0]  > scalar) ? ap[0] : scalar;
+                                cp[1] = (ap[1]  > scalar) ? ap[1] : scalar;
+                                cp[2] = (ap[2]  > scalar) ? ap[2] : scalar;
+                                cp[3] = (ap[3]  > scalar) ? ap[3] : scalar;
+                                cp[4] = (ap[4]  > scalar) ? ap[4] : scalar;
+                                cp[5] = (ap[5]  > scalar) ? ap[5] : scalar;
+                                cp[6] = (ap[6]  > scalar) ? ap[6] : scalar;
+                                cp[7] = (ap[7]  > scalar) ? ap[7] : scalar;
+                                ap += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*ap  > scalar) ? *ap : scalar;
+                                ap++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((fcomplex*)range.Item3);
+                            while (j > 7) {
+                                cp[0] = (scalar  > cp[0]) ? scalar : cp[0];
+                                cp[1] = (scalar  > cp[1]) ? scalar : cp[1];
+                                cp[2] = (scalar  > cp[2]) ? scalar : cp[2];
+                                cp[3] = (scalar  > cp[3]) ? scalar : cp[3];
+                                cp[4] = (scalar  > cp[4]) ? scalar : cp[4];
+                                cp[5] = (scalar  > cp[5]) ? scalar : cp[5];
+                                cp[6] = (scalar  > cp[6]) ? scalar : cp[6];
+                                cp[7] = (scalar  > cp[7]) ? scalar : cp[7];
+                                cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (scalar  > *cp) ? scalar : *cp;
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((fcomplex*)range.Item3);
+                            bp = ((fcomplex*)range.Item4 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (scalar  > bp[0]) ? scalar : bp[0];
+                                cp[1] = (scalar  > bp[1]) ? scalar : bp[1];
+                                cp[2] = (scalar  > bp[2]) ? scalar : bp[2];
+                                cp[3] = (scalar  > bp[3]) ? scalar : bp[3];
+                                cp[4] = (scalar  > bp[4]) ? scalar : bp[4];
+                                cp[5] = (scalar  > bp[5]) ? scalar : bp[5];
+                                cp[6] = (scalar  > bp[6]) ? scalar : bp[6];
+                                cp[7] = (scalar  > bp[7]) ? scalar : bp[7];
+                                bp += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (scalar  > *bp) ? scalar : *bp;
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+
+                fixed (fcomplex* arrAP = arrA)
+                fixed (fcomplex* arrBP = arrB)
+                fixed (fcomplex* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new ILRetArray<fcomplex>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<fcomplex>  maxEx(ILInArray<fcomplex> A, ILInArray<fcomplex> B) {
+            using (ILScope.Enter(A, B)) {
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<fcomplex>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<fcomplex>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<fcomplex>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+
+               
+                fcomplex[] retArr;
+
+               
+                fcomplex[] arrA = A.GetArrayForRead();
+
+               
+                fcomplex[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<fcomplex>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<fcomplex>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<fcomplex> retStorage = new ILDenseStorage<fcomplex>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+
+                   
+                    fcomplex* ap;
+
+                   
+                    fcomplex* bp;
+
+                   
+                    fcomplex* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (fcomplex*)range.Item3;
+                                bp = (fcomplex*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (fcomplex*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap  > *bp) ? *ap : *bp;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (fcomplex*)range.Item3;
+                                cp = (fcomplex*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap  > *cp) ? *ap : *cp;
+                                    ap++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (fcomplex*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (fcomplex*)range.Item4;
+                                cp = (fcomplex*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap  > *bp) ? *ap : *bp;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            for (int s = 0; s < range.Item2; s++) {
+                                bp = (fcomplex*)range.Item4;
+                                cp = (fcomplex*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*cp  > *bp) ? *cp : *bp;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed (fcomplex* arrAP = arrA)
+                fixed (fcomplex* arrBP = arrB)
+                fixed (fcomplex* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<fcomplex>(retStorage);
+            }
+        }
+
+
+       
+        /// <summary>Maximum of A and B elementwise</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Array with the maximum elements of A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<complex>  max(ILInArray<complex> A, ILInArray<complex> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                complex[] retArr;
+                complex[] arrA = A.GetArrayForRead();
+                complex[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size;
+                    if (B.IsScalar) {
+                        return array<complex>(new complex[1] { (A.GetValue(0) > B.GetValue(0)) ? A.GetValue(0) : B.GetValue(0) });
+                    } else if (B.IsEmpty) {
+                        return ILRetArray<complex>.empty(outDims);
+                    } else {
+                        outLen = outDims.NumberOfElements;
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< complex>(outLen);
+                            mode = BinOpItMode.SAN;
+                        } else {
+                            mode = BinOpItMode.SAI;
+                        }
+                    }
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return ILRetArray<complex>.empty(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New<complex>(outLen);
+                            mode = BinOpItMode.ASN;
+                        } else {
+                            mode = BinOpItMode.ASI;
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  maxEx(A, B);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        if (A.TryGetStorage4InplaceOp(out retArr))
+                            mode = BinOpItMode.AAIA;
+                        else if (B.TryGetStorage4InplaceOp(out retArr))
+                            mode = BinOpItMode.AAIB;
+                        else {
+                            retArr = ILMemoryPool.Pool.New<complex>(outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<complex> retStorage = new ILDenseStorage<complex>(retArr, outDims);
+                int i = 0, workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                   
+                    complex* cp = (complex*)range.Item5 + range.Item1;
+                   
+                    complex scalar;
+                    int j = range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           
+                            complex* bp = ((complex*)range.Item4 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (cp[0]  > bp[0]) ? cp[0] : bp[0];
+                                cp[1] = (cp[1]  > bp[1]) ? cp[1] : bp[1];
+                                cp[2] = (cp[2]  > bp[2]) ? cp[2] : bp[2];
+                                cp[3] = (cp[3]  > bp[3]) ? cp[3] : bp[3];
+                                cp[4] = (cp[4]  > bp[4]) ? cp[4] : bp[4];
+                                cp[5] = (cp[5]  > bp[5]) ? cp[5] : bp[5];
+                                cp[6] = (cp[6]  > bp[6]) ? cp[6] : bp[6];
+                                cp[7] = (cp[7]  > bp[7]) ? cp[7] : bp[7];
+                                cp += 8; bp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*cp  > *bp) ? *cp : *bp;
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           
+                            complex* ap = ((complex*)range.Item3 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (ap[0]  > cp[0]) ? ap[0] : cp[0];
+                                cp[1] = (ap[1]  > cp[1]) ? ap[1] : cp[1];
+                                cp[2] = (ap[2]  > cp[2]) ? ap[2] : cp[2];
+                                cp[3] = (ap[3]  > cp[3]) ? ap[3] : cp[3];
+                                cp[4] = (ap[4]  > cp[4]) ? ap[4] : cp[4];
+                                cp[5] = (ap[5]  > cp[5]) ? ap[5] : cp[5];
+                                cp[6] = (ap[6]  > cp[6]) ? ap[6] : cp[6];
+                                cp[7] = (ap[7]  > cp[7]) ? ap[7] : cp[7];
+                                ap += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*ap  > *cp) ? *ap : *cp;
+                                ap++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((complex*)range.Item3 + range.Item1);
+                            bp = ((complex*)range.Item4 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (ap[0]  > bp[0]) ? ap[0] : bp[0];
+                                cp[1] = (ap[1]  > bp[1]) ? ap[1] : bp[1];
+                                cp[2] = (ap[2]  > bp[2]) ? ap[2] : bp[2];
+                                cp[3] = (ap[3]  > bp[3]) ? ap[3] : bp[3];
+                                cp[4] = (ap[4]  > bp[4]) ? ap[4] : bp[4];
+                                cp[5] = (ap[5]  > bp[5]) ? ap[5] : bp[5];
+                                cp[6] = (ap[6]  > bp[6]) ? ap[6] : bp[6];
+                                cp[7] = (ap[7]  > bp[7]) ? ap[7] : bp[7];
+                                ap += 8; bp += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*ap  > *bp) ? *ap : *bp;
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((complex*)range.Item4);
+                            while (j > 7) {
+                                cp[0] = (cp[0]  > scalar) ? cp[0] : scalar;
+                                cp[1] = (cp[1]  > scalar) ? cp[1] : scalar;
+                                cp[2] = (cp[2]  > scalar) ? cp[2] : scalar;
+                                cp[3] = (cp[3]  > scalar) ? cp[3] : scalar;
+                                cp[4] = (cp[4]  > scalar) ? cp[4] : scalar;
+                                cp[5] = (cp[5]  > scalar) ? cp[5] : scalar;
+                                cp[6] = (cp[6]  > scalar) ? cp[6] : scalar;
+                                cp[7] = (cp[7]  > scalar) ? cp[7] : scalar;
+                                cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*cp  > scalar) ? *cp : scalar;
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((complex*)range.Item3 + range.Item1);
+                            scalar = *((complex*)range.Item4);
+                            while (j > 7) {
+                                cp[0] = (ap[0]  > scalar) ? ap[0] : scalar;
+                                cp[1] = (ap[1]  > scalar) ? ap[1] : scalar;
+                                cp[2] = (ap[2]  > scalar) ? ap[2] : scalar;
+                                cp[3] = (ap[3]  > scalar) ? ap[3] : scalar;
+                                cp[4] = (ap[4]  > scalar) ? ap[4] : scalar;
+                                cp[5] = (ap[5]  > scalar) ? ap[5] : scalar;
+                                cp[6] = (ap[6]  > scalar) ? ap[6] : scalar;
+                                cp[7] = (ap[7]  > scalar) ? ap[7] : scalar;
+                                ap += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*ap  > scalar) ? *ap : scalar;
+                                ap++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((complex*)range.Item3);
+                            while (j > 7) {
+                                cp[0] = (scalar  > cp[0]) ? scalar : cp[0];
+                                cp[1] = (scalar  > cp[1]) ? scalar : cp[1];
+                                cp[2] = (scalar  > cp[2]) ? scalar : cp[2];
+                                cp[3] = (scalar  > cp[3]) ? scalar : cp[3];
+                                cp[4] = (scalar  > cp[4]) ? scalar : cp[4];
+                                cp[5] = (scalar  > cp[5]) ? scalar : cp[5];
+                                cp[6] = (scalar  > cp[6]) ? scalar : cp[6];
+                                cp[7] = (scalar  > cp[7]) ? scalar : cp[7];
+                                cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (scalar  > *cp) ? scalar : *cp;
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((complex*)range.Item3);
+                            bp = ((complex*)range.Item4 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (scalar  > bp[0]) ? scalar : bp[0];
+                                cp[1] = (scalar  > bp[1]) ? scalar : bp[1];
+                                cp[2] = (scalar  > bp[2]) ? scalar : bp[2];
+                                cp[3] = (scalar  > bp[3]) ? scalar : bp[3];
+                                cp[4] = (scalar  > bp[4]) ? scalar : bp[4];
+                                cp[5] = (scalar  > bp[5]) ? scalar : bp[5];
+                                cp[6] = (scalar  > bp[6]) ? scalar : bp[6];
+                                cp[7] = (scalar  > bp[7]) ? scalar : bp[7];
+                                bp += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (scalar  > *bp) ? scalar : *bp;
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+
+                fixed (complex* arrAP = arrA)
+                fixed (complex* arrBP = arrB)
+                fixed (complex* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new ILRetArray<complex>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<complex>  maxEx(ILInArray<complex> A, ILInArray<complex> B) {
+            using (ILScope.Enter(A, B)) {
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<complex>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<complex>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<complex>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+
+               
+                complex[] retArr;
+
+               
+                complex[] arrA = A.GetArrayForRead();
+
+               
+                complex[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<complex>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<complex>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<complex> retStorage = new ILDenseStorage<complex>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+
+                   
+                    complex* ap;
+
+                   
+                    complex* bp;
+
+                   
+                    complex* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (complex*)range.Item3;
+                                bp = (complex*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (complex*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap  > *bp) ? *ap : *bp;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (complex*)range.Item3;
+                                cp = (complex*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap  > *cp) ? *ap : *cp;
+                                    ap++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (complex*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (complex*)range.Item4;
+                                cp = (complex*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap  > *bp) ? *ap : *bp;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            for (int s = 0; s < range.Item2; s++) {
+                                bp = (complex*)range.Item4;
+                                cp = (complex*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*cp  > *bp) ? *cp : *bp;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed (complex* arrAP = arrA)
+                fixed (complex* arrBP = arrB)
+                fixed (complex* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<complex>(retStorage);
+            }
+        }
+
+
+       
+        /// <summary>Maximum of A and B elementwise</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Array with the maximum elements of A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<byte>  max(ILInArray<byte> A, ILInArray<byte> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+                byte[] arrA = A.GetArrayForRead();
+                byte[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size;
+                    if (B.IsScalar) {
+                        return array<byte>(new byte[1] { (A.GetValue(0) > B.GetValue(0)) ? A.GetValue(0) : B.GetValue(0) });
+                    } else if (B.IsEmpty) {
+                        return ILRetArray<byte>.empty(outDims);
+                    } else {
+                        outLen = outDims.NumberOfElements;
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< byte>(outLen);
+                            mode = BinOpItMode.SAN;
+                        } else {
+                            mode = BinOpItMode.SAI;
+                        }
+                    }
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return ILRetArray<byte>.empty(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                            mode = BinOpItMode.ASN;
+                        } else {
+                            mode = BinOpItMode.ASI;
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  maxEx(A, B);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        if (A.TryGetStorage4InplaceOp(out retArr))
+                            mode = BinOpItMode.AAIA;
+                        else if (B.TryGetStorage4InplaceOp(out retArr))
+                            mode = BinOpItMode.AAIB;
+                        else {
+                            retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<byte> retStorage = new ILDenseStorage<byte>(retArr, outDims);
+                int i = 0, workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                   
+                    byte* cp = (byte*)range.Item5 + range.Item1;
+                   
+                    byte scalar;
+                    int j = range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           
+                            byte* bp = ((byte*)range.Item4 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (cp[0]  > bp[0]) ? cp[0] : bp[0];
+                                cp[1] = (cp[1]  > bp[1]) ? cp[1] : bp[1];
+                                cp[2] = (cp[2]  > bp[2]) ? cp[2] : bp[2];
+                                cp[3] = (cp[3]  > bp[3]) ? cp[3] : bp[3];
+                                cp[4] = (cp[4]  > bp[4]) ? cp[4] : bp[4];
+                                cp[5] = (cp[5]  > bp[5]) ? cp[5] : bp[5];
+                                cp[6] = (cp[6]  > bp[6]) ? cp[6] : bp[6];
+                                cp[7] = (cp[7]  > bp[7]) ? cp[7] : bp[7];
+                                cp += 8; bp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*cp  > *bp) ? *cp : *bp;
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           
+                            byte* ap = ((byte*)range.Item3 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (ap[0]  > cp[0]) ? ap[0] : cp[0];
+                                cp[1] = (ap[1]  > cp[1]) ? ap[1] : cp[1];
+                                cp[2] = (ap[2]  > cp[2]) ? ap[2] : cp[2];
+                                cp[3] = (ap[3]  > cp[3]) ? ap[3] : cp[3];
+                                cp[4] = (ap[4]  > cp[4]) ? ap[4] : cp[4];
+                                cp[5] = (ap[5]  > cp[5]) ? ap[5] : cp[5];
+                                cp[6] = (ap[6]  > cp[6]) ? ap[6] : cp[6];
+                                cp[7] = (ap[7]  > cp[7]) ? ap[7] : cp[7];
+                                ap += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*ap  > *cp) ? *ap : *cp;
+                                ap++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((byte*)range.Item3 + range.Item1);
+                            bp = ((byte*)range.Item4 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (ap[0]  > bp[0]) ? ap[0] : bp[0];
+                                cp[1] = (ap[1]  > bp[1]) ? ap[1] : bp[1];
+                                cp[2] = (ap[2]  > bp[2]) ? ap[2] : bp[2];
+                                cp[3] = (ap[3]  > bp[3]) ? ap[3] : bp[3];
+                                cp[4] = (ap[4]  > bp[4]) ? ap[4] : bp[4];
+                                cp[5] = (ap[5]  > bp[5]) ? ap[5] : bp[5];
+                                cp[6] = (ap[6]  > bp[6]) ? ap[6] : bp[6];
+                                cp[7] = (ap[7]  > bp[7]) ? ap[7] : bp[7];
+                                ap += 8; bp += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*ap  > *bp) ? *ap : *bp;
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((byte*)range.Item4);
+                            while (j > 7) {
+                                cp[0] = (cp[0]  > scalar) ? cp[0] : scalar;
+                                cp[1] = (cp[1]  > scalar) ? cp[1] : scalar;
+                                cp[2] = (cp[2]  > scalar) ? cp[2] : scalar;
+                                cp[3] = (cp[3]  > scalar) ? cp[3] : scalar;
+                                cp[4] = (cp[4]  > scalar) ? cp[4] : scalar;
+                                cp[5] = (cp[5]  > scalar) ? cp[5] : scalar;
+                                cp[6] = (cp[6]  > scalar) ? cp[6] : scalar;
+                                cp[7] = (cp[7]  > scalar) ? cp[7] : scalar;
+                                cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*cp  > scalar) ? *cp : scalar;
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((byte*)range.Item3 + range.Item1);
+                            scalar = *((byte*)range.Item4);
+                            while (j > 7) {
+                                cp[0] = (ap[0]  > scalar) ? ap[0] : scalar;
+                                cp[1] = (ap[1]  > scalar) ? ap[1] : scalar;
+                                cp[2] = (ap[2]  > scalar) ? ap[2] : scalar;
+                                cp[3] = (ap[3]  > scalar) ? ap[3] : scalar;
+                                cp[4] = (ap[4]  > scalar) ? ap[4] : scalar;
+                                cp[5] = (ap[5]  > scalar) ? ap[5] : scalar;
+                                cp[6] = (ap[6]  > scalar) ? ap[6] : scalar;
+                                cp[7] = (ap[7]  > scalar) ? ap[7] : scalar;
+                                ap += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*ap  > scalar) ? *ap : scalar;
+                                ap++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((byte*)range.Item3);
+                            while (j > 7) {
+                                cp[0] = (scalar  > cp[0]) ? scalar : cp[0];
+                                cp[1] = (scalar  > cp[1]) ? scalar : cp[1];
+                                cp[2] = (scalar  > cp[2]) ? scalar : cp[2];
+                                cp[3] = (scalar  > cp[3]) ? scalar : cp[3];
+                                cp[4] = (scalar  > cp[4]) ? scalar : cp[4];
+                                cp[5] = (scalar  > cp[5]) ? scalar : cp[5];
+                                cp[6] = (scalar  > cp[6]) ? scalar : cp[6];
+                                cp[7] = (scalar  > cp[7]) ? scalar : cp[7];
+                                cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (scalar  > *cp) ? scalar : *cp;
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((byte*)range.Item3);
+                            bp = ((byte*)range.Item4 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (scalar  > bp[0]) ? scalar : bp[0];
+                                cp[1] = (scalar  > bp[1]) ? scalar : bp[1];
+                                cp[2] = (scalar  > bp[2]) ? scalar : bp[2];
+                                cp[3] = (scalar  > bp[3]) ? scalar : bp[3];
+                                cp[4] = (scalar  > bp[4]) ? scalar : bp[4];
+                                cp[5] = (scalar  > bp[5]) ? scalar : bp[5];
+                                cp[6] = (scalar  > bp[6]) ? scalar : bp[6];
+                                cp[7] = (scalar  > bp[7]) ? scalar : bp[7];
+                                bp += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (scalar  > *bp) ? scalar : *bp;
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+
+                fixed (byte* arrAP = arrA)
+                fixed (byte* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new ILRetArray<byte>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<byte>  maxEx(ILInArray<byte> A, ILInArray<byte> B) {
+            using (ILScope.Enter(A, B)) {
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<byte>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<byte>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<byte>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+
+               
+                byte[] retArr;
+
+               
+                byte[] arrA = A.GetArrayForRead();
+
+               
+                byte[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<byte> retStorage = new ILDenseStorage<byte>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+
+                   
+                    byte* ap;
+
+                   
+                    byte* bp;
+
+                   
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (byte*)range.Item3;
+                                bp = (byte*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap  > *bp) ? *ap : *bp;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (byte*)range.Item3;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap  > *cp) ? *ap : *cp;
+                                    ap++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (byte*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (byte*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap  > *bp) ? *ap : *bp;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            for (int s = 0; s < range.Item2; s++) {
+                                bp = (byte*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*cp  > *bp) ? *cp : *bp;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed (byte* arrAP = arrA)
+                fixed (byte* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<byte>(retStorage);
+            }
+        }
+
+
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/Min.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/Min.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/Min.cs	(revision 9102)
@@ -0,0 +1,4697 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions;
+
+namespace ILNumerics {
+
+    public partial class ILMath {
+
+
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>Minimum value along specified dimension</summary>
+        /// <param name="A">Input array</param>
+        /// <param name="I">[Optional] If not null I will hold on return the indices into dim of  
+        /// the values found. If, on entering the function, I is null, those indices 
+        /// will not be computed and I will be ignored.</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns>Array of same inner type and size as A, except for dimension 
+        /// 'dim' which will be reduced to length 1.</returns>
+        public static  ILRetArray<double>  min(ILInArray<double> A, ILOutArray<double> I = null, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (A.IsEmpty) {
+                    if (!object.Equals(I, null))
+                        I.a = empty<double>(ILSize.Empty00);
+                    return new  ILRetArray<double>(A.Size); 
+                }
+                if (dim >= A.Size.NumberOfDimensions || A.Size[dim] == 1) {
+                    // scalar or sum over singleton -> return copy
+                    if (!object.Equals(I, null))
+                        I.a = zeros<double>(A.S);
+                    return new ILRetArray<double>(A.C.Storage);
+                }
+                int[] newDims = A.Size.ToIntArray();
+                int leadDimLen = A.Size[dim];
+                int newLength = A.Size.NumberOfElements / leadDimLen;
+                newDims[dim] = 1;
+               
+                double[] retArr = ILMemoryPool.Pool.New< double>(newLength);
+                #region HYCALPER GLOBAL_INIT
+
+               
+                double result;
+               
+                double curval;
+                double[] indices = null;
+                bool createIndices = false;
+                if (!Object.Equals(I, null)) {
+                    indices = ILMemoryPool.Pool.New<double>(newLength);
+                    createIndices = true;
+                }
+                #endregion HYCALPER GLOBAL_INIT
+                
+
+                // physical -> pointer arithmetic
+                if (dim == 0) {
+                    #region physical along 1st leading dimension
+                    unsafe {
+                        fixed ( double* pOutArr = retArr)
+                        fixed ( double* pInArr = A.GetArrayForRead())
+                        fixed (double* pIndices = indices) {
+                           
+                            double* lastElement;
+                           
+                            double* tmpOut = pOutArr;
+                           
+                            double* tmpIn = pInArr;
+                            if (createIndices) {
+                                double* tmpInd = pIndices;
+                                for (int h = newLength; h-- > 0; ) {
+
+                                    lastElement = tmpIn + leadDimLen;
+
+                                    result = *tmpIn;
+                                    while 
+#pragma warning disable
+                                    (
+                                        double.IsNaN(result)
+                                        && ++tmpIn < lastElement) 
+#pragma warning restore
+                                    {
+                                        result = *tmpIn;
+                                        *tmpInd += 1;
+                                    }
+
+
+                                    
+                                    while (tmpIn < lastElement) {
+                                        curval = *tmpIn;
+                                        if (curval < result) {
+                                                result = curval;
+                                            
+                                            *tmpInd = (double)(tmpIn - (lastElement - leadDimLen));
+                                        }
+                                        tmpIn++;
+                                    }
+                                    *(tmpOut++) = ( double)result;
+                                    tmpInd++;
+                                }
+                            } else {   // no indices
+                                double* tmpInd = pIndices;
+                                for (int h = newLength; h-- > 0; ) {
+                                    lastElement = tmpIn + leadDimLen;
+
+                                    result = *tmpIn;
+                                    while 
+#pragma warning disable
+                                        (
+                                        double.IsNaN(result)
+                                        && ++tmpIn < lastElement) 
+#pragma warning restore
+                                        {
+                                        result = *tmpIn;
+                                    }
+
+                                    
+                                    while (tmpIn < lastElement) {
+                                        curval = *tmpIn++;
+                                        if (curval < result) {
+                                                result = curval;
+                                            
+                                        }
+                                    }
+
+                                    *(tmpOut++) = ( double)result;
+
+                                }
+                            }
+                        }
+                    }
+                    #endregion physical along 1st leading dimension
+                } else {
+                    #region physical along abitrary dimension
+                    // sum along abitrary dimension 
+                    unsafe {
+                        fixed ( double* pOutArr = retArr)
+                        fixed ( double* pInArr = A.GetArrayForRead())
+                        fixed (double* pIndices = indices) {
+                           
+                            double* lastElementOut = newLength + pOutArr - 1;
+                            int inLength = A.Size.NumberOfElements - 1;
+                           
+                            double* lastElementIn = pInArr + inLength;
+                            int inc = A.Size.SequentialIndexDistance(dim);
+                           
+                            double* tmpOut = pOutArr;
+                            int outLength = newLength - 1;
+                           
+                            double* leadEnd;
+                           
+                            double* tmpIn = pInArr;
+                            if (createIndices) {
+                                double* tmpInd = pIndices;
+                                for (int h = newLength; h-- > 0; ) {
+                                    leadEnd = tmpIn + leadDimLen * inc;
+
+                                    result = *tmpIn;
+                                    while 
+#pragma warning disable
+                                        (
+                                        double.IsNaN(result)
+                                        && (tmpIn += inc) < leadEnd)
+#pragma warning restore                 
+                                    {
+                                        result = *tmpIn;
+                                        *tmpInd += 1;
+                                    }
+
+                                    
+                                    while (tmpIn < leadEnd) {
+                                        curval = *tmpIn;
+                                        if (curval < result) {
+                                                result = curval;
+                                            
+                                            *tmpInd = (double)(leadDimLen - (leadEnd - tmpIn) / inc);
+                                        }
+                                        tmpIn += inc;
+                                    }
+
+                                    *(tmpOut) = ( double)result;
+
+                                    tmpOut += inc;
+                                    tmpInd += inc;
+                                    if (tmpOut > lastElementOut) {
+                                        tmpOut -= outLength;
+                                        tmpInd -= outLength;
+                                    }
+                                    if (tmpIn > lastElementIn)
+                                        tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                                }
+                            } else {  // no indices
+                                for (int h = newLength; h-- > 0; ) {
+                                    leadEnd = tmpIn + leadDimLen * inc;
+
+                                    result = *tmpIn;
+                                    while
+#pragma warning disable
+                                    (
+                                        double.IsNaN(result)
+                                        && (tmpIn += inc) < leadEnd)
+#pragma warning restore
+                                    {
+                                        result = *tmpIn;
+                                    }
+
+                                    
+                                    while (tmpIn < leadEnd) {
+                                        curval = *tmpIn;
+                                        if (curval < result) {
+                                                result = curval;
+                                            
+                                        }
+                                        tmpIn += inc;
+                                    }
+
+                                    *(tmpOut) = ( double)result;
+
+                                    tmpOut += inc;
+                                    if (tmpOut > lastElementOut) {
+                                        tmpOut -= outLength;
+                                    }
+                                    if (tmpIn > lastElementIn)
+                                        tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                                }
+                            }
+                        }
+                    }
+                    #endregion
+                }
+                if (createIndices) {
+                    I.a = array<double>(indices, newDims);
+                }
+                return new ILRetArray<double>(retArr, newDims);
+            }
+        }
+        /// <summary>Minimum value along specified dimension</summary>
+        /// <param name="A">Input array</param>
+        /// <param name="I">[Optional] If not null I will hold on return the indices into dim of  
+        /// the values found. If, on entering the function, I is null, those indices 
+        /// will not be computed and I will be ignored.</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns>Array of same inner type and size as A, except for dimension 
+        /// 'dim' which will be reduced to length 1.</returns>
+        public static  ILRetArray<Int64>  min(ILInArray<Int64> A, ILOutArray<double> I = null, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (A.IsEmpty) {
+                    if (!object.Equals(I, null))
+                        I.a = empty<double>(ILSize.Empty00);
+                    return new  ILRetArray<Int64>(A.Size); 
+                }
+                if (dim >= A.Size.NumberOfDimensions || A.Size[dim] == 1) {
+                    // scalar or sum over singleton -> return copy
+                    if (!object.Equals(I, null))
+                        I.a = zeros<double>(A.S);
+                    return new ILRetArray<Int64>(A.C.Storage);
+                }
+                int[] newDims = A.Size.ToIntArray();
+                int leadDimLen = A.Size[dim];
+                int newLength = A.Size.NumberOfElements / leadDimLen;
+                newDims[dim] = 1;
+               
+                Int64[] retArr = ILMemoryPool.Pool.New< Int64>(newLength);
+                #region HYCALPER GLOBAL_INIT
+
+               
+                Int64 result;
+               
+                Int64 curval;
+                double[] indices = null;
+                bool createIndices = false;
+                if (!Object.Equals(I, null)) {
+                    indices = ILMemoryPool.Pool.New<double>(newLength);
+                    createIndices = true;
+                }
+                #endregion HYCALPER GLOBAL_INIT
+                
+
+                // physical -> pointer arithmetic
+                if (dim == 0) {
+                    #region physical along 1st leading dimension
+                    unsafe {
+                        fixed ( Int64* pOutArr = retArr)
+                        fixed ( Int64* pInArr = A.GetArrayForRead())
+                        fixed (double* pIndices = indices) {
+                           
+                            Int64* lastElement;
+                           
+                            Int64* tmpOut = pOutArr;
+                           
+                            Int64* tmpIn = pInArr;
+                            if (createIndices) {
+                                double* tmpInd = pIndices;
+                                for (int h = newLength; h-- > 0; ) {
+
+                                    lastElement = tmpIn + leadDimLen;
+
+                                    result = *tmpIn;
+                                    while 
+#pragma warning disable
+                                    (
+                                        false
+                                        && ++tmpIn < lastElement) 
+#pragma warning restore
+                                    {
+                                        result = *tmpIn;
+                                        *tmpInd += 1;
+                                    }
+
+
+                                    
+                                    while (tmpIn < lastElement) {
+                                        curval = *tmpIn;
+                                        if (curval < result) {
+                                                result = curval;
+                                            
+                                            *tmpInd = (double)(tmpIn - (lastElement - leadDimLen));
+                                        }
+                                        tmpIn++;
+                                    }
+                                    *(tmpOut++) = ( Int64)result;
+                                    tmpInd++;
+                                }
+                            } else {   // no indices
+                                double* tmpInd = pIndices;
+                                for (int h = newLength; h-- > 0; ) {
+                                    lastElement = tmpIn + leadDimLen;
+
+                                    result = *tmpIn;
+                                    while 
+#pragma warning disable
+                                        (
+                                        false
+                                        && ++tmpIn < lastElement) 
+#pragma warning restore
+                                        {
+                                        result = *tmpIn;
+                                    }
+
+                                    
+                                    while (tmpIn < lastElement) {
+                                        curval = *tmpIn++;
+                                        if (curval < result) {
+                                                result = curval;
+                                            
+                                        }
+                                    }
+
+                                    *(tmpOut++) = ( Int64)result;
+
+                                }
+                            }
+                        }
+                    }
+                    #endregion physical along 1st leading dimension
+                } else {
+                    #region physical along abitrary dimension
+                    // sum along abitrary dimension 
+                    unsafe {
+                        fixed ( Int64* pOutArr = retArr)
+                        fixed ( Int64* pInArr = A.GetArrayForRead())
+                        fixed (double* pIndices = indices) {
+                           
+                            Int64* lastElementOut = newLength + pOutArr - 1;
+                            int inLength = A.Size.NumberOfElements - 1;
+                           
+                            Int64* lastElementIn = pInArr + inLength;
+                            int inc = A.Size.SequentialIndexDistance(dim);
+                           
+                            Int64* tmpOut = pOutArr;
+                            int outLength = newLength - 1;
+                           
+                            Int64* leadEnd;
+                           
+                            Int64* tmpIn = pInArr;
+                            if (createIndices) {
+                                double* tmpInd = pIndices;
+                                for (int h = newLength; h-- > 0; ) {
+                                    leadEnd = tmpIn + leadDimLen * inc;
+
+                                    result = *tmpIn;
+                                    while 
+#pragma warning disable
+                                        (
+                                        false
+                                        && (tmpIn += inc) < leadEnd)
+#pragma warning restore                 
+                                    {
+                                        result = *tmpIn;
+                                        *tmpInd += 1;
+                                    }
+
+                                    
+                                    while (tmpIn < leadEnd) {
+                                        curval = *tmpIn;
+                                        if (curval < result) {
+                                                result = curval;
+                                            
+                                            *tmpInd = (double)(leadDimLen - (leadEnd - tmpIn) / inc);
+                                        }
+                                        tmpIn += inc;
+                                    }
+
+                                    *(tmpOut) = ( Int64)result;
+
+                                    tmpOut += inc;
+                                    tmpInd += inc;
+                                    if (tmpOut > lastElementOut) {
+                                        tmpOut -= outLength;
+                                        tmpInd -= outLength;
+                                    }
+                                    if (tmpIn > lastElementIn)
+                                        tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                                }
+                            } else {  // no indices
+                                for (int h = newLength; h-- > 0; ) {
+                                    leadEnd = tmpIn + leadDimLen * inc;
+
+                                    result = *tmpIn;
+                                    while
+#pragma warning disable
+                                    (
+                                        false
+                                        && (tmpIn += inc) < leadEnd)
+#pragma warning restore
+                                    {
+                                        result = *tmpIn;
+                                    }
+
+                                    
+                                    while (tmpIn < leadEnd) {
+                                        curval = *tmpIn;
+                                        if (curval < result) {
+                                                result = curval;
+                                            
+                                        }
+                                        tmpIn += inc;
+                                    }
+
+                                    *(tmpOut) = ( Int64)result;
+
+                                    tmpOut += inc;
+                                    if (tmpOut > lastElementOut) {
+                                        tmpOut -= outLength;
+                                    }
+                                    if (tmpIn > lastElementIn)
+                                        tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                                }
+                            }
+                        }
+                    }
+                    #endregion
+                }
+                if (createIndices) {
+                    I.a = array<double>(indices, newDims);
+                }
+                return new ILRetArray<Int64>(retArr, newDims);
+            }
+        }
+        /// <summary>Minimum value along specified dimension</summary>
+        /// <param name="A">Input array</param>
+        /// <param name="I">[Optional] If not null I will hold on return the indices into dim of  
+        /// the values found. If, on entering the function, I is null, those indices 
+        /// will not be computed and I will be ignored.</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns>Array of same inner type and size as A, except for dimension 
+        /// 'dim' which will be reduced to length 1.</returns>
+        public static  ILRetArray<Int32>  min(ILInArray<Int32> A, ILOutArray<double> I = null, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (A.IsEmpty) {
+                    if (!object.Equals(I, null))
+                        I.a = empty<double>(ILSize.Empty00);
+                    return new  ILRetArray<Int32>(A.Size); 
+                }
+                if (dim >= A.Size.NumberOfDimensions || A.Size[dim] == 1) {
+                    // scalar or sum over singleton -> return copy
+                    if (!object.Equals(I, null))
+                        I.a = zeros<double>(A.S);
+                    return new ILRetArray<Int32>(A.C.Storage);
+                }
+                int[] newDims = A.Size.ToIntArray();
+                int leadDimLen = A.Size[dim];
+                int newLength = A.Size.NumberOfElements / leadDimLen;
+                newDims[dim] = 1;
+               
+                Int32[] retArr = ILMemoryPool.Pool.New< Int32>(newLength);
+                #region HYCALPER GLOBAL_INIT
+
+               
+                Int32 result;
+               
+                Int32 curval;
+                double[] indices = null;
+                bool createIndices = false;
+                if (!Object.Equals(I, null)) {
+                    indices = ILMemoryPool.Pool.New<double>(newLength);
+                    createIndices = true;
+                }
+                #endregion HYCALPER GLOBAL_INIT
+                
+
+                // physical -> pointer arithmetic
+                if (dim == 0) {
+                    #region physical along 1st leading dimension
+                    unsafe {
+                        fixed ( Int32* pOutArr = retArr)
+                        fixed ( Int32* pInArr = A.GetArrayForRead())
+                        fixed (double* pIndices = indices) {
+                           
+                            Int32* lastElement;
+                           
+                            Int32* tmpOut = pOutArr;
+                           
+                            Int32* tmpIn = pInArr;
+                            if (createIndices) {
+                                double* tmpInd = pIndices;
+                                for (int h = newLength; h-- > 0; ) {
+
+                                    lastElement = tmpIn + leadDimLen;
+
+                                    result = *tmpIn;
+                                    while 
+#pragma warning disable
+                                    (
+                                        false
+                                        && ++tmpIn < lastElement) 
+#pragma warning restore
+                                    {
+                                        result = *tmpIn;
+                                        *tmpInd += 1;
+                                    }
+
+
+                                    
+                                    while (tmpIn < lastElement) {
+                                        curval = *tmpIn;
+                                        if (curval < result) {
+                                                result = curval;
+                                            
+                                            *tmpInd = (double)(tmpIn - (lastElement - leadDimLen));
+                                        }
+                                        tmpIn++;
+                                    }
+                                    *(tmpOut++) = ( Int32)result;
+                                    tmpInd++;
+                                }
+                            } else {   // no indices
+                                double* tmpInd = pIndices;
+                                for (int h = newLength; h-- > 0; ) {
+                                    lastElement = tmpIn + leadDimLen;
+
+                                    result = *tmpIn;
+                                    while 
+#pragma warning disable
+                                        (
+                                        false
+                                        && ++tmpIn < lastElement) 
+#pragma warning restore
+                                        {
+                                        result = *tmpIn;
+                                    }
+
+                                    
+                                    while (tmpIn < lastElement) {
+                                        curval = *tmpIn++;
+                                        if (curval < result) {
+                                                result = curval;
+                                            
+                                        }
+                                    }
+
+                                    *(tmpOut++) = ( Int32)result;
+
+                                }
+                            }
+                        }
+                    }
+                    #endregion physical along 1st leading dimension
+                } else {
+                    #region physical along abitrary dimension
+                    // sum along abitrary dimension 
+                    unsafe {
+                        fixed ( Int32* pOutArr = retArr)
+                        fixed ( Int32* pInArr = A.GetArrayForRead())
+                        fixed (double* pIndices = indices) {
+                           
+                            Int32* lastElementOut = newLength + pOutArr - 1;
+                            int inLength = A.Size.NumberOfElements - 1;
+                           
+                            Int32* lastElementIn = pInArr + inLength;
+                            int inc = A.Size.SequentialIndexDistance(dim);
+                           
+                            Int32* tmpOut = pOutArr;
+                            int outLength = newLength - 1;
+                           
+                            Int32* leadEnd;
+                           
+                            Int32* tmpIn = pInArr;
+                            if (createIndices) {
+                                double* tmpInd = pIndices;
+                                for (int h = newLength; h-- > 0; ) {
+                                    leadEnd = tmpIn + leadDimLen * inc;
+
+                                    result = *tmpIn;
+                                    while 
+#pragma warning disable
+                                        (
+                                        false
+                                        && (tmpIn += inc) < leadEnd)
+#pragma warning restore                 
+                                    {
+                                        result = *tmpIn;
+                                        *tmpInd += 1;
+                                    }
+
+                                    
+                                    while (tmpIn < leadEnd) {
+                                        curval = *tmpIn;
+                                        if (curval < result) {
+                                                result = curval;
+                                            
+                                            *tmpInd = (double)(leadDimLen - (leadEnd - tmpIn) / inc);
+                                        }
+                                        tmpIn += inc;
+                                    }
+
+                                    *(tmpOut) = ( Int32)result;
+
+                                    tmpOut += inc;
+                                    tmpInd += inc;
+                                    if (tmpOut > lastElementOut) {
+                                        tmpOut -= outLength;
+                                        tmpInd -= outLength;
+                                    }
+                                    if (tmpIn > lastElementIn)
+                                        tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                                }
+                            } else {  // no indices
+                                for (int h = newLength; h-- > 0; ) {
+                                    leadEnd = tmpIn + leadDimLen * inc;
+
+                                    result = *tmpIn;
+                                    while
+#pragma warning disable
+                                    (
+                                        false
+                                        && (tmpIn += inc) < leadEnd)
+#pragma warning restore
+                                    {
+                                        result = *tmpIn;
+                                    }
+
+                                    
+                                    while (tmpIn < leadEnd) {
+                                        curval = *tmpIn;
+                                        if (curval < result) {
+                                                result = curval;
+                                            
+                                        }
+                                        tmpIn += inc;
+                                    }
+
+                                    *(tmpOut) = ( Int32)result;
+
+                                    tmpOut += inc;
+                                    if (tmpOut > lastElementOut) {
+                                        tmpOut -= outLength;
+                                    }
+                                    if (tmpIn > lastElementIn)
+                                        tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                                }
+                            }
+                        }
+                    }
+                    #endregion
+                }
+                if (createIndices) {
+                    I.a = array<double>(indices, newDims);
+                }
+                return new ILRetArray<Int32>(retArr, newDims);
+            }
+        }
+        /// <summary>Minimum value along specified dimension</summary>
+        /// <param name="A">Input array</param>
+        /// <param name="I">[Optional] If not null I will hold on return the indices into dim of  
+        /// the values found. If, on entering the function, I is null, those indices 
+        /// will not be computed and I will be ignored.</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns>Array of same inner type and size as A, except for dimension 
+        /// 'dim' which will be reduced to length 1.</returns>
+        public static  ILRetLogical  min(ILInArray<byte> A, ILOutArray<double> I = null, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (A.IsEmpty) {
+                    if (!object.Equals(I, null))
+                        I.a = empty<double>(ILSize.Empty00);
+                    return new  ILRetLogical(A.Size); 
+                }
+                if (dim >= A.Size.NumberOfDimensions || A.Size[dim] == 1) {
+                    // scalar or sum over singleton -> return copy
+                    if (!object.Equals(I, null))
+                        I.a = zeros<double>(A.S);
+                    return new ILRetLogical(A.C.Storage);
+                }
+                int[] newDims = A.Size.ToIntArray();
+                int leadDimLen = A.Size[dim];
+                int newLength = A.Size.NumberOfElements / leadDimLen;
+                newDims[dim] = 1;
+               
+                byte[] retArr = ILMemoryPool.Pool.New< byte>(newLength);
+                #region HYCALPER GLOBAL_INIT
+
+               
+                byte result;
+               
+                byte curval;
+                double[] indices = null;
+                bool createIndices = false;
+                if (!Object.Equals(I, null)) {
+                    indices = ILMemoryPool.Pool.New<double>(newLength);
+                    createIndices = true;
+                }
+                #endregion HYCALPER GLOBAL_INIT
+                
+
+                // physical -> pointer arithmetic
+                if (dim == 0) {
+                    #region physical along 1st leading dimension
+                    unsafe {
+                        fixed ( byte* pOutArr = retArr)
+                        fixed ( byte* pInArr = A.GetArrayForRead())
+                        fixed (double* pIndices = indices) {
+                           
+                            byte* lastElement;
+                           
+                            byte* tmpOut = pOutArr;
+                           
+                            byte* tmpIn = pInArr;
+                            if (createIndices) {
+                                double* tmpInd = pIndices;
+                                for (int h = newLength; h-- > 0; ) {
+
+                                    lastElement = tmpIn + leadDimLen;
+
+                                    result = *tmpIn;
+                                    while 
+#pragma warning disable
+                                    (
+                                        false
+                                        && ++tmpIn < lastElement) 
+#pragma warning restore
+                                    {
+                                        result = *tmpIn;
+                                        *tmpInd += 1;
+                                    }
+
+
+                                    
+                                    while (tmpIn < lastElement) {
+                                        curval = *tmpIn;
+                                        if (curval < result) {
+                                                result = curval;
+                                            
+                                            *tmpInd = (double)(tmpIn - (lastElement - leadDimLen));
+                                        }
+                                        tmpIn++;
+                                    }
+                                    *(tmpOut++) = ( byte)result;
+                                    tmpInd++;
+                                }
+                            } else {   // no indices
+                                double* tmpInd = pIndices;
+                                for (int h = newLength; h-- > 0; ) {
+                                    lastElement = tmpIn + leadDimLen;
+
+                                    result = *tmpIn;
+                                    while 
+#pragma warning disable
+                                        (
+                                        false
+                                        && ++tmpIn < lastElement) 
+#pragma warning restore
+                                        {
+                                        result = *tmpIn;
+                                    }
+
+                                    
+                                    while (tmpIn < lastElement) {
+                                        curval = *tmpIn++;
+                                        if (curval < result) {
+                                                result = curval;
+                                            
+                                        }
+                                    }
+
+                                    *(tmpOut++) = ( byte)result;
+
+                                }
+                            }
+                        }
+                    }
+                    #endregion physical along 1st leading dimension
+                } else {
+                    #region physical along abitrary dimension
+                    // sum along abitrary dimension 
+                    unsafe {
+                        fixed ( byte* pOutArr = retArr)
+                        fixed ( byte* pInArr = A.GetArrayForRead())
+                        fixed (double* pIndices = indices) {
+                           
+                            byte* lastElementOut = newLength + pOutArr - 1;
+                            int inLength = A.Size.NumberOfElements - 1;
+                           
+                            byte* lastElementIn = pInArr + inLength;
+                            int inc = A.Size.SequentialIndexDistance(dim);
+                           
+                            byte* tmpOut = pOutArr;
+                            int outLength = newLength - 1;
+                           
+                            byte* leadEnd;
+                           
+                            byte* tmpIn = pInArr;
+                            if (createIndices) {
+                                double* tmpInd = pIndices;
+                                for (int h = newLength; h-- > 0; ) {
+                                    leadEnd = tmpIn + leadDimLen * inc;
+
+                                    result = *tmpIn;
+                                    while 
+#pragma warning disable
+                                        (
+                                        false
+                                        && (tmpIn += inc) < leadEnd)
+#pragma warning restore                 
+                                    {
+                                        result = *tmpIn;
+                                        *tmpInd += 1;
+                                    }
+
+                                    
+                                    while (tmpIn < leadEnd) {
+                                        curval = *tmpIn;
+                                        if (curval < result) {
+                                                result = curval;
+                                            
+                                            *tmpInd = (double)(leadDimLen - (leadEnd - tmpIn) / inc);
+                                        }
+                                        tmpIn += inc;
+                                    }
+
+                                    *(tmpOut) = ( byte)result;
+
+                                    tmpOut += inc;
+                                    tmpInd += inc;
+                                    if (tmpOut > lastElementOut) {
+                                        tmpOut -= outLength;
+                                        tmpInd -= outLength;
+                                    }
+                                    if (tmpIn > lastElementIn)
+                                        tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                                }
+                            } else {  // no indices
+                                for (int h = newLength; h-- > 0; ) {
+                                    leadEnd = tmpIn + leadDimLen * inc;
+
+                                    result = *tmpIn;
+                                    while
+#pragma warning disable
+                                    (
+                                        false
+                                        && (tmpIn += inc) < leadEnd)
+#pragma warning restore
+                                    {
+                                        result = *tmpIn;
+                                    }
+
+                                    
+                                    while (tmpIn < leadEnd) {
+                                        curval = *tmpIn;
+                                        if (curval < result) {
+                                                result = curval;
+                                            
+                                        }
+                                        tmpIn += inc;
+                                    }
+
+                                    *(tmpOut) = ( byte)result;
+
+                                    tmpOut += inc;
+                                    if (tmpOut > lastElementOut) {
+                                        tmpOut -= outLength;
+                                    }
+                                    if (tmpIn > lastElementIn)
+                                        tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                                }
+                            }
+                        }
+                    }
+                    #endregion
+                }
+                if (createIndices) {
+                    I.a = array<double>(indices, newDims);
+                }
+                return new ILRetLogical(retArr, newDims);
+            }
+        }
+        /// <summary>Minimum value along specified dimension</summary>
+        /// <param name="A">Input array</param>
+        /// <param name="I">[Optional] If not null I will hold on return the indices into dim of  
+        /// the values found. If, on entering the function, I is null, those indices 
+        /// will not be computed and I will be ignored.</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns>Array of same inner type and size as A, except for dimension 
+        /// 'dim' which will be reduced to length 1.</returns>
+        public static  ILRetArray<fcomplex>  min(ILInArray<fcomplex> A, ILOutArray<double> I = null, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (A.IsEmpty) {
+                    if (!object.Equals(I, null))
+                        I.a = empty<double>(ILSize.Empty00);
+                    return new  ILRetArray<fcomplex>(A.Size); 
+                }
+                if (dim >= A.Size.NumberOfDimensions || A.Size[dim] == 1) {
+                    // scalar or sum over singleton -> return copy
+                    if (!object.Equals(I, null))
+                        I.a = zeros<double>(A.S);
+                    return new ILRetArray<fcomplex>(A.C.Storage);
+                }
+                int[] newDims = A.Size.ToIntArray();
+                int leadDimLen = A.Size[dim];
+                int newLength = A.Size.NumberOfElements / leadDimLen;
+                newDims[dim] = 1;
+               
+                fcomplex[] retArr = ILMemoryPool.Pool.New< fcomplex>(newLength);
+                #region HYCALPER GLOBAL_INIT
+
+               
+                fcomplex result;
+               
+                fcomplex curval;
+                double[] indices = null;
+                bool createIndices = false;
+                if (!Object.Equals(I, null)) {
+                    indices = ILMemoryPool.Pool.New<double>(newLength);
+                    createIndices = true;
+                }
+                #endregion HYCALPER GLOBAL_INIT
+                float curabsval; float curabsmaxval; 
+
+                // physical -> pointer arithmetic
+                if (dim == 0) {
+                    #region physical along 1st leading dimension
+                    unsafe {
+                        fixed ( fcomplex* pOutArr = retArr)
+                        fixed ( fcomplex* pInArr = A.GetArrayForRead())
+                        fixed (double* pIndices = indices) {
+                           
+                            fcomplex* lastElement;
+                           
+                            fcomplex* tmpOut = pOutArr;
+                           
+                            fcomplex* tmpIn = pInArr;
+                            if (createIndices) {
+                                double* tmpInd = pIndices;
+                                for (int h = newLength; h-- > 0; ) {
+
+                                    lastElement = tmpIn + leadDimLen;
+
+                                    result = *tmpIn;
+                                    while 
+#pragma warning disable
+                                    (
+                                        fcomplex.IsNaN(result)
+                                        && ++tmpIn < lastElement) 
+#pragma warning restore
+                                    {
+                                        result = *tmpIn;
+                                        *tmpInd += 1;
+                                    }
+
+
+                                    curabsmaxval = fcomplex.Abs(result);
+                                    while (tmpIn < lastElement) {
+                                        curval = *tmpIn;
+                                        curabsval = fcomplex.Abs(curval);
+                                            if (curabsval < curabsmaxval) {
+                                                curabsmaxval = curabsval;
+                                                result = curval;
+                                            
+                                            *tmpInd = (double)(tmpIn - (lastElement - leadDimLen));
+                                        }
+                                        tmpIn++;
+                                    }
+                                    *(tmpOut++) = ( fcomplex)result;
+                                    tmpInd++;
+                                }
+                            } else {   // no indices
+                                double* tmpInd = pIndices;
+                                for (int h = newLength; h-- > 0; ) {
+                                    lastElement = tmpIn + leadDimLen;
+
+                                    result = *tmpIn;
+                                    while 
+#pragma warning disable
+                                        (
+                                        fcomplex.IsNaN(result)
+                                        && ++tmpIn < lastElement) 
+#pragma warning restore
+                                        {
+                                        result = *tmpIn;
+                                    }
+
+                                    curabsmaxval = fcomplex.Abs(result);
+                                    while (tmpIn < lastElement) {
+                                        curval = *tmpIn++;
+                                        curabsval = fcomplex.Abs(curval);
+                                            if (curabsval < curabsmaxval) {
+                                                curabsmaxval = curabsval;
+                                                result = curval;
+                                            
+                                        }
+                                    }
+
+                                    *(tmpOut++) = ( fcomplex)result;
+
+                                }
+                            }
+                        }
+                    }
+                    #endregion physical along 1st leading dimension
+                } else {
+                    #region physical along abitrary dimension
+                    // sum along abitrary dimension 
+                    unsafe {
+                        fixed ( fcomplex* pOutArr = retArr)
+                        fixed ( fcomplex* pInArr = A.GetArrayForRead())
+                        fixed (double* pIndices = indices) {
+                           
+                            fcomplex* lastElementOut = newLength + pOutArr - 1;
+                            int inLength = A.Size.NumberOfElements - 1;
+                           
+                            fcomplex* lastElementIn = pInArr + inLength;
+                            int inc = A.Size.SequentialIndexDistance(dim);
+                           
+                            fcomplex* tmpOut = pOutArr;
+                            int outLength = newLength - 1;
+                           
+                            fcomplex* leadEnd;
+                           
+                            fcomplex* tmpIn = pInArr;
+                            if (createIndices) {
+                                double* tmpInd = pIndices;
+                                for (int h = newLength; h-- > 0; ) {
+                                    leadEnd = tmpIn + leadDimLen * inc;
+
+                                    result = *tmpIn;
+                                    while 
+#pragma warning disable
+                                        (
+                                        fcomplex.IsNaN(result)
+                                        && (tmpIn += inc) < leadEnd)
+#pragma warning restore                 
+                                    {
+                                        result = *tmpIn;
+                                        *tmpInd += 1;
+                                    }
+
+                                    curabsmaxval = fcomplex.Abs(result);
+                                    while (tmpIn < leadEnd) {
+                                        curval = *tmpIn;
+                                        curabsval = fcomplex.Abs(curval);
+                                            if (curabsval < curabsmaxval) {
+                                                curabsmaxval = curabsval;
+                                                result = curval;
+                                            
+                                            *tmpInd = (double)(leadDimLen - (leadEnd - tmpIn) / inc);
+                                        }
+                                        tmpIn += inc;
+                                    }
+
+                                    *(tmpOut) = ( fcomplex)result;
+
+                                    tmpOut += inc;
+                                    tmpInd += inc;
+                                    if (tmpOut > lastElementOut) {
+                                        tmpOut -= outLength;
+                                        tmpInd -= outLength;
+                                    }
+                                    if (tmpIn > lastElementIn)
+                                        tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                                }
+                            } else {  // no indices
+                                for (int h = newLength; h-- > 0; ) {
+                                    leadEnd = tmpIn + leadDimLen * inc;
+
+                                    result = *tmpIn;
+                                    while
+#pragma warning disable
+                                    (
+                                        fcomplex.IsNaN(result)
+                                        && (tmpIn += inc) < leadEnd)
+#pragma warning restore
+                                    {
+                                        result = *tmpIn;
+                                    }
+
+                                    curabsmaxval = fcomplex.Abs(result);
+                                    while (tmpIn < leadEnd) {
+                                        curval = *tmpIn;
+                                        curabsval = fcomplex.Abs(curval);
+                                            if (curabsval < curabsmaxval) {
+                                                curabsmaxval = curabsval;
+                                                result = curval;
+                                            
+                                        }
+                                        tmpIn += inc;
+                                    }
+
+                                    *(tmpOut) = ( fcomplex)result;
+
+                                    tmpOut += inc;
+                                    if (tmpOut > lastElementOut) {
+                                        tmpOut -= outLength;
+                                    }
+                                    if (tmpIn > lastElementIn)
+                                        tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                                }
+                            }
+                        }
+                    }
+                    #endregion
+                }
+                if (createIndices) {
+                    I.a = array<double>(indices, newDims);
+                }
+                return new ILRetArray<fcomplex>(retArr, newDims);
+            }
+        }
+        /// <summary>Minimum value along specified dimension</summary>
+        /// <param name="A">Input array</param>
+        /// <param name="I">[Optional] If not null I will hold on return the indices into dim of  
+        /// the values found. If, on entering the function, I is null, those indices 
+        /// will not be computed and I will be ignored.</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns>Array of same inner type and size as A, except for dimension 
+        /// 'dim' which will be reduced to length 1.</returns>
+        public static  ILRetArray<float>  min(ILInArray<float> A, ILOutArray<double> I = null, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (A.IsEmpty) {
+                    if (!object.Equals(I, null))
+                        I.a = empty<double>(ILSize.Empty00);
+                    return new  ILRetArray<float>(A.Size); 
+                }
+                if (dim >= A.Size.NumberOfDimensions || A.Size[dim] == 1) {
+                    // scalar or sum over singleton -> return copy
+                    if (!object.Equals(I, null))
+                        I.a = zeros<double>(A.S);
+                    return new ILRetArray<float>(A.C.Storage);
+                }
+                int[] newDims = A.Size.ToIntArray();
+                int leadDimLen = A.Size[dim];
+                int newLength = A.Size.NumberOfElements / leadDimLen;
+                newDims[dim] = 1;
+               
+                float[] retArr = ILMemoryPool.Pool.New< float>(newLength);
+                #region HYCALPER GLOBAL_INIT
+
+               
+                float result;
+               
+                float curval;
+                double[] indices = null;
+                bool createIndices = false;
+                if (!Object.Equals(I, null)) {
+                    indices = ILMemoryPool.Pool.New<double>(newLength);
+                    createIndices = true;
+                }
+                #endregion HYCALPER GLOBAL_INIT
+                
+
+                // physical -> pointer arithmetic
+                if (dim == 0) {
+                    #region physical along 1st leading dimension
+                    unsafe {
+                        fixed ( float* pOutArr = retArr)
+                        fixed ( float* pInArr = A.GetArrayForRead())
+                        fixed (double* pIndices = indices) {
+                           
+                            float* lastElement;
+                           
+                            float* tmpOut = pOutArr;
+                           
+                            float* tmpIn = pInArr;
+                            if (createIndices) {
+                                double* tmpInd = pIndices;
+                                for (int h = newLength; h-- > 0; ) {
+
+                                    lastElement = tmpIn + leadDimLen;
+
+                                    result = *tmpIn;
+                                    while 
+#pragma warning disable
+                                    (
+                                        float.IsNaN(result)
+                                        && ++tmpIn < lastElement) 
+#pragma warning restore
+                                    {
+                                        result = *tmpIn;
+                                        *tmpInd += 1;
+                                    }
+
+
+                                    
+                                    while (tmpIn < lastElement) {
+                                        curval = *tmpIn;
+                                        if (curval < result) {
+                                                result = curval;
+                                            
+                                            *tmpInd = (double)(tmpIn - (lastElement - leadDimLen));
+                                        }
+                                        tmpIn++;
+                                    }
+                                    *(tmpOut++) = ( float)result;
+                                    tmpInd++;
+                                }
+                            } else {   // no indices
+                                double* tmpInd = pIndices;
+                                for (int h = newLength; h-- > 0; ) {
+                                    lastElement = tmpIn + leadDimLen;
+
+                                    result = *tmpIn;
+                                    while 
+#pragma warning disable
+                                        (
+                                        float.IsNaN(result)
+                                        && ++tmpIn < lastElement) 
+#pragma warning restore
+                                        {
+                                        result = *tmpIn;
+                                    }
+
+                                    
+                                    while (tmpIn < lastElement) {
+                                        curval = *tmpIn++;
+                                        if (curval < result) {
+                                                result = curval;
+                                            
+                                        }
+                                    }
+
+                                    *(tmpOut++) = ( float)result;
+
+                                }
+                            }
+                        }
+                    }
+                    #endregion physical along 1st leading dimension
+                } else {
+                    #region physical along abitrary dimension
+                    // sum along abitrary dimension 
+                    unsafe {
+                        fixed ( float* pOutArr = retArr)
+                        fixed ( float* pInArr = A.GetArrayForRead())
+                        fixed (double* pIndices = indices) {
+                           
+                            float* lastElementOut = newLength + pOutArr - 1;
+                            int inLength = A.Size.NumberOfElements - 1;
+                           
+                            float* lastElementIn = pInArr + inLength;
+                            int inc = A.Size.SequentialIndexDistance(dim);
+                           
+                            float* tmpOut = pOutArr;
+                            int outLength = newLength - 1;
+                           
+                            float* leadEnd;
+                           
+                            float* tmpIn = pInArr;
+                            if (createIndices) {
+                                double* tmpInd = pIndices;
+                                for (int h = newLength; h-- > 0; ) {
+                                    leadEnd = tmpIn + leadDimLen * inc;
+
+                                    result = *tmpIn;
+                                    while 
+#pragma warning disable
+                                        (
+                                        float.IsNaN(result)
+                                        && (tmpIn += inc) < leadEnd)
+#pragma warning restore                 
+                                    {
+                                        result = *tmpIn;
+                                        *tmpInd += 1;
+                                    }
+
+                                    
+                                    while (tmpIn < leadEnd) {
+                                        curval = *tmpIn;
+                                        if (curval < result) {
+                                                result = curval;
+                                            
+                                            *tmpInd = (double)(leadDimLen - (leadEnd - tmpIn) / inc);
+                                        }
+                                        tmpIn += inc;
+                                    }
+
+                                    *(tmpOut) = ( float)result;
+
+                                    tmpOut += inc;
+                                    tmpInd += inc;
+                                    if (tmpOut > lastElementOut) {
+                                        tmpOut -= outLength;
+                                        tmpInd -= outLength;
+                                    }
+                                    if (tmpIn > lastElementIn)
+                                        tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                                }
+                            } else {  // no indices
+                                for (int h = newLength; h-- > 0; ) {
+                                    leadEnd = tmpIn + leadDimLen * inc;
+
+                                    result = *tmpIn;
+                                    while
+#pragma warning disable
+                                    (
+                                        float.IsNaN(result)
+                                        && (tmpIn += inc) < leadEnd)
+#pragma warning restore
+                                    {
+                                        result = *tmpIn;
+                                    }
+
+                                    
+                                    while (tmpIn < leadEnd) {
+                                        curval = *tmpIn;
+                                        if (curval < result) {
+                                                result = curval;
+                                            
+                                        }
+                                        tmpIn += inc;
+                                    }
+
+                                    *(tmpOut) = ( float)result;
+
+                                    tmpOut += inc;
+                                    if (tmpOut > lastElementOut) {
+                                        tmpOut -= outLength;
+                                    }
+                                    if (tmpIn > lastElementIn)
+                                        tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                                }
+                            }
+                        }
+                    }
+                    #endregion
+                }
+                if (createIndices) {
+                    I.a = array<double>(indices, newDims);
+                }
+                return new ILRetArray<float>(retArr, newDims);
+            }
+        }
+        /// <summary>Minimum value along specified dimension</summary>
+        /// <param name="A">Input array</param>
+        /// <param name="I">[Optional] If not null I will hold on return the indices into dim of  
+        /// the values found. If, on entering the function, I is null, those indices 
+        /// will not be computed and I will be ignored.</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns>Array of same inner type and size as A, except for dimension 
+        /// 'dim' which will be reduced to length 1.</returns>
+        public static  ILRetArray<complex>  min(ILInArray<complex> A, ILOutArray<double> I = null, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (A.IsEmpty) {
+                    if (!object.Equals(I, null))
+                        I.a = empty<double>(ILSize.Empty00);
+                    return new  ILRetArray<complex>(A.Size); 
+                }
+                if (dim >= A.Size.NumberOfDimensions || A.Size[dim] == 1) {
+                    // scalar or sum over singleton -> return copy
+                    if (!object.Equals(I, null))
+                        I.a = zeros<double>(A.S);
+                    return new ILRetArray<complex>(A.C.Storage);
+                }
+                int[] newDims = A.Size.ToIntArray();
+                int leadDimLen = A.Size[dim];
+                int newLength = A.Size.NumberOfElements / leadDimLen;
+                newDims[dim] = 1;
+               
+                complex[] retArr = ILMemoryPool.Pool.New< complex>(newLength);
+                #region HYCALPER GLOBAL_INIT
+
+               
+                complex result;
+               
+                complex curval;
+                double[] indices = null;
+                bool createIndices = false;
+                if (!Object.Equals(I, null)) {
+                    indices = ILMemoryPool.Pool.New<double>(newLength);
+                    createIndices = true;
+                }
+                #endregion HYCALPER GLOBAL_INIT
+                double curabsval; double curabsmaxval; 
+
+                // physical -> pointer arithmetic
+                if (dim == 0) {
+                    #region physical along 1st leading dimension
+                    unsafe {
+                        fixed ( complex* pOutArr = retArr)
+                        fixed ( complex* pInArr = A.GetArrayForRead())
+                        fixed (double* pIndices = indices) {
+                           
+                            complex* lastElement;
+                           
+                            complex* tmpOut = pOutArr;
+                           
+                            complex* tmpIn = pInArr;
+                            if (createIndices) {
+                                double* tmpInd = pIndices;
+                                for (int h = newLength; h-- > 0; ) {
+
+                                    lastElement = tmpIn + leadDimLen;
+
+                                    result = *tmpIn;
+                                    while 
+#pragma warning disable
+                                    (
+                                        complex.IsNaN(result)
+                                        && ++tmpIn < lastElement) 
+#pragma warning restore
+                                    {
+                                        result = *tmpIn;
+                                        *tmpInd += 1;
+                                    }
+
+
+                                    curabsmaxval = complex.Abs(result);
+                                    while (tmpIn < lastElement) {
+                                        curval = *tmpIn;
+                                        curabsval = complex.Abs(curval);
+                                            if (curabsval < curabsmaxval) {
+                                                curabsmaxval = curabsval;
+                                                result = curval;
+                                            
+                                            *tmpInd = (double)(tmpIn - (lastElement - leadDimLen));
+                                        }
+                                        tmpIn++;
+                                    }
+                                    *(tmpOut++) = ( complex)result;
+                                    tmpInd++;
+                                }
+                            } else {   // no indices
+                                double* tmpInd = pIndices;
+                                for (int h = newLength; h-- > 0; ) {
+                                    lastElement = tmpIn + leadDimLen;
+
+                                    result = *tmpIn;
+                                    while 
+#pragma warning disable
+                                        (
+                                        complex.IsNaN(result)
+                                        && ++tmpIn < lastElement) 
+#pragma warning restore
+                                        {
+                                        result = *tmpIn;
+                                    }
+
+                                    curabsmaxval = complex.Abs(result);
+                                    while (tmpIn < lastElement) {
+                                        curval = *tmpIn++;
+                                        curabsval = complex.Abs(curval);
+                                            if (curabsval < curabsmaxval) {
+                                                curabsmaxval = curabsval;
+                                                result = curval;
+                                            
+                                        }
+                                    }
+
+                                    *(tmpOut++) = ( complex)result;
+
+                                }
+                            }
+                        }
+                    }
+                    #endregion physical along 1st leading dimension
+                } else {
+                    #region physical along abitrary dimension
+                    // sum along abitrary dimension 
+                    unsafe {
+                        fixed ( complex* pOutArr = retArr)
+                        fixed ( complex* pInArr = A.GetArrayForRead())
+                        fixed (double* pIndices = indices) {
+                           
+                            complex* lastElementOut = newLength + pOutArr - 1;
+                            int inLength = A.Size.NumberOfElements - 1;
+                           
+                            complex* lastElementIn = pInArr + inLength;
+                            int inc = A.Size.SequentialIndexDistance(dim);
+                           
+                            complex* tmpOut = pOutArr;
+                            int outLength = newLength - 1;
+                           
+                            complex* leadEnd;
+                           
+                            complex* tmpIn = pInArr;
+                            if (createIndices) {
+                                double* tmpInd = pIndices;
+                                for (int h = newLength; h-- > 0; ) {
+                                    leadEnd = tmpIn + leadDimLen * inc;
+
+                                    result = *tmpIn;
+                                    while 
+#pragma warning disable
+                                        (
+                                        complex.IsNaN(result)
+                                        && (tmpIn += inc) < leadEnd)
+#pragma warning restore                 
+                                    {
+                                        result = *tmpIn;
+                                        *tmpInd += 1;
+                                    }
+
+                                    curabsmaxval = complex.Abs(result);
+                                    while (tmpIn < leadEnd) {
+                                        curval = *tmpIn;
+                                        curabsval = complex.Abs(curval);
+                                            if (curabsval < curabsmaxval) {
+                                                curabsmaxval = curabsval;
+                                                result = curval;
+                                            
+                                            *tmpInd = (double)(leadDimLen - (leadEnd - tmpIn) / inc);
+                                        }
+                                        tmpIn += inc;
+                                    }
+
+                                    *(tmpOut) = ( complex)result;
+
+                                    tmpOut += inc;
+                                    tmpInd += inc;
+                                    if (tmpOut > lastElementOut) {
+                                        tmpOut -= outLength;
+                                        tmpInd -= outLength;
+                                    }
+                                    if (tmpIn > lastElementIn)
+                                        tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                                }
+                            } else {  // no indices
+                                for (int h = newLength; h-- > 0; ) {
+                                    leadEnd = tmpIn + leadDimLen * inc;
+
+                                    result = *tmpIn;
+                                    while
+#pragma warning disable
+                                    (
+                                        complex.IsNaN(result)
+                                        && (tmpIn += inc) < leadEnd)
+#pragma warning restore
+                                    {
+                                        result = *tmpIn;
+                                    }
+
+                                    curabsmaxval = complex.Abs(result);
+                                    while (tmpIn < leadEnd) {
+                                        curval = *tmpIn;
+                                        curabsval = complex.Abs(curval);
+                                            if (curabsval < curabsmaxval) {
+                                                curabsmaxval = curabsval;
+                                                result = curval;
+                                            
+                                        }
+                                        tmpIn += inc;
+                                    }
+
+                                    *(tmpOut) = ( complex)result;
+
+                                    tmpOut += inc;
+                                    if (tmpOut > lastElementOut) {
+                                        tmpOut -= outLength;
+                                    }
+                                    if (tmpIn > lastElementIn)
+                                        tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                                }
+                            }
+                        }
+                    }
+                    #endregion
+                }
+                if (createIndices) {
+                    I.a = array<double>(indices, newDims);
+                }
+                return new ILRetArray<complex>(retArr, newDims);
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+
+        
+
+#region HYCALPER AUTO GENERATED CODE
+
+       
+        /// <summary>Minimum of A and B elementwise</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Array with the minimum elements of A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<Int64>  min(ILInArray<Int64> A, ILInArray<Int64> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                Int64[] retArr;
+                Int64[] arrA = A.GetArrayForRead();
+                Int64[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size;
+                    if (B.IsScalar) {
+                        return array<Int64>(new Int64[1] { (A.GetValue(0) > B.GetValue(0)) ? A.GetValue(0) : B.GetValue(0) });
+                    } else if (B.IsEmpty) {
+                        return ILRetArray<Int64>.empty(outDims);
+                    } else {
+                        outLen = outDims.NumberOfElements;
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< Int64>(outLen);
+                            mode = BinOpItMode.SAN;
+                        } else {
+                            mode = BinOpItMode.SAI;
+                        }
+                    }
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return ILRetArray<Int64>.empty(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New<Int64>(outLen);
+                            mode = BinOpItMode.ASN;
+                        } else {
+                            mode = BinOpItMode.ASI;
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  minEx(A, B);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        if (A.TryGetStorage4InplaceOp(out retArr))
+                            mode = BinOpItMode.AAIA;
+                        else if (B.TryGetStorage4InplaceOp(out retArr))
+                            mode = BinOpItMode.AAIB;
+                        else {
+                            retArr = ILMemoryPool.Pool.New<Int64>(outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<Int64> retStorage = new ILDenseStorage<Int64>(retArr, outDims);
+                int i = 0, workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                   
+                    Int64* cp = (Int64*)range.Item5 + range.Item1;
+                   
+                    Int64 scalar;
+                    int j = range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           
+                            Int64* bp = ((Int64*)range.Item4 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (cp[0]  < bp[0]) ? cp[0] : bp[0];
+                                cp[1] = (cp[1]  < bp[1]) ? cp[1] : bp[1];
+                                cp[2] = (cp[2]  < bp[2]) ? cp[2] : bp[2];
+                                cp[3] = (cp[3]  < bp[3]) ? cp[3] : bp[3];
+                                cp[4] = (cp[4]  < bp[4]) ? cp[4] : bp[4];
+                                cp[5] = (cp[5]  < bp[5]) ? cp[5] : bp[5];
+                                cp[6] = (cp[6]  < bp[6]) ? cp[6] : bp[6];
+                                cp[7] = (cp[7]  < bp[7]) ? cp[7] : bp[7];
+                                cp += 8; bp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*cp  < *bp) ? *cp : *bp;
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           
+                            Int64* ap = ((Int64*)range.Item3 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (ap[0]  < cp[0]) ? ap[0] : cp[0];
+                                cp[1] = (ap[1]  < cp[1]) ? ap[1] : cp[1];
+                                cp[2] = (ap[2]  < cp[2]) ? ap[2] : cp[2];
+                                cp[3] = (ap[3]  < cp[3]) ? ap[3] : cp[3];
+                                cp[4] = (ap[4]  < cp[4]) ? ap[4] : cp[4];
+                                cp[5] = (ap[5]  < cp[5]) ? ap[5] : cp[5];
+                                cp[6] = (ap[6]  < cp[6]) ? ap[6] : cp[6];
+                                cp[7] = (ap[7]  < cp[7]) ? ap[7] : cp[7];
+                                ap += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*ap  < *cp) ? *ap : *cp;
+                                ap++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((Int64*)range.Item3 + range.Item1);
+                            bp = ((Int64*)range.Item4 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (ap[0]  < bp[0]) ? ap[0] : bp[0];
+                                cp[1] = (ap[1]  < bp[1]) ? ap[1] : bp[1];
+                                cp[2] = (ap[2]  < bp[2]) ? ap[2] : bp[2];
+                                cp[3] = (ap[3]  < bp[3]) ? ap[3] : bp[3];
+                                cp[4] = (ap[4]  < bp[4]) ? ap[4] : bp[4];
+                                cp[5] = (ap[5]  < bp[5]) ? ap[5] : bp[5];
+                                cp[6] = (ap[6]  < bp[6]) ? ap[6] : bp[6];
+                                cp[7] = (ap[7]  < bp[7]) ? ap[7] : bp[7];
+                                ap += 8; bp += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*ap  < *bp) ? *ap : *bp;
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((Int64*)range.Item4);
+                            while (j > 7) {
+                                cp[0] = (cp[0]  < scalar) ? cp[0] : scalar;
+                                cp[1] = (cp[1]  < scalar) ? cp[1] : scalar;
+                                cp[2] = (cp[2]  < scalar) ? cp[2] : scalar;
+                                cp[3] = (cp[3]  < scalar) ? cp[3] : scalar;
+                                cp[4] = (cp[4]  < scalar) ? cp[4] : scalar;
+                                cp[5] = (cp[5]  < scalar) ? cp[5] : scalar;
+                                cp[6] = (cp[6]  < scalar) ? cp[6] : scalar;
+                                cp[7] = (cp[7]  < scalar) ? cp[7] : scalar;
+                                cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*cp  < scalar) ? *cp : scalar;
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((Int64*)range.Item3 + range.Item1);
+                            scalar = *((Int64*)range.Item4);
+                            while (j > 7) {
+                                cp[0] = (ap[0]  < scalar) ? ap[0] : scalar;
+                                cp[1] = (ap[1]  < scalar) ? ap[1] : scalar;
+                                cp[2] = (ap[2]  < scalar) ? ap[2] : scalar;
+                                cp[3] = (ap[3]  < scalar) ? ap[3] : scalar;
+                                cp[4] = (ap[4]  < scalar) ? ap[4] : scalar;
+                                cp[5] = (ap[5]  < scalar) ? ap[5] : scalar;
+                                cp[6] = (ap[6]  < scalar) ? ap[6] : scalar;
+                                cp[7] = (ap[7]  < scalar) ? ap[7] : scalar;
+                                ap += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*ap  < scalar) ? *ap : scalar;
+                                ap++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((Int64*)range.Item3);
+                            while (j > 7) {
+                                cp[0] = (scalar  < cp[0]) ? scalar : cp[0];
+                                cp[1] = (scalar  < cp[1]) ? scalar : cp[1];
+                                cp[2] = (scalar  < cp[2]) ? scalar : cp[2];
+                                cp[3] = (scalar  < cp[3]) ? scalar : cp[3];
+                                cp[4] = (scalar  < cp[4]) ? scalar : cp[4];
+                                cp[5] = (scalar  < cp[5]) ? scalar : cp[5];
+                                cp[6] = (scalar  < cp[6]) ? scalar : cp[6];
+                                cp[7] = (scalar  < cp[7]) ? scalar : cp[7];
+                                cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (scalar  < *cp) ? scalar : *cp;
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((Int64*)range.Item3);
+                            bp = ((Int64*)range.Item4 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (scalar  < bp[0]) ? scalar : bp[0];
+                                cp[1] = (scalar  < bp[1]) ? scalar : bp[1];
+                                cp[2] = (scalar  < bp[2]) ? scalar : bp[2];
+                                cp[3] = (scalar  < bp[3]) ? scalar : bp[3];
+                                cp[4] = (scalar  < bp[4]) ? scalar : bp[4];
+                                cp[5] = (scalar  < bp[5]) ? scalar : bp[5];
+                                cp[6] = (scalar  < bp[6]) ? scalar : bp[6];
+                                cp[7] = (scalar  < bp[7]) ? scalar : bp[7];
+                                bp += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (scalar  < *bp) ? scalar : *bp;
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+
+                fixed (Int64* arrAP = arrA)
+                fixed (Int64* arrBP = arrB)
+                fixed (Int64* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new ILRetArray<Int64>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<Int64>  minEx(ILInArray<Int64> A, ILInArray<Int64> B) {
+            using (ILScope.Enter(A, B)) {
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<Int64>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<Int64>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<Int64>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+
+               
+                Int64[] retArr;
+
+               
+                Int64[] arrA = A.GetArrayForRead();
+
+               
+                Int64[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<Int64>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<Int64>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<Int64> retStorage = new ILDenseStorage<Int64>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+
+                   
+                    Int64* ap;
+
+                   
+                    Int64* bp;
+
+                   
+                    Int64* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (Int64*)range.Item3;
+                                bp = (Int64*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (Int64*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap  < *bp) ? *ap : *bp;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (Int64*)range.Item3;
+                                cp = (Int64*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap  < *cp) ? *ap : *cp;
+                                    ap++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (Int64*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (Int64*)range.Item4;
+                                cp = (Int64*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap  < *bp) ? *ap : *bp;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            for (int s = 0; s < range.Item2; s++) {
+                                bp = (Int64*)range.Item4;
+                                cp = (Int64*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*cp  < *bp) ? *cp : *bp;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed (Int64* arrAP = arrA)
+                fixed (Int64* arrBP = arrB)
+                fixed (Int64* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<Int64>(retStorage);
+            }
+        }
+
+
+       
+        /// <summary>Minimum of A and B elementwise</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Array with the minimum elements of A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<Int32>  min(ILInArray<Int32> A, ILInArray<Int32> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                Int32[] retArr;
+                Int32[] arrA = A.GetArrayForRead();
+                Int32[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size;
+                    if (B.IsScalar) {
+                        return array<Int32>(new Int32[1] { (A.GetValue(0) > B.GetValue(0)) ? A.GetValue(0) : B.GetValue(0) });
+                    } else if (B.IsEmpty) {
+                        return ILRetArray<Int32>.empty(outDims);
+                    } else {
+                        outLen = outDims.NumberOfElements;
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< Int32>(outLen);
+                            mode = BinOpItMode.SAN;
+                        } else {
+                            mode = BinOpItMode.SAI;
+                        }
+                    }
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return ILRetArray<Int32>.empty(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New<Int32>(outLen);
+                            mode = BinOpItMode.ASN;
+                        } else {
+                            mode = BinOpItMode.ASI;
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  minEx(A, B);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        if (A.TryGetStorage4InplaceOp(out retArr))
+                            mode = BinOpItMode.AAIA;
+                        else if (B.TryGetStorage4InplaceOp(out retArr))
+                            mode = BinOpItMode.AAIB;
+                        else {
+                            retArr = ILMemoryPool.Pool.New<Int32>(outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<Int32> retStorage = new ILDenseStorage<Int32>(retArr, outDims);
+                int i = 0, workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                   
+                    Int32* cp = (Int32*)range.Item5 + range.Item1;
+                   
+                    Int32 scalar;
+                    int j = range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           
+                            Int32* bp = ((Int32*)range.Item4 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (cp[0]  < bp[0]) ? cp[0] : bp[0];
+                                cp[1] = (cp[1]  < bp[1]) ? cp[1] : bp[1];
+                                cp[2] = (cp[2]  < bp[2]) ? cp[2] : bp[2];
+                                cp[3] = (cp[3]  < bp[3]) ? cp[3] : bp[3];
+                                cp[4] = (cp[4]  < bp[4]) ? cp[4] : bp[4];
+                                cp[5] = (cp[5]  < bp[5]) ? cp[5] : bp[5];
+                                cp[6] = (cp[6]  < bp[6]) ? cp[6] : bp[6];
+                                cp[7] = (cp[7]  < bp[7]) ? cp[7] : bp[7];
+                                cp += 8; bp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*cp  < *bp) ? *cp : *bp;
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           
+                            Int32* ap = ((Int32*)range.Item3 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (ap[0]  < cp[0]) ? ap[0] : cp[0];
+                                cp[1] = (ap[1]  < cp[1]) ? ap[1] : cp[1];
+                                cp[2] = (ap[2]  < cp[2]) ? ap[2] : cp[2];
+                                cp[3] = (ap[3]  < cp[3]) ? ap[3] : cp[3];
+                                cp[4] = (ap[4]  < cp[4]) ? ap[4] : cp[4];
+                                cp[5] = (ap[5]  < cp[5]) ? ap[5] : cp[5];
+                                cp[6] = (ap[6]  < cp[6]) ? ap[6] : cp[6];
+                                cp[7] = (ap[7]  < cp[7]) ? ap[7] : cp[7];
+                                ap += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*ap  < *cp) ? *ap : *cp;
+                                ap++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((Int32*)range.Item3 + range.Item1);
+                            bp = ((Int32*)range.Item4 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (ap[0]  < bp[0]) ? ap[0] : bp[0];
+                                cp[1] = (ap[1]  < bp[1]) ? ap[1] : bp[1];
+                                cp[2] = (ap[2]  < bp[2]) ? ap[2] : bp[2];
+                                cp[3] = (ap[3]  < bp[3]) ? ap[3] : bp[3];
+                                cp[4] = (ap[4]  < bp[4]) ? ap[4] : bp[4];
+                                cp[5] = (ap[5]  < bp[5]) ? ap[5] : bp[5];
+                                cp[6] = (ap[6]  < bp[6]) ? ap[6] : bp[6];
+                                cp[7] = (ap[7]  < bp[7]) ? ap[7] : bp[7];
+                                ap += 8; bp += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*ap  < *bp) ? *ap : *bp;
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((Int32*)range.Item4);
+                            while (j > 7) {
+                                cp[0] = (cp[0]  < scalar) ? cp[0] : scalar;
+                                cp[1] = (cp[1]  < scalar) ? cp[1] : scalar;
+                                cp[2] = (cp[2]  < scalar) ? cp[2] : scalar;
+                                cp[3] = (cp[3]  < scalar) ? cp[3] : scalar;
+                                cp[4] = (cp[4]  < scalar) ? cp[4] : scalar;
+                                cp[5] = (cp[5]  < scalar) ? cp[5] : scalar;
+                                cp[6] = (cp[6]  < scalar) ? cp[6] : scalar;
+                                cp[7] = (cp[7]  < scalar) ? cp[7] : scalar;
+                                cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*cp  < scalar) ? *cp : scalar;
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((Int32*)range.Item3 + range.Item1);
+                            scalar = *((Int32*)range.Item4);
+                            while (j > 7) {
+                                cp[0] = (ap[0]  < scalar) ? ap[0] : scalar;
+                                cp[1] = (ap[1]  < scalar) ? ap[1] : scalar;
+                                cp[2] = (ap[2]  < scalar) ? ap[2] : scalar;
+                                cp[3] = (ap[3]  < scalar) ? ap[3] : scalar;
+                                cp[4] = (ap[4]  < scalar) ? ap[4] : scalar;
+                                cp[5] = (ap[5]  < scalar) ? ap[5] : scalar;
+                                cp[6] = (ap[6]  < scalar) ? ap[6] : scalar;
+                                cp[7] = (ap[7]  < scalar) ? ap[7] : scalar;
+                                ap += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*ap  < scalar) ? *ap : scalar;
+                                ap++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((Int32*)range.Item3);
+                            while (j > 7) {
+                                cp[0] = (scalar  < cp[0]) ? scalar : cp[0];
+                                cp[1] = (scalar  < cp[1]) ? scalar : cp[1];
+                                cp[2] = (scalar  < cp[2]) ? scalar : cp[2];
+                                cp[3] = (scalar  < cp[3]) ? scalar : cp[3];
+                                cp[4] = (scalar  < cp[4]) ? scalar : cp[4];
+                                cp[5] = (scalar  < cp[5]) ? scalar : cp[5];
+                                cp[6] = (scalar  < cp[6]) ? scalar : cp[6];
+                                cp[7] = (scalar  < cp[7]) ? scalar : cp[7];
+                                cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (scalar  < *cp) ? scalar : *cp;
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((Int32*)range.Item3);
+                            bp = ((Int32*)range.Item4 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (scalar  < bp[0]) ? scalar : bp[0];
+                                cp[1] = (scalar  < bp[1]) ? scalar : bp[1];
+                                cp[2] = (scalar  < bp[2]) ? scalar : bp[2];
+                                cp[3] = (scalar  < bp[3]) ? scalar : bp[3];
+                                cp[4] = (scalar  < bp[4]) ? scalar : bp[4];
+                                cp[5] = (scalar  < bp[5]) ? scalar : bp[5];
+                                cp[6] = (scalar  < bp[6]) ? scalar : bp[6];
+                                cp[7] = (scalar  < bp[7]) ? scalar : bp[7];
+                                bp += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (scalar  < *bp) ? scalar : *bp;
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+
+                fixed (Int32* arrAP = arrA)
+                fixed (Int32* arrBP = arrB)
+                fixed (Int32* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new ILRetArray<Int32>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<Int32>  minEx(ILInArray<Int32> A, ILInArray<Int32> B) {
+            using (ILScope.Enter(A, B)) {
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<Int32>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<Int32>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<Int32>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+
+               
+                Int32[] retArr;
+
+               
+                Int32[] arrA = A.GetArrayForRead();
+
+               
+                Int32[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<Int32>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<Int32>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<Int32> retStorage = new ILDenseStorage<Int32>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+
+                   
+                    Int32* ap;
+
+                   
+                    Int32* bp;
+
+                   
+                    Int32* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (Int32*)range.Item3;
+                                bp = (Int32*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (Int32*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap  < *bp) ? *ap : *bp;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (Int32*)range.Item3;
+                                cp = (Int32*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap  < *cp) ? *ap : *cp;
+                                    ap++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (Int32*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (Int32*)range.Item4;
+                                cp = (Int32*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap  < *bp) ? *ap : *bp;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            for (int s = 0; s < range.Item2; s++) {
+                                bp = (Int32*)range.Item4;
+                                cp = (Int32*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*cp  < *bp) ? *cp : *bp;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed (Int32* arrAP = arrA)
+                fixed (Int32* arrBP = arrB)
+                fixed (Int32* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<Int32>(retStorage);
+            }
+        }
+
+
+       
+        /// <summary>Minimum of A and B elementwise</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Array with the minimum elements of A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<float>  min(ILInArray<float> A, ILInArray<float> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                float[] retArr;
+                float[] arrA = A.GetArrayForRead();
+                float[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size;
+                    if (B.IsScalar) {
+                        return array<float>(new float[1] { (A.GetValue(0) > B.GetValue(0)) ? A.GetValue(0) : B.GetValue(0) });
+                    } else if (B.IsEmpty) {
+                        return ILRetArray<float>.empty(outDims);
+                    } else {
+                        outLen = outDims.NumberOfElements;
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< float>(outLen);
+                            mode = BinOpItMode.SAN;
+                        } else {
+                            mode = BinOpItMode.SAI;
+                        }
+                    }
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return ILRetArray<float>.empty(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New<float>(outLen);
+                            mode = BinOpItMode.ASN;
+                        } else {
+                            mode = BinOpItMode.ASI;
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  minEx(A, B);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        if (A.TryGetStorage4InplaceOp(out retArr))
+                            mode = BinOpItMode.AAIA;
+                        else if (B.TryGetStorage4InplaceOp(out retArr))
+                            mode = BinOpItMode.AAIB;
+                        else {
+                            retArr = ILMemoryPool.Pool.New<float>(outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<float> retStorage = new ILDenseStorage<float>(retArr, outDims);
+                int i = 0, workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                   
+                    float* cp = (float*)range.Item5 + range.Item1;
+                   
+                    float scalar;
+                    int j = range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           
+                            float* bp = ((float*)range.Item4 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (cp[0]  < bp[0]) ? cp[0] : bp[0];
+                                cp[1] = (cp[1]  < bp[1]) ? cp[1] : bp[1];
+                                cp[2] = (cp[2]  < bp[2]) ? cp[2] : bp[2];
+                                cp[3] = (cp[3]  < bp[3]) ? cp[3] : bp[3];
+                                cp[4] = (cp[4]  < bp[4]) ? cp[4] : bp[4];
+                                cp[5] = (cp[5]  < bp[5]) ? cp[5] : bp[5];
+                                cp[6] = (cp[6]  < bp[6]) ? cp[6] : bp[6];
+                                cp[7] = (cp[7]  < bp[7]) ? cp[7] : bp[7];
+                                cp += 8; bp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*cp  < *bp) ? *cp : *bp;
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           
+                            float* ap = ((float*)range.Item3 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (ap[0]  < cp[0]) ? ap[0] : cp[0];
+                                cp[1] = (ap[1]  < cp[1]) ? ap[1] : cp[1];
+                                cp[2] = (ap[2]  < cp[2]) ? ap[2] : cp[2];
+                                cp[3] = (ap[3]  < cp[3]) ? ap[3] : cp[3];
+                                cp[4] = (ap[4]  < cp[4]) ? ap[4] : cp[4];
+                                cp[5] = (ap[5]  < cp[5]) ? ap[5] : cp[5];
+                                cp[6] = (ap[6]  < cp[6]) ? ap[6] : cp[6];
+                                cp[7] = (ap[7]  < cp[7]) ? ap[7] : cp[7];
+                                ap += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*ap  < *cp) ? *ap : *cp;
+                                ap++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((float*)range.Item3 + range.Item1);
+                            bp = ((float*)range.Item4 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (ap[0]  < bp[0]) ? ap[0] : bp[0];
+                                cp[1] = (ap[1]  < bp[1]) ? ap[1] : bp[1];
+                                cp[2] = (ap[2]  < bp[2]) ? ap[2] : bp[2];
+                                cp[3] = (ap[3]  < bp[3]) ? ap[3] : bp[3];
+                                cp[4] = (ap[4]  < bp[4]) ? ap[4] : bp[4];
+                                cp[5] = (ap[5]  < bp[5]) ? ap[5] : bp[5];
+                                cp[6] = (ap[6]  < bp[6]) ? ap[6] : bp[6];
+                                cp[7] = (ap[7]  < bp[7]) ? ap[7] : bp[7];
+                                ap += 8; bp += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*ap  < *bp) ? *ap : *bp;
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((float*)range.Item4);
+                            while (j > 7) {
+                                cp[0] = (cp[0]  < scalar) ? cp[0] : scalar;
+                                cp[1] = (cp[1]  < scalar) ? cp[1] : scalar;
+                                cp[2] = (cp[2]  < scalar) ? cp[2] : scalar;
+                                cp[3] = (cp[3]  < scalar) ? cp[3] : scalar;
+                                cp[4] = (cp[4]  < scalar) ? cp[4] : scalar;
+                                cp[5] = (cp[5]  < scalar) ? cp[5] : scalar;
+                                cp[6] = (cp[6]  < scalar) ? cp[6] : scalar;
+                                cp[7] = (cp[7]  < scalar) ? cp[7] : scalar;
+                                cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*cp  < scalar) ? *cp : scalar;
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((float*)range.Item3 + range.Item1);
+                            scalar = *((float*)range.Item4);
+                            while (j > 7) {
+                                cp[0] = (ap[0]  < scalar) ? ap[0] : scalar;
+                                cp[1] = (ap[1]  < scalar) ? ap[1] : scalar;
+                                cp[2] = (ap[2]  < scalar) ? ap[2] : scalar;
+                                cp[3] = (ap[3]  < scalar) ? ap[3] : scalar;
+                                cp[4] = (ap[4]  < scalar) ? ap[4] : scalar;
+                                cp[5] = (ap[5]  < scalar) ? ap[5] : scalar;
+                                cp[6] = (ap[6]  < scalar) ? ap[6] : scalar;
+                                cp[7] = (ap[7]  < scalar) ? ap[7] : scalar;
+                                ap += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*ap  < scalar) ? *ap : scalar;
+                                ap++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((float*)range.Item3);
+                            while (j > 7) {
+                                cp[0] = (scalar  < cp[0]) ? scalar : cp[0];
+                                cp[1] = (scalar  < cp[1]) ? scalar : cp[1];
+                                cp[2] = (scalar  < cp[2]) ? scalar : cp[2];
+                                cp[3] = (scalar  < cp[3]) ? scalar : cp[3];
+                                cp[4] = (scalar  < cp[4]) ? scalar : cp[4];
+                                cp[5] = (scalar  < cp[5]) ? scalar : cp[5];
+                                cp[6] = (scalar  < cp[6]) ? scalar : cp[6];
+                                cp[7] = (scalar  < cp[7]) ? scalar : cp[7];
+                                cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (scalar  < *cp) ? scalar : *cp;
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((float*)range.Item3);
+                            bp = ((float*)range.Item4 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (scalar  < bp[0]) ? scalar : bp[0];
+                                cp[1] = (scalar  < bp[1]) ? scalar : bp[1];
+                                cp[2] = (scalar  < bp[2]) ? scalar : bp[2];
+                                cp[3] = (scalar  < bp[3]) ? scalar : bp[3];
+                                cp[4] = (scalar  < bp[4]) ? scalar : bp[4];
+                                cp[5] = (scalar  < bp[5]) ? scalar : bp[5];
+                                cp[6] = (scalar  < bp[6]) ? scalar : bp[6];
+                                cp[7] = (scalar  < bp[7]) ? scalar : bp[7];
+                                bp += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (scalar  < *bp) ? scalar : *bp;
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+
+                fixed (float* arrAP = arrA)
+                fixed (float* arrBP = arrB)
+                fixed (float* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new ILRetArray<float>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<float>  minEx(ILInArray<float> A, ILInArray<float> B) {
+            using (ILScope.Enter(A, B)) {
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<float>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<float>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<float>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+
+               
+                float[] retArr;
+
+               
+                float[] arrA = A.GetArrayForRead();
+
+               
+                float[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<float>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<float>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<float> retStorage = new ILDenseStorage<float>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+
+                   
+                    float* ap;
+
+                   
+                    float* bp;
+
+                   
+                    float* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (float*)range.Item3;
+                                bp = (float*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (float*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap  < *bp) ? *ap : *bp;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (float*)range.Item3;
+                                cp = (float*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap  < *cp) ? *ap : *cp;
+                                    ap++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (float*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (float*)range.Item4;
+                                cp = (float*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap  < *bp) ? *ap : *bp;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            for (int s = 0; s < range.Item2; s++) {
+                                bp = (float*)range.Item4;
+                                cp = (float*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*cp  < *bp) ? *cp : *bp;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed (float* arrAP = arrA)
+                fixed (float* arrBP = arrB)
+                fixed (float* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<float>(retStorage);
+            }
+        }
+
+
+       
+        /// <summary>Minimum of A and B elementwise</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Array with the minimum elements of A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<fcomplex>  min(ILInArray<fcomplex> A, ILInArray<fcomplex> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                fcomplex[] retArr;
+                fcomplex[] arrA = A.GetArrayForRead();
+                fcomplex[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size;
+                    if (B.IsScalar) {
+                        return array<fcomplex>(new fcomplex[1] { (A.GetValue(0) > B.GetValue(0)) ? A.GetValue(0) : B.GetValue(0) });
+                    } else if (B.IsEmpty) {
+                        return ILRetArray<fcomplex>.empty(outDims);
+                    } else {
+                        outLen = outDims.NumberOfElements;
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< fcomplex>(outLen);
+                            mode = BinOpItMode.SAN;
+                        } else {
+                            mode = BinOpItMode.SAI;
+                        }
+                    }
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return ILRetArray<fcomplex>.empty(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New<fcomplex>(outLen);
+                            mode = BinOpItMode.ASN;
+                        } else {
+                            mode = BinOpItMode.ASI;
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  minEx(A, B);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        if (A.TryGetStorage4InplaceOp(out retArr))
+                            mode = BinOpItMode.AAIA;
+                        else if (B.TryGetStorage4InplaceOp(out retArr))
+                            mode = BinOpItMode.AAIB;
+                        else {
+                            retArr = ILMemoryPool.Pool.New<fcomplex>(outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<fcomplex> retStorage = new ILDenseStorage<fcomplex>(retArr, outDims);
+                int i = 0, workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                   
+                    fcomplex* cp = (fcomplex*)range.Item5 + range.Item1;
+                   
+                    fcomplex scalar;
+                    int j = range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           
+                            fcomplex* bp = ((fcomplex*)range.Item4 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (cp[0]  < bp[0]) ? cp[0] : bp[0];
+                                cp[1] = (cp[1]  < bp[1]) ? cp[1] : bp[1];
+                                cp[2] = (cp[2]  < bp[2]) ? cp[2] : bp[2];
+                                cp[3] = (cp[3]  < bp[3]) ? cp[3] : bp[3];
+                                cp[4] = (cp[4]  < bp[4]) ? cp[4] : bp[4];
+                                cp[5] = (cp[5]  < bp[5]) ? cp[5] : bp[5];
+                                cp[6] = (cp[6]  < bp[6]) ? cp[6] : bp[6];
+                                cp[7] = (cp[7]  < bp[7]) ? cp[7] : bp[7];
+                                cp += 8; bp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*cp  < *bp) ? *cp : *bp;
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           
+                            fcomplex* ap = ((fcomplex*)range.Item3 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (ap[0]  < cp[0]) ? ap[0] : cp[0];
+                                cp[1] = (ap[1]  < cp[1]) ? ap[1] : cp[1];
+                                cp[2] = (ap[2]  < cp[2]) ? ap[2] : cp[2];
+                                cp[3] = (ap[3]  < cp[3]) ? ap[3] : cp[3];
+                                cp[4] = (ap[4]  < cp[4]) ? ap[4] : cp[4];
+                                cp[5] = (ap[5]  < cp[5]) ? ap[5] : cp[5];
+                                cp[6] = (ap[6]  < cp[6]) ? ap[6] : cp[6];
+                                cp[7] = (ap[7]  < cp[7]) ? ap[7] : cp[7];
+                                ap += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*ap  < *cp) ? *ap : *cp;
+                                ap++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((fcomplex*)range.Item3 + range.Item1);
+                            bp = ((fcomplex*)range.Item4 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (ap[0]  < bp[0]) ? ap[0] : bp[0];
+                                cp[1] = (ap[1]  < bp[1]) ? ap[1] : bp[1];
+                                cp[2] = (ap[2]  < bp[2]) ? ap[2] : bp[2];
+                                cp[3] = (ap[3]  < bp[3]) ? ap[3] : bp[3];
+                                cp[4] = (ap[4]  < bp[4]) ? ap[4] : bp[4];
+                                cp[5] = (ap[5]  < bp[5]) ? ap[5] : bp[5];
+                                cp[6] = (ap[6]  < bp[6]) ? ap[6] : bp[6];
+                                cp[7] = (ap[7]  < bp[7]) ? ap[7] : bp[7];
+                                ap += 8; bp += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*ap  < *bp) ? *ap : *bp;
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((fcomplex*)range.Item4);
+                            while (j > 7) {
+                                cp[0] = (cp[0]  < scalar) ? cp[0] : scalar;
+                                cp[1] = (cp[1]  < scalar) ? cp[1] : scalar;
+                                cp[2] = (cp[2]  < scalar) ? cp[2] : scalar;
+                                cp[3] = (cp[3]  < scalar) ? cp[3] : scalar;
+                                cp[4] = (cp[4]  < scalar) ? cp[4] : scalar;
+                                cp[5] = (cp[5]  < scalar) ? cp[5] : scalar;
+                                cp[6] = (cp[6]  < scalar) ? cp[6] : scalar;
+                                cp[7] = (cp[7]  < scalar) ? cp[7] : scalar;
+                                cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*cp  < scalar) ? *cp : scalar;
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((fcomplex*)range.Item3 + range.Item1);
+                            scalar = *((fcomplex*)range.Item4);
+                            while (j > 7) {
+                                cp[0] = (ap[0]  < scalar) ? ap[0] : scalar;
+                                cp[1] = (ap[1]  < scalar) ? ap[1] : scalar;
+                                cp[2] = (ap[2]  < scalar) ? ap[2] : scalar;
+                                cp[3] = (ap[3]  < scalar) ? ap[3] : scalar;
+                                cp[4] = (ap[4]  < scalar) ? ap[4] : scalar;
+                                cp[5] = (ap[5]  < scalar) ? ap[5] : scalar;
+                                cp[6] = (ap[6]  < scalar) ? ap[6] : scalar;
+                                cp[7] = (ap[7]  < scalar) ? ap[7] : scalar;
+                                ap += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*ap  < scalar) ? *ap : scalar;
+                                ap++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((fcomplex*)range.Item3);
+                            while (j > 7) {
+                                cp[0] = (scalar  < cp[0]) ? scalar : cp[0];
+                                cp[1] = (scalar  < cp[1]) ? scalar : cp[1];
+                                cp[2] = (scalar  < cp[2]) ? scalar : cp[2];
+                                cp[3] = (scalar  < cp[3]) ? scalar : cp[3];
+                                cp[4] = (scalar  < cp[4]) ? scalar : cp[4];
+                                cp[5] = (scalar  < cp[5]) ? scalar : cp[5];
+                                cp[6] = (scalar  < cp[6]) ? scalar : cp[6];
+                                cp[7] = (scalar  < cp[7]) ? scalar : cp[7];
+                                cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (scalar  < *cp) ? scalar : *cp;
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((fcomplex*)range.Item3);
+                            bp = ((fcomplex*)range.Item4 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (scalar  < bp[0]) ? scalar : bp[0];
+                                cp[1] = (scalar  < bp[1]) ? scalar : bp[1];
+                                cp[2] = (scalar  < bp[2]) ? scalar : bp[2];
+                                cp[3] = (scalar  < bp[3]) ? scalar : bp[3];
+                                cp[4] = (scalar  < bp[4]) ? scalar : bp[4];
+                                cp[5] = (scalar  < bp[5]) ? scalar : bp[5];
+                                cp[6] = (scalar  < bp[6]) ? scalar : bp[6];
+                                cp[7] = (scalar  < bp[7]) ? scalar : bp[7];
+                                bp += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (scalar  < *bp) ? scalar : *bp;
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+
+                fixed (fcomplex* arrAP = arrA)
+                fixed (fcomplex* arrBP = arrB)
+                fixed (fcomplex* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new ILRetArray<fcomplex>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<fcomplex>  minEx(ILInArray<fcomplex> A, ILInArray<fcomplex> B) {
+            using (ILScope.Enter(A, B)) {
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<fcomplex>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<fcomplex>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<fcomplex>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+
+               
+                fcomplex[] retArr;
+
+               
+                fcomplex[] arrA = A.GetArrayForRead();
+
+               
+                fcomplex[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<fcomplex>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<fcomplex>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<fcomplex> retStorage = new ILDenseStorage<fcomplex>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+
+                   
+                    fcomplex* ap;
+
+                   
+                    fcomplex* bp;
+
+                   
+                    fcomplex* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (fcomplex*)range.Item3;
+                                bp = (fcomplex*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (fcomplex*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap  < *bp) ? *ap : *bp;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (fcomplex*)range.Item3;
+                                cp = (fcomplex*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap  < *cp) ? *ap : *cp;
+                                    ap++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (fcomplex*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (fcomplex*)range.Item4;
+                                cp = (fcomplex*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap  < *bp) ? *ap : *bp;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            for (int s = 0; s < range.Item2; s++) {
+                                bp = (fcomplex*)range.Item4;
+                                cp = (fcomplex*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*cp  < *bp) ? *cp : *bp;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed (fcomplex* arrAP = arrA)
+                fixed (fcomplex* arrBP = arrB)
+                fixed (fcomplex* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<fcomplex>(retStorage);
+            }
+        }
+
+
+       
+        /// <summary>Minimum of A and B elementwise</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Array with the minimum elements of A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<complex>  min(ILInArray<complex> A, ILInArray<complex> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                complex[] retArr;
+                complex[] arrA = A.GetArrayForRead();
+                complex[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size;
+                    if (B.IsScalar) {
+                        return array<complex>(new complex[1] { (A.GetValue(0) > B.GetValue(0)) ? A.GetValue(0) : B.GetValue(0) });
+                    } else if (B.IsEmpty) {
+                        return ILRetArray<complex>.empty(outDims);
+                    } else {
+                        outLen = outDims.NumberOfElements;
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< complex>(outLen);
+                            mode = BinOpItMode.SAN;
+                        } else {
+                            mode = BinOpItMode.SAI;
+                        }
+                    }
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return ILRetArray<complex>.empty(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New<complex>(outLen);
+                            mode = BinOpItMode.ASN;
+                        } else {
+                            mode = BinOpItMode.ASI;
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  minEx(A, B);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        if (A.TryGetStorage4InplaceOp(out retArr))
+                            mode = BinOpItMode.AAIA;
+                        else if (B.TryGetStorage4InplaceOp(out retArr))
+                            mode = BinOpItMode.AAIB;
+                        else {
+                            retArr = ILMemoryPool.Pool.New<complex>(outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<complex> retStorage = new ILDenseStorage<complex>(retArr, outDims);
+                int i = 0, workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                   
+                    complex* cp = (complex*)range.Item5 + range.Item1;
+                   
+                    complex scalar;
+                    int j = range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           
+                            complex* bp = ((complex*)range.Item4 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (cp[0]  < bp[0]) ? cp[0] : bp[0];
+                                cp[1] = (cp[1]  < bp[1]) ? cp[1] : bp[1];
+                                cp[2] = (cp[2]  < bp[2]) ? cp[2] : bp[2];
+                                cp[3] = (cp[3]  < bp[3]) ? cp[3] : bp[3];
+                                cp[4] = (cp[4]  < bp[4]) ? cp[4] : bp[4];
+                                cp[5] = (cp[5]  < bp[5]) ? cp[5] : bp[5];
+                                cp[6] = (cp[6]  < bp[6]) ? cp[6] : bp[6];
+                                cp[7] = (cp[7]  < bp[7]) ? cp[7] : bp[7];
+                                cp += 8; bp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*cp  < *bp) ? *cp : *bp;
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           
+                            complex* ap = ((complex*)range.Item3 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (ap[0]  < cp[0]) ? ap[0] : cp[0];
+                                cp[1] = (ap[1]  < cp[1]) ? ap[1] : cp[1];
+                                cp[2] = (ap[2]  < cp[2]) ? ap[2] : cp[2];
+                                cp[3] = (ap[3]  < cp[3]) ? ap[3] : cp[3];
+                                cp[4] = (ap[4]  < cp[4]) ? ap[4] : cp[4];
+                                cp[5] = (ap[5]  < cp[5]) ? ap[5] : cp[5];
+                                cp[6] = (ap[6]  < cp[6]) ? ap[6] : cp[6];
+                                cp[7] = (ap[7]  < cp[7]) ? ap[7] : cp[7];
+                                ap += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*ap  < *cp) ? *ap : *cp;
+                                ap++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((complex*)range.Item3 + range.Item1);
+                            bp = ((complex*)range.Item4 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (ap[0]  < bp[0]) ? ap[0] : bp[0];
+                                cp[1] = (ap[1]  < bp[1]) ? ap[1] : bp[1];
+                                cp[2] = (ap[2]  < bp[2]) ? ap[2] : bp[2];
+                                cp[3] = (ap[3]  < bp[3]) ? ap[3] : bp[3];
+                                cp[4] = (ap[4]  < bp[4]) ? ap[4] : bp[4];
+                                cp[5] = (ap[5]  < bp[5]) ? ap[5] : bp[5];
+                                cp[6] = (ap[6]  < bp[6]) ? ap[6] : bp[6];
+                                cp[7] = (ap[7]  < bp[7]) ? ap[7] : bp[7];
+                                ap += 8; bp += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*ap  < *bp) ? *ap : *bp;
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((complex*)range.Item4);
+                            while (j > 7) {
+                                cp[0] = (cp[0]  < scalar) ? cp[0] : scalar;
+                                cp[1] = (cp[1]  < scalar) ? cp[1] : scalar;
+                                cp[2] = (cp[2]  < scalar) ? cp[2] : scalar;
+                                cp[3] = (cp[3]  < scalar) ? cp[3] : scalar;
+                                cp[4] = (cp[4]  < scalar) ? cp[4] : scalar;
+                                cp[5] = (cp[5]  < scalar) ? cp[5] : scalar;
+                                cp[6] = (cp[6]  < scalar) ? cp[6] : scalar;
+                                cp[7] = (cp[7]  < scalar) ? cp[7] : scalar;
+                                cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*cp  < scalar) ? *cp : scalar;
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((complex*)range.Item3 + range.Item1);
+                            scalar = *((complex*)range.Item4);
+                            while (j > 7) {
+                                cp[0] = (ap[0]  < scalar) ? ap[0] : scalar;
+                                cp[1] = (ap[1]  < scalar) ? ap[1] : scalar;
+                                cp[2] = (ap[2]  < scalar) ? ap[2] : scalar;
+                                cp[3] = (ap[3]  < scalar) ? ap[3] : scalar;
+                                cp[4] = (ap[4]  < scalar) ? ap[4] : scalar;
+                                cp[5] = (ap[5]  < scalar) ? ap[5] : scalar;
+                                cp[6] = (ap[6]  < scalar) ? ap[6] : scalar;
+                                cp[7] = (ap[7]  < scalar) ? ap[7] : scalar;
+                                ap += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*ap  < scalar) ? *ap : scalar;
+                                ap++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((complex*)range.Item3);
+                            while (j > 7) {
+                                cp[0] = (scalar  < cp[0]) ? scalar : cp[0];
+                                cp[1] = (scalar  < cp[1]) ? scalar : cp[1];
+                                cp[2] = (scalar  < cp[2]) ? scalar : cp[2];
+                                cp[3] = (scalar  < cp[3]) ? scalar : cp[3];
+                                cp[4] = (scalar  < cp[4]) ? scalar : cp[4];
+                                cp[5] = (scalar  < cp[5]) ? scalar : cp[5];
+                                cp[6] = (scalar  < cp[6]) ? scalar : cp[6];
+                                cp[7] = (scalar  < cp[7]) ? scalar : cp[7];
+                                cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (scalar  < *cp) ? scalar : *cp;
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((complex*)range.Item3);
+                            bp = ((complex*)range.Item4 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (scalar  < bp[0]) ? scalar : bp[0];
+                                cp[1] = (scalar  < bp[1]) ? scalar : bp[1];
+                                cp[2] = (scalar  < bp[2]) ? scalar : bp[2];
+                                cp[3] = (scalar  < bp[3]) ? scalar : bp[3];
+                                cp[4] = (scalar  < bp[4]) ? scalar : bp[4];
+                                cp[5] = (scalar  < bp[5]) ? scalar : bp[5];
+                                cp[6] = (scalar  < bp[6]) ? scalar : bp[6];
+                                cp[7] = (scalar  < bp[7]) ? scalar : bp[7];
+                                bp += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (scalar  < *bp) ? scalar : *bp;
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+
+                fixed (complex* arrAP = arrA)
+                fixed (complex* arrBP = arrB)
+                fixed (complex* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new ILRetArray<complex>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<complex>  minEx(ILInArray<complex> A, ILInArray<complex> B) {
+            using (ILScope.Enter(A, B)) {
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<complex>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<complex>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<complex>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+
+               
+                complex[] retArr;
+
+               
+                complex[] arrA = A.GetArrayForRead();
+
+               
+                complex[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<complex>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<complex>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<complex> retStorage = new ILDenseStorage<complex>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+
+                   
+                    complex* ap;
+
+                   
+                    complex* bp;
+
+                   
+                    complex* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (complex*)range.Item3;
+                                bp = (complex*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (complex*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap  < *bp) ? *ap : *bp;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (complex*)range.Item3;
+                                cp = (complex*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap  < *cp) ? *ap : *cp;
+                                    ap++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (complex*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (complex*)range.Item4;
+                                cp = (complex*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap  < *bp) ? *ap : *bp;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            for (int s = 0; s < range.Item2; s++) {
+                                bp = (complex*)range.Item4;
+                                cp = (complex*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*cp  < *bp) ? *cp : *bp;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed (complex* arrAP = arrA)
+                fixed (complex* arrBP = arrB)
+                fixed (complex* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<complex>(retStorage);
+            }
+        }
+
+
+       
+        /// <summary>Minimum of A and B elementwise</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Array with the minimum elements of A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<byte>  min(ILInArray<byte> A, ILInArray<byte> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+                byte[] arrA = A.GetArrayForRead();
+                byte[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size;
+                    if (B.IsScalar) {
+                        return array<byte>(new byte[1] { (A.GetValue(0) > B.GetValue(0)) ? A.GetValue(0) : B.GetValue(0) });
+                    } else if (B.IsEmpty) {
+                        return ILRetArray<byte>.empty(outDims);
+                    } else {
+                        outLen = outDims.NumberOfElements;
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< byte>(outLen);
+                            mode = BinOpItMode.SAN;
+                        } else {
+                            mode = BinOpItMode.SAI;
+                        }
+                    }
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return ILRetArray<byte>.empty(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                            mode = BinOpItMode.ASN;
+                        } else {
+                            mode = BinOpItMode.ASI;
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  minEx(A, B);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        if (A.TryGetStorage4InplaceOp(out retArr))
+                            mode = BinOpItMode.AAIA;
+                        else if (B.TryGetStorage4InplaceOp(out retArr))
+                            mode = BinOpItMode.AAIB;
+                        else {
+                            retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<byte> retStorage = new ILDenseStorage<byte>(retArr, outDims);
+                int i = 0, workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                   
+                    byte* cp = (byte*)range.Item5 + range.Item1;
+                   
+                    byte scalar;
+                    int j = range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           
+                            byte* bp = ((byte*)range.Item4 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (cp[0]  < bp[0]) ? cp[0] : bp[0];
+                                cp[1] = (cp[1]  < bp[1]) ? cp[1] : bp[1];
+                                cp[2] = (cp[2]  < bp[2]) ? cp[2] : bp[2];
+                                cp[3] = (cp[3]  < bp[3]) ? cp[3] : bp[3];
+                                cp[4] = (cp[4]  < bp[4]) ? cp[4] : bp[4];
+                                cp[5] = (cp[5]  < bp[5]) ? cp[5] : bp[5];
+                                cp[6] = (cp[6]  < bp[6]) ? cp[6] : bp[6];
+                                cp[7] = (cp[7]  < bp[7]) ? cp[7] : bp[7];
+                                cp += 8; bp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*cp  < *bp) ? *cp : *bp;
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           
+                            byte* ap = ((byte*)range.Item3 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (ap[0]  < cp[0]) ? ap[0] : cp[0];
+                                cp[1] = (ap[1]  < cp[1]) ? ap[1] : cp[1];
+                                cp[2] = (ap[2]  < cp[2]) ? ap[2] : cp[2];
+                                cp[3] = (ap[3]  < cp[3]) ? ap[3] : cp[3];
+                                cp[4] = (ap[4]  < cp[4]) ? ap[4] : cp[4];
+                                cp[5] = (ap[5]  < cp[5]) ? ap[5] : cp[5];
+                                cp[6] = (ap[6]  < cp[6]) ? ap[6] : cp[6];
+                                cp[7] = (ap[7]  < cp[7]) ? ap[7] : cp[7];
+                                ap += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*ap  < *cp) ? *ap : *cp;
+                                ap++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((byte*)range.Item3 + range.Item1);
+                            bp = ((byte*)range.Item4 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (ap[0]  < bp[0]) ? ap[0] : bp[0];
+                                cp[1] = (ap[1]  < bp[1]) ? ap[1] : bp[1];
+                                cp[2] = (ap[2]  < bp[2]) ? ap[2] : bp[2];
+                                cp[3] = (ap[3]  < bp[3]) ? ap[3] : bp[3];
+                                cp[4] = (ap[4]  < bp[4]) ? ap[4] : bp[4];
+                                cp[5] = (ap[5]  < bp[5]) ? ap[5] : bp[5];
+                                cp[6] = (ap[6]  < bp[6]) ? ap[6] : bp[6];
+                                cp[7] = (ap[7]  < bp[7]) ? ap[7] : bp[7];
+                                ap += 8; bp += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*ap  < *bp) ? *ap : *bp;
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((byte*)range.Item4);
+                            while (j > 7) {
+                                cp[0] = (cp[0]  < scalar) ? cp[0] : scalar;
+                                cp[1] = (cp[1]  < scalar) ? cp[1] : scalar;
+                                cp[2] = (cp[2]  < scalar) ? cp[2] : scalar;
+                                cp[3] = (cp[3]  < scalar) ? cp[3] : scalar;
+                                cp[4] = (cp[4]  < scalar) ? cp[4] : scalar;
+                                cp[5] = (cp[5]  < scalar) ? cp[5] : scalar;
+                                cp[6] = (cp[6]  < scalar) ? cp[6] : scalar;
+                                cp[7] = (cp[7]  < scalar) ? cp[7] : scalar;
+                                cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*cp  < scalar) ? *cp : scalar;
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((byte*)range.Item3 + range.Item1);
+                            scalar = *((byte*)range.Item4);
+                            while (j > 7) {
+                                cp[0] = (ap[0]  < scalar) ? ap[0] : scalar;
+                                cp[1] = (ap[1]  < scalar) ? ap[1] : scalar;
+                                cp[2] = (ap[2]  < scalar) ? ap[2] : scalar;
+                                cp[3] = (ap[3]  < scalar) ? ap[3] : scalar;
+                                cp[4] = (ap[4]  < scalar) ? ap[4] : scalar;
+                                cp[5] = (ap[5]  < scalar) ? ap[5] : scalar;
+                                cp[6] = (ap[6]  < scalar) ? ap[6] : scalar;
+                                cp[7] = (ap[7]  < scalar) ? ap[7] : scalar;
+                                ap += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*ap  < scalar) ? *ap : scalar;
+                                ap++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((byte*)range.Item3);
+                            while (j > 7) {
+                                cp[0] = (scalar  < cp[0]) ? scalar : cp[0];
+                                cp[1] = (scalar  < cp[1]) ? scalar : cp[1];
+                                cp[2] = (scalar  < cp[2]) ? scalar : cp[2];
+                                cp[3] = (scalar  < cp[3]) ? scalar : cp[3];
+                                cp[4] = (scalar  < cp[4]) ? scalar : cp[4];
+                                cp[5] = (scalar  < cp[5]) ? scalar : cp[5];
+                                cp[6] = (scalar  < cp[6]) ? scalar : cp[6];
+                                cp[7] = (scalar  < cp[7]) ? scalar : cp[7];
+                                cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (scalar  < *cp) ? scalar : *cp;
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((byte*)range.Item3);
+                            bp = ((byte*)range.Item4 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (scalar  < bp[0]) ? scalar : bp[0];
+                                cp[1] = (scalar  < bp[1]) ? scalar : bp[1];
+                                cp[2] = (scalar  < bp[2]) ? scalar : bp[2];
+                                cp[3] = (scalar  < bp[3]) ? scalar : bp[3];
+                                cp[4] = (scalar  < bp[4]) ? scalar : bp[4];
+                                cp[5] = (scalar  < bp[5]) ? scalar : bp[5];
+                                cp[6] = (scalar  < bp[6]) ? scalar : bp[6];
+                                cp[7] = (scalar  < bp[7]) ? scalar : bp[7];
+                                bp += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (scalar  < *bp) ? scalar : *bp;
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+
+                fixed (byte* arrAP = arrA)
+                fixed (byte* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new ILRetArray<byte>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<byte>  minEx(ILInArray<byte> A, ILInArray<byte> B) {
+            using (ILScope.Enter(A, B)) {
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<byte>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<byte>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<byte>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+
+               
+                byte[] retArr;
+
+               
+                byte[] arrA = A.GetArrayForRead();
+
+               
+                byte[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<byte> retStorage = new ILDenseStorage<byte>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+
+                   
+                    byte* ap;
+
+                   
+                    byte* bp;
+
+                   
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (byte*)range.Item3;
+                                bp = (byte*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap  < *bp) ? *ap : *bp;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (byte*)range.Item3;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap  < *cp) ? *ap : *cp;
+                                    ap++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (byte*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (byte*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap  < *bp) ? *ap : *bp;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            for (int s = 0; s < range.Item2; s++) {
+                                bp = (byte*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*cp  < *bp) ? *cp : *bp;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed (byte* arrAP = arrA)
+                fixed (byte* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<byte>(retStorage);
+            }
+        }
+
+
+       
+        /// <summary>Minimum of A and B elementwise</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Array with the minimum elements of A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<double>  min(ILInArray<double> A, ILInArray<double> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                double[] retArr;
+                double[] arrA = A.GetArrayForRead();
+                double[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size;
+                    if (B.IsScalar) {
+                        return array<double>(new double[1] { (A.GetValue(0) > B.GetValue(0)) ? A.GetValue(0) : B.GetValue(0) });
+                    } else if (B.IsEmpty) {
+                        return ILRetArray<double>.empty(outDims);
+                    } else {
+                        outLen = outDims.NumberOfElements;
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< double>(outLen);
+                            mode = BinOpItMode.SAN;
+                        } else {
+                            mode = BinOpItMode.SAI;
+                        }
+                    }
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return ILRetArray<double>.empty(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New<double>(outLen);
+                            mode = BinOpItMode.ASN;
+                        } else {
+                            mode = BinOpItMode.ASI;
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  minEx(A, B);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        if (A.TryGetStorage4InplaceOp(out retArr))
+                            mode = BinOpItMode.AAIA;
+                        else if (B.TryGetStorage4InplaceOp(out retArr))
+                            mode = BinOpItMode.AAIB;
+                        else {
+                            retArr = ILMemoryPool.Pool.New<double>(outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<double> retStorage = new ILDenseStorage<double>(retArr, outDims);
+                int i = 0, workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                   
+                    double* cp = (double*)range.Item5 + range.Item1;
+                   
+                    double scalar;
+                    int j = range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           
+                            double* bp = ((double*)range.Item4 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (cp[0]  < bp[0]) ? cp[0] : bp[0];
+                                cp[1] = (cp[1]  < bp[1]) ? cp[1] : bp[1];
+                                cp[2] = (cp[2]  < bp[2]) ? cp[2] : bp[2];
+                                cp[3] = (cp[3]  < bp[3]) ? cp[3] : bp[3];
+                                cp[4] = (cp[4]  < bp[4]) ? cp[4] : bp[4];
+                                cp[5] = (cp[5]  < bp[5]) ? cp[5] : bp[5];
+                                cp[6] = (cp[6]  < bp[6]) ? cp[6] : bp[6];
+                                cp[7] = (cp[7]  < bp[7]) ? cp[7] : bp[7];
+                                cp += 8; bp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*cp  < *bp) ? *cp : *bp;
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           
+                            double* ap = ((double*)range.Item3 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (ap[0]  < cp[0]) ? ap[0] : cp[0];
+                                cp[1] = (ap[1]  < cp[1]) ? ap[1] : cp[1];
+                                cp[2] = (ap[2]  < cp[2]) ? ap[2] : cp[2];
+                                cp[3] = (ap[3]  < cp[3]) ? ap[3] : cp[3];
+                                cp[4] = (ap[4]  < cp[4]) ? ap[4] : cp[4];
+                                cp[5] = (ap[5]  < cp[5]) ? ap[5] : cp[5];
+                                cp[6] = (ap[6]  < cp[6]) ? ap[6] : cp[6];
+                                cp[7] = (ap[7]  < cp[7]) ? ap[7] : cp[7];
+                                ap += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*ap  < *cp) ? *ap : *cp;
+                                ap++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((double*)range.Item3 + range.Item1);
+                            bp = ((double*)range.Item4 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (ap[0]  < bp[0]) ? ap[0] : bp[0];
+                                cp[1] = (ap[1]  < bp[1]) ? ap[1] : bp[1];
+                                cp[2] = (ap[2]  < bp[2]) ? ap[2] : bp[2];
+                                cp[3] = (ap[3]  < bp[3]) ? ap[3] : bp[3];
+                                cp[4] = (ap[4]  < bp[4]) ? ap[4] : bp[4];
+                                cp[5] = (ap[5]  < bp[5]) ? ap[5] : bp[5];
+                                cp[6] = (ap[6]  < bp[6]) ? ap[6] : bp[6];
+                                cp[7] = (ap[7]  < bp[7]) ? ap[7] : bp[7];
+                                ap += 8; bp += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*ap  < *bp) ? *ap : *bp;
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((double*)range.Item4);
+                            while (j > 7) {
+                                cp[0] = (cp[0]  < scalar) ? cp[0] : scalar;
+                                cp[1] = (cp[1]  < scalar) ? cp[1] : scalar;
+                                cp[2] = (cp[2]  < scalar) ? cp[2] : scalar;
+                                cp[3] = (cp[3]  < scalar) ? cp[3] : scalar;
+                                cp[4] = (cp[4]  < scalar) ? cp[4] : scalar;
+                                cp[5] = (cp[5]  < scalar) ? cp[5] : scalar;
+                                cp[6] = (cp[6]  < scalar) ? cp[6] : scalar;
+                                cp[7] = (cp[7]  < scalar) ? cp[7] : scalar;
+                                cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*cp  < scalar) ? *cp : scalar;
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((double*)range.Item3 + range.Item1);
+                            scalar = *((double*)range.Item4);
+                            while (j > 7) {
+                                cp[0] = (ap[0]  < scalar) ? ap[0] : scalar;
+                                cp[1] = (ap[1]  < scalar) ? ap[1] : scalar;
+                                cp[2] = (ap[2]  < scalar) ? ap[2] : scalar;
+                                cp[3] = (ap[3]  < scalar) ? ap[3] : scalar;
+                                cp[4] = (ap[4]  < scalar) ? ap[4] : scalar;
+                                cp[5] = (ap[5]  < scalar) ? ap[5] : scalar;
+                                cp[6] = (ap[6]  < scalar) ? ap[6] : scalar;
+                                cp[7] = (ap[7]  < scalar) ? ap[7] : scalar;
+                                ap += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (*ap  < scalar) ? *ap : scalar;
+                                ap++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((double*)range.Item3);
+                            while (j > 7) {
+                                cp[0] = (scalar  < cp[0]) ? scalar : cp[0];
+                                cp[1] = (scalar  < cp[1]) ? scalar : cp[1];
+                                cp[2] = (scalar  < cp[2]) ? scalar : cp[2];
+                                cp[3] = (scalar  < cp[3]) ? scalar : cp[3];
+                                cp[4] = (scalar  < cp[4]) ? scalar : cp[4];
+                                cp[5] = (scalar  < cp[5]) ? scalar : cp[5];
+                                cp[6] = (scalar  < cp[6]) ? scalar : cp[6];
+                                cp[7] = (scalar  < cp[7]) ? scalar : cp[7];
+                                cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (scalar  < *cp) ? scalar : *cp;
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((double*)range.Item3);
+                            bp = ((double*)range.Item4 + range.Item1);
+                            while (j > 7) {
+                                cp[0] = (scalar  < bp[0]) ? scalar : bp[0];
+                                cp[1] = (scalar  < bp[1]) ? scalar : bp[1];
+                                cp[2] = (scalar  < bp[2]) ? scalar : bp[2];
+                                cp[3] = (scalar  < bp[3]) ? scalar : bp[3];
+                                cp[4] = (scalar  < bp[4]) ? scalar : bp[4];
+                                cp[5] = (scalar  < bp[5]) ? scalar : bp[5];
+                                cp[6] = (scalar  < bp[6]) ? scalar : bp[6];
+                                cp[7] = (scalar  < bp[7]) ? scalar : bp[7];
+                                bp += 8; cp += 8; j -= 8;
+                            }
+                            while (j-- > 0) {
+                                *cp = (scalar  < *bp) ? scalar : *bp;
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+
+                fixed (double* arrAP = arrA)
+                fixed (double* arrBP = arrB)
+                fixed (double* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new ILRetArray<double>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<double>  minEx(ILInArray<double> A, ILInArray<double> B) {
+            using (ILScope.Enter(A, B)) {
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<double>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<double>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<double>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+
+               
+                double[] retArr;
+
+               
+                double[] arrA = A.GetArrayForRead();
+
+               
+                double[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<double>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<double>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<double> retStorage = new ILDenseStorage<double>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+
+                   
+                    double* ap;
+
+                   
+                    double* bp;
+
+                   
+                    double* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (double*)range.Item3;
+                                bp = (double*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (double*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap  < *bp) ? *ap : *bp;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (double*)range.Item3;
+                                cp = (double*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap  < *cp) ? *ap : *cp;
+                                    ap++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (double*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (double*)range.Item4;
+                                cp = (double*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap  < *bp) ? *ap : *bp;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            for (int s = 0; s < range.Item2; s++) {
+                                bp = (double*)range.Item4;
+                                cp = (double*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*cp  < *bp) ? *cp : *bp;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed (double* arrAP = arrA)
+                fixed (double* arrBP = arrB)
+                fixed (double* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<double>(retStorage);
+            }
+        }
+
+
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/MultiplyElem.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/MultiplyElem.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/MultiplyElem.cs	(revision 9102)
@@ -0,0 +1,5102 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using ILNumerics;
+using ILNumerics.Misc;
+using ILNumerics.Storage;
+using ILNumerics.Native;
+using ILNumerics.Exceptions;
+
+
+
+namespace ILNumerics {
+
+    public partial class ILMath {
+
+
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>Multiply arrays elementwise</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Array with elementwise multiplication of A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<Int64>  multiplyElem(ILInArray<Int64> A, ILInArray<Int64> B) {
+            using (ILScope.Enter(A,B)) {
+                int outLen; 
+                BinOpItMode mode; 
+                Int64 [] retArr;
+                Int64 [] arrA = A.GetArrayForRead();
+                Int64[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size; 
+                    if (B.IsScalar) {
+                       
+                        return new  ILRetArray<Int64> (new  Int64 [1]{ saturateInt64 (A.GetValue(0)  * (double) B.GetValue(0))}, A.Size);
+                    } else if (B.IsEmpty) {
+                        return  ILRetArray<Int64>.empty(outDims); 
+                    } else {
+                        outLen = outDims.NumberOfElements; 
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< Int64 > (outLen);
+                            mode = BinOpItMode.SAN; 
+                        } else {
+                            mode = BinOpItMode.SAI; 
+                        }
+                    }
+                } else {
+                    outDims = A.Size; 
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return  ILRetArray<Int64>.empty(A.Size);  
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< Int64 > (outLen);
+                            mode = BinOpItMode.ASN; 
+                        } else {
+                            mode = BinOpItMode.ASI; 
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  multiplyElemEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (A.TryGetStorage4InplaceOp(out retArr)) 
+                            mode  = BinOpItMode.AAIA; 
+                        else if (B.TryGetStorage4InplaceOp(out retArr)) 
+                            mode = BinOpItMode.AAIB; 
+                        else {
+                            retArr = ILMemoryPool.Pool.New< Int64 > (outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<Int64> retStorage = new ILDenseStorage<Int64>(retArr, outDims);
+                int i = 0, workerCount = 1; 
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    Int64* cp = (Int64*)range.Item5 + range.Item1;
+                    Int64 scalar;
+                    int j = range.Item2; 
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           Int64* bp = ((Int64*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                                cp[0] =  saturateInt64 (cp[0]  * (double) bp[0]);
+                                cp[1] =  saturateInt64 (cp[1]  * (double) bp[1]);
+                                cp[2] =  saturateInt64 (cp[2]  * (double) bp[2]);
+                                cp[3] =  saturateInt64 (cp[3]  * (double) bp[3]);
+                                cp[4] =  saturateInt64 (cp[4]  * (double) bp[4]);
+                                cp[5] =  saturateInt64 (cp[5]  * (double) bp[5]);
+                                cp[6] =  saturateInt64 (cp[6]  * (double) bp[6]);
+                                cp[7] =  saturateInt64 (cp[7]  * (double) bp[7]);
+                                cp[8] =  saturateInt64 (cp[8]  * (double) bp[8]);
+                                cp[9] =  saturateInt64 (cp[9]  * (double) bp[9]);
+                                cp[10] =  saturateInt64 (cp[10]  * (double) bp[10]);
+                                cp[11] =  saturateInt64 (cp[11]  * (double) bp[11]);
+                                cp[12] =  saturateInt64 (cp[12]  * (double) bp[12]);
+                                cp[13] =  saturateInt64 (cp[13]  * (double) bp[13]);
+                                cp[14] =  saturateInt64 (cp[14]  * (double) bp[14]);
+                                cp[15] =  saturateInt64 (cp[15]  * (double) bp[15]);
+                                cp[16] =  saturateInt64 (cp[16]  * (double) bp[16]);
+                                cp[17] =  saturateInt64 (cp[17]  * (double) bp[17]);
+                                cp[18] =  saturateInt64 (cp[18]  * (double) bp[18]);
+                                cp[19] =  saturateInt64 (cp[19]  * (double) bp[19]);
+                                cp[20] =  saturateInt64 (cp[20]  * (double) bp[20]);
+                                cp += 21; bp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt64 (*cp  * (double) *bp);
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           Int64* ap = ((Int64*)range.Item3 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt64 (ap[0]  * (double) cp[0]);
+                                cp[1] =  saturateInt64 (ap[1]  * (double) cp[1]);
+                                cp[2] =  saturateInt64 (ap[2]  * (double) cp[2]);
+                                cp[3] =  saturateInt64 (ap[3]  * (double) cp[3]);
+                                cp[4] =  saturateInt64 (ap[4]  * (double) cp[4]);
+                                cp[5] =  saturateInt64 (ap[5]  * (double) cp[5]);
+                                cp[6] =  saturateInt64 (ap[6]  * (double) cp[6]);
+                                cp[7] =  saturateInt64 (ap[7]  * (double) cp[7]);
+                                cp[8] =  saturateInt64 (ap[8]  * (double) cp[8]);
+                                cp[9] =  saturateInt64 (ap[9]  * (double) cp[9]);
+                                cp[10] =  saturateInt64 (ap[10]  * (double) cp[10]);
+                                cp[11] =  saturateInt64 (ap[11]  * (double) cp[11]);
+                                cp[12] =  saturateInt64 (ap[12]  * (double) cp[12]);
+                                cp[13] =  saturateInt64 (ap[13]  * (double) cp[13]);
+                                cp[14] =  saturateInt64 (ap[14]  * (double) cp[14]);
+                                cp[15] =  saturateInt64 (ap[15]  * (double) cp[15]);
+                                cp[16] =  saturateInt64 (ap[16]  * (double) cp[16]);
+                                cp[17] =  saturateInt64 (ap[17]  * (double) cp[17]);
+                                cp[18] =  saturateInt64 (ap[18]  * (double) cp[18]);
+                                cp[19] =  saturateInt64 (ap[19]  * (double) cp[19]);
+                                cp[20] =  saturateInt64 (ap[20]  * (double) cp[20]);
+                                ap += 21; cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt64 (*ap  * (double) *cp);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((Int64*)range.Item3 + range.Item1);
+                            bp = ((Int64*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt64 (ap[0]  * (double) bp[0]);
+                                cp[1] =  saturateInt64 (ap[1]  * (double) bp[1]);
+                                cp[2] =  saturateInt64 (ap[2]  * (double) bp[2]);
+                                cp[3] =  saturateInt64 (ap[3]  * (double) bp[3]);
+                                cp[4] =  saturateInt64 (ap[4]  * (double) bp[4]);
+                                cp[5] =  saturateInt64 (ap[5]  * (double) bp[5]);
+                                cp[6] =  saturateInt64 (ap[6]  * (double) bp[6]);
+                                cp[7] =  saturateInt64 (ap[7]  * (double) bp[7]);
+                                cp[8] =  saturateInt64 (ap[8]  * (double) bp[8]);
+                                cp[9] =  saturateInt64 (ap[9]  * (double) bp[9]);
+                                cp[10] =  saturateInt64 (ap[10]  * (double) bp[10]);
+                                cp[11] =  saturateInt64 (ap[11]  * (double) bp[11]);
+                                cp[12] =  saturateInt64 (ap[12]  * (double) bp[12]);
+                                cp[13] =  saturateInt64 (ap[13]  * (double) bp[13]);
+                                cp[14] =  saturateInt64 (ap[14]  * (double) bp[14]);
+                                cp[15] =  saturateInt64 (ap[15]  * (double) bp[15]);
+                                cp[16] =  saturateInt64 (ap[16]  * (double) bp[16]);
+                                cp[17] =  saturateInt64 (ap[17]  * (double) bp[17]);
+                                cp[18] =  saturateInt64 (ap[18]  * (double) bp[18]);
+                                cp[19] =  saturateInt64 (ap[19]  * (double) bp[19]);
+                                cp[20] =  saturateInt64 (ap[20]  * (double) bp[20]);
+                                ap+=21; bp+=21; cp+=21; j-=21;
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt64 (*ap  * (double) *bp);
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((Int64*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt64 (cp[0]  * (double) scalar);
+                                cp[1] =  saturateInt64 (cp[1]  * (double) scalar);
+                                cp[2] =  saturateInt64 (cp[2]  * (double) scalar);
+                                cp[3] =  saturateInt64 (cp[3]  * (double) scalar);
+                                cp[4] =  saturateInt64 (cp[4]  * (double) scalar);
+                                cp[5] =  saturateInt64 (cp[5]  * (double) scalar);
+                                cp[6] =  saturateInt64 (cp[6]  * (double) scalar);
+                                cp[7] =  saturateInt64 (cp[7]  * (double) scalar);
+                                cp[8] =  saturateInt64 (cp[8]  * (double) scalar);
+                                cp[9] =  saturateInt64 (cp[9]  * (double) scalar);
+                                cp[10] =  saturateInt64 (cp[10]  * (double) scalar);
+                                cp[11] =  saturateInt64 (cp[11]  * (double) scalar);
+                                cp[12] =  saturateInt64 (cp[12]  * (double) scalar);
+                                cp[13] =  saturateInt64 (cp[13]  * (double) scalar);
+                                cp[14] =  saturateInt64 (cp[14]  * (double) scalar);
+                                cp[15] =  saturateInt64 (cp[15]  * (double) scalar);
+                                cp[16] =  saturateInt64 (cp[16]  * (double) scalar);
+                                cp[17] =  saturateInt64 (cp[17]  * (double) scalar);
+                                cp[18] =  saturateInt64 (cp[18]  * (double) scalar);
+                                cp[19] =  saturateInt64 (cp[19]  * (double) scalar);
+                                cp[20] =  saturateInt64 (cp[20]  * (double) scalar);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt64 (*cp  * (double) scalar);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((Int64*)range.Item3 + range.Item1);
+                            scalar = *((Int64*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt64 (ap[0]  * (double) scalar);
+                                cp[1] =  saturateInt64 (ap[1]  * (double) scalar);
+                                cp[2] =  saturateInt64 (ap[2]  * (double) scalar);
+                                cp[3] =  saturateInt64 (ap[3]  * (double) scalar);
+                                cp[4] =  saturateInt64 (ap[4]  * (double) scalar);
+                                cp[5] =  saturateInt64 (ap[5]  * (double) scalar);
+                                cp[6] =  saturateInt64 (ap[6]  * (double) scalar);
+                                cp[7] =  saturateInt64 (ap[7]  * (double) scalar);
+                                cp[8] =  saturateInt64 (ap[8]  * (double) scalar);
+                                cp[9] =  saturateInt64 (ap[9]  * (double) scalar);
+                                cp[10] =  saturateInt64 (ap[10]  * (double) scalar);
+                                cp[11] =  saturateInt64 (ap[11]  * (double) scalar);
+                                cp[12] =  saturateInt64 (ap[12]  * (double) scalar);
+                                cp[13] =  saturateInt64 (ap[13]  * (double) scalar);
+                                cp[14] =  saturateInt64 (ap[14]  * (double) scalar);
+                                cp[15] =  saturateInt64 (ap[15]  * (double) scalar);
+                                cp[16] =  saturateInt64 (ap[16]  * (double) scalar);
+                                cp[17] =  saturateInt64 (ap[17]  * (double) scalar);
+                                cp[18] =  saturateInt64 (ap[18]  * (double) scalar);
+                                cp[19] =  saturateInt64 (ap[19]  * (double) scalar);
+                                cp[20] =  saturateInt64 (ap[20]  * (double) scalar);
+                                ap+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt64 (*ap  * (double) scalar);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((Int64*)range.Item3);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt64 (scalar  * (double) cp[0]);
+                                cp[1] =  saturateInt64 (scalar  * (double) cp[1]);
+                                cp[2] =  saturateInt64 (scalar  * (double) cp[2]);
+                                cp[3] =  saturateInt64 (scalar  * (double) cp[3]);
+                                cp[4] =  saturateInt64 (scalar  * (double) cp[4]);
+                                cp[5] =  saturateInt64 (scalar  * (double) cp[5]);
+                                cp[6] =  saturateInt64 (scalar  * (double) cp[6]);
+                                cp[7] =  saturateInt64 (scalar  * (double) cp[7]);
+                                cp[8] =  saturateInt64 (scalar  * (double) cp[8]);
+                                cp[9] =  saturateInt64 (scalar  * (double) cp[9]);
+                                cp[10] =  saturateInt64 (scalar  * (double) cp[10]);
+                                cp[11] =  saturateInt64 (scalar  * (double) cp[11]);
+                                cp[12] =  saturateInt64 (scalar  * (double) cp[12]);
+                                cp[13] =  saturateInt64 (scalar  * (double) cp[13]);
+                                cp[14] =  saturateInt64 (scalar  * (double) cp[14]);
+                                cp[15] =  saturateInt64 (scalar  * (double) cp[15]);
+                                cp[16] =  saturateInt64 (scalar  * (double) cp[16]);
+                                cp[17] =  saturateInt64 (scalar  * (double) cp[17]);
+                                cp[18] =  saturateInt64 (scalar  * (double) cp[18]);
+                                cp[19] =  saturateInt64 (scalar  * (double) cp[19]);
+                                cp[20] =  saturateInt64 (scalar  * (double) cp[20]);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt64 (scalar  * (double) *cp);
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((Int64*)range.Item3);
+                            bp = ((Int64*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt64 (scalar  * (double) bp[0]);
+                                cp[1] =  saturateInt64 (scalar  * (double) bp[1]);
+                                cp[2] =  saturateInt64 (scalar  * (double) bp[2]);
+                                cp[3] =  saturateInt64 (scalar  * (double) bp[3]);
+                                cp[4] =  saturateInt64 (scalar  * (double) bp[4]);
+                                cp[5] =  saturateInt64 (scalar  * (double) bp[5]);
+                                cp[6] =  saturateInt64 (scalar  * (double) bp[6]);
+                                cp[7] =  saturateInt64 (scalar  * (double) bp[7]);
+                                cp[8] =  saturateInt64 (scalar  * (double) bp[8]);
+                                cp[9] =  saturateInt64 (scalar  * (double) bp[9]);
+                                cp[10] =  saturateInt64 (scalar  * (double) bp[10]);
+                                cp[11] =  saturateInt64 (scalar  * (double) bp[11]);
+                                cp[12] =  saturateInt64 (scalar  * (double) bp[12]);
+                                cp[13] =  saturateInt64 (scalar  * (double) bp[13]);
+                                cp[14] =  saturateInt64 (scalar  * (double) bp[14]);
+                                cp[15] =  saturateInt64 (scalar  * (double) bp[15]);
+                                cp[16] =  saturateInt64 (scalar  * (double) bp[16]);
+                                cp[17] =  saturateInt64 (scalar  * (double) bp[17]);
+                                cp[18] =  saturateInt64 (scalar  * (double) bp[18]);
+                                cp[19] =  saturateInt64 (scalar  * (double) bp[19]);
+                                cp[20] =  saturateInt64 (scalar  * (double) bp[20]);
+                                bp+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt64 (scalar  * (double) *bp);
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work 
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                
+                fixed ( Int64* arrAP = arrA)
+                fixed ( Int64* arrBP = arrB)
+                fixed ( Int64* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range 
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new  ILRetArray< Int64>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<Int64>  multiplyElemEx(ILInArray<Int64> A, ILInArray<Int64> B) {
+            //using (ILScope.Enter(A, B)) { we cannot start a new scope here, since this would prevent A and B to be used implace if applicable
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<Int64>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<Int64>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<Int64>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                dim = -(dim - 1);  // 0 -> 1, 1 -> 0
+                #endregion
+
+                #region parameter preparation
+               
+                Int64[] retArr;
+               
+                Int64[] arrA = A.GetArrayForRead();
+               
+                Int64[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int workItemMultiplierLenA;
+                int workItemMultiplierLenB;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<Int64>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    workItemMultiplierLenB = outDims[0]; 
+                    workItemMultiplierLenA = dim;  // 0 for column, 1 for row vector
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<Int64>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    workItemMultiplierLenB = dim;  // 0 for column, 1 for row vector
+                    workItemMultiplierLenA = outDims[0]; 
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one singleton dimension in either A or B");
+                }
+                int itLen = outDims[0]; // (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<Int64> retStorage = new ILDenseStorage<Int64>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    Int64* ap;
+                   
+                    Int64* bp;
+                   
+                    Int64* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            if (dim == 0) {
+                                bp = (Int64*)range.Item3;
+                                cp = (Int64*)range.Item4; 
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (Int64*)range.Item2;
+                                    int l = itLen; 
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt64 (ap[0]  * (double) bp[0]);
+                                        cp[1] =  saturateInt64 (ap[1]  * (double) bp[1]);
+                                        cp[2] =  saturateInt64 (ap[2]  * (double) bp[2]);
+                                        cp[3] =  saturateInt64 (ap[3]  * (double) bp[3]);
+                                        cp[4] =  saturateInt64 (ap[4]  * (double) bp[4]);
+                                        cp[5] =  saturateInt64 (ap[5]  * (double) bp[5]);
+                                        cp[6] =  saturateInt64 (ap[6]  * (double) bp[6]);
+                                        cp[7] =  saturateInt64 (ap[7]  * (double) bp[7]);
+                                        cp[8] =  saturateInt64 (ap[8]  * (double) bp[8]);
+                                        cp[9] =  saturateInt64 (ap[9]  * (double) bp[9]);
+                                        cp[10] =  saturateInt64 (ap[10]  * (double) bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =  saturateInt64 (*ap++  * (double) *bp++);
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                ap = (Int64*)range.Item2;
+                                bp = (Int64*)range.Item3;
+                                cp = (Int64*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   Int64 val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt64 (val  * (double) bp[0]);
+                                        cp[1] =  saturateInt64 (val  * (double) bp[1]);
+                                        cp[2] =  saturateInt64 (val  * (double) bp[2]);
+                                        cp[3] =  saturateInt64 (val  * (double) bp[3]);
+                                        cp[4] =  saturateInt64 (val  * (double) bp[4]);
+                                        cp[5] =  saturateInt64 (val  * (double) bp[5]);
+                                        cp[6] =  saturateInt64 (val  * (double) bp[6]);
+                                        cp[7] =  saturateInt64 (val  * (double) bp[7]);
+                                        cp[8] =  saturateInt64 (val  * (double) bp[8]);
+                                        cp[9] =  saturateInt64 (val  * (double) bp[9]);
+                                        cp[10] =  saturateInt64 (val  * (double) bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11; 
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =  saturateInt64 (val  * (double) *bp++);
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            if (dim == 0) {
+                                cp = (Int64*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (Int64*)range.Item2;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt64 (ap[0]  * (double) cp[0]);
+                                        cp[1] =  saturateInt64 (ap[1]  * (double) cp[1]);
+                                        cp[2] =  saturateInt64 (ap[2]  * (double) cp[2]);
+                                        cp[3] =  saturateInt64 (ap[3]  * (double) cp[3]);
+                                        cp[4] =  saturateInt64 (ap[4]  * (double) cp[4]);
+                                        cp[5] =  saturateInt64 (ap[5]  * (double) cp[5]);
+                                        cp[6] =  saturateInt64 (ap[6]  * (double) cp[6]);
+                                        cp[7] =  saturateInt64 (ap[7]  * (double) cp[7]);
+                                        cp[8] =  saturateInt64 (ap[8]  * (double) cp[8]);
+                                        cp[9] =  saturateInt64 (ap[9]  * (double) cp[9]);
+                                        cp[10] =  saturateInt64 (ap[10]  * (double) cp[10]);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt64 (*ap++  * (double) *cp);
+                                        cp++; 
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                cp = (Int64*)range.Item4;
+                                ap = (Int64*)range.Item2;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    Int64 val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt64 (val  * (double) cp[0]);
+                                        cp[1] =  saturateInt64 (val  * (double) cp[1]);
+                                        cp[2] =  saturateInt64 (val  * (double) cp[2]);
+                                        cp[3] =  saturateInt64 (val  * (double) cp[3]);
+                                        cp[4] =  saturateInt64 (val  * (double) cp[4]);
+                                        cp[5] =  saturateInt64 (val  * (double) cp[5]);
+                                        cp[6] =  saturateInt64 (val  * (double) cp[6]);
+                                        cp[7] =  saturateInt64 (val  * (double) cp[7]);
+                                        cp[8] =  saturateInt64 (val  * (double) cp[8]);
+                                        cp[9] =  saturateInt64 (val  * (double) cp[9]);
+                                        cp[10] =  saturateInt64 (val  * (double) cp[10]);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt64 (val  * (double) *cp);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            if (dim == 0) {
+                                ap = (Int64*)range.Item2;
+                                cp = (Int64*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (Int64*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt64 (ap[0]  * (double) bp[0]);
+                                        cp[1] =  saturateInt64 (ap[1]  * (double) bp[1]);
+                                        cp[2] =  saturateInt64 (ap[2]  * (double) bp[2]);
+                                        cp[3] =  saturateInt64 (ap[3]  * (double) bp[3]);
+                                        cp[4] =  saturateInt64 (ap[4]  * (double) bp[4]);
+                                        cp[5] =  saturateInt64 (ap[5]  * (double) bp[5]);
+                                        cp[6] =  saturateInt64 (ap[6]  * (double) bp[6]);
+                                        cp[7] =  saturateInt64 (ap[7]  * (double) bp[7]);
+                                        cp[8] =  saturateInt64 (ap[8]  * (double) bp[8]);
+                                        cp[9] =  saturateInt64 (ap[9]  * (double) bp[9]);
+                                        cp[10] =  saturateInt64 (ap[10]  * (double) bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt64 (*ap  * (double) *bp);
+                                        ap++;
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                ap = (Int64*)range.Item2;
+                                bp = (Int64*)range.Item3;
+                                cp = (Int64*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   Int64 val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt64 (ap[0]  * (double) val);
+                                        cp[1] =  saturateInt64 (ap[1]  * (double) val);
+                                        cp[2] =  saturateInt64 (ap[2]  * (double) val);
+                                        cp[3] =  saturateInt64 (ap[3]  * (double) val);
+                                        cp[4] =  saturateInt64 (ap[4]  * (double) val);
+                                        cp[5] =  saturateInt64 (ap[5]  * (double) val);
+                                        cp[6] =  saturateInt64 (ap[6]  * (double) val);
+                                        cp[7] =  saturateInt64 (ap[7]  * (double) val);
+                                        cp[8] =  saturateInt64 (ap[8]  * (double) val);
+                                        cp[9] =  saturateInt64 (ap[9]  * (double) val);
+                                        cp[10] =  saturateInt64 (ap[10]  * (double) val);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt64 (*ap  * (double) val);
+                                        ap++;
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            if (dim == 0) {
+                                cp = (Int64*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (Int64*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt64 (cp[0]  * (double) bp[0]);
+                                        cp[1] =  saturateInt64 (cp[1]  * (double) bp[1]);
+                                        cp[2] =  saturateInt64 (cp[2]  * (double) bp[2]);
+                                        cp[3] =  saturateInt64 (cp[3]  * (double) bp[3]);
+                                        cp[4] =  saturateInt64 (cp[4]  * (double) bp[4]);
+                                        cp[5] =  saturateInt64 (cp[5]  * (double) bp[5]);
+                                        cp[6] =  saturateInt64 (cp[6]  * (double) bp[6]);
+                                        cp[7] =  saturateInt64 (cp[7]  * (double) bp[7]);
+                                        cp[8] =  saturateInt64 (cp[8]  * (double) bp[8]);
+                                        cp[9] =  saturateInt64 (cp[9]  * (double) bp[9]);
+                                        cp[10] =  saturateInt64 (cp[10]  * (double) bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt64 (*cp  * (double) *bp);
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                bp = (Int64*)range.Item3;
+                                cp = (Int64*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    Int64 val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt64 (cp[0]  * (double) val);
+                                        cp[1] =  saturateInt64 (cp[1]  * (double) val);
+                                        cp[2] =  saturateInt64 (cp[2]  * (double) val);
+                                        cp[3] =  saturateInt64 (cp[3]  * (double) val);
+                                        cp[4] =  saturateInt64 (cp[4]  * (double) val);
+                                        cp[5] =  saturateInt64 (cp[5]  * (double) val);
+                                        cp[6] =  saturateInt64 (cp[6]  * (double) val);
+                                        cp[7] =  saturateInt64 (cp[7]  * (double) val);
+                                        cp[8] =  saturateInt64 (cp[8]  * (double) val);
+                                        cp[9] =  saturateInt64 (cp[9]  * (double) val);
+                                        cp[10] =  saturateInt64 (cp[10]  * (double) val);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l --> 0) {
+                                        *cp =  saturateInt64 (*cp  * (double) val);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outDims.NumberOfElements >= Settings.s_minParallelElement1Count
+                    && outDims[1] > 1) {
+                        if (outDims[1] > workItemCount) {
+                        workItemLength = outDims[1] / workItemCount;
+                    } else {
+                        workItemLength = outDims[1] / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outDims[1];
+                    workItemCount = 1;
+                }
+
+                fixed ( Int64* arrAP = arrA)
+                fixed ( Int64* arrBP = arrB)
+                fixed ( Int64* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, IntPtr, IntPtr, IntPtr> range = new Tuple<int, IntPtr, IntPtr, IntPtr>
+                               (workItemLength
+                               , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                               , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                               , (IntPtr)(retArrP + i * outDims[0] * workItemLength)); 
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, IntPtr, IntPtr, IntPtr>
+                                (outDims[1] - i * workItemLength
+                                , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                                , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                                , (IntPtr)(retArrP + i * outDims[0] * workItemLength)));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<Int64>(retStorage);
+            //}  // no scopes here! it disables implace operations
+        }
+
+        /// <summary>Multiply arrays elementwise</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Array with elementwise multiplication of A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<Int32>  multiplyElem(ILInArray<Int32> A, ILInArray<Int32> B) {
+            using (ILScope.Enter(A,B)) {
+                int outLen; 
+                BinOpItMode mode; 
+                Int32 [] retArr;
+                Int32 [] arrA = A.GetArrayForRead();
+                Int32[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size; 
+                    if (B.IsScalar) {
+                       
+                        return new  ILRetArray<Int32> (new  Int32 [1]{ saturateInt32 (A.GetValue(0)  * (double) B.GetValue(0))}, A.Size);
+                    } else if (B.IsEmpty) {
+                        return  ILRetArray<Int32>.empty(outDims); 
+                    } else {
+                        outLen = outDims.NumberOfElements; 
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< Int32 > (outLen);
+                            mode = BinOpItMode.SAN; 
+                        } else {
+                            mode = BinOpItMode.SAI; 
+                        }
+                    }
+                } else {
+                    outDims = A.Size; 
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return  ILRetArray<Int32>.empty(A.Size);  
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< Int32 > (outLen);
+                            mode = BinOpItMode.ASN; 
+                        } else {
+                            mode = BinOpItMode.ASI; 
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  multiplyElemEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (A.TryGetStorage4InplaceOp(out retArr)) 
+                            mode  = BinOpItMode.AAIA; 
+                        else if (B.TryGetStorage4InplaceOp(out retArr)) 
+                            mode = BinOpItMode.AAIB; 
+                        else {
+                            retArr = ILMemoryPool.Pool.New< Int32 > (outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<Int32> retStorage = new ILDenseStorage<Int32>(retArr, outDims);
+                int i = 0, workerCount = 1; 
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    Int32* cp = (Int32*)range.Item5 + range.Item1;
+                    Int32 scalar;
+                    int j = range.Item2; 
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           Int32* bp = ((Int32*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                                cp[0] =  saturateInt32 (cp[0]  * (double) bp[0]);
+                                cp[1] =  saturateInt32 (cp[1]  * (double) bp[1]);
+                                cp[2] =  saturateInt32 (cp[2]  * (double) bp[2]);
+                                cp[3] =  saturateInt32 (cp[3]  * (double) bp[3]);
+                                cp[4] =  saturateInt32 (cp[4]  * (double) bp[4]);
+                                cp[5] =  saturateInt32 (cp[5]  * (double) bp[5]);
+                                cp[6] =  saturateInt32 (cp[6]  * (double) bp[6]);
+                                cp[7] =  saturateInt32 (cp[7]  * (double) bp[7]);
+                                cp[8] =  saturateInt32 (cp[8]  * (double) bp[8]);
+                                cp[9] =  saturateInt32 (cp[9]  * (double) bp[9]);
+                                cp[10] =  saturateInt32 (cp[10]  * (double) bp[10]);
+                                cp[11] =  saturateInt32 (cp[11]  * (double) bp[11]);
+                                cp[12] =  saturateInt32 (cp[12]  * (double) bp[12]);
+                                cp[13] =  saturateInt32 (cp[13]  * (double) bp[13]);
+                                cp[14] =  saturateInt32 (cp[14]  * (double) bp[14]);
+                                cp[15] =  saturateInt32 (cp[15]  * (double) bp[15]);
+                                cp[16] =  saturateInt32 (cp[16]  * (double) bp[16]);
+                                cp[17] =  saturateInt32 (cp[17]  * (double) bp[17]);
+                                cp[18] =  saturateInt32 (cp[18]  * (double) bp[18]);
+                                cp[19] =  saturateInt32 (cp[19]  * (double) bp[19]);
+                                cp[20] =  saturateInt32 (cp[20]  * (double) bp[20]);
+                                cp += 21; bp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt32 (*cp  * (double) *bp);
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           Int32* ap = ((Int32*)range.Item3 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt32 (ap[0]  * (double) cp[0]);
+                                cp[1] =  saturateInt32 (ap[1]  * (double) cp[1]);
+                                cp[2] =  saturateInt32 (ap[2]  * (double) cp[2]);
+                                cp[3] =  saturateInt32 (ap[3]  * (double) cp[3]);
+                                cp[4] =  saturateInt32 (ap[4]  * (double) cp[4]);
+                                cp[5] =  saturateInt32 (ap[5]  * (double) cp[5]);
+                                cp[6] =  saturateInt32 (ap[6]  * (double) cp[6]);
+                                cp[7] =  saturateInt32 (ap[7]  * (double) cp[7]);
+                                cp[8] =  saturateInt32 (ap[8]  * (double) cp[8]);
+                                cp[9] =  saturateInt32 (ap[9]  * (double) cp[9]);
+                                cp[10] =  saturateInt32 (ap[10]  * (double) cp[10]);
+                                cp[11] =  saturateInt32 (ap[11]  * (double) cp[11]);
+                                cp[12] =  saturateInt32 (ap[12]  * (double) cp[12]);
+                                cp[13] =  saturateInt32 (ap[13]  * (double) cp[13]);
+                                cp[14] =  saturateInt32 (ap[14]  * (double) cp[14]);
+                                cp[15] =  saturateInt32 (ap[15]  * (double) cp[15]);
+                                cp[16] =  saturateInt32 (ap[16]  * (double) cp[16]);
+                                cp[17] =  saturateInt32 (ap[17]  * (double) cp[17]);
+                                cp[18] =  saturateInt32 (ap[18]  * (double) cp[18]);
+                                cp[19] =  saturateInt32 (ap[19]  * (double) cp[19]);
+                                cp[20] =  saturateInt32 (ap[20]  * (double) cp[20]);
+                                ap += 21; cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt32 (*ap  * (double) *cp);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((Int32*)range.Item3 + range.Item1);
+                            bp = ((Int32*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt32 (ap[0]  * (double) bp[0]);
+                                cp[1] =  saturateInt32 (ap[1]  * (double) bp[1]);
+                                cp[2] =  saturateInt32 (ap[2]  * (double) bp[2]);
+                                cp[3] =  saturateInt32 (ap[3]  * (double) bp[3]);
+                                cp[4] =  saturateInt32 (ap[4]  * (double) bp[4]);
+                                cp[5] =  saturateInt32 (ap[5]  * (double) bp[5]);
+                                cp[6] =  saturateInt32 (ap[6]  * (double) bp[6]);
+                                cp[7] =  saturateInt32 (ap[7]  * (double) bp[7]);
+                                cp[8] =  saturateInt32 (ap[8]  * (double) bp[8]);
+                                cp[9] =  saturateInt32 (ap[9]  * (double) bp[9]);
+                                cp[10] =  saturateInt32 (ap[10]  * (double) bp[10]);
+                                cp[11] =  saturateInt32 (ap[11]  * (double) bp[11]);
+                                cp[12] =  saturateInt32 (ap[12]  * (double) bp[12]);
+                                cp[13] =  saturateInt32 (ap[13]  * (double) bp[13]);
+                                cp[14] =  saturateInt32 (ap[14]  * (double) bp[14]);
+                                cp[15] =  saturateInt32 (ap[15]  * (double) bp[15]);
+                                cp[16] =  saturateInt32 (ap[16]  * (double) bp[16]);
+                                cp[17] =  saturateInt32 (ap[17]  * (double) bp[17]);
+                                cp[18] =  saturateInt32 (ap[18]  * (double) bp[18]);
+                                cp[19] =  saturateInt32 (ap[19]  * (double) bp[19]);
+                                cp[20] =  saturateInt32 (ap[20]  * (double) bp[20]);
+                                ap+=21; bp+=21; cp+=21; j-=21;
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt32 (*ap  * (double) *bp);
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((Int32*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt32 (cp[0]  * (double) scalar);
+                                cp[1] =  saturateInt32 (cp[1]  * (double) scalar);
+                                cp[2] =  saturateInt32 (cp[2]  * (double) scalar);
+                                cp[3] =  saturateInt32 (cp[3]  * (double) scalar);
+                                cp[4] =  saturateInt32 (cp[4]  * (double) scalar);
+                                cp[5] =  saturateInt32 (cp[5]  * (double) scalar);
+                                cp[6] =  saturateInt32 (cp[6]  * (double) scalar);
+                                cp[7] =  saturateInt32 (cp[7]  * (double) scalar);
+                                cp[8] =  saturateInt32 (cp[8]  * (double) scalar);
+                                cp[9] =  saturateInt32 (cp[9]  * (double) scalar);
+                                cp[10] =  saturateInt32 (cp[10]  * (double) scalar);
+                                cp[11] =  saturateInt32 (cp[11]  * (double) scalar);
+                                cp[12] =  saturateInt32 (cp[12]  * (double) scalar);
+                                cp[13] =  saturateInt32 (cp[13]  * (double) scalar);
+                                cp[14] =  saturateInt32 (cp[14]  * (double) scalar);
+                                cp[15] =  saturateInt32 (cp[15]  * (double) scalar);
+                                cp[16] =  saturateInt32 (cp[16]  * (double) scalar);
+                                cp[17] =  saturateInt32 (cp[17]  * (double) scalar);
+                                cp[18] =  saturateInt32 (cp[18]  * (double) scalar);
+                                cp[19] =  saturateInt32 (cp[19]  * (double) scalar);
+                                cp[20] =  saturateInt32 (cp[20]  * (double) scalar);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt32 (*cp  * (double) scalar);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((Int32*)range.Item3 + range.Item1);
+                            scalar = *((Int32*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt32 (ap[0]  * (double) scalar);
+                                cp[1] =  saturateInt32 (ap[1]  * (double) scalar);
+                                cp[2] =  saturateInt32 (ap[2]  * (double) scalar);
+                                cp[3] =  saturateInt32 (ap[3]  * (double) scalar);
+                                cp[4] =  saturateInt32 (ap[4]  * (double) scalar);
+                                cp[5] =  saturateInt32 (ap[5]  * (double) scalar);
+                                cp[6] =  saturateInt32 (ap[6]  * (double) scalar);
+                                cp[7] =  saturateInt32 (ap[7]  * (double) scalar);
+                                cp[8] =  saturateInt32 (ap[8]  * (double) scalar);
+                                cp[9] =  saturateInt32 (ap[9]  * (double) scalar);
+                                cp[10] =  saturateInt32 (ap[10]  * (double) scalar);
+                                cp[11] =  saturateInt32 (ap[11]  * (double) scalar);
+                                cp[12] =  saturateInt32 (ap[12]  * (double) scalar);
+                                cp[13] =  saturateInt32 (ap[13]  * (double) scalar);
+                                cp[14] =  saturateInt32 (ap[14]  * (double) scalar);
+                                cp[15] =  saturateInt32 (ap[15]  * (double) scalar);
+                                cp[16] =  saturateInt32 (ap[16]  * (double) scalar);
+                                cp[17] =  saturateInt32 (ap[17]  * (double) scalar);
+                                cp[18] =  saturateInt32 (ap[18]  * (double) scalar);
+                                cp[19] =  saturateInt32 (ap[19]  * (double) scalar);
+                                cp[20] =  saturateInt32 (ap[20]  * (double) scalar);
+                                ap+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt32 (*ap  * (double) scalar);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((Int32*)range.Item3);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt32 (scalar  * (double) cp[0]);
+                                cp[1] =  saturateInt32 (scalar  * (double) cp[1]);
+                                cp[2] =  saturateInt32 (scalar  * (double) cp[2]);
+                                cp[3] =  saturateInt32 (scalar  * (double) cp[3]);
+                                cp[4] =  saturateInt32 (scalar  * (double) cp[4]);
+                                cp[5] =  saturateInt32 (scalar  * (double) cp[5]);
+                                cp[6] =  saturateInt32 (scalar  * (double) cp[6]);
+                                cp[7] =  saturateInt32 (scalar  * (double) cp[7]);
+                                cp[8] =  saturateInt32 (scalar  * (double) cp[8]);
+                                cp[9] =  saturateInt32 (scalar  * (double) cp[9]);
+                                cp[10] =  saturateInt32 (scalar  * (double) cp[10]);
+                                cp[11] =  saturateInt32 (scalar  * (double) cp[11]);
+                                cp[12] =  saturateInt32 (scalar  * (double) cp[12]);
+                                cp[13] =  saturateInt32 (scalar  * (double) cp[13]);
+                                cp[14] =  saturateInt32 (scalar  * (double) cp[14]);
+                                cp[15] =  saturateInt32 (scalar  * (double) cp[15]);
+                                cp[16] =  saturateInt32 (scalar  * (double) cp[16]);
+                                cp[17] =  saturateInt32 (scalar  * (double) cp[17]);
+                                cp[18] =  saturateInt32 (scalar  * (double) cp[18]);
+                                cp[19] =  saturateInt32 (scalar  * (double) cp[19]);
+                                cp[20] =  saturateInt32 (scalar  * (double) cp[20]);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt32 (scalar  * (double) *cp);
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((Int32*)range.Item3);
+                            bp = ((Int32*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt32 (scalar  * (double) bp[0]);
+                                cp[1] =  saturateInt32 (scalar  * (double) bp[1]);
+                                cp[2] =  saturateInt32 (scalar  * (double) bp[2]);
+                                cp[3] =  saturateInt32 (scalar  * (double) bp[3]);
+                                cp[4] =  saturateInt32 (scalar  * (double) bp[4]);
+                                cp[5] =  saturateInt32 (scalar  * (double) bp[5]);
+                                cp[6] =  saturateInt32 (scalar  * (double) bp[6]);
+                                cp[7] =  saturateInt32 (scalar  * (double) bp[7]);
+                                cp[8] =  saturateInt32 (scalar  * (double) bp[8]);
+                                cp[9] =  saturateInt32 (scalar  * (double) bp[9]);
+                                cp[10] =  saturateInt32 (scalar  * (double) bp[10]);
+                                cp[11] =  saturateInt32 (scalar  * (double) bp[11]);
+                                cp[12] =  saturateInt32 (scalar  * (double) bp[12]);
+                                cp[13] =  saturateInt32 (scalar  * (double) bp[13]);
+                                cp[14] =  saturateInt32 (scalar  * (double) bp[14]);
+                                cp[15] =  saturateInt32 (scalar  * (double) bp[15]);
+                                cp[16] =  saturateInt32 (scalar  * (double) bp[16]);
+                                cp[17] =  saturateInt32 (scalar  * (double) bp[17]);
+                                cp[18] =  saturateInt32 (scalar  * (double) bp[18]);
+                                cp[19] =  saturateInt32 (scalar  * (double) bp[19]);
+                                cp[20] =  saturateInt32 (scalar  * (double) bp[20]);
+                                bp+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt32 (scalar  * (double) *bp);
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work 
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                
+                fixed ( Int32* arrAP = arrA)
+                fixed ( Int32* arrBP = arrB)
+                fixed ( Int32* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range 
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new  ILRetArray< Int32>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<Int32>  multiplyElemEx(ILInArray<Int32> A, ILInArray<Int32> B) {
+            //using (ILScope.Enter(A, B)) { we cannot start a new scope here, since this would prevent A and B to be used implace if applicable
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<Int32>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<Int32>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<Int32>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                dim = -(dim - 1);  // 0 -> 1, 1 -> 0
+                #endregion
+
+                #region parameter preparation
+               
+                Int32[] retArr;
+               
+                Int32[] arrA = A.GetArrayForRead();
+               
+                Int32[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int workItemMultiplierLenA;
+                int workItemMultiplierLenB;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<Int32>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    workItemMultiplierLenB = outDims[0]; 
+                    workItemMultiplierLenA = dim;  // 0 for column, 1 for row vector
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<Int32>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    workItemMultiplierLenB = dim;  // 0 for column, 1 for row vector
+                    workItemMultiplierLenA = outDims[0]; 
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one singleton dimension in either A or B");
+                }
+                int itLen = outDims[0]; // (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<Int32> retStorage = new ILDenseStorage<Int32>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    Int32* ap;
+                   
+                    Int32* bp;
+                   
+                    Int32* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            if (dim == 0) {
+                                bp = (Int32*)range.Item3;
+                                cp = (Int32*)range.Item4; 
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (Int32*)range.Item2;
+                                    int l = itLen; 
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt32 (ap[0]  * (double) bp[0]);
+                                        cp[1] =  saturateInt32 (ap[1]  * (double) bp[1]);
+                                        cp[2] =  saturateInt32 (ap[2]  * (double) bp[2]);
+                                        cp[3] =  saturateInt32 (ap[3]  * (double) bp[3]);
+                                        cp[4] =  saturateInt32 (ap[4]  * (double) bp[4]);
+                                        cp[5] =  saturateInt32 (ap[5]  * (double) bp[5]);
+                                        cp[6] =  saturateInt32 (ap[6]  * (double) bp[6]);
+                                        cp[7] =  saturateInt32 (ap[7]  * (double) bp[7]);
+                                        cp[8] =  saturateInt32 (ap[8]  * (double) bp[8]);
+                                        cp[9] =  saturateInt32 (ap[9]  * (double) bp[9]);
+                                        cp[10] =  saturateInt32 (ap[10]  * (double) bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =  saturateInt32 (*ap++  * (double) *bp++);
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                ap = (Int32*)range.Item2;
+                                bp = (Int32*)range.Item3;
+                                cp = (Int32*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   Int32 val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt32 (val  * (double) bp[0]);
+                                        cp[1] =  saturateInt32 (val  * (double) bp[1]);
+                                        cp[2] =  saturateInt32 (val  * (double) bp[2]);
+                                        cp[3] =  saturateInt32 (val  * (double) bp[3]);
+                                        cp[4] =  saturateInt32 (val  * (double) bp[4]);
+                                        cp[5] =  saturateInt32 (val  * (double) bp[5]);
+                                        cp[6] =  saturateInt32 (val  * (double) bp[6]);
+                                        cp[7] =  saturateInt32 (val  * (double) bp[7]);
+                                        cp[8] =  saturateInt32 (val  * (double) bp[8]);
+                                        cp[9] =  saturateInt32 (val  * (double) bp[9]);
+                                        cp[10] =  saturateInt32 (val  * (double) bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11; 
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =  saturateInt32 (val  * (double) *bp++);
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            if (dim == 0) {
+                                cp = (Int32*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (Int32*)range.Item2;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt32 (ap[0]  * (double) cp[0]);
+                                        cp[1] =  saturateInt32 (ap[1]  * (double) cp[1]);
+                                        cp[2] =  saturateInt32 (ap[2]  * (double) cp[2]);
+                                        cp[3] =  saturateInt32 (ap[3]  * (double) cp[3]);
+                                        cp[4] =  saturateInt32 (ap[4]  * (double) cp[4]);
+                                        cp[5] =  saturateInt32 (ap[5]  * (double) cp[5]);
+                                        cp[6] =  saturateInt32 (ap[6]  * (double) cp[6]);
+                                        cp[7] =  saturateInt32 (ap[7]  * (double) cp[7]);
+                                        cp[8] =  saturateInt32 (ap[8]  * (double) cp[8]);
+                                        cp[9] =  saturateInt32 (ap[9]  * (double) cp[9]);
+                                        cp[10] =  saturateInt32 (ap[10]  * (double) cp[10]);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt32 (*ap++  * (double) *cp);
+                                        cp++; 
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                cp = (Int32*)range.Item4;
+                                ap = (Int32*)range.Item2;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    Int32 val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt32 (val  * (double) cp[0]);
+                                        cp[1] =  saturateInt32 (val  * (double) cp[1]);
+                                        cp[2] =  saturateInt32 (val  * (double) cp[2]);
+                                        cp[3] =  saturateInt32 (val  * (double) cp[3]);
+                                        cp[4] =  saturateInt32 (val  * (double) cp[4]);
+                                        cp[5] =  saturateInt32 (val  * (double) cp[5]);
+                                        cp[6] =  saturateInt32 (val  * (double) cp[6]);
+                                        cp[7] =  saturateInt32 (val  * (double) cp[7]);
+                                        cp[8] =  saturateInt32 (val  * (double) cp[8]);
+                                        cp[9] =  saturateInt32 (val  * (double) cp[9]);
+                                        cp[10] =  saturateInt32 (val  * (double) cp[10]);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt32 (val  * (double) *cp);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            if (dim == 0) {
+                                ap = (Int32*)range.Item2;
+                                cp = (Int32*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (Int32*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt32 (ap[0]  * (double) bp[0]);
+                                        cp[1] =  saturateInt32 (ap[1]  * (double) bp[1]);
+                                        cp[2] =  saturateInt32 (ap[2]  * (double) bp[2]);
+                                        cp[3] =  saturateInt32 (ap[3]  * (double) bp[3]);
+                                        cp[4] =  saturateInt32 (ap[4]  * (double) bp[4]);
+                                        cp[5] =  saturateInt32 (ap[5]  * (double) bp[5]);
+                                        cp[6] =  saturateInt32 (ap[6]  * (double) bp[6]);
+                                        cp[7] =  saturateInt32 (ap[7]  * (double) bp[7]);
+                                        cp[8] =  saturateInt32 (ap[8]  * (double) bp[8]);
+                                        cp[9] =  saturateInt32 (ap[9]  * (double) bp[9]);
+                                        cp[10] =  saturateInt32 (ap[10]  * (double) bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt32 (*ap  * (double) *bp);
+                                        ap++;
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                ap = (Int32*)range.Item2;
+                                bp = (Int32*)range.Item3;
+                                cp = (Int32*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   Int32 val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt32 (ap[0]  * (double) val);
+                                        cp[1] =  saturateInt32 (ap[1]  * (double) val);
+                                        cp[2] =  saturateInt32 (ap[2]  * (double) val);
+                                        cp[3] =  saturateInt32 (ap[3]  * (double) val);
+                                        cp[4] =  saturateInt32 (ap[4]  * (double) val);
+                                        cp[5] =  saturateInt32 (ap[5]  * (double) val);
+                                        cp[6] =  saturateInt32 (ap[6]  * (double) val);
+                                        cp[7] =  saturateInt32 (ap[7]  * (double) val);
+                                        cp[8] =  saturateInt32 (ap[8]  * (double) val);
+                                        cp[9] =  saturateInt32 (ap[9]  * (double) val);
+                                        cp[10] =  saturateInt32 (ap[10]  * (double) val);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt32 (*ap  * (double) val);
+                                        ap++;
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            if (dim == 0) {
+                                cp = (Int32*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (Int32*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt32 (cp[0]  * (double) bp[0]);
+                                        cp[1] =  saturateInt32 (cp[1]  * (double) bp[1]);
+                                        cp[2] =  saturateInt32 (cp[2]  * (double) bp[2]);
+                                        cp[3] =  saturateInt32 (cp[3]  * (double) bp[3]);
+                                        cp[4] =  saturateInt32 (cp[4]  * (double) bp[4]);
+                                        cp[5] =  saturateInt32 (cp[5]  * (double) bp[5]);
+                                        cp[6] =  saturateInt32 (cp[6]  * (double) bp[6]);
+                                        cp[7] =  saturateInt32 (cp[7]  * (double) bp[7]);
+                                        cp[8] =  saturateInt32 (cp[8]  * (double) bp[8]);
+                                        cp[9] =  saturateInt32 (cp[9]  * (double) bp[9]);
+                                        cp[10] =  saturateInt32 (cp[10]  * (double) bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt32 (*cp  * (double) *bp);
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                bp = (Int32*)range.Item3;
+                                cp = (Int32*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    Int32 val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt32 (cp[0]  * (double) val);
+                                        cp[1] =  saturateInt32 (cp[1]  * (double) val);
+                                        cp[2] =  saturateInt32 (cp[2]  * (double) val);
+                                        cp[3] =  saturateInt32 (cp[3]  * (double) val);
+                                        cp[4] =  saturateInt32 (cp[4]  * (double) val);
+                                        cp[5] =  saturateInt32 (cp[5]  * (double) val);
+                                        cp[6] =  saturateInt32 (cp[6]  * (double) val);
+                                        cp[7] =  saturateInt32 (cp[7]  * (double) val);
+                                        cp[8] =  saturateInt32 (cp[8]  * (double) val);
+                                        cp[9] =  saturateInt32 (cp[9]  * (double) val);
+                                        cp[10] =  saturateInt32 (cp[10]  * (double) val);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l --> 0) {
+                                        *cp =  saturateInt32 (*cp  * (double) val);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outDims.NumberOfElements >= Settings.s_minParallelElement1Count
+                    && outDims[1] > 1) {
+                        if (outDims[1] > workItemCount) {
+                        workItemLength = outDims[1] / workItemCount;
+                    } else {
+                        workItemLength = outDims[1] / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outDims[1];
+                    workItemCount = 1;
+                }
+
+                fixed ( Int32* arrAP = arrA)
+                fixed ( Int32* arrBP = arrB)
+                fixed ( Int32* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, IntPtr, IntPtr, IntPtr> range = new Tuple<int, IntPtr, IntPtr, IntPtr>
+                               (workItemLength
+                               , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                               , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                               , (IntPtr)(retArrP + i * outDims[0] * workItemLength)); 
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, IntPtr, IntPtr, IntPtr>
+                                (outDims[1] - i * workItemLength
+                                , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                                , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                                , (IntPtr)(retArrP + i * outDims[0] * workItemLength)));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<Int32>(retStorage);
+            //}  // no scopes here! it disables implace operations
+        }
+
+        /// <summary>Multiply arrays elementwise</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Array with elementwise multiplication of A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<float>  multiplyElem(ILInArray<float> A, ILInArray<float> B) {
+            using (ILScope.Enter(A,B)) {
+                int outLen; 
+                BinOpItMode mode; 
+                float [] retArr;
+                float [] arrA = A.GetArrayForRead();
+                float[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size; 
+                    if (B.IsScalar) {
+                       
+                        return new  ILRetArray<float> (new  float [1]{  (A.GetValue(0)  * B.GetValue(0))}, A.Size);
+                    } else if (B.IsEmpty) {
+                        return  ILRetArray<float>.empty(outDims); 
+                    } else {
+                        outLen = outDims.NumberOfElements; 
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< float > (outLen);
+                            mode = BinOpItMode.SAN; 
+                        } else {
+                            mode = BinOpItMode.SAI; 
+                        }
+                    }
+                } else {
+                    outDims = A.Size; 
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return  ILRetArray<float>.empty(A.Size);  
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< float > (outLen);
+                            mode = BinOpItMode.ASN; 
+                        } else {
+                            mode = BinOpItMode.ASI; 
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  multiplyElemEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (A.TryGetStorage4InplaceOp(out retArr)) 
+                            mode  = BinOpItMode.AAIA; 
+                        else if (B.TryGetStorage4InplaceOp(out retArr)) 
+                            mode = BinOpItMode.AAIB; 
+                        else {
+                            retArr = ILMemoryPool.Pool.New< float > (outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<float> retStorage = new ILDenseStorage<float>(retArr, outDims);
+                int i = 0, workerCount = 1; 
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    float* cp = (float*)range.Item5 + range.Item1;
+                    float scalar;
+                    int j = range.Item2; 
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           float* bp = ((float*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                                cp[0] =   (cp[0]  * bp[0]);
+                                cp[1] =   (cp[1]  * bp[1]);
+                                cp[2] =   (cp[2]  * bp[2]);
+                                cp[3] =   (cp[3]  * bp[3]);
+                                cp[4] =   (cp[4]  * bp[4]);
+                                cp[5] =   (cp[5]  * bp[5]);
+                                cp[6] =   (cp[6]  * bp[6]);
+                                cp[7] =   (cp[7]  * bp[7]);
+                                cp[8] =   (cp[8]  * bp[8]);
+                                cp[9] =   (cp[9]  * bp[9]);
+                                cp[10] =   (cp[10]  * bp[10]);
+                                cp[11] =   (cp[11]  * bp[11]);
+                                cp[12] =   (cp[12]  * bp[12]);
+                                cp[13] =   (cp[13]  * bp[13]);
+                                cp[14] =   (cp[14]  * bp[14]);
+                                cp[15] =   (cp[15]  * bp[15]);
+                                cp[16] =   (cp[16]  * bp[16]);
+                                cp[17] =   (cp[17]  * bp[17]);
+                                cp[18] =   (cp[18]  * bp[18]);
+                                cp[19] =   (cp[19]  * bp[19]);
+                                cp[20] =   (cp[20]  * bp[20]);
+                                cp += 21; bp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*cp  * *bp);
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           float* ap = ((float*)range.Item3 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  * cp[0]);
+                                cp[1] =   (ap[1]  * cp[1]);
+                                cp[2] =   (ap[2]  * cp[2]);
+                                cp[3] =   (ap[3]  * cp[3]);
+                                cp[4] =   (ap[4]  * cp[4]);
+                                cp[5] =   (ap[5]  * cp[5]);
+                                cp[6] =   (ap[6]  * cp[6]);
+                                cp[7] =   (ap[7]  * cp[7]);
+                                cp[8] =   (ap[8]  * cp[8]);
+                                cp[9] =   (ap[9]  * cp[9]);
+                                cp[10] =   (ap[10]  * cp[10]);
+                                cp[11] =   (ap[11]  * cp[11]);
+                                cp[12] =   (ap[12]  * cp[12]);
+                                cp[13] =   (ap[13]  * cp[13]);
+                                cp[14] =   (ap[14]  * cp[14]);
+                                cp[15] =   (ap[15]  * cp[15]);
+                                cp[16] =   (ap[16]  * cp[16]);
+                                cp[17] =   (ap[17]  * cp[17]);
+                                cp[18] =   (ap[18]  * cp[18]);
+                                cp[19] =   (ap[19]  * cp[19]);
+                                cp[20] =   (ap[20]  * cp[20]);
+                                ap += 21; cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  * *cp);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((float*)range.Item3 + range.Item1);
+                            bp = ((float*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  * bp[0]);
+                                cp[1] =   (ap[1]  * bp[1]);
+                                cp[2] =   (ap[2]  * bp[2]);
+                                cp[3] =   (ap[3]  * bp[3]);
+                                cp[4] =   (ap[4]  * bp[4]);
+                                cp[5] =   (ap[5]  * bp[5]);
+                                cp[6] =   (ap[6]  * bp[6]);
+                                cp[7] =   (ap[7]  * bp[7]);
+                                cp[8] =   (ap[8]  * bp[8]);
+                                cp[9] =   (ap[9]  * bp[9]);
+                                cp[10] =   (ap[10]  * bp[10]);
+                                cp[11] =   (ap[11]  * bp[11]);
+                                cp[12] =   (ap[12]  * bp[12]);
+                                cp[13] =   (ap[13]  * bp[13]);
+                                cp[14] =   (ap[14]  * bp[14]);
+                                cp[15] =   (ap[15]  * bp[15]);
+                                cp[16] =   (ap[16]  * bp[16]);
+                                cp[17] =   (ap[17]  * bp[17]);
+                                cp[18] =   (ap[18]  * bp[18]);
+                                cp[19] =   (ap[19]  * bp[19]);
+                                cp[20] =   (ap[20]  * bp[20]);
+                                ap+=21; bp+=21; cp+=21; j-=21;
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  * *bp);
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((float*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =   (cp[0]  * scalar);
+                                cp[1] =   (cp[1]  * scalar);
+                                cp[2] =   (cp[2]  * scalar);
+                                cp[3] =   (cp[3]  * scalar);
+                                cp[4] =   (cp[4]  * scalar);
+                                cp[5] =   (cp[5]  * scalar);
+                                cp[6] =   (cp[6]  * scalar);
+                                cp[7] =   (cp[7]  * scalar);
+                                cp[8] =   (cp[8]  * scalar);
+                                cp[9] =   (cp[9]  * scalar);
+                                cp[10] =   (cp[10]  * scalar);
+                                cp[11] =   (cp[11]  * scalar);
+                                cp[12] =   (cp[12]  * scalar);
+                                cp[13] =   (cp[13]  * scalar);
+                                cp[14] =   (cp[14]  * scalar);
+                                cp[15] =   (cp[15]  * scalar);
+                                cp[16] =   (cp[16]  * scalar);
+                                cp[17] =   (cp[17]  * scalar);
+                                cp[18] =   (cp[18]  * scalar);
+                                cp[19] =   (cp[19]  * scalar);
+                                cp[20] =   (cp[20]  * scalar);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*cp  * scalar);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((float*)range.Item3 + range.Item1);
+                            scalar = *((float*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  * scalar);
+                                cp[1] =   (ap[1]  * scalar);
+                                cp[2] =   (ap[2]  * scalar);
+                                cp[3] =   (ap[3]  * scalar);
+                                cp[4] =   (ap[4]  * scalar);
+                                cp[5] =   (ap[5]  * scalar);
+                                cp[6] =   (ap[6]  * scalar);
+                                cp[7] =   (ap[7]  * scalar);
+                                cp[8] =   (ap[8]  * scalar);
+                                cp[9] =   (ap[9]  * scalar);
+                                cp[10] =   (ap[10]  * scalar);
+                                cp[11] =   (ap[11]  * scalar);
+                                cp[12] =   (ap[12]  * scalar);
+                                cp[13] =   (ap[13]  * scalar);
+                                cp[14] =   (ap[14]  * scalar);
+                                cp[15] =   (ap[15]  * scalar);
+                                cp[16] =   (ap[16]  * scalar);
+                                cp[17] =   (ap[17]  * scalar);
+                                cp[18] =   (ap[18]  * scalar);
+                                cp[19] =   (ap[19]  * scalar);
+                                cp[20] =   (ap[20]  * scalar);
+                                ap+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  * scalar);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((float*)range.Item3);
+                            while (j > 20) {
+                               
+                                cp[0] =   (scalar  * cp[0]);
+                                cp[1] =   (scalar  * cp[1]);
+                                cp[2] =   (scalar  * cp[2]);
+                                cp[3] =   (scalar  * cp[3]);
+                                cp[4] =   (scalar  * cp[4]);
+                                cp[5] =   (scalar  * cp[5]);
+                                cp[6] =   (scalar  * cp[6]);
+                                cp[7] =   (scalar  * cp[7]);
+                                cp[8] =   (scalar  * cp[8]);
+                                cp[9] =   (scalar  * cp[9]);
+                                cp[10] =   (scalar  * cp[10]);
+                                cp[11] =   (scalar  * cp[11]);
+                                cp[12] =   (scalar  * cp[12]);
+                                cp[13] =   (scalar  * cp[13]);
+                                cp[14] =   (scalar  * cp[14]);
+                                cp[15] =   (scalar  * cp[15]);
+                                cp[16] =   (scalar  * cp[16]);
+                                cp[17] =   (scalar  * cp[17]);
+                                cp[18] =   (scalar  * cp[18]);
+                                cp[19] =   (scalar  * cp[19]);
+                                cp[20] =   (scalar  * cp[20]);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (scalar  * *cp);
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((float*)range.Item3);
+                            bp = ((float*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (scalar  * bp[0]);
+                                cp[1] =   (scalar  * bp[1]);
+                                cp[2] =   (scalar  * bp[2]);
+                                cp[3] =   (scalar  * bp[3]);
+                                cp[4] =   (scalar  * bp[4]);
+                                cp[5] =   (scalar  * bp[5]);
+                                cp[6] =   (scalar  * bp[6]);
+                                cp[7] =   (scalar  * bp[7]);
+                                cp[8] =   (scalar  * bp[8]);
+                                cp[9] =   (scalar  * bp[9]);
+                                cp[10] =   (scalar  * bp[10]);
+                                cp[11] =   (scalar  * bp[11]);
+                                cp[12] =   (scalar  * bp[12]);
+                                cp[13] =   (scalar  * bp[13]);
+                                cp[14] =   (scalar  * bp[14]);
+                                cp[15] =   (scalar  * bp[15]);
+                                cp[16] =   (scalar  * bp[16]);
+                                cp[17] =   (scalar  * bp[17]);
+                                cp[18] =   (scalar  * bp[18]);
+                                cp[19] =   (scalar  * bp[19]);
+                                cp[20] =   (scalar  * bp[20]);
+                                bp+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (scalar  * *bp);
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work 
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                
+                fixed ( float* arrAP = arrA)
+                fixed ( float* arrBP = arrB)
+                fixed ( float* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range 
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new  ILRetArray< float>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<float>  multiplyElemEx(ILInArray<float> A, ILInArray<float> B) {
+            //using (ILScope.Enter(A, B)) { we cannot start a new scope here, since this would prevent A and B to be used implace if applicable
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<float>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<float>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<float>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                dim = -(dim - 1);  // 0 -> 1, 1 -> 0
+                #endregion
+
+                #region parameter preparation
+               
+                float[] retArr;
+               
+                float[] arrA = A.GetArrayForRead();
+               
+                float[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int workItemMultiplierLenA;
+                int workItemMultiplierLenB;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<float>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    workItemMultiplierLenB = outDims[0]; 
+                    workItemMultiplierLenA = dim;  // 0 for column, 1 for row vector
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<float>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    workItemMultiplierLenB = dim;  // 0 for column, 1 for row vector
+                    workItemMultiplierLenA = outDims[0]; 
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one singleton dimension in either A or B");
+                }
+                int itLen = outDims[0]; // (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<float> retStorage = new ILDenseStorage<float>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    float* ap;
+                   
+                    float* bp;
+                   
+                    float* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            if (dim == 0) {
+                                bp = (float*)range.Item3;
+                                cp = (float*)range.Item4; 
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (float*)range.Item2;
+                                    int l = itLen; 
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  * bp[0]);
+                                        cp[1] =   (ap[1]  * bp[1]);
+                                        cp[2] =   (ap[2]  * bp[2]);
+                                        cp[3] =   (ap[3]  * bp[3]);
+                                        cp[4] =   (ap[4]  * bp[4]);
+                                        cp[5] =   (ap[5]  * bp[5]);
+                                        cp[6] =   (ap[6]  * bp[6]);
+                                        cp[7] =   (ap[7]  * bp[7]);
+                                        cp[8] =   (ap[8]  * bp[8]);
+                                        cp[9] =   (ap[9]  * bp[9]);
+                                        cp[10] =   (ap[10]  * bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =   (*ap++  * *bp++);
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                ap = (float*)range.Item2;
+                                bp = (float*)range.Item3;
+                                cp = (float*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   float val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (val  * bp[0]);
+                                        cp[1] =   (val  * bp[1]);
+                                        cp[2] =   (val  * bp[2]);
+                                        cp[3] =   (val  * bp[3]);
+                                        cp[4] =   (val  * bp[4]);
+                                        cp[5] =   (val  * bp[5]);
+                                        cp[6] =   (val  * bp[6]);
+                                        cp[7] =   (val  * bp[7]);
+                                        cp[8] =   (val  * bp[8]);
+                                        cp[9] =   (val  * bp[9]);
+                                        cp[10] =   (val  * bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11; 
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =   (val  * *bp++);
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            if (dim == 0) {
+                                cp = (float*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (float*)range.Item2;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  * cp[0]);
+                                        cp[1] =   (ap[1]  * cp[1]);
+                                        cp[2] =   (ap[2]  * cp[2]);
+                                        cp[3] =   (ap[3]  * cp[3]);
+                                        cp[4] =   (ap[4]  * cp[4]);
+                                        cp[5] =   (ap[5]  * cp[5]);
+                                        cp[6] =   (ap[6]  * cp[6]);
+                                        cp[7] =   (ap[7]  * cp[7]);
+                                        cp[8] =   (ap[8]  * cp[8]);
+                                        cp[9] =   (ap[9]  * cp[9]);
+                                        cp[10] =   (ap[10]  * cp[10]);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap++  * *cp);
+                                        cp++; 
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                cp = (float*)range.Item4;
+                                ap = (float*)range.Item2;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    float val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (val  * cp[0]);
+                                        cp[1] =   (val  * cp[1]);
+                                        cp[2] =   (val  * cp[2]);
+                                        cp[3] =   (val  * cp[3]);
+                                        cp[4] =   (val  * cp[4]);
+                                        cp[5] =   (val  * cp[5]);
+                                        cp[6] =   (val  * cp[6]);
+                                        cp[7] =   (val  * cp[7]);
+                                        cp[8] =   (val  * cp[8]);
+                                        cp[9] =   (val  * cp[9]);
+                                        cp[10] =   (val  * cp[10]);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (val  * *cp);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            if (dim == 0) {
+                                ap = (float*)range.Item2;
+                                cp = (float*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (float*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  * bp[0]);
+                                        cp[1] =   (ap[1]  * bp[1]);
+                                        cp[2] =   (ap[2]  * bp[2]);
+                                        cp[3] =   (ap[3]  * bp[3]);
+                                        cp[4] =   (ap[4]  * bp[4]);
+                                        cp[5] =   (ap[5]  * bp[5]);
+                                        cp[6] =   (ap[6]  * bp[6]);
+                                        cp[7] =   (ap[7]  * bp[7]);
+                                        cp[8] =   (ap[8]  * bp[8]);
+                                        cp[9] =   (ap[9]  * bp[9]);
+                                        cp[10] =   (ap[10]  * bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap  * *bp);
+                                        ap++;
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                ap = (float*)range.Item2;
+                                bp = (float*)range.Item3;
+                                cp = (float*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   float val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  * val);
+                                        cp[1] =   (ap[1]  * val);
+                                        cp[2] =   (ap[2]  * val);
+                                        cp[3] =   (ap[3]  * val);
+                                        cp[4] =   (ap[4]  * val);
+                                        cp[5] =   (ap[5]  * val);
+                                        cp[6] =   (ap[6]  * val);
+                                        cp[7] =   (ap[7]  * val);
+                                        cp[8] =   (ap[8]  * val);
+                                        cp[9] =   (ap[9]  * val);
+                                        cp[10] =   (ap[10]  * val);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap  * val);
+                                        ap++;
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            if (dim == 0) {
+                                cp = (float*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (float*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (cp[0]  * bp[0]);
+                                        cp[1] =   (cp[1]  * bp[1]);
+                                        cp[2] =   (cp[2]  * bp[2]);
+                                        cp[3] =   (cp[3]  * bp[3]);
+                                        cp[4] =   (cp[4]  * bp[4]);
+                                        cp[5] =   (cp[5]  * bp[5]);
+                                        cp[6] =   (cp[6]  * bp[6]);
+                                        cp[7] =   (cp[7]  * bp[7]);
+                                        cp[8] =   (cp[8]  * bp[8]);
+                                        cp[9] =   (cp[9]  * bp[9]);
+                                        cp[10] =   (cp[10]  * bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*cp  * *bp);
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                bp = (float*)range.Item3;
+                                cp = (float*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    float val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (cp[0]  * val);
+                                        cp[1] =   (cp[1]  * val);
+                                        cp[2] =   (cp[2]  * val);
+                                        cp[3] =   (cp[3]  * val);
+                                        cp[4] =   (cp[4]  * val);
+                                        cp[5] =   (cp[5]  * val);
+                                        cp[6] =   (cp[6]  * val);
+                                        cp[7] =   (cp[7]  * val);
+                                        cp[8] =   (cp[8]  * val);
+                                        cp[9] =   (cp[9]  * val);
+                                        cp[10] =   (cp[10]  * val);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l --> 0) {
+                                        *cp =   (*cp  * val);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outDims.NumberOfElements >= Settings.s_minParallelElement1Count
+                    && outDims[1] > 1) {
+                        if (outDims[1] > workItemCount) {
+                        workItemLength = outDims[1] / workItemCount;
+                    } else {
+                        workItemLength = outDims[1] / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outDims[1];
+                    workItemCount = 1;
+                }
+
+                fixed ( float* arrAP = arrA)
+                fixed ( float* arrBP = arrB)
+                fixed ( float* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, IntPtr, IntPtr, IntPtr> range = new Tuple<int, IntPtr, IntPtr, IntPtr>
+                               (workItemLength
+                               , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                               , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                               , (IntPtr)(retArrP + i * outDims[0] * workItemLength)); 
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, IntPtr, IntPtr, IntPtr>
+                                (outDims[1] - i * workItemLength
+                                , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                                , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                                , (IntPtr)(retArrP + i * outDims[0] * workItemLength)));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<float>(retStorage);
+            //}  // no scopes here! it disables implace operations
+        }
+
+        /// <summary>Multiply arrays elementwise</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Array with elementwise multiplication of A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<fcomplex>  multiplyElem(ILInArray<fcomplex> A, ILInArray<fcomplex> B) {
+            using (ILScope.Enter(A,B)) {
+                int outLen; 
+                BinOpItMode mode; 
+                fcomplex [] retArr;
+                fcomplex [] arrA = A.GetArrayForRead();
+                fcomplex[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size; 
+                    if (B.IsScalar) {
+                       
+                        return new  ILRetArray<fcomplex> (new  fcomplex [1]{  (A.GetValue(0)  * B.GetValue(0))}, A.Size);
+                    } else if (B.IsEmpty) {
+                        return  ILRetArray<fcomplex>.empty(outDims); 
+                    } else {
+                        outLen = outDims.NumberOfElements; 
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< fcomplex > (outLen);
+                            mode = BinOpItMode.SAN; 
+                        } else {
+                            mode = BinOpItMode.SAI; 
+                        }
+                    }
+                } else {
+                    outDims = A.Size; 
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return  ILRetArray<fcomplex>.empty(A.Size);  
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< fcomplex > (outLen);
+                            mode = BinOpItMode.ASN; 
+                        } else {
+                            mode = BinOpItMode.ASI; 
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  multiplyElemEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (A.TryGetStorage4InplaceOp(out retArr)) 
+                            mode  = BinOpItMode.AAIA; 
+                        else if (B.TryGetStorage4InplaceOp(out retArr)) 
+                            mode = BinOpItMode.AAIB; 
+                        else {
+                            retArr = ILMemoryPool.Pool.New< fcomplex > (outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<fcomplex> retStorage = new ILDenseStorage<fcomplex>(retArr, outDims);
+                int i = 0, workerCount = 1; 
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    fcomplex* cp = (fcomplex*)range.Item5 + range.Item1;
+                    fcomplex scalar;
+                    int j = range.Item2; 
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           fcomplex* bp = ((fcomplex*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                                cp[0] =   (cp[0]  * bp[0]);
+                                cp[1] =   (cp[1]  * bp[1]);
+                                cp[2] =   (cp[2]  * bp[2]);
+                                cp[3] =   (cp[3]  * bp[3]);
+                                cp[4] =   (cp[4]  * bp[4]);
+                                cp[5] =   (cp[5]  * bp[5]);
+                                cp[6] =   (cp[6]  * bp[6]);
+                                cp[7] =   (cp[7]  * bp[7]);
+                                cp[8] =   (cp[8]  * bp[8]);
+                                cp[9] =   (cp[9]  * bp[9]);
+                                cp[10] =   (cp[10]  * bp[10]);
+                                cp[11] =   (cp[11]  * bp[11]);
+                                cp[12] =   (cp[12]  * bp[12]);
+                                cp[13] =   (cp[13]  * bp[13]);
+                                cp[14] =   (cp[14]  * bp[14]);
+                                cp[15] =   (cp[15]  * bp[15]);
+                                cp[16] =   (cp[16]  * bp[16]);
+                                cp[17] =   (cp[17]  * bp[17]);
+                                cp[18] =   (cp[18]  * bp[18]);
+                                cp[19] =   (cp[19]  * bp[19]);
+                                cp[20] =   (cp[20]  * bp[20]);
+                                cp += 21; bp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*cp  * *bp);
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           fcomplex* ap = ((fcomplex*)range.Item3 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  * cp[0]);
+                                cp[1] =   (ap[1]  * cp[1]);
+                                cp[2] =   (ap[2]  * cp[2]);
+                                cp[3] =   (ap[3]  * cp[3]);
+                                cp[4] =   (ap[4]  * cp[4]);
+                                cp[5] =   (ap[5]  * cp[5]);
+                                cp[6] =   (ap[6]  * cp[6]);
+                                cp[7] =   (ap[7]  * cp[7]);
+                                cp[8] =   (ap[8]  * cp[8]);
+                                cp[9] =   (ap[9]  * cp[9]);
+                                cp[10] =   (ap[10]  * cp[10]);
+                                cp[11] =   (ap[11]  * cp[11]);
+                                cp[12] =   (ap[12]  * cp[12]);
+                                cp[13] =   (ap[13]  * cp[13]);
+                                cp[14] =   (ap[14]  * cp[14]);
+                                cp[15] =   (ap[15]  * cp[15]);
+                                cp[16] =   (ap[16]  * cp[16]);
+                                cp[17] =   (ap[17]  * cp[17]);
+                                cp[18] =   (ap[18]  * cp[18]);
+                                cp[19] =   (ap[19]  * cp[19]);
+                                cp[20] =   (ap[20]  * cp[20]);
+                                ap += 21; cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  * *cp);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((fcomplex*)range.Item3 + range.Item1);
+                            bp = ((fcomplex*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  * bp[0]);
+                                cp[1] =   (ap[1]  * bp[1]);
+                                cp[2] =   (ap[2]  * bp[2]);
+                                cp[3] =   (ap[3]  * bp[3]);
+                                cp[4] =   (ap[4]  * bp[4]);
+                                cp[5] =   (ap[5]  * bp[5]);
+                                cp[6] =   (ap[6]  * bp[6]);
+                                cp[7] =   (ap[7]  * bp[7]);
+                                cp[8] =   (ap[8]  * bp[8]);
+                                cp[9] =   (ap[9]  * bp[9]);
+                                cp[10] =   (ap[10]  * bp[10]);
+                                cp[11] =   (ap[11]  * bp[11]);
+                                cp[12] =   (ap[12]  * bp[12]);
+                                cp[13] =   (ap[13]  * bp[13]);
+                                cp[14] =   (ap[14]  * bp[14]);
+                                cp[15] =   (ap[15]  * bp[15]);
+                                cp[16] =   (ap[16]  * bp[16]);
+                                cp[17] =   (ap[17]  * bp[17]);
+                                cp[18] =   (ap[18]  * bp[18]);
+                                cp[19] =   (ap[19]  * bp[19]);
+                                cp[20] =   (ap[20]  * bp[20]);
+                                ap+=21; bp+=21; cp+=21; j-=21;
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  * *bp);
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((fcomplex*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =   (cp[0]  * scalar);
+                                cp[1] =   (cp[1]  * scalar);
+                                cp[2] =   (cp[2]  * scalar);
+                                cp[3] =   (cp[3]  * scalar);
+                                cp[4] =   (cp[4]  * scalar);
+                                cp[5] =   (cp[5]  * scalar);
+                                cp[6] =   (cp[6]  * scalar);
+                                cp[7] =   (cp[7]  * scalar);
+                                cp[8] =   (cp[8]  * scalar);
+                                cp[9] =   (cp[9]  * scalar);
+                                cp[10] =   (cp[10]  * scalar);
+                                cp[11] =   (cp[11]  * scalar);
+                                cp[12] =   (cp[12]  * scalar);
+                                cp[13] =   (cp[13]  * scalar);
+                                cp[14] =   (cp[14]  * scalar);
+                                cp[15] =   (cp[15]  * scalar);
+                                cp[16] =   (cp[16]  * scalar);
+                                cp[17] =   (cp[17]  * scalar);
+                                cp[18] =   (cp[18]  * scalar);
+                                cp[19] =   (cp[19]  * scalar);
+                                cp[20] =   (cp[20]  * scalar);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*cp  * scalar);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((fcomplex*)range.Item3 + range.Item1);
+                            scalar = *((fcomplex*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  * scalar);
+                                cp[1] =   (ap[1]  * scalar);
+                                cp[2] =   (ap[2]  * scalar);
+                                cp[3] =   (ap[3]  * scalar);
+                                cp[4] =   (ap[4]  * scalar);
+                                cp[5] =   (ap[5]  * scalar);
+                                cp[6] =   (ap[6]  * scalar);
+                                cp[7] =   (ap[7]  * scalar);
+                                cp[8] =   (ap[8]  * scalar);
+                                cp[9] =   (ap[9]  * scalar);
+                                cp[10] =   (ap[10]  * scalar);
+                                cp[11] =   (ap[11]  * scalar);
+                                cp[12] =   (ap[12]  * scalar);
+                                cp[13] =   (ap[13]  * scalar);
+                                cp[14] =   (ap[14]  * scalar);
+                                cp[15] =   (ap[15]  * scalar);
+                                cp[16] =   (ap[16]  * scalar);
+                                cp[17] =   (ap[17]  * scalar);
+                                cp[18] =   (ap[18]  * scalar);
+                                cp[19] =   (ap[19]  * scalar);
+                                cp[20] =   (ap[20]  * scalar);
+                                ap+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  * scalar);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((fcomplex*)range.Item3);
+                            while (j > 20) {
+                               
+                                cp[0] =   (scalar  * cp[0]);
+                                cp[1] =   (scalar  * cp[1]);
+                                cp[2] =   (scalar  * cp[2]);
+                                cp[3] =   (scalar  * cp[3]);
+                                cp[4] =   (scalar  * cp[4]);
+                                cp[5] =   (scalar  * cp[5]);
+                                cp[6] =   (scalar  * cp[6]);
+                                cp[7] =   (scalar  * cp[7]);
+                                cp[8] =   (scalar  * cp[8]);
+                                cp[9] =   (scalar  * cp[9]);
+                                cp[10] =   (scalar  * cp[10]);
+                                cp[11] =   (scalar  * cp[11]);
+                                cp[12] =   (scalar  * cp[12]);
+                                cp[13] =   (scalar  * cp[13]);
+                                cp[14] =   (scalar  * cp[14]);
+                                cp[15] =   (scalar  * cp[15]);
+                                cp[16] =   (scalar  * cp[16]);
+                                cp[17] =   (scalar  * cp[17]);
+                                cp[18] =   (scalar  * cp[18]);
+                                cp[19] =   (scalar  * cp[19]);
+                                cp[20] =   (scalar  * cp[20]);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (scalar  * *cp);
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((fcomplex*)range.Item3);
+                            bp = ((fcomplex*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (scalar  * bp[0]);
+                                cp[1] =   (scalar  * bp[1]);
+                                cp[2] =   (scalar  * bp[2]);
+                                cp[3] =   (scalar  * bp[3]);
+                                cp[4] =   (scalar  * bp[4]);
+                                cp[5] =   (scalar  * bp[5]);
+                                cp[6] =   (scalar  * bp[6]);
+                                cp[7] =   (scalar  * bp[7]);
+                                cp[8] =   (scalar  * bp[8]);
+                                cp[9] =   (scalar  * bp[9]);
+                                cp[10] =   (scalar  * bp[10]);
+                                cp[11] =   (scalar  * bp[11]);
+                                cp[12] =   (scalar  * bp[12]);
+                                cp[13] =   (scalar  * bp[13]);
+                                cp[14] =   (scalar  * bp[14]);
+                                cp[15] =   (scalar  * bp[15]);
+                                cp[16] =   (scalar  * bp[16]);
+                                cp[17] =   (scalar  * bp[17]);
+                                cp[18] =   (scalar  * bp[18]);
+                                cp[19] =   (scalar  * bp[19]);
+                                cp[20] =   (scalar  * bp[20]);
+                                bp+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (scalar  * *bp);
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work 
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                
+                fixed ( fcomplex* arrAP = arrA)
+                fixed ( fcomplex* arrBP = arrB)
+                fixed ( fcomplex* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range 
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new  ILRetArray< fcomplex>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<fcomplex>  multiplyElemEx(ILInArray<fcomplex> A, ILInArray<fcomplex> B) {
+            //using (ILScope.Enter(A, B)) { we cannot start a new scope here, since this would prevent A and B to be used implace if applicable
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<fcomplex>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<fcomplex>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<fcomplex>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                dim = -(dim - 1);  // 0 -> 1, 1 -> 0
+                #endregion
+
+                #region parameter preparation
+               
+                fcomplex[] retArr;
+               
+                fcomplex[] arrA = A.GetArrayForRead();
+               
+                fcomplex[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int workItemMultiplierLenA;
+                int workItemMultiplierLenB;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<fcomplex>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    workItemMultiplierLenB = outDims[0]; 
+                    workItemMultiplierLenA = dim;  // 0 for column, 1 for row vector
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<fcomplex>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    workItemMultiplierLenB = dim;  // 0 for column, 1 for row vector
+                    workItemMultiplierLenA = outDims[0]; 
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one singleton dimension in either A or B");
+                }
+                int itLen = outDims[0]; // (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<fcomplex> retStorage = new ILDenseStorage<fcomplex>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    fcomplex* ap;
+                   
+                    fcomplex* bp;
+                   
+                    fcomplex* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            if (dim == 0) {
+                                bp = (fcomplex*)range.Item3;
+                                cp = (fcomplex*)range.Item4; 
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (fcomplex*)range.Item2;
+                                    int l = itLen; 
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  * bp[0]);
+                                        cp[1] =   (ap[1]  * bp[1]);
+                                        cp[2] =   (ap[2]  * bp[2]);
+                                        cp[3] =   (ap[3]  * bp[3]);
+                                        cp[4] =   (ap[4]  * bp[4]);
+                                        cp[5] =   (ap[5]  * bp[5]);
+                                        cp[6] =   (ap[6]  * bp[6]);
+                                        cp[7] =   (ap[7]  * bp[7]);
+                                        cp[8] =   (ap[8]  * bp[8]);
+                                        cp[9] =   (ap[9]  * bp[9]);
+                                        cp[10] =   (ap[10]  * bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =   (*ap++  * *bp++);
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                ap = (fcomplex*)range.Item2;
+                                bp = (fcomplex*)range.Item3;
+                                cp = (fcomplex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   fcomplex val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (val  * bp[0]);
+                                        cp[1] =   (val  * bp[1]);
+                                        cp[2] =   (val  * bp[2]);
+                                        cp[3] =   (val  * bp[3]);
+                                        cp[4] =   (val  * bp[4]);
+                                        cp[5] =   (val  * bp[5]);
+                                        cp[6] =   (val  * bp[6]);
+                                        cp[7] =   (val  * bp[7]);
+                                        cp[8] =   (val  * bp[8]);
+                                        cp[9] =   (val  * bp[9]);
+                                        cp[10] =   (val  * bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11; 
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =   (val  * *bp++);
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            if (dim == 0) {
+                                cp = (fcomplex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (fcomplex*)range.Item2;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  * cp[0]);
+                                        cp[1] =   (ap[1]  * cp[1]);
+                                        cp[2] =   (ap[2]  * cp[2]);
+                                        cp[3] =   (ap[3]  * cp[3]);
+                                        cp[4] =   (ap[4]  * cp[4]);
+                                        cp[5] =   (ap[5]  * cp[5]);
+                                        cp[6] =   (ap[6]  * cp[6]);
+                                        cp[7] =   (ap[7]  * cp[7]);
+                                        cp[8] =   (ap[8]  * cp[8]);
+                                        cp[9] =   (ap[9]  * cp[9]);
+                                        cp[10] =   (ap[10]  * cp[10]);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap++  * *cp);
+                                        cp++; 
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                cp = (fcomplex*)range.Item4;
+                                ap = (fcomplex*)range.Item2;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    fcomplex val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (val  * cp[0]);
+                                        cp[1] =   (val  * cp[1]);
+                                        cp[2] =   (val  * cp[2]);
+                                        cp[3] =   (val  * cp[3]);
+                                        cp[4] =   (val  * cp[4]);
+                                        cp[5] =   (val  * cp[5]);
+                                        cp[6] =   (val  * cp[6]);
+                                        cp[7] =   (val  * cp[7]);
+                                        cp[8] =   (val  * cp[8]);
+                                        cp[9] =   (val  * cp[9]);
+                                        cp[10] =   (val  * cp[10]);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (val  * *cp);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            if (dim == 0) {
+                                ap = (fcomplex*)range.Item2;
+                                cp = (fcomplex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (fcomplex*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  * bp[0]);
+                                        cp[1] =   (ap[1]  * bp[1]);
+                                        cp[2] =   (ap[2]  * bp[2]);
+                                        cp[3] =   (ap[3]  * bp[3]);
+                                        cp[4] =   (ap[4]  * bp[4]);
+                                        cp[5] =   (ap[5]  * bp[5]);
+                                        cp[6] =   (ap[6]  * bp[6]);
+                                        cp[7] =   (ap[7]  * bp[7]);
+                                        cp[8] =   (ap[8]  * bp[8]);
+                                        cp[9] =   (ap[9]  * bp[9]);
+                                        cp[10] =   (ap[10]  * bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap  * *bp);
+                                        ap++;
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                ap = (fcomplex*)range.Item2;
+                                bp = (fcomplex*)range.Item3;
+                                cp = (fcomplex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   fcomplex val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  * val);
+                                        cp[1] =   (ap[1]  * val);
+                                        cp[2] =   (ap[2]  * val);
+                                        cp[3] =   (ap[3]  * val);
+                                        cp[4] =   (ap[4]  * val);
+                                        cp[5] =   (ap[5]  * val);
+                                        cp[6] =   (ap[6]  * val);
+                                        cp[7] =   (ap[7]  * val);
+                                        cp[8] =   (ap[8]  * val);
+                                        cp[9] =   (ap[9]  * val);
+                                        cp[10] =   (ap[10]  * val);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap  * val);
+                                        ap++;
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            if (dim == 0) {
+                                cp = (fcomplex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (fcomplex*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (cp[0]  * bp[0]);
+                                        cp[1] =   (cp[1]  * bp[1]);
+                                        cp[2] =   (cp[2]  * bp[2]);
+                                        cp[3] =   (cp[3]  * bp[3]);
+                                        cp[4] =   (cp[4]  * bp[4]);
+                                        cp[5] =   (cp[5]  * bp[5]);
+                                        cp[6] =   (cp[6]  * bp[6]);
+                                        cp[7] =   (cp[7]  * bp[7]);
+                                        cp[8] =   (cp[8]  * bp[8]);
+                                        cp[9] =   (cp[9]  * bp[9]);
+                                        cp[10] =   (cp[10]  * bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*cp  * *bp);
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                bp = (fcomplex*)range.Item3;
+                                cp = (fcomplex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    fcomplex val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (cp[0]  * val);
+                                        cp[1] =   (cp[1]  * val);
+                                        cp[2] =   (cp[2]  * val);
+                                        cp[3] =   (cp[3]  * val);
+                                        cp[4] =   (cp[4]  * val);
+                                        cp[5] =   (cp[5]  * val);
+                                        cp[6] =   (cp[6]  * val);
+                                        cp[7] =   (cp[7]  * val);
+                                        cp[8] =   (cp[8]  * val);
+                                        cp[9] =   (cp[9]  * val);
+                                        cp[10] =   (cp[10]  * val);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l --> 0) {
+                                        *cp =   (*cp  * val);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outDims.NumberOfElements >= Settings.s_minParallelElement1Count
+                    && outDims[1] > 1) {
+                        if (outDims[1] > workItemCount) {
+                        workItemLength = outDims[1] / workItemCount;
+                    } else {
+                        workItemLength = outDims[1] / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outDims[1];
+                    workItemCount = 1;
+                }
+
+                fixed ( fcomplex* arrAP = arrA)
+                fixed ( fcomplex* arrBP = arrB)
+                fixed ( fcomplex* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, IntPtr, IntPtr, IntPtr> range = new Tuple<int, IntPtr, IntPtr, IntPtr>
+                               (workItemLength
+                               , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                               , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                               , (IntPtr)(retArrP + i * outDims[0] * workItemLength)); 
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, IntPtr, IntPtr, IntPtr>
+                                (outDims[1] - i * workItemLength
+                                , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                                , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                                , (IntPtr)(retArrP + i * outDims[0] * workItemLength)));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<fcomplex>(retStorage);
+            //}  // no scopes here! it disables implace operations
+        }
+
+        /// <summary>Multiply arrays elementwise</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Array with elementwise multiplication of A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<complex>  multiplyElem(ILInArray<complex> A, ILInArray<complex> B) {
+            using (ILScope.Enter(A,B)) {
+                int outLen; 
+                BinOpItMode mode; 
+                complex [] retArr;
+                complex [] arrA = A.GetArrayForRead();
+                complex[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size; 
+                    if (B.IsScalar) {
+                       
+                        return new  ILRetArray<complex> (new  complex [1]{  (A.GetValue(0)  * B.GetValue(0))}, A.Size);
+                    } else if (B.IsEmpty) {
+                        return  ILRetArray<complex>.empty(outDims); 
+                    } else {
+                        outLen = outDims.NumberOfElements; 
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< complex > (outLen);
+                            mode = BinOpItMode.SAN; 
+                        } else {
+                            mode = BinOpItMode.SAI; 
+                        }
+                    }
+                } else {
+                    outDims = A.Size; 
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return  ILRetArray<complex>.empty(A.Size);  
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< complex > (outLen);
+                            mode = BinOpItMode.ASN; 
+                        } else {
+                            mode = BinOpItMode.ASI; 
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  multiplyElemEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (A.TryGetStorage4InplaceOp(out retArr)) 
+                            mode  = BinOpItMode.AAIA; 
+                        else if (B.TryGetStorage4InplaceOp(out retArr)) 
+                            mode = BinOpItMode.AAIB; 
+                        else {
+                            retArr = ILMemoryPool.Pool.New< complex > (outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<complex> retStorage = new ILDenseStorage<complex>(retArr, outDims);
+                int i = 0, workerCount = 1; 
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    complex* cp = (complex*)range.Item5 + range.Item1;
+                    complex scalar;
+                    int j = range.Item2; 
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           complex* bp = ((complex*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                                cp[0] =   (cp[0]  * bp[0]);
+                                cp[1] =   (cp[1]  * bp[1]);
+                                cp[2] =   (cp[2]  * bp[2]);
+                                cp[3] =   (cp[3]  * bp[3]);
+                                cp[4] =   (cp[4]  * bp[4]);
+                                cp[5] =   (cp[5]  * bp[5]);
+                                cp[6] =   (cp[6]  * bp[6]);
+                                cp[7] =   (cp[7]  * bp[7]);
+                                cp[8] =   (cp[8]  * bp[8]);
+                                cp[9] =   (cp[9]  * bp[9]);
+                                cp[10] =   (cp[10]  * bp[10]);
+                                cp[11] =   (cp[11]  * bp[11]);
+                                cp[12] =   (cp[12]  * bp[12]);
+                                cp[13] =   (cp[13]  * bp[13]);
+                                cp[14] =   (cp[14]  * bp[14]);
+                                cp[15] =   (cp[15]  * bp[15]);
+                                cp[16] =   (cp[16]  * bp[16]);
+                                cp[17] =   (cp[17]  * bp[17]);
+                                cp[18] =   (cp[18]  * bp[18]);
+                                cp[19] =   (cp[19]  * bp[19]);
+                                cp[20] =   (cp[20]  * bp[20]);
+                                cp += 21; bp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*cp  * *bp);
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           complex* ap = ((complex*)range.Item3 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  * cp[0]);
+                                cp[1] =   (ap[1]  * cp[1]);
+                                cp[2] =   (ap[2]  * cp[2]);
+                                cp[3] =   (ap[3]  * cp[3]);
+                                cp[4] =   (ap[4]  * cp[4]);
+                                cp[5] =   (ap[5]  * cp[5]);
+                                cp[6] =   (ap[6]  * cp[6]);
+                                cp[7] =   (ap[7]  * cp[7]);
+                                cp[8] =   (ap[8]  * cp[8]);
+                                cp[9] =   (ap[9]  * cp[9]);
+                                cp[10] =   (ap[10]  * cp[10]);
+                                cp[11] =   (ap[11]  * cp[11]);
+                                cp[12] =   (ap[12]  * cp[12]);
+                                cp[13] =   (ap[13]  * cp[13]);
+                                cp[14] =   (ap[14]  * cp[14]);
+                                cp[15] =   (ap[15]  * cp[15]);
+                                cp[16] =   (ap[16]  * cp[16]);
+                                cp[17] =   (ap[17]  * cp[17]);
+                                cp[18] =   (ap[18]  * cp[18]);
+                                cp[19] =   (ap[19]  * cp[19]);
+                                cp[20] =   (ap[20]  * cp[20]);
+                                ap += 21; cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  * *cp);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((complex*)range.Item3 + range.Item1);
+                            bp = ((complex*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  * bp[0]);
+                                cp[1] =   (ap[1]  * bp[1]);
+                                cp[2] =   (ap[2]  * bp[2]);
+                                cp[3] =   (ap[3]  * bp[3]);
+                                cp[4] =   (ap[4]  * bp[4]);
+                                cp[5] =   (ap[5]  * bp[5]);
+                                cp[6] =   (ap[6]  * bp[6]);
+                                cp[7] =   (ap[7]  * bp[7]);
+                                cp[8] =   (ap[8]  * bp[8]);
+                                cp[9] =   (ap[9]  * bp[9]);
+                                cp[10] =   (ap[10]  * bp[10]);
+                                cp[11] =   (ap[11]  * bp[11]);
+                                cp[12] =   (ap[12]  * bp[12]);
+                                cp[13] =   (ap[13]  * bp[13]);
+                                cp[14] =   (ap[14]  * bp[14]);
+                                cp[15] =   (ap[15]  * bp[15]);
+                                cp[16] =   (ap[16]  * bp[16]);
+                                cp[17] =   (ap[17]  * bp[17]);
+                                cp[18] =   (ap[18]  * bp[18]);
+                                cp[19] =   (ap[19]  * bp[19]);
+                                cp[20] =   (ap[20]  * bp[20]);
+                                ap+=21; bp+=21; cp+=21; j-=21;
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  * *bp);
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((complex*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =   (cp[0]  * scalar);
+                                cp[1] =   (cp[1]  * scalar);
+                                cp[2] =   (cp[2]  * scalar);
+                                cp[3] =   (cp[3]  * scalar);
+                                cp[4] =   (cp[4]  * scalar);
+                                cp[5] =   (cp[5]  * scalar);
+                                cp[6] =   (cp[6]  * scalar);
+                                cp[7] =   (cp[7]  * scalar);
+                                cp[8] =   (cp[8]  * scalar);
+                                cp[9] =   (cp[9]  * scalar);
+                                cp[10] =   (cp[10]  * scalar);
+                                cp[11] =   (cp[11]  * scalar);
+                                cp[12] =   (cp[12]  * scalar);
+                                cp[13] =   (cp[13]  * scalar);
+                                cp[14] =   (cp[14]  * scalar);
+                                cp[15] =   (cp[15]  * scalar);
+                                cp[16] =   (cp[16]  * scalar);
+                                cp[17] =   (cp[17]  * scalar);
+                                cp[18] =   (cp[18]  * scalar);
+                                cp[19] =   (cp[19]  * scalar);
+                                cp[20] =   (cp[20]  * scalar);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*cp  * scalar);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((complex*)range.Item3 + range.Item1);
+                            scalar = *((complex*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  * scalar);
+                                cp[1] =   (ap[1]  * scalar);
+                                cp[2] =   (ap[2]  * scalar);
+                                cp[3] =   (ap[3]  * scalar);
+                                cp[4] =   (ap[4]  * scalar);
+                                cp[5] =   (ap[5]  * scalar);
+                                cp[6] =   (ap[6]  * scalar);
+                                cp[7] =   (ap[7]  * scalar);
+                                cp[8] =   (ap[8]  * scalar);
+                                cp[9] =   (ap[9]  * scalar);
+                                cp[10] =   (ap[10]  * scalar);
+                                cp[11] =   (ap[11]  * scalar);
+                                cp[12] =   (ap[12]  * scalar);
+                                cp[13] =   (ap[13]  * scalar);
+                                cp[14] =   (ap[14]  * scalar);
+                                cp[15] =   (ap[15]  * scalar);
+                                cp[16] =   (ap[16]  * scalar);
+                                cp[17] =   (ap[17]  * scalar);
+                                cp[18] =   (ap[18]  * scalar);
+                                cp[19] =   (ap[19]  * scalar);
+                                cp[20] =   (ap[20]  * scalar);
+                                ap+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  * scalar);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((complex*)range.Item3);
+                            while (j > 20) {
+                               
+                                cp[0] =   (scalar  * cp[0]);
+                                cp[1] =   (scalar  * cp[1]);
+                                cp[2] =   (scalar  * cp[2]);
+                                cp[3] =   (scalar  * cp[3]);
+                                cp[4] =   (scalar  * cp[4]);
+                                cp[5] =   (scalar  * cp[5]);
+                                cp[6] =   (scalar  * cp[6]);
+                                cp[7] =   (scalar  * cp[7]);
+                                cp[8] =   (scalar  * cp[8]);
+                                cp[9] =   (scalar  * cp[9]);
+                                cp[10] =   (scalar  * cp[10]);
+                                cp[11] =   (scalar  * cp[11]);
+                                cp[12] =   (scalar  * cp[12]);
+                                cp[13] =   (scalar  * cp[13]);
+                                cp[14] =   (scalar  * cp[14]);
+                                cp[15] =   (scalar  * cp[15]);
+                                cp[16] =   (scalar  * cp[16]);
+                                cp[17] =   (scalar  * cp[17]);
+                                cp[18] =   (scalar  * cp[18]);
+                                cp[19] =   (scalar  * cp[19]);
+                                cp[20] =   (scalar  * cp[20]);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (scalar  * *cp);
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((complex*)range.Item3);
+                            bp = ((complex*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (scalar  * bp[0]);
+                                cp[1] =   (scalar  * bp[1]);
+                                cp[2] =   (scalar  * bp[2]);
+                                cp[3] =   (scalar  * bp[3]);
+                                cp[4] =   (scalar  * bp[4]);
+                                cp[5] =   (scalar  * bp[5]);
+                                cp[6] =   (scalar  * bp[6]);
+                                cp[7] =   (scalar  * bp[7]);
+                                cp[8] =   (scalar  * bp[8]);
+                                cp[9] =   (scalar  * bp[9]);
+                                cp[10] =   (scalar  * bp[10]);
+                                cp[11] =   (scalar  * bp[11]);
+                                cp[12] =   (scalar  * bp[12]);
+                                cp[13] =   (scalar  * bp[13]);
+                                cp[14] =   (scalar  * bp[14]);
+                                cp[15] =   (scalar  * bp[15]);
+                                cp[16] =   (scalar  * bp[16]);
+                                cp[17] =   (scalar  * bp[17]);
+                                cp[18] =   (scalar  * bp[18]);
+                                cp[19] =   (scalar  * bp[19]);
+                                cp[20] =   (scalar  * bp[20]);
+                                bp+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (scalar  * *bp);
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work 
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                
+                fixed ( complex* arrAP = arrA)
+                fixed ( complex* arrBP = arrB)
+                fixed ( complex* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range 
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new  ILRetArray< complex>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<complex>  multiplyElemEx(ILInArray<complex> A, ILInArray<complex> B) {
+            //using (ILScope.Enter(A, B)) { we cannot start a new scope here, since this would prevent A and B to be used implace if applicable
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<complex>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<complex>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<complex>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                dim = -(dim - 1);  // 0 -> 1, 1 -> 0
+                #endregion
+
+                #region parameter preparation
+               
+                complex[] retArr;
+               
+                complex[] arrA = A.GetArrayForRead();
+               
+                complex[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int workItemMultiplierLenA;
+                int workItemMultiplierLenB;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<complex>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    workItemMultiplierLenB = outDims[0]; 
+                    workItemMultiplierLenA = dim;  // 0 for column, 1 for row vector
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<complex>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    workItemMultiplierLenB = dim;  // 0 for column, 1 for row vector
+                    workItemMultiplierLenA = outDims[0]; 
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one singleton dimension in either A or B");
+                }
+                int itLen = outDims[0]; // (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<complex> retStorage = new ILDenseStorage<complex>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    complex* ap;
+                   
+                    complex* bp;
+                   
+                    complex* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            if (dim == 0) {
+                                bp = (complex*)range.Item3;
+                                cp = (complex*)range.Item4; 
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (complex*)range.Item2;
+                                    int l = itLen; 
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  * bp[0]);
+                                        cp[1] =   (ap[1]  * bp[1]);
+                                        cp[2] =   (ap[2]  * bp[2]);
+                                        cp[3] =   (ap[3]  * bp[3]);
+                                        cp[4] =   (ap[4]  * bp[4]);
+                                        cp[5] =   (ap[5]  * bp[5]);
+                                        cp[6] =   (ap[6]  * bp[6]);
+                                        cp[7] =   (ap[7]  * bp[7]);
+                                        cp[8] =   (ap[8]  * bp[8]);
+                                        cp[9] =   (ap[9]  * bp[9]);
+                                        cp[10] =   (ap[10]  * bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =   (*ap++  * *bp++);
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                ap = (complex*)range.Item2;
+                                bp = (complex*)range.Item3;
+                                cp = (complex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   complex val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (val  * bp[0]);
+                                        cp[1] =   (val  * bp[1]);
+                                        cp[2] =   (val  * bp[2]);
+                                        cp[3] =   (val  * bp[3]);
+                                        cp[4] =   (val  * bp[4]);
+                                        cp[5] =   (val  * bp[5]);
+                                        cp[6] =   (val  * bp[6]);
+                                        cp[7] =   (val  * bp[7]);
+                                        cp[8] =   (val  * bp[8]);
+                                        cp[9] =   (val  * bp[9]);
+                                        cp[10] =   (val  * bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11; 
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =   (val  * *bp++);
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            if (dim == 0) {
+                                cp = (complex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (complex*)range.Item2;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  * cp[0]);
+                                        cp[1] =   (ap[1]  * cp[1]);
+                                        cp[2] =   (ap[2]  * cp[2]);
+                                        cp[3] =   (ap[3]  * cp[3]);
+                                        cp[4] =   (ap[4]  * cp[4]);
+                                        cp[5] =   (ap[5]  * cp[5]);
+                                        cp[6] =   (ap[6]  * cp[6]);
+                                        cp[7] =   (ap[7]  * cp[7]);
+                                        cp[8] =   (ap[8]  * cp[8]);
+                                        cp[9] =   (ap[9]  * cp[9]);
+                                        cp[10] =   (ap[10]  * cp[10]);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap++  * *cp);
+                                        cp++; 
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                cp = (complex*)range.Item4;
+                                ap = (complex*)range.Item2;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    complex val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (val  * cp[0]);
+                                        cp[1] =   (val  * cp[1]);
+                                        cp[2] =   (val  * cp[2]);
+                                        cp[3] =   (val  * cp[3]);
+                                        cp[4] =   (val  * cp[4]);
+                                        cp[5] =   (val  * cp[5]);
+                                        cp[6] =   (val  * cp[6]);
+                                        cp[7] =   (val  * cp[7]);
+                                        cp[8] =   (val  * cp[8]);
+                                        cp[9] =   (val  * cp[9]);
+                                        cp[10] =   (val  * cp[10]);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (val  * *cp);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            if (dim == 0) {
+                                ap = (complex*)range.Item2;
+                                cp = (complex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (complex*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  * bp[0]);
+                                        cp[1] =   (ap[1]  * bp[1]);
+                                        cp[2] =   (ap[2]  * bp[2]);
+                                        cp[3] =   (ap[3]  * bp[3]);
+                                        cp[4] =   (ap[4]  * bp[4]);
+                                        cp[5] =   (ap[5]  * bp[5]);
+                                        cp[6] =   (ap[6]  * bp[6]);
+                                        cp[7] =   (ap[7]  * bp[7]);
+                                        cp[8] =   (ap[8]  * bp[8]);
+                                        cp[9] =   (ap[9]  * bp[9]);
+                                        cp[10] =   (ap[10]  * bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap  * *bp);
+                                        ap++;
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                ap = (complex*)range.Item2;
+                                bp = (complex*)range.Item3;
+                                cp = (complex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   complex val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  * val);
+                                        cp[1] =   (ap[1]  * val);
+                                        cp[2] =   (ap[2]  * val);
+                                        cp[3] =   (ap[3]  * val);
+                                        cp[4] =   (ap[4]  * val);
+                                        cp[5] =   (ap[5]  * val);
+                                        cp[6] =   (ap[6]  * val);
+                                        cp[7] =   (ap[7]  * val);
+                                        cp[8] =   (ap[8]  * val);
+                                        cp[9] =   (ap[9]  * val);
+                                        cp[10] =   (ap[10]  * val);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap  * val);
+                                        ap++;
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            if (dim == 0) {
+                                cp = (complex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (complex*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (cp[0]  * bp[0]);
+                                        cp[1] =   (cp[1]  * bp[1]);
+                                        cp[2] =   (cp[2]  * bp[2]);
+                                        cp[3] =   (cp[3]  * bp[3]);
+                                        cp[4] =   (cp[4]  * bp[4]);
+                                        cp[5] =   (cp[5]  * bp[5]);
+                                        cp[6] =   (cp[6]  * bp[6]);
+                                        cp[7] =   (cp[7]  * bp[7]);
+                                        cp[8] =   (cp[8]  * bp[8]);
+                                        cp[9] =   (cp[9]  * bp[9]);
+                                        cp[10] =   (cp[10]  * bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*cp  * *bp);
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                bp = (complex*)range.Item3;
+                                cp = (complex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    complex val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (cp[0]  * val);
+                                        cp[1] =   (cp[1]  * val);
+                                        cp[2] =   (cp[2]  * val);
+                                        cp[3] =   (cp[3]  * val);
+                                        cp[4] =   (cp[4]  * val);
+                                        cp[5] =   (cp[5]  * val);
+                                        cp[6] =   (cp[6]  * val);
+                                        cp[7] =   (cp[7]  * val);
+                                        cp[8] =   (cp[8]  * val);
+                                        cp[9] =   (cp[9]  * val);
+                                        cp[10] =   (cp[10]  * val);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l --> 0) {
+                                        *cp =   (*cp  * val);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outDims.NumberOfElements >= Settings.s_minParallelElement1Count
+                    && outDims[1] > 1) {
+                        if (outDims[1] > workItemCount) {
+                        workItemLength = outDims[1] / workItemCount;
+                    } else {
+                        workItemLength = outDims[1] / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outDims[1];
+                    workItemCount = 1;
+                }
+
+                fixed ( complex* arrAP = arrA)
+                fixed ( complex* arrBP = arrB)
+                fixed ( complex* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, IntPtr, IntPtr, IntPtr> range = new Tuple<int, IntPtr, IntPtr, IntPtr>
+                               (workItemLength
+                               , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                               , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                               , (IntPtr)(retArrP + i * outDims[0] * workItemLength)); 
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, IntPtr, IntPtr, IntPtr>
+                                (outDims[1] - i * workItemLength
+                                , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                                , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                                , (IntPtr)(retArrP + i * outDims[0] * workItemLength)));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<complex>(retStorage);
+            //}  // no scopes here! it disables implace operations
+        }
+
+        /// <summary>Multiply arrays elementwise</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Array with elementwise multiplication of A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<byte>  multiplyElem(ILInArray<byte> A, ILInArray<byte> B) {
+            using (ILScope.Enter(A,B)) {
+                int outLen; 
+                BinOpItMode mode; 
+                byte [] retArr;
+                byte [] arrA = A.GetArrayForRead();
+                byte[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size; 
+                    if (B.IsScalar) {
+                       
+                        return new  ILRetArray<byte> (new  byte [1]{ saturateByte (A.GetValue(0)  * (double) B.GetValue(0))}, A.Size);
+                    } else if (B.IsEmpty) {
+                        return  ILRetArray<byte>.empty(outDims); 
+                    } else {
+                        outLen = outDims.NumberOfElements; 
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< byte > (outLen);
+                            mode = BinOpItMode.SAN; 
+                        } else {
+                            mode = BinOpItMode.SAI; 
+                        }
+                    }
+                } else {
+                    outDims = A.Size; 
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return  ILRetArray<byte>.empty(A.Size);  
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< byte > (outLen);
+                            mode = BinOpItMode.ASN; 
+                        } else {
+                            mode = BinOpItMode.ASI; 
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  multiplyElemEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (A.TryGetStorage4InplaceOp(out retArr)) 
+                            mode  = BinOpItMode.AAIA; 
+                        else if (B.TryGetStorage4InplaceOp(out retArr)) 
+                            mode = BinOpItMode.AAIB; 
+                        else {
+                            retArr = ILMemoryPool.Pool.New< byte > (outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<byte> retStorage = new ILDenseStorage<byte>(retArr, outDims);
+                int i = 0, workerCount = 1; 
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cp = (byte*)range.Item5 + range.Item1;
+                    byte scalar;
+                    int j = range.Item2; 
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           byte* bp = ((byte*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                                cp[0] =  saturateByte (cp[0]  * (double) bp[0]);
+                                cp[1] =  saturateByte (cp[1]  * (double) bp[1]);
+                                cp[2] =  saturateByte (cp[2]  * (double) bp[2]);
+                                cp[3] =  saturateByte (cp[3]  * (double) bp[3]);
+                                cp[4] =  saturateByte (cp[4]  * (double) bp[4]);
+                                cp[5] =  saturateByte (cp[5]  * (double) bp[5]);
+                                cp[6] =  saturateByte (cp[6]  * (double) bp[6]);
+                                cp[7] =  saturateByte (cp[7]  * (double) bp[7]);
+                                cp[8] =  saturateByte (cp[8]  * (double) bp[8]);
+                                cp[9] =  saturateByte (cp[9]  * (double) bp[9]);
+                                cp[10] =  saturateByte (cp[10]  * (double) bp[10]);
+                                cp[11] =  saturateByte (cp[11]  * (double) bp[11]);
+                                cp[12] =  saturateByte (cp[12]  * (double) bp[12]);
+                                cp[13] =  saturateByte (cp[13]  * (double) bp[13]);
+                                cp[14] =  saturateByte (cp[14]  * (double) bp[14]);
+                                cp[15] =  saturateByte (cp[15]  * (double) bp[15]);
+                                cp[16] =  saturateByte (cp[16]  * (double) bp[16]);
+                                cp[17] =  saturateByte (cp[17]  * (double) bp[17]);
+                                cp[18] =  saturateByte (cp[18]  * (double) bp[18]);
+                                cp[19] =  saturateByte (cp[19]  * (double) bp[19]);
+                                cp[20] =  saturateByte (cp[20]  * (double) bp[20]);
+                                cp += 21; bp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateByte (*cp  * (double) *bp);
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           byte* ap = ((byte*)range.Item3 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateByte (ap[0]  * (double) cp[0]);
+                                cp[1] =  saturateByte (ap[1]  * (double) cp[1]);
+                                cp[2] =  saturateByte (ap[2]  * (double) cp[2]);
+                                cp[3] =  saturateByte (ap[3]  * (double) cp[3]);
+                                cp[4] =  saturateByte (ap[4]  * (double) cp[4]);
+                                cp[5] =  saturateByte (ap[5]  * (double) cp[5]);
+                                cp[6] =  saturateByte (ap[6]  * (double) cp[6]);
+                                cp[7] =  saturateByte (ap[7]  * (double) cp[7]);
+                                cp[8] =  saturateByte (ap[8]  * (double) cp[8]);
+                                cp[9] =  saturateByte (ap[9]  * (double) cp[9]);
+                                cp[10] =  saturateByte (ap[10]  * (double) cp[10]);
+                                cp[11] =  saturateByte (ap[11]  * (double) cp[11]);
+                                cp[12] =  saturateByte (ap[12]  * (double) cp[12]);
+                                cp[13] =  saturateByte (ap[13]  * (double) cp[13]);
+                                cp[14] =  saturateByte (ap[14]  * (double) cp[14]);
+                                cp[15] =  saturateByte (ap[15]  * (double) cp[15]);
+                                cp[16] =  saturateByte (ap[16]  * (double) cp[16]);
+                                cp[17] =  saturateByte (ap[17]  * (double) cp[17]);
+                                cp[18] =  saturateByte (ap[18]  * (double) cp[18]);
+                                cp[19] =  saturateByte (ap[19]  * (double) cp[19]);
+                                cp[20] =  saturateByte (ap[20]  * (double) cp[20]);
+                                ap += 21; cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateByte (*ap  * (double) *cp);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((byte*)range.Item3 + range.Item1);
+                            bp = ((byte*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateByte (ap[0]  * (double) bp[0]);
+                                cp[1] =  saturateByte (ap[1]  * (double) bp[1]);
+                                cp[2] =  saturateByte (ap[2]  * (double) bp[2]);
+                                cp[3] =  saturateByte (ap[3]  * (double) bp[3]);
+                                cp[4] =  saturateByte (ap[4]  * (double) bp[4]);
+                                cp[5] =  saturateByte (ap[5]  * (double) bp[5]);
+                                cp[6] =  saturateByte (ap[6]  * (double) bp[6]);
+                                cp[7] =  saturateByte (ap[7]  * (double) bp[7]);
+                                cp[8] =  saturateByte (ap[8]  * (double) bp[8]);
+                                cp[9] =  saturateByte (ap[9]  * (double) bp[9]);
+                                cp[10] =  saturateByte (ap[10]  * (double) bp[10]);
+                                cp[11] =  saturateByte (ap[11]  * (double) bp[11]);
+                                cp[12] =  saturateByte (ap[12]  * (double) bp[12]);
+                                cp[13] =  saturateByte (ap[13]  * (double) bp[13]);
+                                cp[14] =  saturateByte (ap[14]  * (double) bp[14]);
+                                cp[15] =  saturateByte (ap[15]  * (double) bp[15]);
+                                cp[16] =  saturateByte (ap[16]  * (double) bp[16]);
+                                cp[17] =  saturateByte (ap[17]  * (double) bp[17]);
+                                cp[18] =  saturateByte (ap[18]  * (double) bp[18]);
+                                cp[19] =  saturateByte (ap[19]  * (double) bp[19]);
+                                cp[20] =  saturateByte (ap[20]  * (double) bp[20]);
+                                ap+=21; bp+=21; cp+=21; j-=21;
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateByte (*ap  * (double) *bp);
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((byte*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateByte (cp[0]  * (double) scalar);
+                                cp[1] =  saturateByte (cp[1]  * (double) scalar);
+                                cp[2] =  saturateByte (cp[2]  * (double) scalar);
+                                cp[3] =  saturateByte (cp[3]  * (double) scalar);
+                                cp[4] =  saturateByte (cp[4]  * (double) scalar);
+                                cp[5] =  saturateByte (cp[5]  * (double) scalar);
+                                cp[6] =  saturateByte (cp[6]  * (double) scalar);
+                                cp[7] =  saturateByte (cp[7]  * (double) scalar);
+                                cp[8] =  saturateByte (cp[8]  * (double) scalar);
+                                cp[9] =  saturateByte (cp[9]  * (double) scalar);
+                                cp[10] =  saturateByte (cp[10]  * (double) scalar);
+                                cp[11] =  saturateByte (cp[11]  * (double) scalar);
+                                cp[12] =  saturateByte (cp[12]  * (double) scalar);
+                                cp[13] =  saturateByte (cp[13]  * (double) scalar);
+                                cp[14] =  saturateByte (cp[14]  * (double) scalar);
+                                cp[15] =  saturateByte (cp[15]  * (double) scalar);
+                                cp[16] =  saturateByte (cp[16]  * (double) scalar);
+                                cp[17] =  saturateByte (cp[17]  * (double) scalar);
+                                cp[18] =  saturateByte (cp[18]  * (double) scalar);
+                                cp[19] =  saturateByte (cp[19]  * (double) scalar);
+                                cp[20] =  saturateByte (cp[20]  * (double) scalar);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateByte (*cp  * (double) scalar);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((byte*)range.Item3 + range.Item1);
+                            scalar = *((byte*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateByte (ap[0]  * (double) scalar);
+                                cp[1] =  saturateByte (ap[1]  * (double) scalar);
+                                cp[2] =  saturateByte (ap[2]  * (double) scalar);
+                                cp[3] =  saturateByte (ap[3]  * (double) scalar);
+                                cp[4] =  saturateByte (ap[4]  * (double) scalar);
+                                cp[5] =  saturateByte (ap[5]  * (double) scalar);
+                                cp[6] =  saturateByte (ap[6]  * (double) scalar);
+                                cp[7] =  saturateByte (ap[7]  * (double) scalar);
+                                cp[8] =  saturateByte (ap[8]  * (double) scalar);
+                                cp[9] =  saturateByte (ap[9]  * (double) scalar);
+                                cp[10] =  saturateByte (ap[10]  * (double) scalar);
+                                cp[11] =  saturateByte (ap[11]  * (double) scalar);
+                                cp[12] =  saturateByte (ap[12]  * (double) scalar);
+                                cp[13] =  saturateByte (ap[13]  * (double) scalar);
+                                cp[14] =  saturateByte (ap[14]  * (double) scalar);
+                                cp[15] =  saturateByte (ap[15]  * (double) scalar);
+                                cp[16] =  saturateByte (ap[16]  * (double) scalar);
+                                cp[17] =  saturateByte (ap[17]  * (double) scalar);
+                                cp[18] =  saturateByte (ap[18]  * (double) scalar);
+                                cp[19] =  saturateByte (ap[19]  * (double) scalar);
+                                cp[20] =  saturateByte (ap[20]  * (double) scalar);
+                                ap+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateByte (*ap  * (double) scalar);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((byte*)range.Item3);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateByte (scalar  * (double) cp[0]);
+                                cp[1] =  saturateByte (scalar  * (double) cp[1]);
+                                cp[2] =  saturateByte (scalar  * (double) cp[2]);
+                                cp[3] =  saturateByte (scalar  * (double) cp[3]);
+                                cp[4] =  saturateByte (scalar  * (double) cp[4]);
+                                cp[5] =  saturateByte (scalar  * (double) cp[5]);
+                                cp[6] =  saturateByte (scalar  * (double) cp[6]);
+                                cp[7] =  saturateByte (scalar  * (double) cp[7]);
+                                cp[8] =  saturateByte (scalar  * (double) cp[8]);
+                                cp[9] =  saturateByte (scalar  * (double) cp[9]);
+                                cp[10] =  saturateByte (scalar  * (double) cp[10]);
+                                cp[11] =  saturateByte (scalar  * (double) cp[11]);
+                                cp[12] =  saturateByte (scalar  * (double) cp[12]);
+                                cp[13] =  saturateByte (scalar  * (double) cp[13]);
+                                cp[14] =  saturateByte (scalar  * (double) cp[14]);
+                                cp[15] =  saturateByte (scalar  * (double) cp[15]);
+                                cp[16] =  saturateByte (scalar  * (double) cp[16]);
+                                cp[17] =  saturateByte (scalar  * (double) cp[17]);
+                                cp[18] =  saturateByte (scalar  * (double) cp[18]);
+                                cp[19] =  saturateByte (scalar  * (double) cp[19]);
+                                cp[20] =  saturateByte (scalar  * (double) cp[20]);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateByte (scalar  * (double) *cp);
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((byte*)range.Item3);
+                            bp = ((byte*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateByte (scalar  * (double) bp[0]);
+                                cp[1] =  saturateByte (scalar  * (double) bp[1]);
+                                cp[2] =  saturateByte (scalar  * (double) bp[2]);
+                                cp[3] =  saturateByte (scalar  * (double) bp[3]);
+                                cp[4] =  saturateByte (scalar  * (double) bp[4]);
+                                cp[5] =  saturateByte (scalar  * (double) bp[5]);
+                                cp[6] =  saturateByte (scalar  * (double) bp[6]);
+                                cp[7] =  saturateByte (scalar  * (double) bp[7]);
+                                cp[8] =  saturateByte (scalar  * (double) bp[8]);
+                                cp[9] =  saturateByte (scalar  * (double) bp[9]);
+                                cp[10] =  saturateByte (scalar  * (double) bp[10]);
+                                cp[11] =  saturateByte (scalar  * (double) bp[11]);
+                                cp[12] =  saturateByte (scalar  * (double) bp[12]);
+                                cp[13] =  saturateByte (scalar  * (double) bp[13]);
+                                cp[14] =  saturateByte (scalar  * (double) bp[14]);
+                                cp[15] =  saturateByte (scalar  * (double) bp[15]);
+                                cp[16] =  saturateByte (scalar  * (double) bp[16]);
+                                cp[17] =  saturateByte (scalar  * (double) bp[17]);
+                                cp[18] =  saturateByte (scalar  * (double) bp[18]);
+                                cp[19] =  saturateByte (scalar  * (double) bp[19]);
+                                cp[20] =  saturateByte (scalar  * (double) bp[20]);
+                                bp+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateByte (scalar  * (double) *bp);
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work 
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                
+                fixed ( byte* arrAP = arrA)
+                fixed ( byte* arrBP = arrB)
+                fixed ( byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range 
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new  ILRetArray< byte>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<byte>  multiplyElemEx(ILInArray<byte> A, ILInArray<byte> B) {
+            //using (ILScope.Enter(A, B)) { we cannot start a new scope here, since this would prevent A and B to be used implace if applicable
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<byte>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<byte>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<byte>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                dim = -(dim - 1);  // 0 -> 1, 1 -> 0
+                #endregion
+
+                #region parameter preparation
+               
+                byte[] retArr;
+               
+                byte[] arrA = A.GetArrayForRead();
+               
+                byte[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int workItemMultiplierLenA;
+                int workItemMultiplierLenB;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    workItemMultiplierLenB = outDims[0]; 
+                    workItemMultiplierLenA = dim;  // 0 for column, 1 for row vector
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    workItemMultiplierLenB = dim;  // 0 for column, 1 for row vector
+                    workItemMultiplierLenA = outDims[0]; 
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one singleton dimension in either A or B");
+                }
+                int itLen = outDims[0]; // (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<byte> retStorage = new ILDenseStorage<byte>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    byte* ap;
+                   
+                    byte* bp;
+                   
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            if (dim == 0) {
+                                bp = (byte*)range.Item3;
+                                cp = (byte*)range.Item4; 
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (byte*)range.Item2;
+                                    int l = itLen; 
+                                    while (l > 10) {
+                                        cp[0] =  saturateByte (ap[0]  * (double) bp[0]);
+                                        cp[1] =  saturateByte (ap[1]  * (double) bp[1]);
+                                        cp[2] =  saturateByte (ap[2]  * (double) bp[2]);
+                                        cp[3] =  saturateByte (ap[3]  * (double) bp[3]);
+                                        cp[4] =  saturateByte (ap[4]  * (double) bp[4]);
+                                        cp[5] =  saturateByte (ap[5]  * (double) bp[5]);
+                                        cp[6] =  saturateByte (ap[6]  * (double) bp[6]);
+                                        cp[7] =  saturateByte (ap[7]  * (double) bp[7]);
+                                        cp[8] =  saturateByte (ap[8]  * (double) bp[8]);
+                                        cp[9] =  saturateByte (ap[9]  * (double) bp[9]);
+                                        cp[10] =  saturateByte (ap[10]  * (double) bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =  saturateByte (*ap++  * (double) *bp++);
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                ap = (byte*)range.Item2;
+                                bp = (byte*)range.Item3;
+                                cp = (byte*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   byte val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateByte (val  * (double) bp[0]);
+                                        cp[1] =  saturateByte (val  * (double) bp[1]);
+                                        cp[2] =  saturateByte (val  * (double) bp[2]);
+                                        cp[3] =  saturateByte (val  * (double) bp[3]);
+                                        cp[4] =  saturateByte (val  * (double) bp[4]);
+                                        cp[5] =  saturateByte (val  * (double) bp[5]);
+                                        cp[6] =  saturateByte (val  * (double) bp[6]);
+                                        cp[7] =  saturateByte (val  * (double) bp[7]);
+                                        cp[8] =  saturateByte (val  * (double) bp[8]);
+                                        cp[9] =  saturateByte (val  * (double) bp[9]);
+                                        cp[10] =  saturateByte (val  * (double) bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11; 
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =  saturateByte (val  * (double) *bp++);
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            if (dim == 0) {
+                                cp = (byte*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (byte*)range.Item2;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateByte (ap[0]  * (double) cp[0]);
+                                        cp[1] =  saturateByte (ap[1]  * (double) cp[1]);
+                                        cp[2] =  saturateByte (ap[2]  * (double) cp[2]);
+                                        cp[3] =  saturateByte (ap[3]  * (double) cp[3]);
+                                        cp[4] =  saturateByte (ap[4]  * (double) cp[4]);
+                                        cp[5] =  saturateByte (ap[5]  * (double) cp[5]);
+                                        cp[6] =  saturateByte (ap[6]  * (double) cp[6]);
+                                        cp[7] =  saturateByte (ap[7]  * (double) cp[7]);
+                                        cp[8] =  saturateByte (ap[8]  * (double) cp[8]);
+                                        cp[9] =  saturateByte (ap[9]  * (double) cp[9]);
+                                        cp[10] =  saturateByte (ap[10]  * (double) cp[10]);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateByte (*ap++  * (double) *cp);
+                                        cp++; 
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                cp = (byte*)range.Item4;
+                                ap = (byte*)range.Item2;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    byte val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateByte (val  * (double) cp[0]);
+                                        cp[1] =  saturateByte (val  * (double) cp[1]);
+                                        cp[2] =  saturateByte (val  * (double) cp[2]);
+                                        cp[3] =  saturateByte (val  * (double) cp[3]);
+                                        cp[4] =  saturateByte (val  * (double) cp[4]);
+                                        cp[5] =  saturateByte (val  * (double) cp[5]);
+                                        cp[6] =  saturateByte (val  * (double) cp[6]);
+                                        cp[7] =  saturateByte (val  * (double) cp[7]);
+                                        cp[8] =  saturateByte (val  * (double) cp[8]);
+                                        cp[9] =  saturateByte (val  * (double) cp[9]);
+                                        cp[10] =  saturateByte (val  * (double) cp[10]);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateByte (val  * (double) *cp);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            if (dim == 0) {
+                                ap = (byte*)range.Item2;
+                                cp = (byte*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (byte*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateByte (ap[0]  * (double) bp[0]);
+                                        cp[1] =  saturateByte (ap[1]  * (double) bp[1]);
+                                        cp[2] =  saturateByte (ap[2]  * (double) bp[2]);
+                                        cp[3] =  saturateByte (ap[3]  * (double) bp[3]);
+                                        cp[4] =  saturateByte (ap[4]  * (double) bp[4]);
+                                        cp[5] =  saturateByte (ap[5]  * (double) bp[5]);
+                                        cp[6] =  saturateByte (ap[6]  * (double) bp[6]);
+                                        cp[7] =  saturateByte (ap[7]  * (double) bp[7]);
+                                        cp[8] =  saturateByte (ap[8]  * (double) bp[8]);
+                                        cp[9] =  saturateByte (ap[9]  * (double) bp[9]);
+                                        cp[10] =  saturateByte (ap[10]  * (double) bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateByte (*ap  * (double) *bp);
+                                        ap++;
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                ap = (byte*)range.Item2;
+                                bp = (byte*)range.Item3;
+                                cp = (byte*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   byte val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateByte (ap[0]  * (double) val);
+                                        cp[1] =  saturateByte (ap[1]  * (double) val);
+                                        cp[2] =  saturateByte (ap[2]  * (double) val);
+                                        cp[3] =  saturateByte (ap[3]  * (double) val);
+                                        cp[4] =  saturateByte (ap[4]  * (double) val);
+                                        cp[5] =  saturateByte (ap[5]  * (double) val);
+                                        cp[6] =  saturateByte (ap[6]  * (double) val);
+                                        cp[7] =  saturateByte (ap[7]  * (double) val);
+                                        cp[8] =  saturateByte (ap[8]  * (double) val);
+                                        cp[9] =  saturateByte (ap[9]  * (double) val);
+                                        cp[10] =  saturateByte (ap[10]  * (double) val);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateByte (*ap  * (double) val);
+                                        ap++;
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            if (dim == 0) {
+                                cp = (byte*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (byte*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateByte (cp[0]  * (double) bp[0]);
+                                        cp[1] =  saturateByte (cp[1]  * (double) bp[1]);
+                                        cp[2] =  saturateByte (cp[2]  * (double) bp[2]);
+                                        cp[3] =  saturateByte (cp[3]  * (double) bp[3]);
+                                        cp[4] =  saturateByte (cp[4]  * (double) bp[4]);
+                                        cp[5] =  saturateByte (cp[5]  * (double) bp[5]);
+                                        cp[6] =  saturateByte (cp[6]  * (double) bp[6]);
+                                        cp[7] =  saturateByte (cp[7]  * (double) bp[7]);
+                                        cp[8] =  saturateByte (cp[8]  * (double) bp[8]);
+                                        cp[9] =  saturateByte (cp[9]  * (double) bp[9]);
+                                        cp[10] =  saturateByte (cp[10]  * (double) bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateByte (*cp  * (double) *bp);
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                bp = (byte*)range.Item3;
+                                cp = (byte*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    byte val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateByte (cp[0]  * (double) val);
+                                        cp[1] =  saturateByte (cp[1]  * (double) val);
+                                        cp[2] =  saturateByte (cp[2]  * (double) val);
+                                        cp[3] =  saturateByte (cp[3]  * (double) val);
+                                        cp[4] =  saturateByte (cp[4]  * (double) val);
+                                        cp[5] =  saturateByte (cp[5]  * (double) val);
+                                        cp[6] =  saturateByte (cp[6]  * (double) val);
+                                        cp[7] =  saturateByte (cp[7]  * (double) val);
+                                        cp[8] =  saturateByte (cp[8]  * (double) val);
+                                        cp[9] =  saturateByte (cp[9]  * (double) val);
+                                        cp[10] =  saturateByte (cp[10]  * (double) val);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l --> 0) {
+                                        *cp =  saturateByte (*cp  * (double) val);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outDims.NumberOfElements >= Settings.s_minParallelElement1Count
+                    && outDims[1] > 1) {
+                        if (outDims[1] > workItemCount) {
+                        workItemLength = outDims[1] / workItemCount;
+                    } else {
+                        workItemLength = outDims[1] / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outDims[1];
+                    workItemCount = 1;
+                }
+
+                fixed ( byte* arrAP = arrA)
+                fixed ( byte* arrBP = arrB)
+                fixed ( byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, IntPtr, IntPtr, IntPtr> range = new Tuple<int, IntPtr, IntPtr, IntPtr>
+                               (workItemLength
+                               , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                               , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                               , (IntPtr)(retArrP + i * outDims[0] * workItemLength)); 
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, IntPtr, IntPtr, IntPtr>
+                                (outDims[1] - i * workItemLength
+                                , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                                , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                                , (IntPtr)(retArrP + i * outDims[0] * workItemLength)));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<byte>(retStorage);
+            //}  // no scopes here! it disables implace operations
+        }
+
+        /// <summary>Multiply arrays elementwise</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Array with elementwise multiplication of A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<double>  multiplyElem(ILInArray<double> A, ILInArray<double> B) {
+            using (ILScope.Enter(A,B)) {
+                int outLen; 
+                BinOpItMode mode; 
+                double [] retArr;
+                double [] arrA = A.GetArrayForRead();
+                double[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size; 
+                    if (B.IsScalar) {
+                       
+                        return new  ILRetArray<double> (new  double [1]{  (A.GetValue(0)  * B.GetValue(0))}, A.Size);
+                    } else if (B.IsEmpty) {
+                        return  ILRetArray<double>.empty(outDims); 
+                    } else {
+                        outLen = outDims.NumberOfElements; 
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< double > (outLen);
+                            mode = BinOpItMode.SAN; 
+                        } else {
+                            mode = BinOpItMode.SAI; 
+                        }
+                    }
+                } else {
+                    outDims = A.Size; 
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return  ILRetArray<double>.empty(A.Size);  
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< double > (outLen);
+                            mode = BinOpItMode.ASN; 
+                        } else {
+                            mode = BinOpItMode.ASI; 
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  multiplyElemEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (A.TryGetStorage4InplaceOp(out retArr)) 
+                            mode  = BinOpItMode.AAIA; 
+                        else if (B.TryGetStorage4InplaceOp(out retArr)) 
+                            mode = BinOpItMode.AAIB; 
+                        else {
+                            retArr = ILMemoryPool.Pool.New< double > (outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<double> retStorage = new ILDenseStorage<double>(retArr, outDims);
+                int i = 0, workerCount = 1; 
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    double* cp = (double*)range.Item5 + range.Item1;
+                    double scalar;
+                    int j = range.Item2; 
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           double* bp = ((double*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                                cp[0] =   (cp[0]  * bp[0]);
+                                cp[1] =   (cp[1]  * bp[1]);
+                                cp[2] =   (cp[2]  * bp[2]);
+                                cp[3] =   (cp[3]  * bp[3]);
+                                cp[4] =   (cp[4]  * bp[4]);
+                                cp[5] =   (cp[5]  * bp[5]);
+                                cp[6] =   (cp[6]  * bp[6]);
+                                cp[7] =   (cp[7]  * bp[7]);
+                                cp[8] =   (cp[8]  * bp[8]);
+                                cp[9] =   (cp[9]  * bp[9]);
+                                cp[10] =   (cp[10]  * bp[10]);
+                                cp[11] =   (cp[11]  * bp[11]);
+                                cp[12] =   (cp[12]  * bp[12]);
+                                cp[13] =   (cp[13]  * bp[13]);
+                                cp[14] =   (cp[14]  * bp[14]);
+                                cp[15] =   (cp[15]  * bp[15]);
+                                cp[16] =   (cp[16]  * bp[16]);
+                                cp[17] =   (cp[17]  * bp[17]);
+                                cp[18] =   (cp[18]  * bp[18]);
+                                cp[19] =   (cp[19]  * bp[19]);
+                                cp[20] =   (cp[20]  * bp[20]);
+                                cp += 21; bp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*cp  * *bp);
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           double* ap = ((double*)range.Item3 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  * cp[0]);
+                                cp[1] =   (ap[1]  * cp[1]);
+                                cp[2] =   (ap[2]  * cp[2]);
+                                cp[3] =   (ap[3]  * cp[3]);
+                                cp[4] =   (ap[4]  * cp[4]);
+                                cp[5] =   (ap[5]  * cp[5]);
+                                cp[6] =   (ap[6]  * cp[6]);
+                                cp[7] =   (ap[7]  * cp[7]);
+                                cp[8] =   (ap[8]  * cp[8]);
+                                cp[9] =   (ap[9]  * cp[9]);
+                                cp[10] =   (ap[10]  * cp[10]);
+                                cp[11] =   (ap[11]  * cp[11]);
+                                cp[12] =   (ap[12]  * cp[12]);
+                                cp[13] =   (ap[13]  * cp[13]);
+                                cp[14] =   (ap[14]  * cp[14]);
+                                cp[15] =   (ap[15]  * cp[15]);
+                                cp[16] =   (ap[16]  * cp[16]);
+                                cp[17] =   (ap[17]  * cp[17]);
+                                cp[18] =   (ap[18]  * cp[18]);
+                                cp[19] =   (ap[19]  * cp[19]);
+                                cp[20] =   (ap[20]  * cp[20]);
+                                ap += 21; cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  * *cp);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((double*)range.Item3 + range.Item1);
+                            bp = ((double*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  * bp[0]);
+                                cp[1] =   (ap[1]  * bp[1]);
+                                cp[2] =   (ap[2]  * bp[2]);
+                                cp[3] =   (ap[3]  * bp[3]);
+                                cp[4] =   (ap[4]  * bp[4]);
+                                cp[5] =   (ap[5]  * bp[5]);
+                                cp[6] =   (ap[6]  * bp[6]);
+                                cp[7] =   (ap[7]  * bp[7]);
+                                cp[8] =   (ap[8]  * bp[8]);
+                                cp[9] =   (ap[9]  * bp[9]);
+                                cp[10] =   (ap[10]  * bp[10]);
+                                cp[11] =   (ap[11]  * bp[11]);
+                                cp[12] =   (ap[12]  * bp[12]);
+                                cp[13] =   (ap[13]  * bp[13]);
+                                cp[14] =   (ap[14]  * bp[14]);
+                                cp[15] =   (ap[15]  * bp[15]);
+                                cp[16] =   (ap[16]  * bp[16]);
+                                cp[17] =   (ap[17]  * bp[17]);
+                                cp[18] =   (ap[18]  * bp[18]);
+                                cp[19] =   (ap[19]  * bp[19]);
+                                cp[20] =   (ap[20]  * bp[20]);
+                                ap+=21; bp+=21; cp+=21; j-=21;
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  * *bp);
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((double*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =   (cp[0]  * scalar);
+                                cp[1] =   (cp[1]  * scalar);
+                                cp[2] =   (cp[2]  * scalar);
+                                cp[3] =   (cp[3]  * scalar);
+                                cp[4] =   (cp[4]  * scalar);
+                                cp[5] =   (cp[5]  * scalar);
+                                cp[6] =   (cp[6]  * scalar);
+                                cp[7] =   (cp[7]  * scalar);
+                                cp[8] =   (cp[8]  * scalar);
+                                cp[9] =   (cp[9]  * scalar);
+                                cp[10] =   (cp[10]  * scalar);
+                                cp[11] =   (cp[11]  * scalar);
+                                cp[12] =   (cp[12]  * scalar);
+                                cp[13] =   (cp[13]  * scalar);
+                                cp[14] =   (cp[14]  * scalar);
+                                cp[15] =   (cp[15]  * scalar);
+                                cp[16] =   (cp[16]  * scalar);
+                                cp[17] =   (cp[17]  * scalar);
+                                cp[18] =   (cp[18]  * scalar);
+                                cp[19] =   (cp[19]  * scalar);
+                                cp[20] =   (cp[20]  * scalar);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*cp  * scalar);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((double*)range.Item3 + range.Item1);
+                            scalar = *((double*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  * scalar);
+                                cp[1] =   (ap[1]  * scalar);
+                                cp[2] =   (ap[2]  * scalar);
+                                cp[3] =   (ap[3]  * scalar);
+                                cp[4] =   (ap[4]  * scalar);
+                                cp[5] =   (ap[5]  * scalar);
+                                cp[6] =   (ap[6]  * scalar);
+                                cp[7] =   (ap[7]  * scalar);
+                                cp[8] =   (ap[8]  * scalar);
+                                cp[9] =   (ap[9]  * scalar);
+                                cp[10] =   (ap[10]  * scalar);
+                                cp[11] =   (ap[11]  * scalar);
+                                cp[12] =   (ap[12]  * scalar);
+                                cp[13] =   (ap[13]  * scalar);
+                                cp[14] =   (ap[14]  * scalar);
+                                cp[15] =   (ap[15]  * scalar);
+                                cp[16] =   (ap[16]  * scalar);
+                                cp[17] =   (ap[17]  * scalar);
+                                cp[18] =   (ap[18]  * scalar);
+                                cp[19] =   (ap[19]  * scalar);
+                                cp[20] =   (ap[20]  * scalar);
+                                ap+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  * scalar);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((double*)range.Item3);
+                            while (j > 20) {
+                               
+                                cp[0] =   (scalar  * cp[0]);
+                                cp[1] =   (scalar  * cp[1]);
+                                cp[2] =   (scalar  * cp[2]);
+                                cp[3] =   (scalar  * cp[3]);
+                                cp[4] =   (scalar  * cp[4]);
+                                cp[5] =   (scalar  * cp[5]);
+                                cp[6] =   (scalar  * cp[6]);
+                                cp[7] =   (scalar  * cp[7]);
+                                cp[8] =   (scalar  * cp[8]);
+                                cp[9] =   (scalar  * cp[9]);
+                                cp[10] =   (scalar  * cp[10]);
+                                cp[11] =   (scalar  * cp[11]);
+                                cp[12] =   (scalar  * cp[12]);
+                                cp[13] =   (scalar  * cp[13]);
+                                cp[14] =   (scalar  * cp[14]);
+                                cp[15] =   (scalar  * cp[15]);
+                                cp[16] =   (scalar  * cp[16]);
+                                cp[17] =   (scalar  * cp[17]);
+                                cp[18] =   (scalar  * cp[18]);
+                                cp[19] =   (scalar  * cp[19]);
+                                cp[20] =   (scalar  * cp[20]);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (scalar  * *cp);
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((double*)range.Item3);
+                            bp = ((double*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (scalar  * bp[0]);
+                                cp[1] =   (scalar  * bp[1]);
+                                cp[2] =   (scalar  * bp[2]);
+                                cp[3] =   (scalar  * bp[3]);
+                                cp[4] =   (scalar  * bp[4]);
+                                cp[5] =   (scalar  * bp[5]);
+                                cp[6] =   (scalar  * bp[6]);
+                                cp[7] =   (scalar  * bp[7]);
+                                cp[8] =   (scalar  * bp[8]);
+                                cp[9] =   (scalar  * bp[9]);
+                                cp[10] =   (scalar  * bp[10]);
+                                cp[11] =   (scalar  * bp[11]);
+                                cp[12] =   (scalar  * bp[12]);
+                                cp[13] =   (scalar  * bp[13]);
+                                cp[14] =   (scalar  * bp[14]);
+                                cp[15] =   (scalar  * bp[15]);
+                                cp[16] =   (scalar  * bp[16]);
+                                cp[17] =   (scalar  * bp[17]);
+                                cp[18] =   (scalar  * bp[18]);
+                                cp[19] =   (scalar  * bp[19]);
+                                cp[20] =   (scalar  * bp[20]);
+                                bp+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (scalar  * *bp);
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work 
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                
+                fixed ( double* arrAP = arrA)
+                fixed ( double* arrBP = arrB)
+                fixed ( double* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range 
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new  ILRetArray< double>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<double>  multiplyElemEx(ILInArray<double> A, ILInArray<double> B) {
+            //using (ILScope.Enter(A, B)) { we cannot start a new scope here, since this would prevent A and B to be used implace if applicable
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<double>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<double>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<double>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                dim = -(dim - 1);  // 0 -> 1, 1 -> 0
+                #endregion
+
+                #region parameter preparation
+               
+                double[] retArr;
+               
+                double[] arrA = A.GetArrayForRead();
+               
+                double[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int workItemMultiplierLenA;
+                int workItemMultiplierLenB;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<double>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    workItemMultiplierLenB = outDims[0]; 
+                    workItemMultiplierLenA = dim;  // 0 for column, 1 for row vector
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<double>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    workItemMultiplierLenB = dim;  // 0 for column, 1 for row vector
+                    workItemMultiplierLenA = outDims[0]; 
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one singleton dimension in either A or B");
+                }
+                int itLen = outDims[0]; // (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<double> retStorage = new ILDenseStorage<double>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    double* ap;
+                   
+                    double* bp;
+                   
+                    double* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            if (dim == 0) {
+                                bp = (double*)range.Item3;
+                                cp = (double*)range.Item4; 
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (double*)range.Item2;
+                                    int l = itLen; 
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  * bp[0]);
+                                        cp[1] =   (ap[1]  * bp[1]);
+                                        cp[2] =   (ap[2]  * bp[2]);
+                                        cp[3] =   (ap[3]  * bp[3]);
+                                        cp[4] =   (ap[4]  * bp[4]);
+                                        cp[5] =   (ap[5]  * bp[5]);
+                                        cp[6] =   (ap[6]  * bp[6]);
+                                        cp[7] =   (ap[7]  * bp[7]);
+                                        cp[8] =   (ap[8]  * bp[8]);
+                                        cp[9] =   (ap[9]  * bp[9]);
+                                        cp[10] =   (ap[10]  * bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =   (*ap++  * *bp++);
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                ap = (double*)range.Item2;
+                                bp = (double*)range.Item3;
+                                cp = (double*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   double val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (val  * bp[0]);
+                                        cp[1] =   (val  * bp[1]);
+                                        cp[2] =   (val  * bp[2]);
+                                        cp[3] =   (val  * bp[3]);
+                                        cp[4] =   (val  * bp[4]);
+                                        cp[5] =   (val  * bp[5]);
+                                        cp[6] =   (val  * bp[6]);
+                                        cp[7] =   (val  * bp[7]);
+                                        cp[8] =   (val  * bp[8]);
+                                        cp[9] =   (val  * bp[9]);
+                                        cp[10] =   (val  * bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11; 
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =   (val  * *bp++);
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            if (dim == 0) {
+                                cp = (double*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (double*)range.Item2;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  * cp[0]);
+                                        cp[1] =   (ap[1]  * cp[1]);
+                                        cp[2] =   (ap[2]  * cp[2]);
+                                        cp[3] =   (ap[3]  * cp[3]);
+                                        cp[4] =   (ap[4]  * cp[4]);
+                                        cp[5] =   (ap[5]  * cp[5]);
+                                        cp[6] =   (ap[6]  * cp[6]);
+                                        cp[7] =   (ap[7]  * cp[7]);
+                                        cp[8] =   (ap[8]  * cp[8]);
+                                        cp[9] =   (ap[9]  * cp[9]);
+                                        cp[10] =   (ap[10]  * cp[10]);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap++  * *cp);
+                                        cp++; 
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                cp = (double*)range.Item4;
+                                ap = (double*)range.Item2;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    double val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (val  * cp[0]);
+                                        cp[1] =   (val  * cp[1]);
+                                        cp[2] =   (val  * cp[2]);
+                                        cp[3] =   (val  * cp[3]);
+                                        cp[4] =   (val  * cp[4]);
+                                        cp[5] =   (val  * cp[5]);
+                                        cp[6] =   (val  * cp[6]);
+                                        cp[7] =   (val  * cp[7]);
+                                        cp[8] =   (val  * cp[8]);
+                                        cp[9] =   (val  * cp[9]);
+                                        cp[10] =   (val  * cp[10]);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (val  * *cp);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            if (dim == 0) {
+                                ap = (double*)range.Item2;
+                                cp = (double*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (double*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  * bp[0]);
+                                        cp[1] =   (ap[1]  * bp[1]);
+                                        cp[2] =   (ap[2]  * bp[2]);
+                                        cp[3] =   (ap[3]  * bp[3]);
+                                        cp[4] =   (ap[4]  * bp[4]);
+                                        cp[5] =   (ap[5]  * bp[5]);
+                                        cp[6] =   (ap[6]  * bp[6]);
+                                        cp[7] =   (ap[7]  * bp[7]);
+                                        cp[8] =   (ap[8]  * bp[8]);
+                                        cp[9] =   (ap[9]  * bp[9]);
+                                        cp[10] =   (ap[10]  * bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap  * *bp);
+                                        ap++;
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                ap = (double*)range.Item2;
+                                bp = (double*)range.Item3;
+                                cp = (double*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   double val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  * val);
+                                        cp[1] =   (ap[1]  * val);
+                                        cp[2] =   (ap[2]  * val);
+                                        cp[3] =   (ap[3]  * val);
+                                        cp[4] =   (ap[4]  * val);
+                                        cp[5] =   (ap[5]  * val);
+                                        cp[6] =   (ap[6]  * val);
+                                        cp[7] =   (ap[7]  * val);
+                                        cp[8] =   (ap[8]  * val);
+                                        cp[9] =   (ap[9]  * val);
+                                        cp[10] =   (ap[10]  * val);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap  * val);
+                                        ap++;
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            if (dim == 0) {
+                                cp = (double*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (double*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (cp[0]  * bp[0]);
+                                        cp[1] =   (cp[1]  * bp[1]);
+                                        cp[2] =   (cp[2]  * bp[2]);
+                                        cp[3] =   (cp[3]  * bp[3]);
+                                        cp[4] =   (cp[4]  * bp[4]);
+                                        cp[5] =   (cp[5]  * bp[5]);
+                                        cp[6] =   (cp[6]  * bp[6]);
+                                        cp[7] =   (cp[7]  * bp[7]);
+                                        cp[8] =   (cp[8]  * bp[8]);
+                                        cp[9] =   (cp[9]  * bp[9]);
+                                        cp[10] =   (cp[10]  * bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*cp  * *bp);
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                bp = (double*)range.Item3;
+                                cp = (double*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    double val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (cp[0]  * val);
+                                        cp[1] =   (cp[1]  * val);
+                                        cp[2] =   (cp[2]  * val);
+                                        cp[3] =   (cp[3]  * val);
+                                        cp[4] =   (cp[4]  * val);
+                                        cp[5] =   (cp[5]  * val);
+                                        cp[6] =   (cp[6]  * val);
+                                        cp[7] =   (cp[7]  * val);
+                                        cp[8] =   (cp[8]  * val);
+                                        cp[9] =   (cp[9]  * val);
+                                        cp[10] =   (cp[10]  * val);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l --> 0) {
+                                        *cp =   (*cp  * val);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outDims.NumberOfElements >= Settings.s_minParallelElement1Count
+                    && outDims[1] > 1) {
+                        if (outDims[1] > workItemCount) {
+                        workItemLength = outDims[1] / workItemCount;
+                    } else {
+                        workItemLength = outDims[1] / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outDims[1];
+                    workItemCount = 1;
+                }
+
+                fixed ( double* arrAP = arrA)
+                fixed ( double* arrBP = arrB)
+                fixed ( double* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, IntPtr, IntPtr, IntPtr> range = new Tuple<int, IntPtr, IntPtr, IntPtr>
+                               (workItemLength
+                               , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                               , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                               , (IntPtr)(retArrP + i * outDims[0] * workItemLength)); 
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, IntPtr, IntPtr, IntPtr>
+                                (outDims[1] - i * workItemLength
+                                , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                                , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                                , (IntPtr)(retArrP + i * outDims[0] * workItemLength)));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<double>(retStorage);
+            //}  // no scopes here! it disables implace operations
+        }
+
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/Norm.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/Norm.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/Norm.cs	(revision 9102)
@@ -0,0 +1,263 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions;
+
+
+
+namespace ILNumerics  {
+
+    public partial class ILMath {
+        
+
+        /// <summary>
+        /// Vector or matrix norm
+        /// </summary>
+        /// <param name="A">Input matrix/ vector</param>
+        /// <param name="degree">[Optional] Degree of norm (default = 2). For vectors this must be one of: 
+        /// <list type="bullet">
+        /// <item>arbitrary double value : returns sum(pow(abs(A),degree))^(1/degree)</item>
+        /// <item>System.double.PositiveInfinity: return Max(abs(A))</item>
+        /// <item>System.double.NegativeInfinity: return Min(abs(A))</item>
+        /// </list>
+        /// For matrices this must be one out of: 
+        /// <list type="bullet">
+        /// <item>0: returns Frobenius norm: sqrt(sum(diag(multiply(A, A[1]))))</item>
+        /// <item>1: returns 1-norm, max(sum(abs(A)))</item>
+        /// <item>2: returns the largest singular value of A, max(svd(A))</item>
+        /// <item>PositiveInfinity: returns max(sum(abs(A), 2)), the largest value of the sums along the rows</item>
+        /// </list>
+        /// </param>
+        /// <returns>Array of same type as input array A</returns>
+        public static ILRetArray< double > norm(ILInArray< double > A, double degree = 2) {
+            using (ILScope.Enter(A)) {
+                if (Object.Equals(A, null) || !A.IsMatrix)
+                    throw new ILArgumentSizeException("input array must be matrix or vector.");
+                if (A.IsEmpty)
+                    return new ILRetArray< double>(ILSize.Scalar1_1);
+                else if (A.IsVector) {
+                    if (degree == Double.PositiveInfinity) {
+                        return max(abs(A));
+                    } else if (degree == Double.NegativeInfinity) {
+                        return min(abs(A));
+                    } else {
+                        if (degree == 0.0)
+                            return array< double>( (  double)Double.PositiveInfinity , 1, 1);
+                        return pow(sum(pow(abs(A), (  double)degree)), (  double)(1.0 / degree));
+                    }
+                } else {
+                    if (degree == 1.0) {
+                        return max(sum(abs(A)));
+                    } else if (degree == 2.0) {
+                        return max(svd(A));
+                    } else if (degree == Double.PositiveInfinity) {
+                        return max(sum(abs(A), 2));
+                    } else if (degree == 0.0) {
+                        
+                        return sqrt(sum(diag <double>(multiply(A, A[1]))));
+                    } else {
+                        throw new ILArgumentException("invalid argument 'degree' supplied. valid for matrices: 0,1,2,Double.PositiveInfinity");
+                    }
+                }
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// Vector or matrix norm
+        /// </summary>
+        /// <param name="A">Input matrix/ vector</param>
+        /// <param name="degree">[Optional] Degree of norm (default = 2). For vectors this must be one of: 
+        /// <list type="bullet">
+        /// <item>arbitrary double value : returns sum(pow(abs(A),degree))^(1/degree)</item>
+        /// <item>System.double.PositiveInfinity: return Max(abs(A))</item>
+        /// <item>System.double.NegativeInfinity: return Min(abs(A))</item>
+        /// </list>
+        /// For matrices this must be one out of: 
+        /// <list type="bullet">
+        /// <item>0: returns Frobenius norm: sqrt(sum(diag(multiply(A, A[1]))))</item>
+        /// <item>1: returns 1-norm, max(sum(abs(A)))</item>
+        /// <item>2: returns the largest singular value of A, max(svd(A))</item>
+        /// <item>PositiveInfinity: returns max(sum(abs(A), 2)), the largest value of the sums along the rows</item>
+        /// </list>
+        /// </param>
+        /// <returns>Array of same type as input array A</returns>
+        public static ILRetArray< float > norm(ILInArray< fcomplex > A, double degree = 2) {
+            using (ILScope.Enter(A)) {
+                if (Object.Equals(A, null) || !A.IsMatrix)
+                    throw new ILArgumentSizeException("input array must be matrix or vector.");
+                if (A.IsEmpty)
+                    return new ILRetArray< float>(ILSize.Scalar1_1);
+                else if (A.IsVector) {
+                    if (degree == Double.PositiveInfinity) {
+                        return max(abs(A));
+                    } else if (degree == Double.NegativeInfinity) {
+                        return min(abs(A));
+                    } else {
+                        if (degree == 0.0)
+                            return array< float>( (  float)Double.PositiveInfinity , 1, 1);
+                        return pow(sum(pow(abs(A), (  float)degree)), (  float)(1.0 / degree));
+                    }
+                } else {
+                    if (degree == 1.0) {
+                        return max(sum(abs(A)));
+                    } else if (degree == 2.0) {
+                        return max(svd(A));
+                    } else if (degree == Double.PositiveInfinity) {
+                        return max(sum(abs(A), 2));
+                    } else if (degree == 0.0) {
+                        return sqrt(sum(real(diag<fcomplex>(multiply(A, A[1])))));
+                    } else {
+                        throw new ILArgumentException("invalid argument 'degree' supplied. valid for matrices: 0,1,2,Double.PositiveInfinity");
+                    }
+                }
+            }
+        }
+        /// <summary>
+        /// Vector or matrix norm
+        /// </summary>
+        /// <param name="A">Input matrix/ vector</param>
+        /// <param name="degree">[Optional] Degree of norm (default = 2). For vectors this must be one of: 
+        /// <list type="bullet">
+        /// <item>arbitrary double value : returns sum(pow(abs(A),degree))^(1/degree)</item>
+        /// <item>System.double.PositiveInfinity: return Max(abs(A))</item>
+        /// <item>System.double.NegativeInfinity: return Min(abs(A))</item>
+        /// </list>
+        /// For matrices this must be one out of: 
+        /// <list type="bullet">
+        /// <item>0: returns Frobenius norm: sqrt(sum(diag(multiply(A, A[1]))))</item>
+        /// <item>1: returns 1-norm, max(sum(abs(A)))</item>
+        /// <item>2: returns the largest singular value of A, max(svd(A))</item>
+        /// <item>PositiveInfinity: returns max(sum(abs(A), 2)), the largest value of the sums along the rows</item>
+        /// </list>
+        /// </param>
+        /// <returns>Array of same type as input array A</returns>
+        public static ILRetArray< float > norm(ILInArray< float > A, double degree = 2) {
+            using (ILScope.Enter(A)) {
+                if (Object.Equals(A, null) || !A.IsMatrix)
+                    throw new ILArgumentSizeException("input array must be matrix or vector.");
+                if (A.IsEmpty)
+                    return new ILRetArray< float>(ILSize.Scalar1_1);
+                else if (A.IsVector) {
+                    if (degree == Double.PositiveInfinity) {
+                        return max(abs(A));
+                    } else if (degree == Double.NegativeInfinity) {
+                        return min(abs(A));
+                    } else {
+                        if (degree == 0.0)
+                            return array< float>( (  float)Double.PositiveInfinity , 1, 1);
+                        return pow(sum(pow(abs(A), (  float)degree)), (  float)(1.0 / degree));
+                    }
+                } else {
+                    if (degree == 1.0) {
+                        return max(sum(abs(A)));
+                    } else if (degree == 2.0) {
+                        return max(svd(A));
+                    } else if (degree == Double.PositiveInfinity) {
+                        return max(sum(abs(A), 2));
+                    } else if (degree == 0.0) {
+                        return sqrt(sum(diag<float>(multiply(A, A[1]))));
+                    } else {
+                        throw new ILArgumentException("invalid argument 'degree' supplied. valid for matrices: 0,1,2,Double.PositiveInfinity");
+                    }
+                }
+            }
+        }
+        /// <summary>
+        /// Vector or matrix norm
+        /// </summary>
+        /// <param name="A">Input matrix/ vector</param>
+        /// <param name="degree">[Optional] Degree of norm (default = 2). For vectors this must be one of: 
+        /// <list type="bullet">
+        /// <item>arbitrary double value : returns sum(pow(abs(A),degree))^(1/degree)</item>
+        /// <item>System.double.PositiveInfinity: return Max(abs(A))</item>
+        /// <item>System.double.NegativeInfinity: return Min(abs(A))</item>
+        /// </list>
+        /// For matrices this must be one out of: 
+        /// <list type="bullet">
+        /// <item>0: returns Frobenius norm: sqrt(sum(diag(multiply(A, A[1]))))</item>
+        /// <item>1: returns 1-norm, max(sum(abs(A)))</item>
+        /// <item>2: returns the largest singular value of A, max(svd(A))</item>
+        /// <item>PositiveInfinity: returns max(sum(abs(A), 2)), the largest value of the sums along the rows</item>
+        /// </list>
+        /// </param>
+        /// <returns>Array of same type as input array A</returns>
+        public static ILRetArray< double > norm(ILInArray< complex > A, double degree = 2) {
+            using (ILScope.Enter(A)) {
+                if (Object.Equals(A, null) || !A.IsMatrix)
+                    throw new ILArgumentSizeException("input array must be matrix or vector.");
+                if (A.IsEmpty)
+                    return new ILRetArray< double>(ILSize.Scalar1_1);
+                else if (A.IsVector) {
+                    if (degree == Double.PositiveInfinity) {
+                        return max(abs(A));
+                    } else if (degree == Double.NegativeInfinity) {
+                        return min(abs(A));
+                    } else {
+                        if (degree == 0.0)
+                            return array< double>( (  double)Double.PositiveInfinity , 1, 1);
+                        return pow(sum(pow(abs(A), (  double)degree)), (  double)(1.0 / degree));
+                    }
+                } else {
+                    if (degree == 1.0) {
+                        return max(sum(abs(A)));
+                    } else if (degree == 2.0) {
+                        return max(svd(A));
+                    } else if (degree == Double.PositiveInfinity) {
+                        return max(sum(abs(A), 2));
+                    } else if (degree == 0.0) {
+                        return sqrt(sum(real(diag<complex>(multiply(A, A[1])))));
+                    } else {
+                        throw new ILArgumentException("invalid argument 'degree' supplied. valid for matrices: 0,1,2,Double.PositiveInfinity");
+                    }
+                }
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/Subtract.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/Subtract.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/Subtract.cs	(revision 9102)
@@ -0,0 +1,5102 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using ILNumerics;
+using ILNumerics.Misc;
+using ILNumerics.Storage;
+using ILNumerics.Native;
+using ILNumerics.Exceptions;
+
+
+
+namespace ILNumerics {
+
+    public partial class ILMath {
+
+
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>Subtract arrays elementwise</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>New array with result of subtraction</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<Int64>  subtract(ILInArray<Int64> A, ILInArray<Int64> B) {
+            using (ILScope.Enter(A,B)) {
+                int outLen; 
+                BinOpItMode mode; 
+                Int64 [] retArr;
+                Int64 [] arrA = A.GetArrayForRead();
+                Int64[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size; 
+                    if (B.IsScalar) {
+                       
+                        return new  ILRetArray<Int64> (new  Int64 [1]{ saturateInt64 (A.GetValue(0)  - (double) B.GetValue(0))}, A.Size);
+                    } else if (B.IsEmpty) {
+                        return  ILRetArray<Int64>.empty(outDims); 
+                    } else {
+                        outLen = outDims.NumberOfElements; 
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< Int64 > (outLen);
+                            mode = BinOpItMode.SAN; 
+                        } else {
+                            mode = BinOpItMode.SAI; 
+                        }
+                    }
+                } else {
+                    outDims = A.Size; 
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return  ILRetArray<Int64>.empty(A.Size);  
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< Int64 > (outLen);
+                            mode = BinOpItMode.ASN; 
+                        } else {
+                            mode = BinOpItMode.ASI; 
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  subtractEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (A.TryGetStorage4InplaceOp(out retArr)) 
+                            mode  = BinOpItMode.AAIA; 
+                        else if (B.TryGetStorage4InplaceOp(out retArr)) 
+                            mode = BinOpItMode.AAIB; 
+                        else {
+                            retArr = ILMemoryPool.Pool.New< Int64 > (outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<Int64> retStorage = new ILDenseStorage<Int64>(retArr, outDims);
+                int i = 0, workerCount = 1; 
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    Int64* cp = (Int64*)range.Item5 + range.Item1;
+                    Int64 scalar;
+                    int j = range.Item2; 
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           Int64* bp = ((Int64*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                                cp[0] =  saturateInt64 (cp[0]  - (double) bp[0]);
+                                cp[1] =  saturateInt64 (cp[1]  - (double) bp[1]);
+                                cp[2] =  saturateInt64 (cp[2]  - (double) bp[2]);
+                                cp[3] =  saturateInt64 (cp[3]  - (double) bp[3]);
+                                cp[4] =  saturateInt64 (cp[4]  - (double) bp[4]);
+                                cp[5] =  saturateInt64 (cp[5]  - (double) bp[5]);
+                                cp[6] =  saturateInt64 (cp[6]  - (double) bp[6]);
+                                cp[7] =  saturateInt64 (cp[7]  - (double) bp[7]);
+                                cp[8] =  saturateInt64 (cp[8]  - (double) bp[8]);
+                                cp[9] =  saturateInt64 (cp[9]  - (double) bp[9]);
+                                cp[10] =  saturateInt64 (cp[10]  - (double) bp[10]);
+                                cp[11] =  saturateInt64 (cp[11]  - (double) bp[11]);
+                                cp[12] =  saturateInt64 (cp[12]  - (double) bp[12]);
+                                cp[13] =  saturateInt64 (cp[13]  - (double) bp[13]);
+                                cp[14] =  saturateInt64 (cp[14]  - (double) bp[14]);
+                                cp[15] =  saturateInt64 (cp[15]  - (double) bp[15]);
+                                cp[16] =  saturateInt64 (cp[16]  - (double) bp[16]);
+                                cp[17] =  saturateInt64 (cp[17]  - (double) bp[17]);
+                                cp[18] =  saturateInt64 (cp[18]  - (double) bp[18]);
+                                cp[19] =  saturateInt64 (cp[19]  - (double) bp[19]);
+                                cp[20] =  saturateInt64 (cp[20]  - (double) bp[20]);
+                                cp += 21; bp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt64 (*cp  - (double) *bp);
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           Int64* ap = ((Int64*)range.Item3 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt64 (ap[0]  - (double) cp[0]);
+                                cp[1] =  saturateInt64 (ap[1]  - (double) cp[1]);
+                                cp[2] =  saturateInt64 (ap[2]  - (double) cp[2]);
+                                cp[3] =  saturateInt64 (ap[3]  - (double) cp[3]);
+                                cp[4] =  saturateInt64 (ap[4]  - (double) cp[4]);
+                                cp[5] =  saturateInt64 (ap[5]  - (double) cp[5]);
+                                cp[6] =  saturateInt64 (ap[6]  - (double) cp[6]);
+                                cp[7] =  saturateInt64 (ap[7]  - (double) cp[7]);
+                                cp[8] =  saturateInt64 (ap[8]  - (double) cp[8]);
+                                cp[9] =  saturateInt64 (ap[9]  - (double) cp[9]);
+                                cp[10] =  saturateInt64 (ap[10]  - (double) cp[10]);
+                                cp[11] =  saturateInt64 (ap[11]  - (double) cp[11]);
+                                cp[12] =  saturateInt64 (ap[12]  - (double) cp[12]);
+                                cp[13] =  saturateInt64 (ap[13]  - (double) cp[13]);
+                                cp[14] =  saturateInt64 (ap[14]  - (double) cp[14]);
+                                cp[15] =  saturateInt64 (ap[15]  - (double) cp[15]);
+                                cp[16] =  saturateInt64 (ap[16]  - (double) cp[16]);
+                                cp[17] =  saturateInt64 (ap[17]  - (double) cp[17]);
+                                cp[18] =  saturateInt64 (ap[18]  - (double) cp[18]);
+                                cp[19] =  saturateInt64 (ap[19]  - (double) cp[19]);
+                                cp[20] =  saturateInt64 (ap[20]  - (double) cp[20]);
+                                ap += 21; cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt64 (*ap  - (double) *cp);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((Int64*)range.Item3 + range.Item1);
+                            bp = ((Int64*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt64 (ap[0]  - (double) bp[0]);
+                                cp[1] =  saturateInt64 (ap[1]  - (double) bp[1]);
+                                cp[2] =  saturateInt64 (ap[2]  - (double) bp[2]);
+                                cp[3] =  saturateInt64 (ap[3]  - (double) bp[3]);
+                                cp[4] =  saturateInt64 (ap[4]  - (double) bp[4]);
+                                cp[5] =  saturateInt64 (ap[5]  - (double) bp[5]);
+                                cp[6] =  saturateInt64 (ap[6]  - (double) bp[6]);
+                                cp[7] =  saturateInt64 (ap[7]  - (double) bp[7]);
+                                cp[8] =  saturateInt64 (ap[8]  - (double) bp[8]);
+                                cp[9] =  saturateInt64 (ap[9]  - (double) bp[9]);
+                                cp[10] =  saturateInt64 (ap[10]  - (double) bp[10]);
+                                cp[11] =  saturateInt64 (ap[11]  - (double) bp[11]);
+                                cp[12] =  saturateInt64 (ap[12]  - (double) bp[12]);
+                                cp[13] =  saturateInt64 (ap[13]  - (double) bp[13]);
+                                cp[14] =  saturateInt64 (ap[14]  - (double) bp[14]);
+                                cp[15] =  saturateInt64 (ap[15]  - (double) bp[15]);
+                                cp[16] =  saturateInt64 (ap[16]  - (double) bp[16]);
+                                cp[17] =  saturateInt64 (ap[17]  - (double) bp[17]);
+                                cp[18] =  saturateInt64 (ap[18]  - (double) bp[18]);
+                                cp[19] =  saturateInt64 (ap[19]  - (double) bp[19]);
+                                cp[20] =  saturateInt64 (ap[20]  - (double) bp[20]);
+                                ap+=21; bp+=21; cp+=21; j-=21;
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt64 (*ap  - (double) *bp);
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((Int64*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt64 (cp[0]  - (double) scalar);
+                                cp[1] =  saturateInt64 (cp[1]  - (double) scalar);
+                                cp[2] =  saturateInt64 (cp[2]  - (double) scalar);
+                                cp[3] =  saturateInt64 (cp[3]  - (double) scalar);
+                                cp[4] =  saturateInt64 (cp[4]  - (double) scalar);
+                                cp[5] =  saturateInt64 (cp[5]  - (double) scalar);
+                                cp[6] =  saturateInt64 (cp[6]  - (double) scalar);
+                                cp[7] =  saturateInt64 (cp[7]  - (double) scalar);
+                                cp[8] =  saturateInt64 (cp[8]  - (double) scalar);
+                                cp[9] =  saturateInt64 (cp[9]  - (double) scalar);
+                                cp[10] =  saturateInt64 (cp[10]  - (double) scalar);
+                                cp[11] =  saturateInt64 (cp[11]  - (double) scalar);
+                                cp[12] =  saturateInt64 (cp[12]  - (double) scalar);
+                                cp[13] =  saturateInt64 (cp[13]  - (double) scalar);
+                                cp[14] =  saturateInt64 (cp[14]  - (double) scalar);
+                                cp[15] =  saturateInt64 (cp[15]  - (double) scalar);
+                                cp[16] =  saturateInt64 (cp[16]  - (double) scalar);
+                                cp[17] =  saturateInt64 (cp[17]  - (double) scalar);
+                                cp[18] =  saturateInt64 (cp[18]  - (double) scalar);
+                                cp[19] =  saturateInt64 (cp[19]  - (double) scalar);
+                                cp[20] =  saturateInt64 (cp[20]  - (double) scalar);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt64 (*cp  - (double) scalar);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((Int64*)range.Item3 + range.Item1);
+                            scalar = *((Int64*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt64 (ap[0]  - (double) scalar);
+                                cp[1] =  saturateInt64 (ap[1]  - (double) scalar);
+                                cp[2] =  saturateInt64 (ap[2]  - (double) scalar);
+                                cp[3] =  saturateInt64 (ap[3]  - (double) scalar);
+                                cp[4] =  saturateInt64 (ap[4]  - (double) scalar);
+                                cp[5] =  saturateInt64 (ap[5]  - (double) scalar);
+                                cp[6] =  saturateInt64 (ap[6]  - (double) scalar);
+                                cp[7] =  saturateInt64 (ap[7]  - (double) scalar);
+                                cp[8] =  saturateInt64 (ap[8]  - (double) scalar);
+                                cp[9] =  saturateInt64 (ap[9]  - (double) scalar);
+                                cp[10] =  saturateInt64 (ap[10]  - (double) scalar);
+                                cp[11] =  saturateInt64 (ap[11]  - (double) scalar);
+                                cp[12] =  saturateInt64 (ap[12]  - (double) scalar);
+                                cp[13] =  saturateInt64 (ap[13]  - (double) scalar);
+                                cp[14] =  saturateInt64 (ap[14]  - (double) scalar);
+                                cp[15] =  saturateInt64 (ap[15]  - (double) scalar);
+                                cp[16] =  saturateInt64 (ap[16]  - (double) scalar);
+                                cp[17] =  saturateInt64 (ap[17]  - (double) scalar);
+                                cp[18] =  saturateInt64 (ap[18]  - (double) scalar);
+                                cp[19] =  saturateInt64 (ap[19]  - (double) scalar);
+                                cp[20] =  saturateInt64 (ap[20]  - (double) scalar);
+                                ap+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt64 (*ap  - (double) scalar);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((Int64*)range.Item3);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt64 (scalar  - (double) cp[0]);
+                                cp[1] =  saturateInt64 (scalar  - (double) cp[1]);
+                                cp[2] =  saturateInt64 (scalar  - (double) cp[2]);
+                                cp[3] =  saturateInt64 (scalar  - (double) cp[3]);
+                                cp[4] =  saturateInt64 (scalar  - (double) cp[4]);
+                                cp[5] =  saturateInt64 (scalar  - (double) cp[5]);
+                                cp[6] =  saturateInt64 (scalar  - (double) cp[6]);
+                                cp[7] =  saturateInt64 (scalar  - (double) cp[7]);
+                                cp[8] =  saturateInt64 (scalar  - (double) cp[8]);
+                                cp[9] =  saturateInt64 (scalar  - (double) cp[9]);
+                                cp[10] =  saturateInt64 (scalar  - (double) cp[10]);
+                                cp[11] =  saturateInt64 (scalar  - (double) cp[11]);
+                                cp[12] =  saturateInt64 (scalar  - (double) cp[12]);
+                                cp[13] =  saturateInt64 (scalar  - (double) cp[13]);
+                                cp[14] =  saturateInt64 (scalar  - (double) cp[14]);
+                                cp[15] =  saturateInt64 (scalar  - (double) cp[15]);
+                                cp[16] =  saturateInt64 (scalar  - (double) cp[16]);
+                                cp[17] =  saturateInt64 (scalar  - (double) cp[17]);
+                                cp[18] =  saturateInt64 (scalar  - (double) cp[18]);
+                                cp[19] =  saturateInt64 (scalar  - (double) cp[19]);
+                                cp[20] =  saturateInt64 (scalar  - (double) cp[20]);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt64 (scalar  - (double) *cp);
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((Int64*)range.Item3);
+                            bp = ((Int64*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt64 (scalar  - (double) bp[0]);
+                                cp[1] =  saturateInt64 (scalar  - (double) bp[1]);
+                                cp[2] =  saturateInt64 (scalar  - (double) bp[2]);
+                                cp[3] =  saturateInt64 (scalar  - (double) bp[3]);
+                                cp[4] =  saturateInt64 (scalar  - (double) bp[4]);
+                                cp[5] =  saturateInt64 (scalar  - (double) bp[5]);
+                                cp[6] =  saturateInt64 (scalar  - (double) bp[6]);
+                                cp[7] =  saturateInt64 (scalar  - (double) bp[7]);
+                                cp[8] =  saturateInt64 (scalar  - (double) bp[8]);
+                                cp[9] =  saturateInt64 (scalar  - (double) bp[9]);
+                                cp[10] =  saturateInt64 (scalar  - (double) bp[10]);
+                                cp[11] =  saturateInt64 (scalar  - (double) bp[11]);
+                                cp[12] =  saturateInt64 (scalar  - (double) bp[12]);
+                                cp[13] =  saturateInt64 (scalar  - (double) bp[13]);
+                                cp[14] =  saturateInt64 (scalar  - (double) bp[14]);
+                                cp[15] =  saturateInt64 (scalar  - (double) bp[15]);
+                                cp[16] =  saturateInt64 (scalar  - (double) bp[16]);
+                                cp[17] =  saturateInt64 (scalar  - (double) bp[17]);
+                                cp[18] =  saturateInt64 (scalar  - (double) bp[18]);
+                                cp[19] =  saturateInt64 (scalar  - (double) bp[19]);
+                                cp[20] =  saturateInt64 (scalar  - (double) bp[20]);
+                                bp+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt64 (scalar  - (double) *bp);
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work 
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                
+                fixed ( Int64* arrAP = arrA)
+                fixed ( Int64* arrBP = arrB)
+                fixed ( Int64* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range 
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new  ILRetArray< Int64>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<Int64>  subtractEx(ILInArray<Int64> A, ILInArray<Int64> B) {
+            //using (ILScope.Enter(A, B)) { we cannot start a new scope here, since this would prevent A and B to be used implace if applicable
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<Int64>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<Int64>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<Int64>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                dim = -(dim - 1);  // 0 -> 1, 1 -> 0
+                #endregion
+
+                #region parameter preparation
+               
+                Int64[] retArr;
+               
+                Int64[] arrA = A.GetArrayForRead();
+               
+                Int64[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int workItemMultiplierLenA;
+                int workItemMultiplierLenB;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<Int64>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    workItemMultiplierLenB = outDims[0]; 
+                    workItemMultiplierLenA = dim;  // 0 for column, 1 for row vector
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<Int64>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    workItemMultiplierLenB = dim;  // 0 for column, 1 for row vector
+                    workItemMultiplierLenA = outDims[0]; 
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one singleton dimension in either A or B");
+                }
+                int itLen = outDims[0]; // (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<Int64> retStorage = new ILDenseStorage<Int64>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    Int64* ap;
+                   
+                    Int64* bp;
+                   
+                    Int64* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            if (dim == 0) {
+                                bp = (Int64*)range.Item3;
+                                cp = (Int64*)range.Item4; 
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (Int64*)range.Item2;
+                                    int l = itLen; 
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt64 (ap[0]  - (double) bp[0]);
+                                        cp[1] =  saturateInt64 (ap[1]  - (double) bp[1]);
+                                        cp[2] =  saturateInt64 (ap[2]  - (double) bp[2]);
+                                        cp[3] =  saturateInt64 (ap[3]  - (double) bp[3]);
+                                        cp[4] =  saturateInt64 (ap[4]  - (double) bp[4]);
+                                        cp[5] =  saturateInt64 (ap[5]  - (double) bp[5]);
+                                        cp[6] =  saturateInt64 (ap[6]  - (double) bp[6]);
+                                        cp[7] =  saturateInt64 (ap[7]  - (double) bp[7]);
+                                        cp[8] =  saturateInt64 (ap[8]  - (double) bp[8]);
+                                        cp[9] =  saturateInt64 (ap[9]  - (double) bp[9]);
+                                        cp[10] =  saturateInt64 (ap[10]  - (double) bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =  saturateInt64 (*ap++  - (double) *bp++);
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                ap = (Int64*)range.Item2;
+                                bp = (Int64*)range.Item3;
+                                cp = (Int64*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   Int64 val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt64 (val  - (double) bp[0]);
+                                        cp[1] =  saturateInt64 (val  - (double) bp[1]);
+                                        cp[2] =  saturateInt64 (val  - (double) bp[2]);
+                                        cp[3] =  saturateInt64 (val  - (double) bp[3]);
+                                        cp[4] =  saturateInt64 (val  - (double) bp[4]);
+                                        cp[5] =  saturateInt64 (val  - (double) bp[5]);
+                                        cp[6] =  saturateInt64 (val  - (double) bp[6]);
+                                        cp[7] =  saturateInt64 (val  - (double) bp[7]);
+                                        cp[8] =  saturateInt64 (val  - (double) bp[8]);
+                                        cp[9] =  saturateInt64 (val  - (double) bp[9]);
+                                        cp[10] =  saturateInt64 (val  - (double) bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11; 
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =  saturateInt64 (val  - (double) *bp++);
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            if (dim == 0) {
+                                cp = (Int64*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (Int64*)range.Item2;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt64 (ap[0]  - (double) cp[0]);
+                                        cp[1] =  saturateInt64 (ap[1]  - (double) cp[1]);
+                                        cp[2] =  saturateInt64 (ap[2]  - (double) cp[2]);
+                                        cp[3] =  saturateInt64 (ap[3]  - (double) cp[3]);
+                                        cp[4] =  saturateInt64 (ap[4]  - (double) cp[4]);
+                                        cp[5] =  saturateInt64 (ap[5]  - (double) cp[5]);
+                                        cp[6] =  saturateInt64 (ap[6]  - (double) cp[6]);
+                                        cp[7] =  saturateInt64 (ap[7]  - (double) cp[7]);
+                                        cp[8] =  saturateInt64 (ap[8]  - (double) cp[8]);
+                                        cp[9] =  saturateInt64 (ap[9]  - (double) cp[9]);
+                                        cp[10] =  saturateInt64 (ap[10]  - (double) cp[10]);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt64 (*ap++  - (double) *cp);
+                                        cp++; 
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                cp = (Int64*)range.Item4;
+                                ap = (Int64*)range.Item2;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    Int64 val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt64 (val  - (double) cp[0]);
+                                        cp[1] =  saturateInt64 (val  - (double) cp[1]);
+                                        cp[2] =  saturateInt64 (val  - (double) cp[2]);
+                                        cp[3] =  saturateInt64 (val  - (double) cp[3]);
+                                        cp[4] =  saturateInt64 (val  - (double) cp[4]);
+                                        cp[5] =  saturateInt64 (val  - (double) cp[5]);
+                                        cp[6] =  saturateInt64 (val  - (double) cp[6]);
+                                        cp[7] =  saturateInt64 (val  - (double) cp[7]);
+                                        cp[8] =  saturateInt64 (val  - (double) cp[8]);
+                                        cp[9] =  saturateInt64 (val  - (double) cp[9]);
+                                        cp[10] =  saturateInt64 (val  - (double) cp[10]);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt64 (val  - (double) *cp);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            if (dim == 0) {
+                                ap = (Int64*)range.Item2;
+                                cp = (Int64*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (Int64*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt64 (ap[0]  - (double) bp[0]);
+                                        cp[1] =  saturateInt64 (ap[1]  - (double) bp[1]);
+                                        cp[2] =  saturateInt64 (ap[2]  - (double) bp[2]);
+                                        cp[3] =  saturateInt64 (ap[3]  - (double) bp[3]);
+                                        cp[4] =  saturateInt64 (ap[4]  - (double) bp[4]);
+                                        cp[5] =  saturateInt64 (ap[5]  - (double) bp[5]);
+                                        cp[6] =  saturateInt64 (ap[6]  - (double) bp[6]);
+                                        cp[7] =  saturateInt64 (ap[7]  - (double) bp[7]);
+                                        cp[8] =  saturateInt64 (ap[8]  - (double) bp[8]);
+                                        cp[9] =  saturateInt64 (ap[9]  - (double) bp[9]);
+                                        cp[10] =  saturateInt64 (ap[10]  - (double) bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt64 (*ap  - (double) *bp);
+                                        ap++;
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                ap = (Int64*)range.Item2;
+                                bp = (Int64*)range.Item3;
+                                cp = (Int64*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   Int64 val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt64 (ap[0]  - (double) val);
+                                        cp[1] =  saturateInt64 (ap[1]  - (double) val);
+                                        cp[2] =  saturateInt64 (ap[2]  - (double) val);
+                                        cp[3] =  saturateInt64 (ap[3]  - (double) val);
+                                        cp[4] =  saturateInt64 (ap[4]  - (double) val);
+                                        cp[5] =  saturateInt64 (ap[5]  - (double) val);
+                                        cp[6] =  saturateInt64 (ap[6]  - (double) val);
+                                        cp[7] =  saturateInt64 (ap[7]  - (double) val);
+                                        cp[8] =  saturateInt64 (ap[8]  - (double) val);
+                                        cp[9] =  saturateInt64 (ap[9]  - (double) val);
+                                        cp[10] =  saturateInt64 (ap[10]  - (double) val);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt64 (*ap  - (double) val);
+                                        ap++;
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            if (dim == 0) {
+                                cp = (Int64*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (Int64*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt64 (cp[0]  - (double) bp[0]);
+                                        cp[1] =  saturateInt64 (cp[1]  - (double) bp[1]);
+                                        cp[2] =  saturateInt64 (cp[2]  - (double) bp[2]);
+                                        cp[3] =  saturateInt64 (cp[3]  - (double) bp[3]);
+                                        cp[4] =  saturateInt64 (cp[4]  - (double) bp[4]);
+                                        cp[5] =  saturateInt64 (cp[5]  - (double) bp[5]);
+                                        cp[6] =  saturateInt64 (cp[6]  - (double) bp[6]);
+                                        cp[7] =  saturateInt64 (cp[7]  - (double) bp[7]);
+                                        cp[8] =  saturateInt64 (cp[8]  - (double) bp[8]);
+                                        cp[9] =  saturateInt64 (cp[9]  - (double) bp[9]);
+                                        cp[10] =  saturateInt64 (cp[10]  - (double) bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt64 (*cp  - (double) *bp);
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                bp = (Int64*)range.Item3;
+                                cp = (Int64*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    Int64 val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt64 (cp[0]  - (double) val);
+                                        cp[1] =  saturateInt64 (cp[1]  - (double) val);
+                                        cp[2] =  saturateInt64 (cp[2]  - (double) val);
+                                        cp[3] =  saturateInt64 (cp[3]  - (double) val);
+                                        cp[4] =  saturateInt64 (cp[4]  - (double) val);
+                                        cp[5] =  saturateInt64 (cp[5]  - (double) val);
+                                        cp[6] =  saturateInt64 (cp[6]  - (double) val);
+                                        cp[7] =  saturateInt64 (cp[7]  - (double) val);
+                                        cp[8] =  saturateInt64 (cp[8]  - (double) val);
+                                        cp[9] =  saturateInt64 (cp[9]  - (double) val);
+                                        cp[10] =  saturateInt64 (cp[10]  - (double) val);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l --> 0) {
+                                        *cp =  saturateInt64 (*cp  - (double) val);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outDims.NumberOfElements >= Settings.s_minParallelElement1Count
+                    && outDims[1] > 1) {
+                        if (outDims[1] > workItemCount) {
+                        workItemLength = outDims[1] / workItemCount;
+                    } else {
+                        workItemLength = outDims[1] / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outDims[1];
+                    workItemCount = 1;
+                }
+
+                fixed ( Int64* arrAP = arrA)
+                fixed ( Int64* arrBP = arrB)
+                fixed ( Int64* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, IntPtr, IntPtr, IntPtr> range = new Tuple<int, IntPtr, IntPtr, IntPtr>
+                               (workItemLength
+                               , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                               , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                               , (IntPtr)(retArrP + i * outDims[0] * workItemLength)); 
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, IntPtr, IntPtr, IntPtr>
+                                (outDims[1] - i * workItemLength
+                                , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                                , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                                , (IntPtr)(retArrP + i * outDims[0] * workItemLength)));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<Int64>(retStorage);
+            //}  // no scopes here! it disables implace operations
+        }
+
+        /// <summary>Subtract arrays elementwise</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>New array with result of subtraction</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<Int32>  subtract(ILInArray<Int32> A, ILInArray<Int32> B) {
+            using (ILScope.Enter(A,B)) {
+                int outLen; 
+                BinOpItMode mode; 
+                Int32 [] retArr;
+                Int32 [] arrA = A.GetArrayForRead();
+                Int32[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size; 
+                    if (B.IsScalar) {
+                       
+                        return new  ILRetArray<Int32> (new  Int32 [1]{ saturateInt32 (A.GetValue(0)  - (double) B.GetValue(0))}, A.Size);
+                    } else if (B.IsEmpty) {
+                        return  ILRetArray<Int32>.empty(outDims); 
+                    } else {
+                        outLen = outDims.NumberOfElements; 
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< Int32 > (outLen);
+                            mode = BinOpItMode.SAN; 
+                        } else {
+                            mode = BinOpItMode.SAI; 
+                        }
+                    }
+                } else {
+                    outDims = A.Size; 
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return  ILRetArray<Int32>.empty(A.Size);  
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< Int32 > (outLen);
+                            mode = BinOpItMode.ASN; 
+                        } else {
+                            mode = BinOpItMode.ASI; 
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  subtractEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (A.TryGetStorage4InplaceOp(out retArr)) 
+                            mode  = BinOpItMode.AAIA; 
+                        else if (B.TryGetStorage4InplaceOp(out retArr)) 
+                            mode = BinOpItMode.AAIB; 
+                        else {
+                            retArr = ILMemoryPool.Pool.New< Int32 > (outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<Int32> retStorage = new ILDenseStorage<Int32>(retArr, outDims);
+                int i = 0, workerCount = 1; 
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    Int32* cp = (Int32*)range.Item5 + range.Item1;
+                    Int32 scalar;
+                    int j = range.Item2; 
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           Int32* bp = ((Int32*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                                cp[0] =  saturateInt32 (cp[0]  - (double) bp[0]);
+                                cp[1] =  saturateInt32 (cp[1]  - (double) bp[1]);
+                                cp[2] =  saturateInt32 (cp[2]  - (double) bp[2]);
+                                cp[3] =  saturateInt32 (cp[3]  - (double) bp[3]);
+                                cp[4] =  saturateInt32 (cp[4]  - (double) bp[4]);
+                                cp[5] =  saturateInt32 (cp[5]  - (double) bp[5]);
+                                cp[6] =  saturateInt32 (cp[6]  - (double) bp[6]);
+                                cp[7] =  saturateInt32 (cp[7]  - (double) bp[7]);
+                                cp[8] =  saturateInt32 (cp[8]  - (double) bp[8]);
+                                cp[9] =  saturateInt32 (cp[9]  - (double) bp[9]);
+                                cp[10] =  saturateInt32 (cp[10]  - (double) bp[10]);
+                                cp[11] =  saturateInt32 (cp[11]  - (double) bp[11]);
+                                cp[12] =  saturateInt32 (cp[12]  - (double) bp[12]);
+                                cp[13] =  saturateInt32 (cp[13]  - (double) bp[13]);
+                                cp[14] =  saturateInt32 (cp[14]  - (double) bp[14]);
+                                cp[15] =  saturateInt32 (cp[15]  - (double) bp[15]);
+                                cp[16] =  saturateInt32 (cp[16]  - (double) bp[16]);
+                                cp[17] =  saturateInt32 (cp[17]  - (double) bp[17]);
+                                cp[18] =  saturateInt32 (cp[18]  - (double) bp[18]);
+                                cp[19] =  saturateInt32 (cp[19]  - (double) bp[19]);
+                                cp[20] =  saturateInt32 (cp[20]  - (double) bp[20]);
+                                cp += 21; bp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt32 (*cp  - (double) *bp);
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           Int32* ap = ((Int32*)range.Item3 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt32 (ap[0]  - (double) cp[0]);
+                                cp[1] =  saturateInt32 (ap[1]  - (double) cp[1]);
+                                cp[2] =  saturateInt32 (ap[2]  - (double) cp[2]);
+                                cp[3] =  saturateInt32 (ap[3]  - (double) cp[3]);
+                                cp[4] =  saturateInt32 (ap[4]  - (double) cp[4]);
+                                cp[5] =  saturateInt32 (ap[5]  - (double) cp[5]);
+                                cp[6] =  saturateInt32 (ap[6]  - (double) cp[6]);
+                                cp[7] =  saturateInt32 (ap[7]  - (double) cp[7]);
+                                cp[8] =  saturateInt32 (ap[8]  - (double) cp[8]);
+                                cp[9] =  saturateInt32 (ap[9]  - (double) cp[9]);
+                                cp[10] =  saturateInt32 (ap[10]  - (double) cp[10]);
+                                cp[11] =  saturateInt32 (ap[11]  - (double) cp[11]);
+                                cp[12] =  saturateInt32 (ap[12]  - (double) cp[12]);
+                                cp[13] =  saturateInt32 (ap[13]  - (double) cp[13]);
+                                cp[14] =  saturateInt32 (ap[14]  - (double) cp[14]);
+                                cp[15] =  saturateInt32 (ap[15]  - (double) cp[15]);
+                                cp[16] =  saturateInt32 (ap[16]  - (double) cp[16]);
+                                cp[17] =  saturateInt32 (ap[17]  - (double) cp[17]);
+                                cp[18] =  saturateInt32 (ap[18]  - (double) cp[18]);
+                                cp[19] =  saturateInt32 (ap[19]  - (double) cp[19]);
+                                cp[20] =  saturateInt32 (ap[20]  - (double) cp[20]);
+                                ap += 21; cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt32 (*ap  - (double) *cp);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((Int32*)range.Item3 + range.Item1);
+                            bp = ((Int32*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt32 (ap[0]  - (double) bp[0]);
+                                cp[1] =  saturateInt32 (ap[1]  - (double) bp[1]);
+                                cp[2] =  saturateInt32 (ap[2]  - (double) bp[2]);
+                                cp[3] =  saturateInt32 (ap[3]  - (double) bp[3]);
+                                cp[4] =  saturateInt32 (ap[4]  - (double) bp[4]);
+                                cp[5] =  saturateInt32 (ap[5]  - (double) bp[5]);
+                                cp[6] =  saturateInt32 (ap[6]  - (double) bp[6]);
+                                cp[7] =  saturateInt32 (ap[7]  - (double) bp[7]);
+                                cp[8] =  saturateInt32 (ap[8]  - (double) bp[8]);
+                                cp[9] =  saturateInt32 (ap[9]  - (double) bp[9]);
+                                cp[10] =  saturateInt32 (ap[10]  - (double) bp[10]);
+                                cp[11] =  saturateInt32 (ap[11]  - (double) bp[11]);
+                                cp[12] =  saturateInt32 (ap[12]  - (double) bp[12]);
+                                cp[13] =  saturateInt32 (ap[13]  - (double) bp[13]);
+                                cp[14] =  saturateInt32 (ap[14]  - (double) bp[14]);
+                                cp[15] =  saturateInt32 (ap[15]  - (double) bp[15]);
+                                cp[16] =  saturateInt32 (ap[16]  - (double) bp[16]);
+                                cp[17] =  saturateInt32 (ap[17]  - (double) bp[17]);
+                                cp[18] =  saturateInt32 (ap[18]  - (double) bp[18]);
+                                cp[19] =  saturateInt32 (ap[19]  - (double) bp[19]);
+                                cp[20] =  saturateInt32 (ap[20]  - (double) bp[20]);
+                                ap+=21; bp+=21; cp+=21; j-=21;
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt32 (*ap  - (double) *bp);
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((Int32*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt32 (cp[0]  - (double) scalar);
+                                cp[1] =  saturateInt32 (cp[1]  - (double) scalar);
+                                cp[2] =  saturateInt32 (cp[2]  - (double) scalar);
+                                cp[3] =  saturateInt32 (cp[3]  - (double) scalar);
+                                cp[4] =  saturateInt32 (cp[4]  - (double) scalar);
+                                cp[5] =  saturateInt32 (cp[5]  - (double) scalar);
+                                cp[6] =  saturateInt32 (cp[6]  - (double) scalar);
+                                cp[7] =  saturateInt32 (cp[7]  - (double) scalar);
+                                cp[8] =  saturateInt32 (cp[8]  - (double) scalar);
+                                cp[9] =  saturateInt32 (cp[9]  - (double) scalar);
+                                cp[10] =  saturateInt32 (cp[10]  - (double) scalar);
+                                cp[11] =  saturateInt32 (cp[11]  - (double) scalar);
+                                cp[12] =  saturateInt32 (cp[12]  - (double) scalar);
+                                cp[13] =  saturateInt32 (cp[13]  - (double) scalar);
+                                cp[14] =  saturateInt32 (cp[14]  - (double) scalar);
+                                cp[15] =  saturateInt32 (cp[15]  - (double) scalar);
+                                cp[16] =  saturateInt32 (cp[16]  - (double) scalar);
+                                cp[17] =  saturateInt32 (cp[17]  - (double) scalar);
+                                cp[18] =  saturateInt32 (cp[18]  - (double) scalar);
+                                cp[19] =  saturateInt32 (cp[19]  - (double) scalar);
+                                cp[20] =  saturateInt32 (cp[20]  - (double) scalar);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt32 (*cp  - (double) scalar);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((Int32*)range.Item3 + range.Item1);
+                            scalar = *((Int32*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt32 (ap[0]  - (double) scalar);
+                                cp[1] =  saturateInt32 (ap[1]  - (double) scalar);
+                                cp[2] =  saturateInt32 (ap[2]  - (double) scalar);
+                                cp[3] =  saturateInt32 (ap[3]  - (double) scalar);
+                                cp[4] =  saturateInt32 (ap[4]  - (double) scalar);
+                                cp[5] =  saturateInt32 (ap[5]  - (double) scalar);
+                                cp[6] =  saturateInt32 (ap[6]  - (double) scalar);
+                                cp[7] =  saturateInt32 (ap[7]  - (double) scalar);
+                                cp[8] =  saturateInt32 (ap[8]  - (double) scalar);
+                                cp[9] =  saturateInt32 (ap[9]  - (double) scalar);
+                                cp[10] =  saturateInt32 (ap[10]  - (double) scalar);
+                                cp[11] =  saturateInt32 (ap[11]  - (double) scalar);
+                                cp[12] =  saturateInt32 (ap[12]  - (double) scalar);
+                                cp[13] =  saturateInt32 (ap[13]  - (double) scalar);
+                                cp[14] =  saturateInt32 (ap[14]  - (double) scalar);
+                                cp[15] =  saturateInt32 (ap[15]  - (double) scalar);
+                                cp[16] =  saturateInt32 (ap[16]  - (double) scalar);
+                                cp[17] =  saturateInt32 (ap[17]  - (double) scalar);
+                                cp[18] =  saturateInt32 (ap[18]  - (double) scalar);
+                                cp[19] =  saturateInt32 (ap[19]  - (double) scalar);
+                                cp[20] =  saturateInt32 (ap[20]  - (double) scalar);
+                                ap+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt32 (*ap  - (double) scalar);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((Int32*)range.Item3);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt32 (scalar  - (double) cp[0]);
+                                cp[1] =  saturateInt32 (scalar  - (double) cp[1]);
+                                cp[2] =  saturateInt32 (scalar  - (double) cp[2]);
+                                cp[3] =  saturateInt32 (scalar  - (double) cp[3]);
+                                cp[4] =  saturateInt32 (scalar  - (double) cp[4]);
+                                cp[5] =  saturateInt32 (scalar  - (double) cp[5]);
+                                cp[6] =  saturateInt32 (scalar  - (double) cp[6]);
+                                cp[7] =  saturateInt32 (scalar  - (double) cp[7]);
+                                cp[8] =  saturateInt32 (scalar  - (double) cp[8]);
+                                cp[9] =  saturateInt32 (scalar  - (double) cp[9]);
+                                cp[10] =  saturateInt32 (scalar  - (double) cp[10]);
+                                cp[11] =  saturateInt32 (scalar  - (double) cp[11]);
+                                cp[12] =  saturateInt32 (scalar  - (double) cp[12]);
+                                cp[13] =  saturateInt32 (scalar  - (double) cp[13]);
+                                cp[14] =  saturateInt32 (scalar  - (double) cp[14]);
+                                cp[15] =  saturateInt32 (scalar  - (double) cp[15]);
+                                cp[16] =  saturateInt32 (scalar  - (double) cp[16]);
+                                cp[17] =  saturateInt32 (scalar  - (double) cp[17]);
+                                cp[18] =  saturateInt32 (scalar  - (double) cp[18]);
+                                cp[19] =  saturateInt32 (scalar  - (double) cp[19]);
+                                cp[20] =  saturateInt32 (scalar  - (double) cp[20]);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt32 (scalar  - (double) *cp);
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((Int32*)range.Item3);
+                            bp = ((Int32*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt32 (scalar  - (double) bp[0]);
+                                cp[1] =  saturateInt32 (scalar  - (double) bp[1]);
+                                cp[2] =  saturateInt32 (scalar  - (double) bp[2]);
+                                cp[3] =  saturateInt32 (scalar  - (double) bp[3]);
+                                cp[4] =  saturateInt32 (scalar  - (double) bp[4]);
+                                cp[5] =  saturateInt32 (scalar  - (double) bp[5]);
+                                cp[6] =  saturateInt32 (scalar  - (double) bp[6]);
+                                cp[7] =  saturateInt32 (scalar  - (double) bp[7]);
+                                cp[8] =  saturateInt32 (scalar  - (double) bp[8]);
+                                cp[9] =  saturateInt32 (scalar  - (double) bp[9]);
+                                cp[10] =  saturateInt32 (scalar  - (double) bp[10]);
+                                cp[11] =  saturateInt32 (scalar  - (double) bp[11]);
+                                cp[12] =  saturateInt32 (scalar  - (double) bp[12]);
+                                cp[13] =  saturateInt32 (scalar  - (double) bp[13]);
+                                cp[14] =  saturateInt32 (scalar  - (double) bp[14]);
+                                cp[15] =  saturateInt32 (scalar  - (double) bp[15]);
+                                cp[16] =  saturateInt32 (scalar  - (double) bp[16]);
+                                cp[17] =  saturateInt32 (scalar  - (double) bp[17]);
+                                cp[18] =  saturateInt32 (scalar  - (double) bp[18]);
+                                cp[19] =  saturateInt32 (scalar  - (double) bp[19]);
+                                cp[20] =  saturateInt32 (scalar  - (double) bp[20]);
+                                bp+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt32 (scalar  - (double) *bp);
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work 
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                
+                fixed ( Int32* arrAP = arrA)
+                fixed ( Int32* arrBP = arrB)
+                fixed ( Int32* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range 
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new  ILRetArray< Int32>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<Int32>  subtractEx(ILInArray<Int32> A, ILInArray<Int32> B) {
+            //using (ILScope.Enter(A, B)) { we cannot start a new scope here, since this would prevent A and B to be used implace if applicable
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<Int32>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<Int32>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<Int32>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                dim = -(dim - 1);  // 0 -> 1, 1 -> 0
+                #endregion
+
+                #region parameter preparation
+               
+                Int32[] retArr;
+               
+                Int32[] arrA = A.GetArrayForRead();
+               
+                Int32[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int workItemMultiplierLenA;
+                int workItemMultiplierLenB;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<Int32>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    workItemMultiplierLenB = outDims[0]; 
+                    workItemMultiplierLenA = dim;  // 0 for column, 1 for row vector
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<Int32>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    workItemMultiplierLenB = dim;  // 0 for column, 1 for row vector
+                    workItemMultiplierLenA = outDims[0]; 
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one singleton dimension in either A or B");
+                }
+                int itLen = outDims[0]; // (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<Int32> retStorage = new ILDenseStorage<Int32>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    Int32* ap;
+                   
+                    Int32* bp;
+                   
+                    Int32* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            if (dim == 0) {
+                                bp = (Int32*)range.Item3;
+                                cp = (Int32*)range.Item4; 
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (Int32*)range.Item2;
+                                    int l = itLen; 
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt32 (ap[0]  - (double) bp[0]);
+                                        cp[1] =  saturateInt32 (ap[1]  - (double) bp[1]);
+                                        cp[2] =  saturateInt32 (ap[2]  - (double) bp[2]);
+                                        cp[3] =  saturateInt32 (ap[3]  - (double) bp[3]);
+                                        cp[4] =  saturateInt32 (ap[4]  - (double) bp[4]);
+                                        cp[5] =  saturateInt32 (ap[5]  - (double) bp[5]);
+                                        cp[6] =  saturateInt32 (ap[6]  - (double) bp[6]);
+                                        cp[7] =  saturateInt32 (ap[7]  - (double) bp[7]);
+                                        cp[8] =  saturateInt32 (ap[8]  - (double) bp[8]);
+                                        cp[9] =  saturateInt32 (ap[9]  - (double) bp[9]);
+                                        cp[10] =  saturateInt32 (ap[10]  - (double) bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =  saturateInt32 (*ap++  - (double) *bp++);
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                ap = (Int32*)range.Item2;
+                                bp = (Int32*)range.Item3;
+                                cp = (Int32*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   Int32 val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt32 (val  - (double) bp[0]);
+                                        cp[1] =  saturateInt32 (val  - (double) bp[1]);
+                                        cp[2] =  saturateInt32 (val  - (double) bp[2]);
+                                        cp[3] =  saturateInt32 (val  - (double) bp[3]);
+                                        cp[4] =  saturateInt32 (val  - (double) bp[4]);
+                                        cp[5] =  saturateInt32 (val  - (double) bp[5]);
+                                        cp[6] =  saturateInt32 (val  - (double) bp[6]);
+                                        cp[7] =  saturateInt32 (val  - (double) bp[7]);
+                                        cp[8] =  saturateInt32 (val  - (double) bp[8]);
+                                        cp[9] =  saturateInt32 (val  - (double) bp[9]);
+                                        cp[10] =  saturateInt32 (val  - (double) bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11; 
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =  saturateInt32 (val  - (double) *bp++);
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            if (dim == 0) {
+                                cp = (Int32*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (Int32*)range.Item2;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt32 (ap[0]  - (double) cp[0]);
+                                        cp[1] =  saturateInt32 (ap[1]  - (double) cp[1]);
+                                        cp[2] =  saturateInt32 (ap[2]  - (double) cp[2]);
+                                        cp[3] =  saturateInt32 (ap[3]  - (double) cp[3]);
+                                        cp[4] =  saturateInt32 (ap[4]  - (double) cp[4]);
+                                        cp[5] =  saturateInt32 (ap[5]  - (double) cp[5]);
+                                        cp[6] =  saturateInt32 (ap[6]  - (double) cp[6]);
+                                        cp[7] =  saturateInt32 (ap[7]  - (double) cp[7]);
+                                        cp[8] =  saturateInt32 (ap[8]  - (double) cp[8]);
+                                        cp[9] =  saturateInt32 (ap[9]  - (double) cp[9]);
+                                        cp[10] =  saturateInt32 (ap[10]  - (double) cp[10]);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt32 (*ap++  - (double) *cp);
+                                        cp++; 
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                cp = (Int32*)range.Item4;
+                                ap = (Int32*)range.Item2;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    Int32 val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt32 (val  - (double) cp[0]);
+                                        cp[1] =  saturateInt32 (val  - (double) cp[1]);
+                                        cp[2] =  saturateInt32 (val  - (double) cp[2]);
+                                        cp[3] =  saturateInt32 (val  - (double) cp[3]);
+                                        cp[4] =  saturateInt32 (val  - (double) cp[4]);
+                                        cp[5] =  saturateInt32 (val  - (double) cp[5]);
+                                        cp[6] =  saturateInt32 (val  - (double) cp[6]);
+                                        cp[7] =  saturateInt32 (val  - (double) cp[7]);
+                                        cp[8] =  saturateInt32 (val  - (double) cp[8]);
+                                        cp[9] =  saturateInt32 (val  - (double) cp[9]);
+                                        cp[10] =  saturateInt32 (val  - (double) cp[10]);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt32 (val  - (double) *cp);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            if (dim == 0) {
+                                ap = (Int32*)range.Item2;
+                                cp = (Int32*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (Int32*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt32 (ap[0]  - (double) bp[0]);
+                                        cp[1] =  saturateInt32 (ap[1]  - (double) bp[1]);
+                                        cp[2] =  saturateInt32 (ap[2]  - (double) bp[2]);
+                                        cp[3] =  saturateInt32 (ap[3]  - (double) bp[3]);
+                                        cp[4] =  saturateInt32 (ap[4]  - (double) bp[4]);
+                                        cp[5] =  saturateInt32 (ap[5]  - (double) bp[5]);
+                                        cp[6] =  saturateInt32 (ap[6]  - (double) bp[6]);
+                                        cp[7] =  saturateInt32 (ap[7]  - (double) bp[7]);
+                                        cp[8] =  saturateInt32 (ap[8]  - (double) bp[8]);
+                                        cp[9] =  saturateInt32 (ap[9]  - (double) bp[9]);
+                                        cp[10] =  saturateInt32 (ap[10]  - (double) bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt32 (*ap  - (double) *bp);
+                                        ap++;
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                ap = (Int32*)range.Item2;
+                                bp = (Int32*)range.Item3;
+                                cp = (Int32*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   Int32 val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt32 (ap[0]  - (double) val);
+                                        cp[1] =  saturateInt32 (ap[1]  - (double) val);
+                                        cp[2] =  saturateInt32 (ap[2]  - (double) val);
+                                        cp[3] =  saturateInt32 (ap[3]  - (double) val);
+                                        cp[4] =  saturateInt32 (ap[4]  - (double) val);
+                                        cp[5] =  saturateInt32 (ap[5]  - (double) val);
+                                        cp[6] =  saturateInt32 (ap[6]  - (double) val);
+                                        cp[7] =  saturateInt32 (ap[7]  - (double) val);
+                                        cp[8] =  saturateInt32 (ap[8]  - (double) val);
+                                        cp[9] =  saturateInt32 (ap[9]  - (double) val);
+                                        cp[10] =  saturateInt32 (ap[10]  - (double) val);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt32 (*ap  - (double) val);
+                                        ap++;
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            if (dim == 0) {
+                                cp = (Int32*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (Int32*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt32 (cp[0]  - (double) bp[0]);
+                                        cp[1] =  saturateInt32 (cp[1]  - (double) bp[1]);
+                                        cp[2] =  saturateInt32 (cp[2]  - (double) bp[2]);
+                                        cp[3] =  saturateInt32 (cp[3]  - (double) bp[3]);
+                                        cp[4] =  saturateInt32 (cp[4]  - (double) bp[4]);
+                                        cp[5] =  saturateInt32 (cp[5]  - (double) bp[5]);
+                                        cp[6] =  saturateInt32 (cp[6]  - (double) bp[6]);
+                                        cp[7] =  saturateInt32 (cp[7]  - (double) bp[7]);
+                                        cp[8] =  saturateInt32 (cp[8]  - (double) bp[8]);
+                                        cp[9] =  saturateInt32 (cp[9]  - (double) bp[9]);
+                                        cp[10] =  saturateInt32 (cp[10]  - (double) bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt32 (*cp  - (double) *bp);
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                bp = (Int32*)range.Item3;
+                                cp = (Int32*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    Int32 val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt32 (cp[0]  - (double) val);
+                                        cp[1] =  saturateInt32 (cp[1]  - (double) val);
+                                        cp[2] =  saturateInt32 (cp[2]  - (double) val);
+                                        cp[3] =  saturateInt32 (cp[3]  - (double) val);
+                                        cp[4] =  saturateInt32 (cp[4]  - (double) val);
+                                        cp[5] =  saturateInt32 (cp[5]  - (double) val);
+                                        cp[6] =  saturateInt32 (cp[6]  - (double) val);
+                                        cp[7] =  saturateInt32 (cp[7]  - (double) val);
+                                        cp[8] =  saturateInt32 (cp[8]  - (double) val);
+                                        cp[9] =  saturateInt32 (cp[9]  - (double) val);
+                                        cp[10] =  saturateInt32 (cp[10]  - (double) val);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l --> 0) {
+                                        *cp =  saturateInt32 (*cp  - (double) val);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outDims.NumberOfElements >= Settings.s_minParallelElement1Count
+                    && outDims[1] > 1) {
+                        if (outDims[1] > workItemCount) {
+                        workItemLength = outDims[1] / workItemCount;
+                    } else {
+                        workItemLength = outDims[1] / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outDims[1];
+                    workItemCount = 1;
+                }
+
+                fixed ( Int32* arrAP = arrA)
+                fixed ( Int32* arrBP = arrB)
+                fixed ( Int32* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, IntPtr, IntPtr, IntPtr> range = new Tuple<int, IntPtr, IntPtr, IntPtr>
+                               (workItemLength
+                               , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                               , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                               , (IntPtr)(retArrP + i * outDims[0] * workItemLength)); 
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, IntPtr, IntPtr, IntPtr>
+                                (outDims[1] - i * workItemLength
+                                , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                                , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                                , (IntPtr)(retArrP + i * outDims[0] * workItemLength)));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<Int32>(retStorage);
+            //}  // no scopes here! it disables implace operations
+        }
+
+        /// <summary>Subtract arrays elementwise</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>New array with result of subtraction</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<float>  subtract(ILInArray<float> A, ILInArray<float> B) {
+            using (ILScope.Enter(A,B)) {
+                int outLen; 
+                BinOpItMode mode; 
+                float [] retArr;
+                float [] arrA = A.GetArrayForRead();
+                float[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size; 
+                    if (B.IsScalar) {
+                       
+                        return new  ILRetArray<float> (new  float [1]{  (A.GetValue(0)  - B.GetValue(0))}, A.Size);
+                    } else if (B.IsEmpty) {
+                        return  ILRetArray<float>.empty(outDims); 
+                    } else {
+                        outLen = outDims.NumberOfElements; 
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< float > (outLen);
+                            mode = BinOpItMode.SAN; 
+                        } else {
+                            mode = BinOpItMode.SAI; 
+                        }
+                    }
+                } else {
+                    outDims = A.Size; 
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return  ILRetArray<float>.empty(A.Size);  
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< float > (outLen);
+                            mode = BinOpItMode.ASN; 
+                        } else {
+                            mode = BinOpItMode.ASI; 
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  subtractEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (A.TryGetStorage4InplaceOp(out retArr)) 
+                            mode  = BinOpItMode.AAIA; 
+                        else if (B.TryGetStorage4InplaceOp(out retArr)) 
+                            mode = BinOpItMode.AAIB; 
+                        else {
+                            retArr = ILMemoryPool.Pool.New< float > (outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<float> retStorage = new ILDenseStorage<float>(retArr, outDims);
+                int i = 0, workerCount = 1; 
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    float* cp = (float*)range.Item5 + range.Item1;
+                    float scalar;
+                    int j = range.Item2; 
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           float* bp = ((float*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                                cp[0] =   (cp[0]  - bp[0]);
+                                cp[1] =   (cp[1]  - bp[1]);
+                                cp[2] =   (cp[2]  - bp[2]);
+                                cp[3] =   (cp[3]  - bp[3]);
+                                cp[4] =   (cp[4]  - bp[4]);
+                                cp[5] =   (cp[5]  - bp[5]);
+                                cp[6] =   (cp[6]  - bp[6]);
+                                cp[7] =   (cp[7]  - bp[7]);
+                                cp[8] =   (cp[8]  - bp[8]);
+                                cp[9] =   (cp[9]  - bp[9]);
+                                cp[10] =   (cp[10]  - bp[10]);
+                                cp[11] =   (cp[11]  - bp[11]);
+                                cp[12] =   (cp[12]  - bp[12]);
+                                cp[13] =   (cp[13]  - bp[13]);
+                                cp[14] =   (cp[14]  - bp[14]);
+                                cp[15] =   (cp[15]  - bp[15]);
+                                cp[16] =   (cp[16]  - bp[16]);
+                                cp[17] =   (cp[17]  - bp[17]);
+                                cp[18] =   (cp[18]  - bp[18]);
+                                cp[19] =   (cp[19]  - bp[19]);
+                                cp[20] =   (cp[20]  - bp[20]);
+                                cp += 21; bp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*cp  - *bp);
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           float* ap = ((float*)range.Item3 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  - cp[0]);
+                                cp[1] =   (ap[1]  - cp[1]);
+                                cp[2] =   (ap[2]  - cp[2]);
+                                cp[3] =   (ap[3]  - cp[3]);
+                                cp[4] =   (ap[4]  - cp[4]);
+                                cp[5] =   (ap[5]  - cp[5]);
+                                cp[6] =   (ap[6]  - cp[6]);
+                                cp[7] =   (ap[7]  - cp[7]);
+                                cp[8] =   (ap[8]  - cp[8]);
+                                cp[9] =   (ap[9]  - cp[9]);
+                                cp[10] =   (ap[10]  - cp[10]);
+                                cp[11] =   (ap[11]  - cp[11]);
+                                cp[12] =   (ap[12]  - cp[12]);
+                                cp[13] =   (ap[13]  - cp[13]);
+                                cp[14] =   (ap[14]  - cp[14]);
+                                cp[15] =   (ap[15]  - cp[15]);
+                                cp[16] =   (ap[16]  - cp[16]);
+                                cp[17] =   (ap[17]  - cp[17]);
+                                cp[18] =   (ap[18]  - cp[18]);
+                                cp[19] =   (ap[19]  - cp[19]);
+                                cp[20] =   (ap[20]  - cp[20]);
+                                ap += 21; cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  - *cp);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((float*)range.Item3 + range.Item1);
+                            bp = ((float*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  - bp[0]);
+                                cp[1] =   (ap[1]  - bp[1]);
+                                cp[2] =   (ap[2]  - bp[2]);
+                                cp[3] =   (ap[3]  - bp[3]);
+                                cp[4] =   (ap[4]  - bp[4]);
+                                cp[5] =   (ap[5]  - bp[5]);
+                                cp[6] =   (ap[6]  - bp[6]);
+                                cp[7] =   (ap[7]  - bp[7]);
+                                cp[8] =   (ap[8]  - bp[8]);
+                                cp[9] =   (ap[9]  - bp[9]);
+                                cp[10] =   (ap[10]  - bp[10]);
+                                cp[11] =   (ap[11]  - bp[11]);
+                                cp[12] =   (ap[12]  - bp[12]);
+                                cp[13] =   (ap[13]  - bp[13]);
+                                cp[14] =   (ap[14]  - bp[14]);
+                                cp[15] =   (ap[15]  - bp[15]);
+                                cp[16] =   (ap[16]  - bp[16]);
+                                cp[17] =   (ap[17]  - bp[17]);
+                                cp[18] =   (ap[18]  - bp[18]);
+                                cp[19] =   (ap[19]  - bp[19]);
+                                cp[20] =   (ap[20]  - bp[20]);
+                                ap+=21; bp+=21; cp+=21; j-=21;
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  - *bp);
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((float*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =   (cp[0]  - scalar);
+                                cp[1] =   (cp[1]  - scalar);
+                                cp[2] =   (cp[2]  - scalar);
+                                cp[3] =   (cp[3]  - scalar);
+                                cp[4] =   (cp[4]  - scalar);
+                                cp[5] =   (cp[5]  - scalar);
+                                cp[6] =   (cp[6]  - scalar);
+                                cp[7] =   (cp[7]  - scalar);
+                                cp[8] =   (cp[8]  - scalar);
+                                cp[9] =   (cp[9]  - scalar);
+                                cp[10] =   (cp[10]  - scalar);
+                                cp[11] =   (cp[11]  - scalar);
+                                cp[12] =   (cp[12]  - scalar);
+                                cp[13] =   (cp[13]  - scalar);
+                                cp[14] =   (cp[14]  - scalar);
+                                cp[15] =   (cp[15]  - scalar);
+                                cp[16] =   (cp[16]  - scalar);
+                                cp[17] =   (cp[17]  - scalar);
+                                cp[18] =   (cp[18]  - scalar);
+                                cp[19] =   (cp[19]  - scalar);
+                                cp[20] =   (cp[20]  - scalar);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*cp  - scalar);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((float*)range.Item3 + range.Item1);
+                            scalar = *((float*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  - scalar);
+                                cp[1] =   (ap[1]  - scalar);
+                                cp[2] =   (ap[2]  - scalar);
+                                cp[3] =   (ap[3]  - scalar);
+                                cp[4] =   (ap[4]  - scalar);
+                                cp[5] =   (ap[5]  - scalar);
+                                cp[6] =   (ap[6]  - scalar);
+                                cp[7] =   (ap[7]  - scalar);
+                                cp[8] =   (ap[8]  - scalar);
+                                cp[9] =   (ap[9]  - scalar);
+                                cp[10] =   (ap[10]  - scalar);
+                                cp[11] =   (ap[11]  - scalar);
+                                cp[12] =   (ap[12]  - scalar);
+                                cp[13] =   (ap[13]  - scalar);
+                                cp[14] =   (ap[14]  - scalar);
+                                cp[15] =   (ap[15]  - scalar);
+                                cp[16] =   (ap[16]  - scalar);
+                                cp[17] =   (ap[17]  - scalar);
+                                cp[18] =   (ap[18]  - scalar);
+                                cp[19] =   (ap[19]  - scalar);
+                                cp[20] =   (ap[20]  - scalar);
+                                ap+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  - scalar);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((float*)range.Item3);
+                            while (j > 20) {
+                               
+                                cp[0] =   (scalar  - cp[0]);
+                                cp[1] =   (scalar  - cp[1]);
+                                cp[2] =   (scalar  - cp[2]);
+                                cp[3] =   (scalar  - cp[3]);
+                                cp[4] =   (scalar  - cp[4]);
+                                cp[5] =   (scalar  - cp[5]);
+                                cp[6] =   (scalar  - cp[6]);
+                                cp[7] =   (scalar  - cp[7]);
+                                cp[8] =   (scalar  - cp[8]);
+                                cp[9] =   (scalar  - cp[9]);
+                                cp[10] =   (scalar  - cp[10]);
+                                cp[11] =   (scalar  - cp[11]);
+                                cp[12] =   (scalar  - cp[12]);
+                                cp[13] =   (scalar  - cp[13]);
+                                cp[14] =   (scalar  - cp[14]);
+                                cp[15] =   (scalar  - cp[15]);
+                                cp[16] =   (scalar  - cp[16]);
+                                cp[17] =   (scalar  - cp[17]);
+                                cp[18] =   (scalar  - cp[18]);
+                                cp[19] =   (scalar  - cp[19]);
+                                cp[20] =   (scalar  - cp[20]);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (scalar  - *cp);
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((float*)range.Item3);
+                            bp = ((float*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (scalar  - bp[0]);
+                                cp[1] =   (scalar  - bp[1]);
+                                cp[2] =   (scalar  - bp[2]);
+                                cp[3] =   (scalar  - bp[3]);
+                                cp[4] =   (scalar  - bp[4]);
+                                cp[5] =   (scalar  - bp[5]);
+                                cp[6] =   (scalar  - bp[6]);
+                                cp[7] =   (scalar  - bp[7]);
+                                cp[8] =   (scalar  - bp[8]);
+                                cp[9] =   (scalar  - bp[9]);
+                                cp[10] =   (scalar  - bp[10]);
+                                cp[11] =   (scalar  - bp[11]);
+                                cp[12] =   (scalar  - bp[12]);
+                                cp[13] =   (scalar  - bp[13]);
+                                cp[14] =   (scalar  - bp[14]);
+                                cp[15] =   (scalar  - bp[15]);
+                                cp[16] =   (scalar  - bp[16]);
+                                cp[17] =   (scalar  - bp[17]);
+                                cp[18] =   (scalar  - bp[18]);
+                                cp[19] =   (scalar  - bp[19]);
+                                cp[20] =   (scalar  - bp[20]);
+                                bp+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (scalar  - *bp);
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work 
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                
+                fixed ( float* arrAP = arrA)
+                fixed ( float* arrBP = arrB)
+                fixed ( float* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range 
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new  ILRetArray< float>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<float>  subtractEx(ILInArray<float> A, ILInArray<float> B) {
+            //using (ILScope.Enter(A, B)) { we cannot start a new scope here, since this would prevent A and B to be used implace if applicable
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<float>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<float>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<float>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                dim = -(dim - 1);  // 0 -> 1, 1 -> 0
+                #endregion
+
+                #region parameter preparation
+               
+                float[] retArr;
+               
+                float[] arrA = A.GetArrayForRead();
+               
+                float[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int workItemMultiplierLenA;
+                int workItemMultiplierLenB;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<float>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    workItemMultiplierLenB = outDims[0]; 
+                    workItemMultiplierLenA = dim;  // 0 for column, 1 for row vector
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<float>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    workItemMultiplierLenB = dim;  // 0 for column, 1 for row vector
+                    workItemMultiplierLenA = outDims[0]; 
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one singleton dimension in either A or B");
+                }
+                int itLen = outDims[0]; // (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<float> retStorage = new ILDenseStorage<float>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    float* ap;
+                   
+                    float* bp;
+                   
+                    float* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            if (dim == 0) {
+                                bp = (float*)range.Item3;
+                                cp = (float*)range.Item4; 
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (float*)range.Item2;
+                                    int l = itLen; 
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  - bp[0]);
+                                        cp[1] =   (ap[1]  - bp[1]);
+                                        cp[2] =   (ap[2]  - bp[2]);
+                                        cp[3] =   (ap[3]  - bp[3]);
+                                        cp[4] =   (ap[4]  - bp[4]);
+                                        cp[5] =   (ap[5]  - bp[5]);
+                                        cp[6] =   (ap[6]  - bp[6]);
+                                        cp[7] =   (ap[7]  - bp[7]);
+                                        cp[8] =   (ap[8]  - bp[8]);
+                                        cp[9] =   (ap[9]  - bp[9]);
+                                        cp[10] =   (ap[10]  - bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =   (*ap++  - *bp++);
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                ap = (float*)range.Item2;
+                                bp = (float*)range.Item3;
+                                cp = (float*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   float val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (val  - bp[0]);
+                                        cp[1] =   (val  - bp[1]);
+                                        cp[2] =   (val  - bp[2]);
+                                        cp[3] =   (val  - bp[3]);
+                                        cp[4] =   (val  - bp[4]);
+                                        cp[5] =   (val  - bp[5]);
+                                        cp[6] =   (val  - bp[6]);
+                                        cp[7] =   (val  - bp[7]);
+                                        cp[8] =   (val  - bp[8]);
+                                        cp[9] =   (val  - bp[9]);
+                                        cp[10] =   (val  - bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11; 
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =   (val  - *bp++);
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            if (dim == 0) {
+                                cp = (float*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (float*)range.Item2;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  - cp[0]);
+                                        cp[1] =   (ap[1]  - cp[1]);
+                                        cp[2] =   (ap[2]  - cp[2]);
+                                        cp[3] =   (ap[3]  - cp[3]);
+                                        cp[4] =   (ap[4]  - cp[4]);
+                                        cp[5] =   (ap[5]  - cp[5]);
+                                        cp[6] =   (ap[6]  - cp[6]);
+                                        cp[7] =   (ap[7]  - cp[7]);
+                                        cp[8] =   (ap[8]  - cp[8]);
+                                        cp[9] =   (ap[9]  - cp[9]);
+                                        cp[10] =   (ap[10]  - cp[10]);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap++  - *cp);
+                                        cp++; 
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                cp = (float*)range.Item4;
+                                ap = (float*)range.Item2;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    float val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (val  - cp[0]);
+                                        cp[1] =   (val  - cp[1]);
+                                        cp[2] =   (val  - cp[2]);
+                                        cp[3] =   (val  - cp[3]);
+                                        cp[4] =   (val  - cp[4]);
+                                        cp[5] =   (val  - cp[5]);
+                                        cp[6] =   (val  - cp[6]);
+                                        cp[7] =   (val  - cp[7]);
+                                        cp[8] =   (val  - cp[8]);
+                                        cp[9] =   (val  - cp[9]);
+                                        cp[10] =   (val  - cp[10]);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (val  - *cp);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            if (dim == 0) {
+                                ap = (float*)range.Item2;
+                                cp = (float*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (float*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  - bp[0]);
+                                        cp[1] =   (ap[1]  - bp[1]);
+                                        cp[2] =   (ap[2]  - bp[2]);
+                                        cp[3] =   (ap[3]  - bp[3]);
+                                        cp[4] =   (ap[4]  - bp[4]);
+                                        cp[5] =   (ap[5]  - bp[5]);
+                                        cp[6] =   (ap[6]  - bp[6]);
+                                        cp[7] =   (ap[7]  - bp[7]);
+                                        cp[8] =   (ap[8]  - bp[8]);
+                                        cp[9] =   (ap[9]  - bp[9]);
+                                        cp[10] =   (ap[10]  - bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap  - *bp);
+                                        ap++;
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                ap = (float*)range.Item2;
+                                bp = (float*)range.Item3;
+                                cp = (float*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   float val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  - val);
+                                        cp[1] =   (ap[1]  - val);
+                                        cp[2] =   (ap[2]  - val);
+                                        cp[3] =   (ap[3]  - val);
+                                        cp[4] =   (ap[4]  - val);
+                                        cp[5] =   (ap[5]  - val);
+                                        cp[6] =   (ap[6]  - val);
+                                        cp[7] =   (ap[7]  - val);
+                                        cp[8] =   (ap[8]  - val);
+                                        cp[9] =   (ap[9]  - val);
+                                        cp[10] =   (ap[10]  - val);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap  - val);
+                                        ap++;
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            if (dim == 0) {
+                                cp = (float*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (float*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (cp[0]  - bp[0]);
+                                        cp[1] =   (cp[1]  - bp[1]);
+                                        cp[2] =   (cp[2]  - bp[2]);
+                                        cp[3] =   (cp[3]  - bp[3]);
+                                        cp[4] =   (cp[4]  - bp[4]);
+                                        cp[5] =   (cp[5]  - bp[5]);
+                                        cp[6] =   (cp[6]  - bp[6]);
+                                        cp[7] =   (cp[7]  - bp[7]);
+                                        cp[8] =   (cp[8]  - bp[8]);
+                                        cp[9] =   (cp[9]  - bp[9]);
+                                        cp[10] =   (cp[10]  - bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*cp  - *bp);
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                bp = (float*)range.Item3;
+                                cp = (float*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    float val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (cp[0]  - val);
+                                        cp[1] =   (cp[1]  - val);
+                                        cp[2] =   (cp[2]  - val);
+                                        cp[3] =   (cp[3]  - val);
+                                        cp[4] =   (cp[4]  - val);
+                                        cp[5] =   (cp[5]  - val);
+                                        cp[6] =   (cp[6]  - val);
+                                        cp[7] =   (cp[7]  - val);
+                                        cp[8] =   (cp[8]  - val);
+                                        cp[9] =   (cp[9]  - val);
+                                        cp[10] =   (cp[10]  - val);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l --> 0) {
+                                        *cp =   (*cp  - val);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outDims.NumberOfElements >= Settings.s_minParallelElement1Count
+                    && outDims[1] > 1) {
+                        if (outDims[1] > workItemCount) {
+                        workItemLength = outDims[1] / workItemCount;
+                    } else {
+                        workItemLength = outDims[1] / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outDims[1];
+                    workItemCount = 1;
+                }
+
+                fixed ( float* arrAP = arrA)
+                fixed ( float* arrBP = arrB)
+                fixed ( float* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, IntPtr, IntPtr, IntPtr> range = new Tuple<int, IntPtr, IntPtr, IntPtr>
+                               (workItemLength
+                               , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                               , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                               , (IntPtr)(retArrP + i * outDims[0] * workItemLength)); 
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, IntPtr, IntPtr, IntPtr>
+                                (outDims[1] - i * workItemLength
+                                , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                                , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                                , (IntPtr)(retArrP + i * outDims[0] * workItemLength)));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<float>(retStorage);
+            //}  // no scopes here! it disables implace operations
+        }
+
+        /// <summary>Subtract arrays elementwise</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>New array with result of subtraction</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<fcomplex>  subtract(ILInArray<fcomplex> A, ILInArray<fcomplex> B) {
+            using (ILScope.Enter(A,B)) {
+                int outLen; 
+                BinOpItMode mode; 
+                fcomplex [] retArr;
+                fcomplex [] arrA = A.GetArrayForRead();
+                fcomplex[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size; 
+                    if (B.IsScalar) {
+                       
+                        return new  ILRetArray<fcomplex> (new  fcomplex [1]{  (A.GetValue(0)  - B.GetValue(0))}, A.Size);
+                    } else if (B.IsEmpty) {
+                        return  ILRetArray<fcomplex>.empty(outDims); 
+                    } else {
+                        outLen = outDims.NumberOfElements; 
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< fcomplex > (outLen);
+                            mode = BinOpItMode.SAN; 
+                        } else {
+                            mode = BinOpItMode.SAI; 
+                        }
+                    }
+                } else {
+                    outDims = A.Size; 
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return  ILRetArray<fcomplex>.empty(A.Size);  
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< fcomplex > (outLen);
+                            mode = BinOpItMode.ASN; 
+                        } else {
+                            mode = BinOpItMode.ASI; 
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  subtractEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (A.TryGetStorage4InplaceOp(out retArr)) 
+                            mode  = BinOpItMode.AAIA; 
+                        else if (B.TryGetStorage4InplaceOp(out retArr)) 
+                            mode = BinOpItMode.AAIB; 
+                        else {
+                            retArr = ILMemoryPool.Pool.New< fcomplex > (outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<fcomplex> retStorage = new ILDenseStorage<fcomplex>(retArr, outDims);
+                int i = 0, workerCount = 1; 
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    fcomplex* cp = (fcomplex*)range.Item5 + range.Item1;
+                    fcomplex scalar;
+                    int j = range.Item2; 
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           fcomplex* bp = ((fcomplex*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                                cp[0] =   (cp[0]  - bp[0]);
+                                cp[1] =   (cp[1]  - bp[1]);
+                                cp[2] =   (cp[2]  - bp[2]);
+                                cp[3] =   (cp[3]  - bp[3]);
+                                cp[4] =   (cp[4]  - bp[4]);
+                                cp[5] =   (cp[5]  - bp[5]);
+                                cp[6] =   (cp[6]  - bp[6]);
+                                cp[7] =   (cp[7]  - bp[7]);
+                                cp[8] =   (cp[8]  - bp[8]);
+                                cp[9] =   (cp[9]  - bp[9]);
+                                cp[10] =   (cp[10]  - bp[10]);
+                                cp[11] =   (cp[11]  - bp[11]);
+                                cp[12] =   (cp[12]  - bp[12]);
+                                cp[13] =   (cp[13]  - bp[13]);
+                                cp[14] =   (cp[14]  - bp[14]);
+                                cp[15] =   (cp[15]  - bp[15]);
+                                cp[16] =   (cp[16]  - bp[16]);
+                                cp[17] =   (cp[17]  - bp[17]);
+                                cp[18] =   (cp[18]  - bp[18]);
+                                cp[19] =   (cp[19]  - bp[19]);
+                                cp[20] =   (cp[20]  - bp[20]);
+                                cp += 21; bp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*cp  - *bp);
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           fcomplex* ap = ((fcomplex*)range.Item3 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  - cp[0]);
+                                cp[1] =   (ap[1]  - cp[1]);
+                                cp[2] =   (ap[2]  - cp[2]);
+                                cp[3] =   (ap[3]  - cp[3]);
+                                cp[4] =   (ap[4]  - cp[4]);
+                                cp[5] =   (ap[5]  - cp[5]);
+                                cp[6] =   (ap[6]  - cp[6]);
+                                cp[7] =   (ap[7]  - cp[7]);
+                                cp[8] =   (ap[8]  - cp[8]);
+                                cp[9] =   (ap[9]  - cp[9]);
+                                cp[10] =   (ap[10]  - cp[10]);
+                                cp[11] =   (ap[11]  - cp[11]);
+                                cp[12] =   (ap[12]  - cp[12]);
+                                cp[13] =   (ap[13]  - cp[13]);
+                                cp[14] =   (ap[14]  - cp[14]);
+                                cp[15] =   (ap[15]  - cp[15]);
+                                cp[16] =   (ap[16]  - cp[16]);
+                                cp[17] =   (ap[17]  - cp[17]);
+                                cp[18] =   (ap[18]  - cp[18]);
+                                cp[19] =   (ap[19]  - cp[19]);
+                                cp[20] =   (ap[20]  - cp[20]);
+                                ap += 21; cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  - *cp);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((fcomplex*)range.Item3 + range.Item1);
+                            bp = ((fcomplex*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  - bp[0]);
+                                cp[1] =   (ap[1]  - bp[1]);
+                                cp[2] =   (ap[2]  - bp[2]);
+                                cp[3] =   (ap[3]  - bp[3]);
+                                cp[4] =   (ap[4]  - bp[4]);
+                                cp[5] =   (ap[5]  - bp[5]);
+                                cp[6] =   (ap[6]  - bp[6]);
+                                cp[7] =   (ap[7]  - bp[7]);
+                                cp[8] =   (ap[8]  - bp[8]);
+                                cp[9] =   (ap[9]  - bp[9]);
+                                cp[10] =   (ap[10]  - bp[10]);
+                                cp[11] =   (ap[11]  - bp[11]);
+                                cp[12] =   (ap[12]  - bp[12]);
+                                cp[13] =   (ap[13]  - bp[13]);
+                                cp[14] =   (ap[14]  - bp[14]);
+                                cp[15] =   (ap[15]  - bp[15]);
+                                cp[16] =   (ap[16]  - bp[16]);
+                                cp[17] =   (ap[17]  - bp[17]);
+                                cp[18] =   (ap[18]  - bp[18]);
+                                cp[19] =   (ap[19]  - bp[19]);
+                                cp[20] =   (ap[20]  - bp[20]);
+                                ap+=21; bp+=21; cp+=21; j-=21;
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  - *bp);
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((fcomplex*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =   (cp[0]  - scalar);
+                                cp[1] =   (cp[1]  - scalar);
+                                cp[2] =   (cp[2]  - scalar);
+                                cp[3] =   (cp[3]  - scalar);
+                                cp[4] =   (cp[4]  - scalar);
+                                cp[5] =   (cp[5]  - scalar);
+                                cp[6] =   (cp[6]  - scalar);
+                                cp[7] =   (cp[7]  - scalar);
+                                cp[8] =   (cp[8]  - scalar);
+                                cp[9] =   (cp[9]  - scalar);
+                                cp[10] =   (cp[10]  - scalar);
+                                cp[11] =   (cp[11]  - scalar);
+                                cp[12] =   (cp[12]  - scalar);
+                                cp[13] =   (cp[13]  - scalar);
+                                cp[14] =   (cp[14]  - scalar);
+                                cp[15] =   (cp[15]  - scalar);
+                                cp[16] =   (cp[16]  - scalar);
+                                cp[17] =   (cp[17]  - scalar);
+                                cp[18] =   (cp[18]  - scalar);
+                                cp[19] =   (cp[19]  - scalar);
+                                cp[20] =   (cp[20]  - scalar);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*cp  - scalar);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((fcomplex*)range.Item3 + range.Item1);
+                            scalar = *((fcomplex*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  - scalar);
+                                cp[1] =   (ap[1]  - scalar);
+                                cp[2] =   (ap[2]  - scalar);
+                                cp[3] =   (ap[3]  - scalar);
+                                cp[4] =   (ap[4]  - scalar);
+                                cp[5] =   (ap[5]  - scalar);
+                                cp[6] =   (ap[6]  - scalar);
+                                cp[7] =   (ap[7]  - scalar);
+                                cp[8] =   (ap[8]  - scalar);
+                                cp[9] =   (ap[9]  - scalar);
+                                cp[10] =   (ap[10]  - scalar);
+                                cp[11] =   (ap[11]  - scalar);
+                                cp[12] =   (ap[12]  - scalar);
+                                cp[13] =   (ap[13]  - scalar);
+                                cp[14] =   (ap[14]  - scalar);
+                                cp[15] =   (ap[15]  - scalar);
+                                cp[16] =   (ap[16]  - scalar);
+                                cp[17] =   (ap[17]  - scalar);
+                                cp[18] =   (ap[18]  - scalar);
+                                cp[19] =   (ap[19]  - scalar);
+                                cp[20] =   (ap[20]  - scalar);
+                                ap+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  - scalar);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((fcomplex*)range.Item3);
+                            while (j > 20) {
+                               
+                                cp[0] =   (scalar  - cp[0]);
+                                cp[1] =   (scalar  - cp[1]);
+                                cp[2] =   (scalar  - cp[2]);
+                                cp[3] =   (scalar  - cp[3]);
+                                cp[4] =   (scalar  - cp[4]);
+                                cp[5] =   (scalar  - cp[5]);
+                                cp[6] =   (scalar  - cp[6]);
+                                cp[7] =   (scalar  - cp[7]);
+                                cp[8] =   (scalar  - cp[8]);
+                                cp[9] =   (scalar  - cp[9]);
+                                cp[10] =   (scalar  - cp[10]);
+                                cp[11] =   (scalar  - cp[11]);
+                                cp[12] =   (scalar  - cp[12]);
+                                cp[13] =   (scalar  - cp[13]);
+                                cp[14] =   (scalar  - cp[14]);
+                                cp[15] =   (scalar  - cp[15]);
+                                cp[16] =   (scalar  - cp[16]);
+                                cp[17] =   (scalar  - cp[17]);
+                                cp[18] =   (scalar  - cp[18]);
+                                cp[19] =   (scalar  - cp[19]);
+                                cp[20] =   (scalar  - cp[20]);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (scalar  - *cp);
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((fcomplex*)range.Item3);
+                            bp = ((fcomplex*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (scalar  - bp[0]);
+                                cp[1] =   (scalar  - bp[1]);
+                                cp[2] =   (scalar  - bp[2]);
+                                cp[3] =   (scalar  - bp[3]);
+                                cp[4] =   (scalar  - bp[4]);
+                                cp[5] =   (scalar  - bp[5]);
+                                cp[6] =   (scalar  - bp[6]);
+                                cp[7] =   (scalar  - bp[7]);
+                                cp[8] =   (scalar  - bp[8]);
+                                cp[9] =   (scalar  - bp[9]);
+                                cp[10] =   (scalar  - bp[10]);
+                                cp[11] =   (scalar  - bp[11]);
+                                cp[12] =   (scalar  - bp[12]);
+                                cp[13] =   (scalar  - bp[13]);
+                                cp[14] =   (scalar  - bp[14]);
+                                cp[15] =   (scalar  - bp[15]);
+                                cp[16] =   (scalar  - bp[16]);
+                                cp[17] =   (scalar  - bp[17]);
+                                cp[18] =   (scalar  - bp[18]);
+                                cp[19] =   (scalar  - bp[19]);
+                                cp[20] =   (scalar  - bp[20]);
+                                bp+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (scalar  - *bp);
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work 
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                
+                fixed ( fcomplex* arrAP = arrA)
+                fixed ( fcomplex* arrBP = arrB)
+                fixed ( fcomplex* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range 
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new  ILRetArray< fcomplex>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<fcomplex>  subtractEx(ILInArray<fcomplex> A, ILInArray<fcomplex> B) {
+            //using (ILScope.Enter(A, B)) { we cannot start a new scope here, since this would prevent A and B to be used implace if applicable
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<fcomplex>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<fcomplex>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<fcomplex>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                dim = -(dim - 1);  // 0 -> 1, 1 -> 0
+                #endregion
+
+                #region parameter preparation
+               
+                fcomplex[] retArr;
+               
+                fcomplex[] arrA = A.GetArrayForRead();
+               
+                fcomplex[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int workItemMultiplierLenA;
+                int workItemMultiplierLenB;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<fcomplex>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    workItemMultiplierLenB = outDims[0]; 
+                    workItemMultiplierLenA = dim;  // 0 for column, 1 for row vector
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<fcomplex>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    workItemMultiplierLenB = dim;  // 0 for column, 1 for row vector
+                    workItemMultiplierLenA = outDims[0]; 
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one singleton dimension in either A or B");
+                }
+                int itLen = outDims[0]; // (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<fcomplex> retStorage = new ILDenseStorage<fcomplex>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    fcomplex* ap;
+                   
+                    fcomplex* bp;
+                   
+                    fcomplex* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            if (dim == 0) {
+                                bp = (fcomplex*)range.Item3;
+                                cp = (fcomplex*)range.Item4; 
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (fcomplex*)range.Item2;
+                                    int l = itLen; 
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  - bp[0]);
+                                        cp[1] =   (ap[1]  - bp[1]);
+                                        cp[2] =   (ap[2]  - bp[2]);
+                                        cp[3] =   (ap[3]  - bp[3]);
+                                        cp[4] =   (ap[4]  - bp[4]);
+                                        cp[5] =   (ap[5]  - bp[5]);
+                                        cp[6] =   (ap[6]  - bp[6]);
+                                        cp[7] =   (ap[7]  - bp[7]);
+                                        cp[8] =   (ap[8]  - bp[8]);
+                                        cp[9] =   (ap[9]  - bp[9]);
+                                        cp[10] =   (ap[10]  - bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =   (*ap++  - *bp++);
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                ap = (fcomplex*)range.Item2;
+                                bp = (fcomplex*)range.Item3;
+                                cp = (fcomplex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   fcomplex val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (val  - bp[0]);
+                                        cp[1] =   (val  - bp[1]);
+                                        cp[2] =   (val  - bp[2]);
+                                        cp[3] =   (val  - bp[3]);
+                                        cp[4] =   (val  - bp[4]);
+                                        cp[5] =   (val  - bp[5]);
+                                        cp[6] =   (val  - bp[6]);
+                                        cp[7] =   (val  - bp[7]);
+                                        cp[8] =   (val  - bp[8]);
+                                        cp[9] =   (val  - bp[9]);
+                                        cp[10] =   (val  - bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11; 
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =   (val  - *bp++);
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            if (dim == 0) {
+                                cp = (fcomplex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (fcomplex*)range.Item2;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  - cp[0]);
+                                        cp[1] =   (ap[1]  - cp[1]);
+                                        cp[2] =   (ap[2]  - cp[2]);
+                                        cp[3] =   (ap[3]  - cp[3]);
+                                        cp[4] =   (ap[4]  - cp[4]);
+                                        cp[5] =   (ap[5]  - cp[5]);
+                                        cp[6] =   (ap[6]  - cp[6]);
+                                        cp[7] =   (ap[7]  - cp[7]);
+                                        cp[8] =   (ap[8]  - cp[8]);
+                                        cp[9] =   (ap[9]  - cp[9]);
+                                        cp[10] =   (ap[10]  - cp[10]);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap++  - *cp);
+                                        cp++; 
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                cp = (fcomplex*)range.Item4;
+                                ap = (fcomplex*)range.Item2;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    fcomplex val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (val  - cp[0]);
+                                        cp[1] =   (val  - cp[1]);
+                                        cp[2] =   (val  - cp[2]);
+                                        cp[3] =   (val  - cp[3]);
+                                        cp[4] =   (val  - cp[4]);
+                                        cp[5] =   (val  - cp[5]);
+                                        cp[6] =   (val  - cp[6]);
+                                        cp[7] =   (val  - cp[7]);
+                                        cp[8] =   (val  - cp[8]);
+                                        cp[9] =   (val  - cp[9]);
+                                        cp[10] =   (val  - cp[10]);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (val  - *cp);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            if (dim == 0) {
+                                ap = (fcomplex*)range.Item2;
+                                cp = (fcomplex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (fcomplex*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  - bp[0]);
+                                        cp[1] =   (ap[1]  - bp[1]);
+                                        cp[2] =   (ap[2]  - bp[2]);
+                                        cp[3] =   (ap[3]  - bp[3]);
+                                        cp[4] =   (ap[4]  - bp[4]);
+                                        cp[5] =   (ap[5]  - bp[5]);
+                                        cp[6] =   (ap[6]  - bp[6]);
+                                        cp[7] =   (ap[7]  - bp[7]);
+                                        cp[8] =   (ap[8]  - bp[8]);
+                                        cp[9] =   (ap[9]  - bp[9]);
+                                        cp[10] =   (ap[10]  - bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap  - *bp);
+                                        ap++;
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                ap = (fcomplex*)range.Item2;
+                                bp = (fcomplex*)range.Item3;
+                                cp = (fcomplex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   fcomplex val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  - val);
+                                        cp[1] =   (ap[1]  - val);
+                                        cp[2] =   (ap[2]  - val);
+                                        cp[3] =   (ap[3]  - val);
+                                        cp[4] =   (ap[4]  - val);
+                                        cp[5] =   (ap[5]  - val);
+                                        cp[6] =   (ap[6]  - val);
+                                        cp[7] =   (ap[7]  - val);
+                                        cp[8] =   (ap[8]  - val);
+                                        cp[9] =   (ap[9]  - val);
+                                        cp[10] =   (ap[10]  - val);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap  - val);
+                                        ap++;
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            if (dim == 0) {
+                                cp = (fcomplex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (fcomplex*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (cp[0]  - bp[0]);
+                                        cp[1] =   (cp[1]  - bp[1]);
+                                        cp[2] =   (cp[2]  - bp[2]);
+                                        cp[3] =   (cp[3]  - bp[3]);
+                                        cp[4] =   (cp[4]  - bp[4]);
+                                        cp[5] =   (cp[5]  - bp[5]);
+                                        cp[6] =   (cp[6]  - bp[6]);
+                                        cp[7] =   (cp[7]  - bp[7]);
+                                        cp[8] =   (cp[8]  - bp[8]);
+                                        cp[9] =   (cp[9]  - bp[9]);
+                                        cp[10] =   (cp[10]  - bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*cp  - *bp);
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                bp = (fcomplex*)range.Item3;
+                                cp = (fcomplex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    fcomplex val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (cp[0]  - val);
+                                        cp[1] =   (cp[1]  - val);
+                                        cp[2] =   (cp[2]  - val);
+                                        cp[3] =   (cp[3]  - val);
+                                        cp[4] =   (cp[4]  - val);
+                                        cp[5] =   (cp[5]  - val);
+                                        cp[6] =   (cp[6]  - val);
+                                        cp[7] =   (cp[7]  - val);
+                                        cp[8] =   (cp[8]  - val);
+                                        cp[9] =   (cp[9]  - val);
+                                        cp[10] =   (cp[10]  - val);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l --> 0) {
+                                        *cp =   (*cp  - val);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outDims.NumberOfElements >= Settings.s_minParallelElement1Count
+                    && outDims[1] > 1) {
+                        if (outDims[1] > workItemCount) {
+                        workItemLength = outDims[1] / workItemCount;
+                    } else {
+                        workItemLength = outDims[1] / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outDims[1];
+                    workItemCount = 1;
+                }
+
+                fixed ( fcomplex* arrAP = arrA)
+                fixed ( fcomplex* arrBP = arrB)
+                fixed ( fcomplex* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, IntPtr, IntPtr, IntPtr> range = new Tuple<int, IntPtr, IntPtr, IntPtr>
+                               (workItemLength
+                               , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                               , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                               , (IntPtr)(retArrP + i * outDims[0] * workItemLength)); 
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, IntPtr, IntPtr, IntPtr>
+                                (outDims[1] - i * workItemLength
+                                , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                                , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                                , (IntPtr)(retArrP + i * outDims[0] * workItemLength)));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<fcomplex>(retStorage);
+            //}  // no scopes here! it disables implace operations
+        }
+
+        /// <summary>Subtract arrays elementwise</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>New array with result of subtraction</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<complex>  subtract(ILInArray<complex> A, ILInArray<complex> B) {
+            using (ILScope.Enter(A,B)) {
+                int outLen; 
+                BinOpItMode mode; 
+                complex [] retArr;
+                complex [] arrA = A.GetArrayForRead();
+                complex[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size; 
+                    if (B.IsScalar) {
+                       
+                        return new  ILRetArray<complex> (new  complex [1]{  (A.GetValue(0)  - B.GetValue(0))}, A.Size);
+                    } else if (B.IsEmpty) {
+                        return  ILRetArray<complex>.empty(outDims); 
+                    } else {
+                        outLen = outDims.NumberOfElements; 
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< complex > (outLen);
+                            mode = BinOpItMode.SAN; 
+                        } else {
+                            mode = BinOpItMode.SAI; 
+                        }
+                    }
+                } else {
+                    outDims = A.Size; 
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return  ILRetArray<complex>.empty(A.Size);  
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< complex > (outLen);
+                            mode = BinOpItMode.ASN; 
+                        } else {
+                            mode = BinOpItMode.ASI; 
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  subtractEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (A.TryGetStorage4InplaceOp(out retArr)) 
+                            mode  = BinOpItMode.AAIA; 
+                        else if (B.TryGetStorage4InplaceOp(out retArr)) 
+                            mode = BinOpItMode.AAIB; 
+                        else {
+                            retArr = ILMemoryPool.Pool.New< complex > (outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<complex> retStorage = new ILDenseStorage<complex>(retArr, outDims);
+                int i = 0, workerCount = 1; 
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    complex* cp = (complex*)range.Item5 + range.Item1;
+                    complex scalar;
+                    int j = range.Item2; 
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           complex* bp = ((complex*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                                cp[0] =   (cp[0]  - bp[0]);
+                                cp[1] =   (cp[1]  - bp[1]);
+                                cp[2] =   (cp[2]  - bp[2]);
+                                cp[3] =   (cp[3]  - bp[3]);
+                                cp[4] =   (cp[4]  - bp[4]);
+                                cp[5] =   (cp[5]  - bp[5]);
+                                cp[6] =   (cp[6]  - bp[6]);
+                                cp[7] =   (cp[7]  - bp[7]);
+                                cp[8] =   (cp[8]  - bp[8]);
+                                cp[9] =   (cp[9]  - bp[9]);
+                                cp[10] =   (cp[10]  - bp[10]);
+                                cp[11] =   (cp[11]  - bp[11]);
+                                cp[12] =   (cp[12]  - bp[12]);
+                                cp[13] =   (cp[13]  - bp[13]);
+                                cp[14] =   (cp[14]  - bp[14]);
+                                cp[15] =   (cp[15]  - bp[15]);
+                                cp[16] =   (cp[16]  - bp[16]);
+                                cp[17] =   (cp[17]  - bp[17]);
+                                cp[18] =   (cp[18]  - bp[18]);
+                                cp[19] =   (cp[19]  - bp[19]);
+                                cp[20] =   (cp[20]  - bp[20]);
+                                cp += 21; bp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*cp  - *bp);
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           complex* ap = ((complex*)range.Item3 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  - cp[0]);
+                                cp[1] =   (ap[1]  - cp[1]);
+                                cp[2] =   (ap[2]  - cp[2]);
+                                cp[3] =   (ap[3]  - cp[3]);
+                                cp[4] =   (ap[4]  - cp[4]);
+                                cp[5] =   (ap[5]  - cp[5]);
+                                cp[6] =   (ap[6]  - cp[6]);
+                                cp[7] =   (ap[7]  - cp[7]);
+                                cp[8] =   (ap[8]  - cp[8]);
+                                cp[9] =   (ap[9]  - cp[9]);
+                                cp[10] =   (ap[10]  - cp[10]);
+                                cp[11] =   (ap[11]  - cp[11]);
+                                cp[12] =   (ap[12]  - cp[12]);
+                                cp[13] =   (ap[13]  - cp[13]);
+                                cp[14] =   (ap[14]  - cp[14]);
+                                cp[15] =   (ap[15]  - cp[15]);
+                                cp[16] =   (ap[16]  - cp[16]);
+                                cp[17] =   (ap[17]  - cp[17]);
+                                cp[18] =   (ap[18]  - cp[18]);
+                                cp[19] =   (ap[19]  - cp[19]);
+                                cp[20] =   (ap[20]  - cp[20]);
+                                ap += 21; cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  - *cp);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((complex*)range.Item3 + range.Item1);
+                            bp = ((complex*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  - bp[0]);
+                                cp[1] =   (ap[1]  - bp[1]);
+                                cp[2] =   (ap[2]  - bp[2]);
+                                cp[3] =   (ap[3]  - bp[3]);
+                                cp[4] =   (ap[4]  - bp[4]);
+                                cp[5] =   (ap[5]  - bp[5]);
+                                cp[6] =   (ap[6]  - bp[6]);
+                                cp[7] =   (ap[7]  - bp[7]);
+                                cp[8] =   (ap[8]  - bp[8]);
+                                cp[9] =   (ap[9]  - bp[9]);
+                                cp[10] =   (ap[10]  - bp[10]);
+                                cp[11] =   (ap[11]  - bp[11]);
+                                cp[12] =   (ap[12]  - bp[12]);
+                                cp[13] =   (ap[13]  - bp[13]);
+                                cp[14] =   (ap[14]  - bp[14]);
+                                cp[15] =   (ap[15]  - bp[15]);
+                                cp[16] =   (ap[16]  - bp[16]);
+                                cp[17] =   (ap[17]  - bp[17]);
+                                cp[18] =   (ap[18]  - bp[18]);
+                                cp[19] =   (ap[19]  - bp[19]);
+                                cp[20] =   (ap[20]  - bp[20]);
+                                ap+=21; bp+=21; cp+=21; j-=21;
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  - *bp);
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((complex*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =   (cp[0]  - scalar);
+                                cp[1] =   (cp[1]  - scalar);
+                                cp[2] =   (cp[2]  - scalar);
+                                cp[3] =   (cp[3]  - scalar);
+                                cp[4] =   (cp[4]  - scalar);
+                                cp[5] =   (cp[5]  - scalar);
+                                cp[6] =   (cp[6]  - scalar);
+                                cp[7] =   (cp[7]  - scalar);
+                                cp[8] =   (cp[8]  - scalar);
+                                cp[9] =   (cp[9]  - scalar);
+                                cp[10] =   (cp[10]  - scalar);
+                                cp[11] =   (cp[11]  - scalar);
+                                cp[12] =   (cp[12]  - scalar);
+                                cp[13] =   (cp[13]  - scalar);
+                                cp[14] =   (cp[14]  - scalar);
+                                cp[15] =   (cp[15]  - scalar);
+                                cp[16] =   (cp[16]  - scalar);
+                                cp[17] =   (cp[17]  - scalar);
+                                cp[18] =   (cp[18]  - scalar);
+                                cp[19] =   (cp[19]  - scalar);
+                                cp[20] =   (cp[20]  - scalar);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*cp  - scalar);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((complex*)range.Item3 + range.Item1);
+                            scalar = *((complex*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  - scalar);
+                                cp[1] =   (ap[1]  - scalar);
+                                cp[2] =   (ap[2]  - scalar);
+                                cp[3] =   (ap[3]  - scalar);
+                                cp[4] =   (ap[4]  - scalar);
+                                cp[5] =   (ap[5]  - scalar);
+                                cp[6] =   (ap[6]  - scalar);
+                                cp[7] =   (ap[7]  - scalar);
+                                cp[8] =   (ap[8]  - scalar);
+                                cp[9] =   (ap[9]  - scalar);
+                                cp[10] =   (ap[10]  - scalar);
+                                cp[11] =   (ap[11]  - scalar);
+                                cp[12] =   (ap[12]  - scalar);
+                                cp[13] =   (ap[13]  - scalar);
+                                cp[14] =   (ap[14]  - scalar);
+                                cp[15] =   (ap[15]  - scalar);
+                                cp[16] =   (ap[16]  - scalar);
+                                cp[17] =   (ap[17]  - scalar);
+                                cp[18] =   (ap[18]  - scalar);
+                                cp[19] =   (ap[19]  - scalar);
+                                cp[20] =   (ap[20]  - scalar);
+                                ap+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  - scalar);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((complex*)range.Item3);
+                            while (j > 20) {
+                               
+                                cp[0] =   (scalar  - cp[0]);
+                                cp[1] =   (scalar  - cp[1]);
+                                cp[2] =   (scalar  - cp[2]);
+                                cp[3] =   (scalar  - cp[3]);
+                                cp[4] =   (scalar  - cp[4]);
+                                cp[5] =   (scalar  - cp[5]);
+                                cp[6] =   (scalar  - cp[6]);
+                                cp[7] =   (scalar  - cp[7]);
+                                cp[8] =   (scalar  - cp[8]);
+                                cp[9] =   (scalar  - cp[9]);
+                                cp[10] =   (scalar  - cp[10]);
+                                cp[11] =   (scalar  - cp[11]);
+                                cp[12] =   (scalar  - cp[12]);
+                                cp[13] =   (scalar  - cp[13]);
+                                cp[14] =   (scalar  - cp[14]);
+                                cp[15] =   (scalar  - cp[15]);
+                                cp[16] =   (scalar  - cp[16]);
+                                cp[17] =   (scalar  - cp[17]);
+                                cp[18] =   (scalar  - cp[18]);
+                                cp[19] =   (scalar  - cp[19]);
+                                cp[20] =   (scalar  - cp[20]);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (scalar  - *cp);
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((complex*)range.Item3);
+                            bp = ((complex*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (scalar  - bp[0]);
+                                cp[1] =   (scalar  - bp[1]);
+                                cp[2] =   (scalar  - bp[2]);
+                                cp[3] =   (scalar  - bp[3]);
+                                cp[4] =   (scalar  - bp[4]);
+                                cp[5] =   (scalar  - bp[5]);
+                                cp[6] =   (scalar  - bp[6]);
+                                cp[7] =   (scalar  - bp[7]);
+                                cp[8] =   (scalar  - bp[8]);
+                                cp[9] =   (scalar  - bp[9]);
+                                cp[10] =   (scalar  - bp[10]);
+                                cp[11] =   (scalar  - bp[11]);
+                                cp[12] =   (scalar  - bp[12]);
+                                cp[13] =   (scalar  - bp[13]);
+                                cp[14] =   (scalar  - bp[14]);
+                                cp[15] =   (scalar  - bp[15]);
+                                cp[16] =   (scalar  - bp[16]);
+                                cp[17] =   (scalar  - bp[17]);
+                                cp[18] =   (scalar  - bp[18]);
+                                cp[19] =   (scalar  - bp[19]);
+                                cp[20] =   (scalar  - bp[20]);
+                                bp+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (scalar  - *bp);
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work 
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                
+                fixed ( complex* arrAP = arrA)
+                fixed ( complex* arrBP = arrB)
+                fixed ( complex* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range 
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new  ILRetArray< complex>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<complex>  subtractEx(ILInArray<complex> A, ILInArray<complex> B) {
+            //using (ILScope.Enter(A, B)) { we cannot start a new scope here, since this would prevent A and B to be used implace if applicable
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<complex>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<complex>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<complex>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                dim = -(dim - 1);  // 0 -> 1, 1 -> 0
+                #endregion
+
+                #region parameter preparation
+               
+                complex[] retArr;
+               
+                complex[] arrA = A.GetArrayForRead();
+               
+                complex[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int workItemMultiplierLenA;
+                int workItemMultiplierLenB;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<complex>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    workItemMultiplierLenB = outDims[0]; 
+                    workItemMultiplierLenA = dim;  // 0 for column, 1 for row vector
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<complex>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    workItemMultiplierLenB = dim;  // 0 for column, 1 for row vector
+                    workItemMultiplierLenA = outDims[0]; 
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one singleton dimension in either A or B");
+                }
+                int itLen = outDims[0]; // (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<complex> retStorage = new ILDenseStorage<complex>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    complex* ap;
+                   
+                    complex* bp;
+                   
+                    complex* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            if (dim == 0) {
+                                bp = (complex*)range.Item3;
+                                cp = (complex*)range.Item4; 
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (complex*)range.Item2;
+                                    int l = itLen; 
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  - bp[0]);
+                                        cp[1] =   (ap[1]  - bp[1]);
+                                        cp[2] =   (ap[2]  - bp[2]);
+                                        cp[3] =   (ap[3]  - bp[3]);
+                                        cp[4] =   (ap[4]  - bp[4]);
+                                        cp[5] =   (ap[5]  - bp[5]);
+                                        cp[6] =   (ap[6]  - bp[6]);
+                                        cp[7] =   (ap[7]  - bp[7]);
+                                        cp[8] =   (ap[8]  - bp[8]);
+                                        cp[9] =   (ap[9]  - bp[9]);
+                                        cp[10] =   (ap[10]  - bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =   (*ap++  - *bp++);
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                ap = (complex*)range.Item2;
+                                bp = (complex*)range.Item3;
+                                cp = (complex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   complex val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (val  - bp[0]);
+                                        cp[1] =   (val  - bp[1]);
+                                        cp[2] =   (val  - bp[2]);
+                                        cp[3] =   (val  - bp[3]);
+                                        cp[4] =   (val  - bp[4]);
+                                        cp[5] =   (val  - bp[5]);
+                                        cp[6] =   (val  - bp[6]);
+                                        cp[7] =   (val  - bp[7]);
+                                        cp[8] =   (val  - bp[8]);
+                                        cp[9] =   (val  - bp[9]);
+                                        cp[10] =   (val  - bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11; 
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =   (val  - *bp++);
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            if (dim == 0) {
+                                cp = (complex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (complex*)range.Item2;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  - cp[0]);
+                                        cp[1] =   (ap[1]  - cp[1]);
+                                        cp[2] =   (ap[2]  - cp[2]);
+                                        cp[3] =   (ap[3]  - cp[3]);
+                                        cp[4] =   (ap[4]  - cp[4]);
+                                        cp[5] =   (ap[5]  - cp[5]);
+                                        cp[6] =   (ap[6]  - cp[6]);
+                                        cp[7] =   (ap[7]  - cp[7]);
+                                        cp[8] =   (ap[8]  - cp[8]);
+                                        cp[9] =   (ap[9]  - cp[9]);
+                                        cp[10] =   (ap[10]  - cp[10]);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap++  - *cp);
+                                        cp++; 
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                cp = (complex*)range.Item4;
+                                ap = (complex*)range.Item2;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    complex val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (val  - cp[0]);
+                                        cp[1] =   (val  - cp[1]);
+                                        cp[2] =   (val  - cp[2]);
+                                        cp[3] =   (val  - cp[3]);
+                                        cp[4] =   (val  - cp[4]);
+                                        cp[5] =   (val  - cp[5]);
+                                        cp[6] =   (val  - cp[6]);
+                                        cp[7] =   (val  - cp[7]);
+                                        cp[8] =   (val  - cp[8]);
+                                        cp[9] =   (val  - cp[9]);
+                                        cp[10] =   (val  - cp[10]);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (val  - *cp);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            if (dim == 0) {
+                                ap = (complex*)range.Item2;
+                                cp = (complex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (complex*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  - bp[0]);
+                                        cp[1] =   (ap[1]  - bp[1]);
+                                        cp[2] =   (ap[2]  - bp[2]);
+                                        cp[3] =   (ap[3]  - bp[3]);
+                                        cp[4] =   (ap[4]  - bp[4]);
+                                        cp[5] =   (ap[5]  - bp[5]);
+                                        cp[6] =   (ap[6]  - bp[6]);
+                                        cp[7] =   (ap[7]  - bp[7]);
+                                        cp[8] =   (ap[8]  - bp[8]);
+                                        cp[9] =   (ap[9]  - bp[9]);
+                                        cp[10] =   (ap[10]  - bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap  - *bp);
+                                        ap++;
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                ap = (complex*)range.Item2;
+                                bp = (complex*)range.Item3;
+                                cp = (complex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   complex val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  - val);
+                                        cp[1] =   (ap[1]  - val);
+                                        cp[2] =   (ap[2]  - val);
+                                        cp[3] =   (ap[3]  - val);
+                                        cp[4] =   (ap[4]  - val);
+                                        cp[5] =   (ap[5]  - val);
+                                        cp[6] =   (ap[6]  - val);
+                                        cp[7] =   (ap[7]  - val);
+                                        cp[8] =   (ap[8]  - val);
+                                        cp[9] =   (ap[9]  - val);
+                                        cp[10] =   (ap[10]  - val);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap  - val);
+                                        ap++;
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            if (dim == 0) {
+                                cp = (complex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (complex*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (cp[0]  - bp[0]);
+                                        cp[1] =   (cp[1]  - bp[1]);
+                                        cp[2] =   (cp[2]  - bp[2]);
+                                        cp[3] =   (cp[3]  - bp[3]);
+                                        cp[4] =   (cp[4]  - bp[4]);
+                                        cp[5] =   (cp[5]  - bp[5]);
+                                        cp[6] =   (cp[6]  - bp[6]);
+                                        cp[7] =   (cp[7]  - bp[7]);
+                                        cp[8] =   (cp[8]  - bp[8]);
+                                        cp[9] =   (cp[9]  - bp[9]);
+                                        cp[10] =   (cp[10]  - bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*cp  - *bp);
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                bp = (complex*)range.Item3;
+                                cp = (complex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    complex val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (cp[0]  - val);
+                                        cp[1] =   (cp[1]  - val);
+                                        cp[2] =   (cp[2]  - val);
+                                        cp[3] =   (cp[3]  - val);
+                                        cp[4] =   (cp[4]  - val);
+                                        cp[5] =   (cp[5]  - val);
+                                        cp[6] =   (cp[6]  - val);
+                                        cp[7] =   (cp[7]  - val);
+                                        cp[8] =   (cp[8]  - val);
+                                        cp[9] =   (cp[9]  - val);
+                                        cp[10] =   (cp[10]  - val);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l --> 0) {
+                                        *cp =   (*cp  - val);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outDims.NumberOfElements >= Settings.s_minParallelElement1Count
+                    && outDims[1] > 1) {
+                        if (outDims[1] > workItemCount) {
+                        workItemLength = outDims[1] / workItemCount;
+                    } else {
+                        workItemLength = outDims[1] / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outDims[1];
+                    workItemCount = 1;
+                }
+
+                fixed ( complex* arrAP = arrA)
+                fixed ( complex* arrBP = arrB)
+                fixed ( complex* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, IntPtr, IntPtr, IntPtr> range = new Tuple<int, IntPtr, IntPtr, IntPtr>
+                               (workItemLength
+                               , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                               , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                               , (IntPtr)(retArrP + i * outDims[0] * workItemLength)); 
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, IntPtr, IntPtr, IntPtr>
+                                (outDims[1] - i * workItemLength
+                                , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                                , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                                , (IntPtr)(retArrP + i * outDims[0] * workItemLength)));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<complex>(retStorage);
+            //}  // no scopes here! it disables implace operations
+        }
+
+        /// <summary>Subtract arrays elementwise</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>New array with result of subtraction</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<byte>  subtract(ILInArray<byte> A, ILInArray<byte> B) {
+            using (ILScope.Enter(A,B)) {
+                int outLen; 
+                BinOpItMode mode; 
+                byte [] retArr;
+                byte [] arrA = A.GetArrayForRead();
+                byte[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size; 
+                    if (B.IsScalar) {
+                       
+                        return new  ILRetArray<byte> (new  byte [1]{ saturateByte (A.GetValue(0)  - (double) B.GetValue(0))}, A.Size);
+                    } else if (B.IsEmpty) {
+                        return  ILRetArray<byte>.empty(outDims); 
+                    } else {
+                        outLen = outDims.NumberOfElements; 
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< byte > (outLen);
+                            mode = BinOpItMode.SAN; 
+                        } else {
+                            mode = BinOpItMode.SAI; 
+                        }
+                    }
+                } else {
+                    outDims = A.Size; 
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return  ILRetArray<byte>.empty(A.Size);  
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< byte > (outLen);
+                            mode = BinOpItMode.ASN; 
+                        } else {
+                            mode = BinOpItMode.ASI; 
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  subtractEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (A.TryGetStorage4InplaceOp(out retArr)) 
+                            mode  = BinOpItMode.AAIA; 
+                        else if (B.TryGetStorage4InplaceOp(out retArr)) 
+                            mode = BinOpItMode.AAIB; 
+                        else {
+                            retArr = ILMemoryPool.Pool.New< byte > (outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<byte> retStorage = new ILDenseStorage<byte>(retArr, outDims);
+                int i = 0, workerCount = 1; 
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cp = (byte*)range.Item5 + range.Item1;
+                    byte scalar;
+                    int j = range.Item2; 
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           byte* bp = ((byte*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                                cp[0] =  saturateByte (cp[0]  - (double) bp[0]);
+                                cp[1] =  saturateByte (cp[1]  - (double) bp[1]);
+                                cp[2] =  saturateByte (cp[2]  - (double) bp[2]);
+                                cp[3] =  saturateByte (cp[3]  - (double) bp[3]);
+                                cp[4] =  saturateByte (cp[4]  - (double) bp[4]);
+                                cp[5] =  saturateByte (cp[5]  - (double) bp[5]);
+                                cp[6] =  saturateByte (cp[6]  - (double) bp[6]);
+                                cp[7] =  saturateByte (cp[7]  - (double) bp[7]);
+                                cp[8] =  saturateByte (cp[8]  - (double) bp[8]);
+                                cp[9] =  saturateByte (cp[9]  - (double) bp[9]);
+                                cp[10] =  saturateByte (cp[10]  - (double) bp[10]);
+                                cp[11] =  saturateByte (cp[11]  - (double) bp[11]);
+                                cp[12] =  saturateByte (cp[12]  - (double) bp[12]);
+                                cp[13] =  saturateByte (cp[13]  - (double) bp[13]);
+                                cp[14] =  saturateByte (cp[14]  - (double) bp[14]);
+                                cp[15] =  saturateByte (cp[15]  - (double) bp[15]);
+                                cp[16] =  saturateByte (cp[16]  - (double) bp[16]);
+                                cp[17] =  saturateByte (cp[17]  - (double) bp[17]);
+                                cp[18] =  saturateByte (cp[18]  - (double) bp[18]);
+                                cp[19] =  saturateByte (cp[19]  - (double) bp[19]);
+                                cp[20] =  saturateByte (cp[20]  - (double) bp[20]);
+                                cp += 21; bp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateByte (*cp  - (double) *bp);
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           byte* ap = ((byte*)range.Item3 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateByte (ap[0]  - (double) cp[0]);
+                                cp[1] =  saturateByte (ap[1]  - (double) cp[1]);
+                                cp[2] =  saturateByte (ap[2]  - (double) cp[2]);
+                                cp[3] =  saturateByte (ap[3]  - (double) cp[3]);
+                                cp[4] =  saturateByte (ap[4]  - (double) cp[4]);
+                                cp[5] =  saturateByte (ap[5]  - (double) cp[5]);
+                                cp[6] =  saturateByte (ap[6]  - (double) cp[6]);
+                                cp[7] =  saturateByte (ap[7]  - (double) cp[7]);
+                                cp[8] =  saturateByte (ap[8]  - (double) cp[8]);
+                                cp[9] =  saturateByte (ap[9]  - (double) cp[9]);
+                                cp[10] =  saturateByte (ap[10]  - (double) cp[10]);
+                                cp[11] =  saturateByte (ap[11]  - (double) cp[11]);
+                                cp[12] =  saturateByte (ap[12]  - (double) cp[12]);
+                                cp[13] =  saturateByte (ap[13]  - (double) cp[13]);
+                                cp[14] =  saturateByte (ap[14]  - (double) cp[14]);
+                                cp[15] =  saturateByte (ap[15]  - (double) cp[15]);
+                                cp[16] =  saturateByte (ap[16]  - (double) cp[16]);
+                                cp[17] =  saturateByte (ap[17]  - (double) cp[17]);
+                                cp[18] =  saturateByte (ap[18]  - (double) cp[18]);
+                                cp[19] =  saturateByte (ap[19]  - (double) cp[19]);
+                                cp[20] =  saturateByte (ap[20]  - (double) cp[20]);
+                                ap += 21; cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateByte (*ap  - (double) *cp);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((byte*)range.Item3 + range.Item1);
+                            bp = ((byte*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateByte (ap[0]  - (double) bp[0]);
+                                cp[1] =  saturateByte (ap[1]  - (double) bp[1]);
+                                cp[2] =  saturateByte (ap[2]  - (double) bp[2]);
+                                cp[3] =  saturateByte (ap[3]  - (double) bp[3]);
+                                cp[4] =  saturateByte (ap[4]  - (double) bp[4]);
+                                cp[5] =  saturateByte (ap[5]  - (double) bp[5]);
+                                cp[6] =  saturateByte (ap[6]  - (double) bp[6]);
+                                cp[7] =  saturateByte (ap[7]  - (double) bp[7]);
+                                cp[8] =  saturateByte (ap[8]  - (double) bp[8]);
+                                cp[9] =  saturateByte (ap[9]  - (double) bp[9]);
+                                cp[10] =  saturateByte (ap[10]  - (double) bp[10]);
+                                cp[11] =  saturateByte (ap[11]  - (double) bp[11]);
+                                cp[12] =  saturateByte (ap[12]  - (double) bp[12]);
+                                cp[13] =  saturateByte (ap[13]  - (double) bp[13]);
+                                cp[14] =  saturateByte (ap[14]  - (double) bp[14]);
+                                cp[15] =  saturateByte (ap[15]  - (double) bp[15]);
+                                cp[16] =  saturateByte (ap[16]  - (double) bp[16]);
+                                cp[17] =  saturateByte (ap[17]  - (double) bp[17]);
+                                cp[18] =  saturateByte (ap[18]  - (double) bp[18]);
+                                cp[19] =  saturateByte (ap[19]  - (double) bp[19]);
+                                cp[20] =  saturateByte (ap[20]  - (double) bp[20]);
+                                ap+=21; bp+=21; cp+=21; j-=21;
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateByte (*ap  - (double) *bp);
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((byte*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateByte (cp[0]  - (double) scalar);
+                                cp[1] =  saturateByte (cp[1]  - (double) scalar);
+                                cp[2] =  saturateByte (cp[2]  - (double) scalar);
+                                cp[3] =  saturateByte (cp[3]  - (double) scalar);
+                                cp[4] =  saturateByte (cp[4]  - (double) scalar);
+                                cp[5] =  saturateByte (cp[5]  - (double) scalar);
+                                cp[6] =  saturateByte (cp[6]  - (double) scalar);
+                                cp[7] =  saturateByte (cp[7]  - (double) scalar);
+                                cp[8] =  saturateByte (cp[8]  - (double) scalar);
+                                cp[9] =  saturateByte (cp[9]  - (double) scalar);
+                                cp[10] =  saturateByte (cp[10]  - (double) scalar);
+                                cp[11] =  saturateByte (cp[11]  - (double) scalar);
+                                cp[12] =  saturateByte (cp[12]  - (double) scalar);
+                                cp[13] =  saturateByte (cp[13]  - (double) scalar);
+                                cp[14] =  saturateByte (cp[14]  - (double) scalar);
+                                cp[15] =  saturateByte (cp[15]  - (double) scalar);
+                                cp[16] =  saturateByte (cp[16]  - (double) scalar);
+                                cp[17] =  saturateByte (cp[17]  - (double) scalar);
+                                cp[18] =  saturateByte (cp[18]  - (double) scalar);
+                                cp[19] =  saturateByte (cp[19]  - (double) scalar);
+                                cp[20] =  saturateByte (cp[20]  - (double) scalar);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateByte (*cp  - (double) scalar);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((byte*)range.Item3 + range.Item1);
+                            scalar = *((byte*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateByte (ap[0]  - (double) scalar);
+                                cp[1] =  saturateByte (ap[1]  - (double) scalar);
+                                cp[2] =  saturateByte (ap[2]  - (double) scalar);
+                                cp[3] =  saturateByte (ap[3]  - (double) scalar);
+                                cp[4] =  saturateByte (ap[4]  - (double) scalar);
+                                cp[5] =  saturateByte (ap[5]  - (double) scalar);
+                                cp[6] =  saturateByte (ap[6]  - (double) scalar);
+                                cp[7] =  saturateByte (ap[7]  - (double) scalar);
+                                cp[8] =  saturateByte (ap[8]  - (double) scalar);
+                                cp[9] =  saturateByte (ap[9]  - (double) scalar);
+                                cp[10] =  saturateByte (ap[10]  - (double) scalar);
+                                cp[11] =  saturateByte (ap[11]  - (double) scalar);
+                                cp[12] =  saturateByte (ap[12]  - (double) scalar);
+                                cp[13] =  saturateByte (ap[13]  - (double) scalar);
+                                cp[14] =  saturateByte (ap[14]  - (double) scalar);
+                                cp[15] =  saturateByte (ap[15]  - (double) scalar);
+                                cp[16] =  saturateByte (ap[16]  - (double) scalar);
+                                cp[17] =  saturateByte (ap[17]  - (double) scalar);
+                                cp[18] =  saturateByte (ap[18]  - (double) scalar);
+                                cp[19] =  saturateByte (ap[19]  - (double) scalar);
+                                cp[20] =  saturateByte (ap[20]  - (double) scalar);
+                                ap+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateByte (*ap  - (double) scalar);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((byte*)range.Item3);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateByte (scalar  - (double) cp[0]);
+                                cp[1] =  saturateByte (scalar  - (double) cp[1]);
+                                cp[2] =  saturateByte (scalar  - (double) cp[2]);
+                                cp[3] =  saturateByte (scalar  - (double) cp[3]);
+                                cp[4] =  saturateByte (scalar  - (double) cp[4]);
+                                cp[5] =  saturateByte (scalar  - (double) cp[5]);
+                                cp[6] =  saturateByte (scalar  - (double) cp[6]);
+                                cp[7] =  saturateByte (scalar  - (double) cp[7]);
+                                cp[8] =  saturateByte (scalar  - (double) cp[8]);
+                                cp[9] =  saturateByte (scalar  - (double) cp[9]);
+                                cp[10] =  saturateByte (scalar  - (double) cp[10]);
+                                cp[11] =  saturateByte (scalar  - (double) cp[11]);
+                                cp[12] =  saturateByte (scalar  - (double) cp[12]);
+                                cp[13] =  saturateByte (scalar  - (double) cp[13]);
+                                cp[14] =  saturateByte (scalar  - (double) cp[14]);
+                                cp[15] =  saturateByte (scalar  - (double) cp[15]);
+                                cp[16] =  saturateByte (scalar  - (double) cp[16]);
+                                cp[17] =  saturateByte (scalar  - (double) cp[17]);
+                                cp[18] =  saturateByte (scalar  - (double) cp[18]);
+                                cp[19] =  saturateByte (scalar  - (double) cp[19]);
+                                cp[20] =  saturateByte (scalar  - (double) cp[20]);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateByte (scalar  - (double) *cp);
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((byte*)range.Item3);
+                            bp = ((byte*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateByte (scalar  - (double) bp[0]);
+                                cp[1] =  saturateByte (scalar  - (double) bp[1]);
+                                cp[2] =  saturateByte (scalar  - (double) bp[2]);
+                                cp[3] =  saturateByte (scalar  - (double) bp[3]);
+                                cp[4] =  saturateByte (scalar  - (double) bp[4]);
+                                cp[5] =  saturateByte (scalar  - (double) bp[5]);
+                                cp[6] =  saturateByte (scalar  - (double) bp[6]);
+                                cp[7] =  saturateByte (scalar  - (double) bp[7]);
+                                cp[8] =  saturateByte (scalar  - (double) bp[8]);
+                                cp[9] =  saturateByte (scalar  - (double) bp[9]);
+                                cp[10] =  saturateByte (scalar  - (double) bp[10]);
+                                cp[11] =  saturateByte (scalar  - (double) bp[11]);
+                                cp[12] =  saturateByte (scalar  - (double) bp[12]);
+                                cp[13] =  saturateByte (scalar  - (double) bp[13]);
+                                cp[14] =  saturateByte (scalar  - (double) bp[14]);
+                                cp[15] =  saturateByte (scalar  - (double) bp[15]);
+                                cp[16] =  saturateByte (scalar  - (double) bp[16]);
+                                cp[17] =  saturateByte (scalar  - (double) bp[17]);
+                                cp[18] =  saturateByte (scalar  - (double) bp[18]);
+                                cp[19] =  saturateByte (scalar  - (double) bp[19]);
+                                cp[20] =  saturateByte (scalar  - (double) bp[20]);
+                                bp+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateByte (scalar  - (double) *bp);
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work 
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                
+                fixed ( byte* arrAP = arrA)
+                fixed ( byte* arrBP = arrB)
+                fixed ( byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range 
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new  ILRetArray< byte>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<byte>  subtractEx(ILInArray<byte> A, ILInArray<byte> B) {
+            //using (ILScope.Enter(A, B)) { we cannot start a new scope here, since this would prevent A and B to be used implace if applicable
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<byte>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<byte>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<byte>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                dim = -(dim - 1);  // 0 -> 1, 1 -> 0
+                #endregion
+
+                #region parameter preparation
+               
+                byte[] retArr;
+               
+                byte[] arrA = A.GetArrayForRead();
+               
+                byte[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int workItemMultiplierLenA;
+                int workItemMultiplierLenB;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    workItemMultiplierLenB = outDims[0]; 
+                    workItemMultiplierLenA = dim;  // 0 for column, 1 for row vector
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    workItemMultiplierLenB = dim;  // 0 for column, 1 for row vector
+                    workItemMultiplierLenA = outDims[0]; 
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one singleton dimension in either A or B");
+                }
+                int itLen = outDims[0]; // (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<byte> retStorage = new ILDenseStorage<byte>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    byte* ap;
+                   
+                    byte* bp;
+                   
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            if (dim == 0) {
+                                bp = (byte*)range.Item3;
+                                cp = (byte*)range.Item4; 
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (byte*)range.Item2;
+                                    int l = itLen; 
+                                    while (l > 10) {
+                                        cp[0] =  saturateByte (ap[0]  - (double) bp[0]);
+                                        cp[1] =  saturateByte (ap[1]  - (double) bp[1]);
+                                        cp[2] =  saturateByte (ap[2]  - (double) bp[2]);
+                                        cp[3] =  saturateByte (ap[3]  - (double) bp[3]);
+                                        cp[4] =  saturateByte (ap[4]  - (double) bp[4]);
+                                        cp[5] =  saturateByte (ap[5]  - (double) bp[5]);
+                                        cp[6] =  saturateByte (ap[6]  - (double) bp[6]);
+                                        cp[7] =  saturateByte (ap[7]  - (double) bp[7]);
+                                        cp[8] =  saturateByte (ap[8]  - (double) bp[8]);
+                                        cp[9] =  saturateByte (ap[9]  - (double) bp[9]);
+                                        cp[10] =  saturateByte (ap[10]  - (double) bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =  saturateByte (*ap++  - (double) *bp++);
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                ap = (byte*)range.Item2;
+                                bp = (byte*)range.Item3;
+                                cp = (byte*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   byte val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateByte (val  - (double) bp[0]);
+                                        cp[1] =  saturateByte (val  - (double) bp[1]);
+                                        cp[2] =  saturateByte (val  - (double) bp[2]);
+                                        cp[3] =  saturateByte (val  - (double) bp[3]);
+                                        cp[4] =  saturateByte (val  - (double) bp[4]);
+                                        cp[5] =  saturateByte (val  - (double) bp[5]);
+                                        cp[6] =  saturateByte (val  - (double) bp[6]);
+                                        cp[7] =  saturateByte (val  - (double) bp[7]);
+                                        cp[8] =  saturateByte (val  - (double) bp[8]);
+                                        cp[9] =  saturateByte (val  - (double) bp[9]);
+                                        cp[10] =  saturateByte (val  - (double) bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11; 
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =  saturateByte (val  - (double) *bp++);
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            if (dim == 0) {
+                                cp = (byte*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (byte*)range.Item2;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateByte (ap[0]  - (double) cp[0]);
+                                        cp[1] =  saturateByte (ap[1]  - (double) cp[1]);
+                                        cp[2] =  saturateByte (ap[2]  - (double) cp[2]);
+                                        cp[3] =  saturateByte (ap[3]  - (double) cp[3]);
+                                        cp[4] =  saturateByte (ap[4]  - (double) cp[4]);
+                                        cp[5] =  saturateByte (ap[5]  - (double) cp[5]);
+                                        cp[6] =  saturateByte (ap[6]  - (double) cp[6]);
+                                        cp[7] =  saturateByte (ap[7]  - (double) cp[7]);
+                                        cp[8] =  saturateByte (ap[8]  - (double) cp[8]);
+                                        cp[9] =  saturateByte (ap[9]  - (double) cp[9]);
+                                        cp[10] =  saturateByte (ap[10]  - (double) cp[10]);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateByte (*ap++  - (double) *cp);
+                                        cp++; 
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                cp = (byte*)range.Item4;
+                                ap = (byte*)range.Item2;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    byte val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateByte (val  - (double) cp[0]);
+                                        cp[1] =  saturateByte (val  - (double) cp[1]);
+                                        cp[2] =  saturateByte (val  - (double) cp[2]);
+                                        cp[3] =  saturateByte (val  - (double) cp[3]);
+                                        cp[4] =  saturateByte (val  - (double) cp[4]);
+                                        cp[5] =  saturateByte (val  - (double) cp[5]);
+                                        cp[6] =  saturateByte (val  - (double) cp[6]);
+                                        cp[7] =  saturateByte (val  - (double) cp[7]);
+                                        cp[8] =  saturateByte (val  - (double) cp[8]);
+                                        cp[9] =  saturateByte (val  - (double) cp[9]);
+                                        cp[10] =  saturateByte (val  - (double) cp[10]);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateByte (val  - (double) *cp);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            if (dim == 0) {
+                                ap = (byte*)range.Item2;
+                                cp = (byte*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (byte*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateByte (ap[0]  - (double) bp[0]);
+                                        cp[1] =  saturateByte (ap[1]  - (double) bp[1]);
+                                        cp[2] =  saturateByte (ap[2]  - (double) bp[2]);
+                                        cp[3] =  saturateByte (ap[3]  - (double) bp[3]);
+                                        cp[4] =  saturateByte (ap[4]  - (double) bp[4]);
+                                        cp[5] =  saturateByte (ap[5]  - (double) bp[5]);
+                                        cp[6] =  saturateByte (ap[6]  - (double) bp[6]);
+                                        cp[7] =  saturateByte (ap[7]  - (double) bp[7]);
+                                        cp[8] =  saturateByte (ap[8]  - (double) bp[8]);
+                                        cp[9] =  saturateByte (ap[9]  - (double) bp[9]);
+                                        cp[10] =  saturateByte (ap[10]  - (double) bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateByte (*ap  - (double) *bp);
+                                        ap++;
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                ap = (byte*)range.Item2;
+                                bp = (byte*)range.Item3;
+                                cp = (byte*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   byte val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateByte (ap[0]  - (double) val);
+                                        cp[1] =  saturateByte (ap[1]  - (double) val);
+                                        cp[2] =  saturateByte (ap[2]  - (double) val);
+                                        cp[3] =  saturateByte (ap[3]  - (double) val);
+                                        cp[4] =  saturateByte (ap[4]  - (double) val);
+                                        cp[5] =  saturateByte (ap[5]  - (double) val);
+                                        cp[6] =  saturateByte (ap[6]  - (double) val);
+                                        cp[7] =  saturateByte (ap[7]  - (double) val);
+                                        cp[8] =  saturateByte (ap[8]  - (double) val);
+                                        cp[9] =  saturateByte (ap[9]  - (double) val);
+                                        cp[10] =  saturateByte (ap[10]  - (double) val);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateByte (*ap  - (double) val);
+                                        ap++;
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            if (dim == 0) {
+                                cp = (byte*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (byte*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateByte (cp[0]  - (double) bp[0]);
+                                        cp[1] =  saturateByte (cp[1]  - (double) bp[1]);
+                                        cp[2] =  saturateByte (cp[2]  - (double) bp[2]);
+                                        cp[3] =  saturateByte (cp[3]  - (double) bp[3]);
+                                        cp[4] =  saturateByte (cp[4]  - (double) bp[4]);
+                                        cp[5] =  saturateByte (cp[5]  - (double) bp[5]);
+                                        cp[6] =  saturateByte (cp[6]  - (double) bp[6]);
+                                        cp[7] =  saturateByte (cp[7]  - (double) bp[7]);
+                                        cp[8] =  saturateByte (cp[8]  - (double) bp[8]);
+                                        cp[9] =  saturateByte (cp[9]  - (double) bp[9]);
+                                        cp[10] =  saturateByte (cp[10]  - (double) bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateByte (*cp  - (double) *bp);
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                bp = (byte*)range.Item3;
+                                cp = (byte*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    byte val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateByte (cp[0]  - (double) val);
+                                        cp[1] =  saturateByte (cp[1]  - (double) val);
+                                        cp[2] =  saturateByte (cp[2]  - (double) val);
+                                        cp[3] =  saturateByte (cp[3]  - (double) val);
+                                        cp[4] =  saturateByte (cp[4]  - (double) val);
+                                        cp[5] =  saturateByte (cp[5]  - (double) val);
+                                        cp[6] =  saturateByte (cp[6]  - (double) val);
+                                        cp[7] =  saturateByte (cp[7]  - (double) val);
+                                        cp[8] =  saturateByte (cp[8]  - (double) val);
+                                        cp[9] =  saturateByte (cp[9]  - (double) val);
+                                        cp[10] =  saturateByte (cp[10]  - (double) val);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l --> 0) {
+                                        *cp =  saturateByte (*cp  - (double) val);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outDims.NumberOfElements >= Settings.s_minParallelElement1Count
+                    && outDims[1] > 1) {
+                        if (outDims[1] > workItemCount) {
+                        workItemLength = outDims[1] / workItemCount;
+                    } else {
+                        workItemLength = outDims[1] / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outDims[1];
+                    workItemCount = 1;
+                }
+
+                fixed ( byte* arrAP = arrA)
+                fixed ( byte* arrBP = arrB)
+                fixed ( byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, IntPtr, IntPtr, IntPtr> range = new Tuple<int, IntPtr, IntPtr, IntPtr>
+                               (workItemLength
+                               , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                               , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                               , (IntPtr)(retArrP + i * outDims[0] * workItemLength)); 
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, IntPtr, IntPtr, IntPtr>
+                                (outDims[1] - i * workItemLength
+                                , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                                , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                                , (IntPtr)(retArrP + i * outDims[0] * workItemLength)));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<byte>(retStorage);
+            //}  // no scopes here! it disables implace operations
+        }
+
+        /// <summary>Subtract arrays elementwise</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>New array with result of subtraction</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<double>  subtract(ILInArray<double> A, ILInArray<double> B) {
+            using (ILScope.Enter(A,B)) {
+                int outLen; 
+                BinOpItMode mode; 
+                double [] retArr;
+                double [] arrA = A.GetArrayForRead();
+                double[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size; 
+                    if (B.IsScalar) {
+                       
+                        return new  ILRetArray<double> (new  double [1]{  (A.GetValue(0)  - B.GetValue(0))}, A.Size);
+                    } else if (B.IsEmpty) {
+                        return  ILRetArray<double>.empty(outDims); 
+                    } else {
+                        outLen = outDims.NumberOfElements; 
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< double > (outLen);
+                            mode = BinOpItMode.SAN; 
+                        } else {
+                            mode = BinOpItMode.SAI; 
+                        }
+                    }
+                } else {
+                    outDims = A.Size; 
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return  ILRetArray<double>.empty(A.Size);  
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< double > (outLen);
+                            mode = BinOpItMode.ASN; 
+                        } else {
+                            mode = BinOpItMode.ASI; 
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  subtractEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (A.TryGetStorage4InplaceOp(out retArr)) 
+                            mode  = BinOpItMode.AAIA; 
+                        else if (B.TryGetStorage4InplaceOp(out retArr)) 
+                            mode = BinOpItMode.AAIB; 
+                        else {
+                            retArr = ILMemoryPool.Pool.New< double > (outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<double> retStorage = new ILDenseStorage<double>(retArr, outDims);
+                int i = 0, workerCount = 1; 
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    double* cp = (double*)range.Item5 + range.Item1;
+                    double scalar;
+                    int j = range.Item2; 
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           double* bp = ((double*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                                cp[0] =   (cp[0]  - bp[0]);
+                                cp[1] =   (cp[1]  - bp[1]);
+                                cp[2] =   (cp[2]  - bp[2]);
+                                cp[3] =   (cp[3]  - bp[3]);
+                                cp[4] =   (cp[4]  - bp[4]);
+                                cp[5] =   (cp[5]  - bp[5]);
+                                cp[6] =   (cp[6]  - bp[6]);
+                                cp[7] =   (cp[7]  - bp[7]);
+                                cp[8] =   (cp[8]  - bp[8]);
+                                cp[9] =   (cp[9]  - bp[9]);
+                                cp[10] =   (cp[10]  - bp[10]);
+                                cp[11] =   (cp[11]  - bp[11]);
+                                cp[12] =   (cp[12]  - bp[12]);
+                                cp[13] =   (cp[13]  - bp[13]);
+                                cp[14] =   (cp[14]  - bp[14]);
+                                cp[15] =   (cp[15]  - bp[15]);
+                                cp[16] =   (cp[16]  - bp[16]);
+                                cp[17] =   (cp[17]  - bp[17]);
+                                cp[18] =   (cp[18]  - bp[18]);
+                                cp[19] =   (cp[19]  - bp[19]);
+                                cp[20] =   (cp[20]  - bp[20]);
+                                cp += 21; bp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*cp  - *bp);
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           double* ap = ((double*)range.Item3 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  - cp[0]);
+                                cp[1] =   (ap[1]  - cp[1]);
+                                cp[2] =   (ap[2]  - cp[2]);
+                                cp[3] =   (ap[3]  - cp[3]);
+                                cp[4] =   (ap[4]  - cp[4]);
+                                cp[5] =   (ap[5]  - cp[5]);
+                                cp[6] =   (ap[6]  - cp[6]);
+                                cp[7] =   (ap[7]  - cp[7]);
+                                cp[8] =   (ap[8]  - cp[8]);
+                                cp[9] =   (ap[9]  - cp[9]);
+                                cp[10] =   (ap[10]  - cp[10]);
+                                cp[11] =   (ap[11]  - cp[11]);
+                                cp[12] =   (ap[12]  - cp[12]);
+                                cp[13] =   (ap[13]  - cp[13]);
+                                cp[14] =   (ap[14]  - cp[14]);
+                                cp[15] =   (ap[15]  - cp[15]);
+                                cp[16] =   (ap[16]  - cp[16]);
+                                cp[17] =   (ap[17]  - cp[17]);
+                                cp[18] =   (ap[18]  - cp[18]);
+                                cp[19] =   (ap[19]  - cp[19]);
+                                cp[20] =   (ap[20]  - cp[20]);
+                                ap += 21; cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  - *cp);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((double*)range.Item3 + range.Item1);
+                            bp = ((double*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  - bp[0]);
+                                cp[1] =   (ap[1]  - bp[1]);
+                                cp[2] =   (ap[2]  - bp[2]);
+                                cp[3] =   (ap[3]  - bp[3]);
+                                cp[4] =   (ap[4]  - bp[4]);
+                                cp[5] =   (ap[5]  - bp[5]);
+                                cp[6] =   (ap[6]  - bp[6]);
+                                cp[7] =   (ap[7]  - bp[7]);
+                                cp[8] =   (ap[8]  - bp[8]);
+                                cp[9] =   (ap[9]  - bp[9]);
+                                cp[10] =   (ap[10]  - bp[10]);
+                                cp[11] =   (ap[11]  - bp[11]);
+                                cp[12] =   (ap[12]  - bp[12]);
+                                cp[13] =   (ap[13]  - bp[13]);
+                                cp[14] =   (ap[14]  - bp[14]);
+                                cp[15] =   (ap[15]  - bp[15]);
+                                cp[16] =   (ap[16]  - bp[16]);
+                                cp[17] =   (ap[17]  - bp[17]);
+                                cp[18] =   (ap[18]  - bp[18]);
+                                cp[19] =   (ap[19]  - bp[19]);
+                                cp[20] =   (ap[20]  - bp[20]);
+                                ap+=21; bp+=21; cp+=21; j-=21;
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  - *bp);
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((double*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =   (cp[0]  - scalar);
+                                cp[1] =   (cp[1]  - scalar);
+                                cp[2] =   (cp[2]  - scalar);
+                                cp[3] =   (cp[3]  - scalar);
+                                cp[4] =   (cp[4]  - scalar);
+                                cp[5] =   (cp[5]  - scalar);
+                                cp[6] =   (cp[6]  - scalar);
+                                cp[7] =   (cp[7]  - scalar);
+                                cp[8] =   (cp[8]  - scalar);
+                                cp[9] =   (cp[9]  - scalar);
+                                cp[10] =   (cp[10]  - scalar);
+                                cp[11] =   (cp[11]  - scalar);
+                                cp[12] =   (cp[12]  - scalar);
+                                cp[13] =   (cp[13]  - scalar);
+                                cp[14] =   (cp[14]  - scalar);
+                                cp[15] =   (cp[15]  - scalar);
+                                cp[16] =   (cp[16]  - scalar);
+                                cp[17] =   (cp[17]  - scalar);
+                                cp[18] =   (cp[18]  - scalar);
+                                cp[19] =   (cp[19]  - scalar);
+                                cp[20] =   (cp[20]  - scalar);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*cp  - scalar);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((double*)range.Item3 + range.Item1);
+                            scalar = *((double*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  - scalar);
+                                cp[1] =   (ap[1]  - scalar);
+                                cp[2] =   (ap[2]  - scalar);
+                                cp[3] =   (ap[3]  - scalar);
+                                cp[4] =   (ap[4]  - scalar);
+                                cp[5] =   (ap[5]  - scalar);
+                                cp[6] =   (ap[6]  - scalar);
+                                cp[7] =   (ap[7]  - scalar);
+                                cp[8] =   (ap[8]  - scalar);
+                                cp[9] =   (ap[9]  - scalar);
+                                cp[10] =   (ap[10]  - scalar);
+                                cp[11] =   (ap[11]  - scalar);
+                                cp[12] =   (ap[12]  - scalar);
+                                cp[13] =   (ap[13]  - scalar);
+                                cp[14] =   (ap[14]  - scalar);
+                                cp[15] =   (ap[15]  - scalar);
+                                cp[16] =   (ap[16]  - scalar);
+                                cp[17] =   (ap[17]  - scalar);
+                                cp[18] =   (ap[18]  - scalar);
+                                cp[19] =   (ap[19]  - scalar);
+                                cp[20] =   (ap[20]  - scalar);
+                                ap+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  - scalar);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((double*)range.Item3);
+                            while (j > 20) {
+                               
+                                cp[0] =   (scalar  - cp[0]);
+                                cp[1] =   (scalar  - cp[1]);
+                                cp[2] =   (scalar  - cp[2]);
+                                cp[3] =   (scalar  - cp[3]);
+                                cp[4] =   (scalar  - cp[4]);
+                                cp[5] =   (scalar  - cp[5]);
+                                cp[6] =   (scalar  - cp[6]);
+                                cp[7] =   (scalar  - cp[7]);
+                                cp[8] =   (scalar  - cp[8]);
+                                cp[9] =   (scalar  - cp[9]);
+                                cp[10] =   (scalar  - cp[10]);
+                                cp[11] =   (scalar  - cp[11]);
+                                cp[12] =   (scalar  - cp[12]);
+                                cp[13] =   (scalar  - cp[13]);
+                                cp[14] =   (scalar  - cp[14]);
+                                cp[15] =   (scalar  - cp[15]);
+                                cp[16] =   (scalar  - cp[16]);
+                                cp[17] =   (scalar  - cp[17]);
+                                cp[18] =   (scalar  - cp[18]);
+                                cp[19] =   (scalar  - cp[19]);
+                                cp[20] =   (scalar  - cp[20]);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (scalar  - *cp);
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((double*)range.Item3);
+                            bp = ((double*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (scalar  - bp[0]);
+                                cp[1] =   (scalar  - bp[1]);
+                                cp[2] =   (scalar  - bp[2]);
+                                cp[3] =   (scalar  - bp[3]);
+                                cp[4] =   (scalar  - bp[4]);
+                                cp[5] =   (scalar  - bp[5]);
+                                cp[6] =   (scalar  - bp[6]);
+                                cp[7] =   (scalar  - bp[7]);
+                                cp[8] =   (scalar  - bp[8]);
+                                cp[9] =   (scalar  - bp[9]);
+                                cp[10] =   (scalar  - bp[10]);
+                                cp[11] =   (scalar  - bp[11]);
+                                cp[12] =   (scalar  - bp[12]);
+                                cp[13] =   (scalar  - bp[13]);
+                                cp[14] =   (scalar  - bp[14]);
+                                cp[15] =   (scalar  - bp[15]);
+                                cp[16] =   (scalar  - bp[16]);
+                                cp[17] =   (scalar  - bp[17]);
+                                cp[18] =   (scalar  - bp[18]);
+                                cp[19] =   (scalar  - bp[19]);
+                                cp[20] =   (scalar  - bp[20]);
+                                bp+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (scalar  - *bp);
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work 
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                
+                fixed ( double* arrAP = arrA)
+                fixed ( double* arrBP = arrB)
+                fixed ( double* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range 
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new  ILRetArray< double>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<double>  subtractEx(ILInArray<double> A, ILInArray<double> B) {
+            //using (ILScope.Enter(A, B)) { we cannot start a new scope here, since this would prevent A and B to be used implace if applicable
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<double>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<double>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<double>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                dim = -(dim - 1);  // 0 -> 1, 1 -> 0
+                #endregion
+
+                #region parameter preparation
+               
+                double[] retArr;
+               
+                double[] arrA = A.GetArrayForRead();
+               
+                double[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int workItemMultiplierLenA;
+                int workItemMultiplierLenB;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<double>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    workItemMultiplierLenB = outDims[0]; 
+                    workItemMultiplierLenA = dim;  // 0 for column, 1 for row vector
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<double>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    workItemMultiplierLenB = dim;  // 0 for column, 1 for row vector
+                    workItemMultiplierLenA = outDims[0]; 
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one singleton dimension in either A or B");
+                }
+                int itLen = outDims[0]; // (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<double> retStorage = new ILDenseStorage<double>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    double* ap;
+                   
+                    double* bp;
+                   
+                    double* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            if (dim == 0) {
+                                bp = (double*)range.Item3;
+                                cp = (double*)range.Item4; 
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (double*)range.Item2;
+                                    int l = itLen; 
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  - bp[0]);
+                                        cp[1] =   (ap[1]  - bp[1]);
+                                        cp[2] =   (ap[2]  - bp[2]);
+                                        cp[3] =   (ap[3]  - bp[3]);
+                                        cp[4] =   (ap[4]  - bp[4]);
+                                        cp[5] =   (ap[5]  - bp[5]);
+                                        cp[6] =   (ap[6]  - bp[6]);
+                                        cp[7] =   (ap[7]  - bp[7]);
+                                        cp[8] =   (ap[8]  - bp[8]);
+                                        cp[9] =   (ap[9]  - bp[9]);
+                                        cp[10] =   (ap[10]  - bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =   (*ap++  - *bp++);
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                ap = (double*)range.Item2;
+                                bp = (double*)range.Item3;
+                                cp = (double*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   double val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (val  - bp[0]);
+                                        cp[1] =   (val  - bp[1]);
+                                        cp[2] =   (val  - bp[2]);
+                                        cp[3] =   (val  - bp[3]);
+                                        cp[4] =   (val  - bp[4]);
+                                        cp[5] =   (val  - bp[5]);
+                                        cp[6] =   (val  - bp[6]);
+                                        cp[7] =   (val  - bp[7]);
+                                        cp[8] =   (val  - bp[8]);
+                                        cp[9] =   (val  - bp[9]);
+                                        cp[10] =   (val  - bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11; 
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =   (val  - *bp++);
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            if (dim == 0) {
+                                cp = (double*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (double*)range.Item2;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  - cp[0]);
+                                        cp[1] =   (ap[1]  - cp[1]);
+                                        cp[2] =   (ap[2]  - cp[2]);
+                                        cp[3] =   (ap[3]  - cp[3]);
+                                        cp[4] =   (ap[4]  - cp[4]);
+                                        cp[5] =   (ap[5]  - cp[5]);
+                                        cp[6] =   (ap[6]  - cp[6]);
+                                        cp[7] =   (ap[7]  - cp[7]);
+                                        cp[8] =   (ap[8]  - cp[8]);
+                                        cp[9] =   (ap[9]  - cp[9]);
+                                        cp[10] =   (ap[10]  - cp[10]);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap++  - *cp);
+                                        cp++; 
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                cp = (double*)range.Item4;
+                                ap = (double*)range.Item2;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    double val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (val  - cp[0]);
+                                        cp[1] =   (val  - cp[1]);
+                                        cp[2] =   (val  - cp[2]);
+                                        cp[3] =   (val  - cp[3]);
+                                        cp[4] =   (val  - cp[4]);
+                                        cp[5] =   (val  - cp[5]);
+                                        cp[6] =   (val  - cp[6]);
+                                        cp[7] =   (val  - cp[7]);
+                                        cp[8] =   (val  - cp[8]);
+                                        cp[9] =   (val  - cp[9]);
+                                        cp[10] =   (val  - cp[10]);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (val  - *cp);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            if (dim == 0) {
+                                ap = (double*)range.Item2;
+                                cp = (double*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (double*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  - bp[0]);
+                                        cp[1] =   (ap[1]  - bp[1]);
+                                        cp[2] =   (ap[2]  - bp[2]);
+                                        cp[3] =   (ap[3]  - bp[3]);
+                                        cp[4] =   (ap[4]  - bp[4]);
+                                        cp[5] =   (ap[5]  - bp[5]);
+                                        cp[6] =   (ap[6]  - bp[6]);
+                                        cp[7] =   (ap[7]  - bp[7]);
+                                        cp[8] =   (ap[8]  - bp[8]);
+                                        cp[9] =   (ap[9]  - bp[9]);
+                                        cp[10] =   (ap[10]  - bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap  - *bp);
+                                        ap++;
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                ap = (double*)range.Item2;
+                                bp = (double*)range.Item3;
+                                cp = (double*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   double val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  - val);
+                                        cp[1] =   (ap[1]  - val);
+                                        cp[2] =   (ap[2]  - val);
+                                        cp[3] =   (ap[3]  - val);
+                                        cp[4] =   (ap[4]  - val);
+                                        cp[5] =   (ap[5]  - val);
+                                        cp[6] =   (ap[6]  - val);
+                                        cp[7] =   (ap[7]  - val);
+                                        cp[8] =   (ap[8]  - val);
+                                        cp[9] =   (ap[9]  - val);
+                                        cp[10] =   (ap[10]  - val);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap  - val);
+                                        ap++;
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            if (dim == 0) {
+                                cp = (double*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (double*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (cp[0]  - bp[0]);
+                                        cp[1] =   (cp[1]  - bp[1]);
+                                        cp[2] =   (cp[2]  - bp[2]);
+                                        cp[3] =   (cp[3]  - bp[3]);
+                                        cp[4] =   (cp[4]  - bp[4]);
+                                        cp[5] =   (cp[5]  - bp[5]);
+                                        cp[6] =   (cp[6]  - bp[6]);
+                                        cp[7] =   (cp[7]  - bp[7]);
+                                        cp[8] =   (cp[8]  - bp[8]);
+                                        cp[9] =   (cp[9]  - bp[9]);
+                                        cp[10] =   (cp[10]  - bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*cp  - *bp);
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                bp = (double*)range.Item3;
+                                cp = (double*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    double val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (cp[0]  - val);
+                                        cp[1] =   (cp[1]  - val);
+                                        cp[2] =   (cp[2]  - val);
+                                        cp[3] =   (cp[3]  - val);
+                                        cp[4] =   (cp[4]  - val);
+                                        cp[5] =   (cp[5]  - val);
+                                        cp[6] =   (cp[6]  - val);
+                                        cp[7] =   (cp[7]  - val);
+                                        cp[8] =   (cp[8]  - val);
+                                        cp[9] =   (cp[9]  - val);
+                                        cp[10] =   (cp[10]  - val);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l --> 0) {
+                                        *cp =   (*cp  - val);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outDims.NumberOfElements >= Settings.s_minParallelElement1Count
+                    && outDims[1] > 1) {
+                        if (outDims[1] > workItemCount) {
+                        workItemLength = outDims[1] / workItemCount;
+                    } else {
+                        workItemLength = outDims[1] / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outDims[1];
+                    workItemCount = 1;
+                }
+
+                fixed ( double* arrAP = arrA)
+                fixed ( double* arrBP = arrB)
+                fixed ( double* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, IntPtr, IntPtr, IntPtr> range = new Tuple<int, IntPtr, IntPtr, IntPtr>
+                               (workItemLength
+                               , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                               , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                               , (IntPtr)(retArrP + i * outDims[0] * workItemLength)); 
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, IntPtr, IntPtr, IntPtr>
+                                (outDims[1] - i * workItemLength
+                                , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                                , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                                , (IntPtr)(retArrP + i * outDims[0] * workItemLength)));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<double>(retStorage);
+            //}  // no scopes here! it disables implace operations
+        }
+
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/Sum.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/Sum.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/Sum.cs	(revision 9102)
@@ -0,0 +1,832 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions;
+ 
+
+
+namespace ILNumerics  {
+    public partial class ILMath {
+ 
+       
+
+        /// <summary>
+        /// Sum elements of A along dimension specified.
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns>Array, same size as A, but having the specified or first non singleton dimension reduced to the length 1 with the sum of all
+        /// elements along that dimension.</returns>
+        public static  ILRetArray<double>  sum (ILInArray<double> A, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (dim >= A.Size.NumberOfDimensions)
+                    throw new ILArgumentException("dimension parameter out of range!");
+                if (A.IsEmpty)
+                    return new  ILRetArray<double>(A.Size);
+                if (A.IsScalar) {
+                    
+                    return new  ILRetArray<double>(new double[] { A.GetValue(0) }, 1, 1);
+                }
+                ILSize inDim = A.Size;
+                int[] newDims = inDim.ToIntArray();
+                
+                if (inDim[dim] == 1) return A.C;
+
+                int newLength;
+                
+                double[] retArr;
+                // build ILSize
+                newLength = inDim.NumberOfElements / newDims[dim];
+                newDims[dim] = 1;
+                retArr = ILMemoryPool.Pool.New< double>(newLength);
+                ILSize newDimension = new ILSize(newDims);
+                int incOut = newDimension.SequentialIndexDistance(dim);
+                int dimLen = inDim[dim];
+                int nrHigherDims = inDim.NumberOfElements / dimLen;
+                if (dim == 0) {
+                    #region physical along 1st leading dimension
+                    unsafe {
+                        fixed ( double* pOutArr = retArr)
+                        fixed ( double* pInArr = A.GetArrayForRead()) {
+                            
+                            double* lastElement;
+                            
+                            double* tmpOut = pOutArr;
+                            
+                            double* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                lastElement = tmpIn + dimLen;
+                                
+                                *tmpOut = 0.0;
+                                while (tmpIn < lastElement) {
+                                    
+                                    double inVal = *(tmpIn++);
+                                    
+                                    /*dummy*/
+                                    
+                                    *tmpOut  +=   (double) /*dummy*/ (inVal)  ; 
+                                }
+                                
+                                /*dummy*/
+                                tmpOut++;
+                            }
+                        }
+                    }
+                    #endregion
+                } else {
+                    #region physical along abitrary dimension
+                    // sum along abitrary dimension 
+                    unsafe {
+                        fixed ( double* pOutArr = retArr)
+                        fixed ( double* pInArr = A.GetArrayForRead()) {
+                            
+                            double* lastElementOut = newLength + pOutArr - 1;
+                            int inLength = inDim.NumberOfElements - 1;
+                            
+                            double* lastElementIn = pInArr + inLength;
+                            int inc = inDim.SequentialIndexDistance(dim);
+                            
+                            double* tmpOut = pOutArr;
+                            int outLength = newLength - 1;
+                            
+                            double* leadEnd;
+                            
+                            double* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                leadEnd = tmpIn + dimLen * inc;
+                                
+                                *tmpOut = 0.0;
+                                while (tmpIn < leadEnd) {
+                                    
+                                    double inVal = *(tmpIn);
+                                    tmpIn += inc;
+                                    
+                                    /*dummy*/
+                                    
+                                    *tmpOut  +=  (double) /*dummy*/ (inVal)  ; //
+                                }
+                                
+                                /*dummy*/
+                                tmpOut += inc;
+                                if (tmpOut > lastElementOut)
+                                    tmpOut = pOutArr + ((tmpOut - pOutArr) - outLength);
+                                if (tmpIn > lastElementIn)
+                                    tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                            }
+                        }
+                    }
+                    #endregion
+                }
+                return new  ILRetArray<double>(retArr, newDims);
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// Sum elements of A along dimension specified.
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns>Array, same size as A, but having the specified or first non singleton dimension reduced to the length 1 with the sum of all
+        /// elements along that dimension.</returns>
+        public static  ILRetArray<Int64>  sum (ILInArray<Int64> A, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (dim >= A.Size.NumberOfDimensions)
+                    throw new ILArgumentException("dimension parameter out of range!");
+                if (A.IsEmpty)
+                    return new  ILRetArray<Int64>(A.Size);
+                if (A.IsScalar) {
+                   
+                    return new  ILRetArray<Int64>(new Int64[] { A.GetValue(0) }, 1, 1);
+                }
+                ILSize inDim = A.Size;
+                int[] newDims = inDim.ToIntArray();
+               
+                if (inDim[dim] == 1) return A.C;
+
+                int newLength;
+               
+                Int64[] retArr;
+                // build ILSize
+                newLength = inDim.NumberOfElements / newDims[dim];
+                newDims[dim] = 1;
+                retArr = ILMemoryPool.Pool.New< Int64>(newLength);
+                ILSize newDimension = new ILSize(newDims);
+                int incOut = newDimension.SequentialIndexDistance(dim);
+                int dimLen = inDim[dim];
+                int nrHigherDims = inDim.NumberOfElements / dimLen;
+                if (dim == 0) {
+                    #region physical along 1st leading dimension
+                    unsafe {
+                        fixed ( Int64* pOutArr = retArr)
+                        fixed ( Int64* pInArr = A.GetArrayForRead()) {
+                           
+                            Int64* lastElement;
+                           
+                            Int64* tmpOut = pOutArr;
+                           
+                            Int64* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                lastElement = tmpIn + dimLen;
+                                *tmpOut = 0;
+                                while (tmpIn < lastElement) {
+                                   
+                                    Int64 inVal = *(tmpIn++);
+                                   
+                                    /*dummy*/
+                                   
+                                    *tmpOut  +=   (Int64) /*dummy*/ (inVal)  ; 
+                                }
+                               
+                                /*dummy*/
+                                tmpOut++;
+                            }
+                        }
+                    }
+                    #endregion
+                } else {
+                    #region physical along abitrary dimension
+                    // sum along abitrary dimension 
+                    unsafe {
+                        fixed ( Int64* pOutArr = retArr)
+                        fixed ( Int64* pInArr = A.GetArrayForRead()) {
+                           
+                            Int64* lastElementOut = newLength + pOutArr - 1;
+                            int inLength = inDim.NumberOfElements - 1;
+                           
+                            Int64* lastElementIn = pInArr + inLength;
+                            int inc = inDim.SequentialIndexDistance(dim);
+                           
+                            Int64* tmpOut = pOutArr;
+                            int outLength = newLength - 1;
+                           
+                            Int64* leadEnd;
+                           
+                            Int64* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                leadEnd = tmpIn + dimLen * inc;
+                                *tmpOut = 0;
+                                while (tmpIn < leadEnd) {
+                                   
+                                    Int64 inVal = *(tmpIn);
+                                    tmpIn += inc;
+                                   
+                                    /*dummy*/
+                                   
+                                    *tmpOut  +=  (Int64) /*dummy*/ (inVal)  ; //
+                                }
+                               
+                                /*dummy*/
+                                tmpOut += inc;
+                                if (tmpOut > lastElementOut)
+                                    tmpOut = pOutArr + ((tmpOut - pOutArr) - outLength);
+                                if (tmpIn > lastElementIn)
+                                    tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                            }
+                        }
+                    }
+                    #endregion
+                }
+                return new  ILRetArray<Int64>(retArr, newDims);
+            }
+        }
+        /// <summary>
+        /// Sum elements of A along dimension specified.
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns>Array, same size as A, but having the specified or first non singleton dimension reduced to the length 1 with the sum of all
+        /// elements along that dimension.</returns>
+        public static  ILRetArray<Int32>  sum (ILInArray<Int32> A, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (dim >= A.Size.NumberOfDimensions)
+                    throw new ILArgumentException("dimension parameter out of range!");
+                if (A.IsEmpty)
+                    return new  ILRetArray<Int32>(A.Size);
+                if (A.IsScalar) {
+                   
+                    return new  ILRetArray<Int32>(new Int32[] { A.GetValue(0) }, 1, 1);
+                }
+                ILSize inDim = A.Size;
+                int[] newDims = inDim.ToIntArray();
+               
+                if (inDim[dim] == 1) return A.C;
+
+                int newLength;
+               
+                Int32[] retArr;
+                // build ILSize
+                newLength = inDim.NumberOfElements / newDims[dim];
+                newDims[dim] = 1;
+                retArr = ILMemoryPool.Pool.New< Int32>(newLength);
+                ILSize newDimension = new ILSize(newDims);
+                int incOut = newDimension.SequentialIndexDistance(dim);
+                int dimLen = inDim[dim];
+                int nrHigherDims = inDim.NumberOfElements / dimLen;
+                if (dim == 0) {
+                    #region physical along 1st leading dimension
+                    unsafe {
+                        fixed ( Int32* pOutArr = retArr)
+                        fixed ( Int32* pInArr = A.GetArrayForRead()) {
+                           
+                            Int32* lastElement;
+                           
+                            Int32* tmpOut = pOutArr;
+                           
+                            Int32* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                lastElement = tmpIn + dimLen;
+                                *tmpOut = 0;
+                                while (tmpIn < lastElement) {
+                                   
+                                    Int32 inVal = *(tmpIn++);
+                                   
+                                    /*dummy*/
+                                   
+                                    *tmpOut  +=   (Int32) /*dummy*/ (inVal)  ; 
+                                }
+                               
+                                /*dummy*/
+                                tmpOut++;
+                            }
+                        }
+                    }
+                    #endregion
+                } else {
+                    #region physical along abitrary dimension
+                    // sum along abitrary dimension 
+                    unsafe {
+                        fixed ( Int32* pOutArr = retArr)
+                        fixed ( Int32* pInArr = A.GetArrayForRead()) {
+                           
+                            Int32* lastElementOut = newLength + pOutArr - 1;
+                            int inLength = inDim.NumberOfElements - 1;
+                           
+                            Int32* lastElementIn = pInArr + inLength;
+                            int inc = inDim.SequentialIndexDistance(dim);
+                           
+                            Int32* tmpOut = pOutArr;
+                            int outLength = newLength - 1;
+                           
+                            Int32* leadEnd;
+                           
+                            Int32* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                leadEnd = tmpIn + dimLen * inc;
+                                *tmpOut = 0;
+                                while (tmpIn < leadEnd) {
+                                   
+                                    Int32 inVal = *(tmpIn);
+                                    tmpIn += inc;
+                                   
+                                    /*dummy*/
+                                   
+                                    *tmpOut  +=  (Int32) /*dummy*/ (inVal)  ; //
+                                }
+                               
+                                /*dummy*/
+                                tmpOut += inc;
+                                if (tmpOut > lastElementOut)
+                                    tmpOut = pOutArr + ((tmpOut - pOutArr) - outLength);
+                                if (tmpIn > lastElementIn)
+                                    tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                            }
+                        }
+                    }
+                    #endregion
+                }
+                return new  ILRetArray<Int32>(retArr, newDims);
+            }
+        }
+        /// <summary>
+        /// Sum elements of A along dimension specified.
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns>Array, same size as A, but having the specified or first non singleton dimension reduced to the length 1 with the sum of all
+        /// elements along that dimension.</returns>
+        public static  ILRetArray<byte>  sum (ILInArray<byte> A, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (dim >= A.Size.NumberOfDimensions)
+                    throw new ILArgumentException("dimension parameter out of range!");
+                if (A.IsEmpty)
+                    return new  ILRetArray<byte>(A.Size);
+                if (A.IsScalar) {
+                   
+                    return new  ILRetArray<byte>(new byte[] { A.GetValue(0) }, 1, 1);
+                }
+                ILSize inDim = A.Size;
+                int[] newDims = inDim.ToIntArray();
+               
+                if (inDim[dim] == 1) return A.C;
+
+                int newLength;
+               
+                byte[] retArr;
+                // build ILSize
+                newLength = inDim.NumberOfElements / newDims[dim];
+                newDims[dim] = 1;
+                retArr = ILMemoryPool.Pool.New< byte>(newLength);
+                ILSize newDimension = new ILSize(newDims);
+                int incOut = newDimension.SequentialIndexDistance(dim);
+                int dimLen = inDim[dim];
+                int nrHigherDims = inDim.NumberOfElements / dimLen;
+                if (dim == 0) {
+                    #region physical along 1st leading dimension
+                    unsafe {
+                        fixed ( byte* pOutArr = retArr)
+                        fixed ( byte* pInArr = A.GetArrayForRead()) {
+                           
+                            byte* lastElement;
+                           
+                            byte* tmpOut = pOutArr;
+                           
+                            byte* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                lastElement = tmpIn + dimLen;
+                                *tmpOut = 0;
+                                while (tmpIn < lastElement) {
+                                   
+                                    byte inVal = *(tmpIn++);
+                                   
+                                    /*dummy*/
+                                   
+                                    *tmpOut  +=   (byte) /*dummy*/ (inVal)  ; 
+                                }
+                               
+                                /*dummy*/
+                                tmpOut++;
+                            }
+                        }
+                    }
+                    #endregion
+                } else {
+                    #region physical along abitrary dimension
+                    // sum along abitrary dimension 
+                    unsafe {
+                        fixed ( byte* pOutArr = retArr)
+                        fixed ( byte* pInArr = A.GetArrayForRead()) {
+                           
+                            byte* lastElementOut = newLength + pOutArr - 1;
+                            int inLength = inDim.NumberOfElements - 1;
+                           
+                            byte* lastElementIn = pInArr + inLength;
+                            int inc = inDim.SequentialIndexDistance(dim);
+                           
+                            byte* tmpOut = pOutArr;
+                            int outLength = newLength - 1;
+                           
+                            byte* leadEnd;
+                           
+                            byte* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                leadEnd = tmpIn + dimLen * inc;
+                                *tmpOut = 0;
+                                while (tmpIn < leadEnd) {
+                                   
+                                    byte inVal = *(tmpIn);
+                                    tmpIn += inc;
+                                   
+                                    /*dummy*/
+                                   
+                                    *tmpOut  +=  (byte) /*dummy*/ (inVal)  ; //
+                                }
+                               
+                                /*dummy*/
+                                tmpOut += inc;
+                                if (tmpOut > lastElementOut)
+                                    tmpOut = pOutArr + ((tmpOut - pOutArr) - outLength);
+                                if (tmpIn > lastElementIn)
+                                    tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                            }
+                        }
+                    }
+                    #endregion
+                }
+                return new  ILRetArray<byte>(retArr, newDims);
+            }
+        }
+        /// <summary>
+        /// Sum elements of A along dimension specified.
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns>Array, same size as A, but having the specified or first non singleton dimension reduced to the length 1 with the sum of all
+        /// elements along that dimension.</returns>
+        public static  ILRetArray<fcomplex>  sum (ILInArray<fcomplex> A, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (dim >= A.Size.NumberOfDimensions)
+                    throw new ILArgumentException("dimension parameter out of range!");
+                if (A.IsEmpty)
+                    return new  ILRetArray<fcomplex>(A.Size);
+                if (A.IsScalar) {
+                   
+                    return new  ILRetArray<fcomplex>(new fcomplex[] { A.GetValue(0) }, 1, 1);
+                }
+                ILSize inDim = A.Size;
+                int[] newDims = inDim.ToIntArray();
+               
+                if (inDim[dim] == 1) return A.C;
+
+                int newLength;
+               
+                fcomplex[] retArr;
+                // build ILSize
+                newLength = inDim.NumberOfElements / newDims[dim];
+                newDims[dim] = 1;
+                retArr = ILMemoryPool.Pool.New< fcomplex>(newLength);
+                ILSize newDimension = new ILSize(newDims);
+                int incOut = newDimension.SequentialIndexDistance(dim);
+                int dimLen = inDim[dim];
+                int nrHigherDims = inDim.NumberOfElements / dimLen;
+                if (dim == 0) {
+                    #region physical along 1st leading dimension
+                    unsafe {
+                        fixed ( fcomplex* pOutArr = retArr)
+                        fixed ( fcomplex* pInArr = A.GetArrayForRead()) {
+                           
+                            fcomplex* lastElement;
+                           
+                            fcomplex* tmpOut = pOutArr;
+                           
+                            fcomplex* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                lastElement = tmpIn + dimLen;
+                                *tmpOut = 0.0f;
+                                while (tmpIn < lastElement) {
+                                   
+                                    fcomplex inVal = *(tmpIn++);
+                                   
+                                    /*dummy*/
+                                   
+                                    *tmpOut  +=   (fcomplex) /*dummy*/ (inVal)  ; 
+                                }
+                               
+                                /*dummy*/
+                                tmpOut++;
+                            }
+                        }
+                    }
+                    #endregion
+                } else {
+                    #region physical along abitrary dimension
+                    // sum along abitrary dimension 
+                    unsafe {
+                        fixed ( fcomplex* pOutArr = retArr)
+                        fixed ( fcomplex* pInArr = A.GetArrayForRead()) {
+                           
+                            fcomplex* lastElementOut = newLength + pOutArr - 1;
+                            int inLength = inDim.NumberOfElements - 1;
+                           
+                            fcomplex* lastElementIn = pInArr + inLength;
+                            int inc = inDim.SequentialIndexDistance(dim);
+                           
+                            fcomplex* tmpOut = pOutArr;
+                            int outLength = newLength - 1;
+                           
+                            fcomplex* leadEnd;
+                           
+                            fcomplex* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                leadEnd = tmpIn + dimLen * inc;
+                                *tmpOut = 0.0f;
+                                while (tmpIn < leadEnd) {
+                                   
+                                    fcomplex inVal = *(tmpIn);
+                                    tmpIn += inc;
+                                   
+                                    /*dummy*/
+                                   
+                                    *tmpOut  +=  (fcomplex) /*dummy*/ (inVal)  ; //
+                                }
+                               
+                                /*dummy*/
+                                tmpOut += inc;
+                                if (tmpOut > lastElementOut)
+                                    tmpOut = pOutArr + ((tmpOut - pOutArr) - outLength);
+                                if (tmpIn > lastElementIn)
+                                    tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                            }
+                        }
+                    }
+                    #endregion
+                }
+                return new  ILRetArray<fcomplex>(retArr, newDims);
+            }
+        }
+        /// <summary>
+        /// Sum elements of A along dimension specified.
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns>Array, same size as A, but having the specified or first non singleton dimension reduced to the length 1 with the sum of all
+        /// elements along that dimension.</returns>
+        public static  ILRetArray<float>  sum (ILInArray<float> A, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (dim >= A.Size.NumberOfDimensions)
+                    throw new ILArgumentException("dimension parameter out of range!");
+                if (A.IsEmpty)
+                    return new  ILRetArray<float>(A.Size);
+                if (A.IsScalar) {
+                   
+                    return new  ILRetArray<float>(new float[] { A.GetValue(0) }, 1, 1);
+                }
+                ILSize inDim = A.Size;
+                int[] newDims = inDim.ToIntArray();
+               
+                if (inDim[dim] == 1) return A.C;
+
+                int newLength;
+               
+                float[] retArr;
+                // build ILSize
+                newLength = inDim.NumberOfElements / newDims[dim];
+                newDims[dim] = 1;
+                retArr = ILMemoryPool.Pool.New< float>(newLength);
+                ILSize newDimension = new ILSize(newDims);
+                int incOut = newDimension.SequentialIndexDistance(dim);
+                int dimLen = inDim[dim];
+                int nrHigherDims = inDim.NumberOfElements / dimLen;
+                if (dim == 0) {
+                    #region physical along 1st leading dimension
+                    unsafe {
+                        fixed ( float* pOutArr = retArr)
+                        fixed ( float* pInArr = A.GetArrayForRead()) {
+                           
+                            float* lastElement;
+                           
+                            float* tmpOut = pOutArr;
+                           
+                            float* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                lastElement = tmpIn + dimLen;
+                                *tmpOut = 0.0f;
+                                while (tmpIn < lastElement) {
+                                   
+                                    float inVal = *(tmpIn++);
+                                   
+                                    /*dummy*/
+                                   
+                                    *tmpOut  +=   (float) /*dummy*/ (inVal)  ; 
+                                }
+                               
+                                /*dummy*/
+                                tmpOut++;
+                            }
+                        }
+                    }
+                    #endregion
+                } else {
+                    #region physical along abitrary dimension
+                    // sum along abitrary dimension 
+                    unsafe {
+                        fixed ( float* pOutArr = retArr)
+                        fixed ( float* pInArr = A.GetArrayForRead()) {
+                           
+                            float* lastElementOut = newLength + pOutArr - 1;
+                            int inLength = inDim.NumberOfElements - 1;
+                           
+                            float* lastElementIn = pInArr + inLength;
+                            int inc = inDim.SequentialIndexDistance(dim);
+                           
+                            float* tmpOut = pOutArr;
+                            int outLength = newLength - 1;
+                           
+                            float* leadEnd;
+                           
+                            float* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                leadEnd = tmpIn + dimLen * inc;
+                                *tmpOut = 0.0f;
+                                while (tmpIn < leadEnd) {
+                                   
+                                    float inVal = *(tmpIn);
+                                    tmpIn += inc;
+                                   
+                                    /*dummy*/
+                                   
+                                    *tmpOut  +=  (float) /*dummy*/ (inVal)  ; //
+                                }
+                               
+                                /*dummy*/
+                                tmpOut += inc;
+                                if (tmpOut > lastElementOut)
+                                    tmpOut = pOutArr + ((tmpOut - pOutArr) - outLength);
+                                if (tmpIn > lastElementIn)
+                                    tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                            }
+                        }
+                    }
+                    #endregion
+                }
+                return new  ILRetArray<float>(retArr, newDims);
+            }
+        }
+        /// <summary>
+        /// Sum elements of A along dimension specified.
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns>Array, same size as A, but having the specified or first non singleton dimension reduced to the length 1 with the sum of all
+        /// elements along that dimension.</returns>
+        public static  ILRetArray<complex>  sum (ILInArray<complex> A, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (dim >= A.Size.NumberOfDimensions)
+                    throw new ILArgumentException("dimension parameter out of range!");
+                if (A.IsEmpty)
+                    return new  ILRetArray<complex>(A.Size);
+                if (A.IsScalar) {
+                   
+                    return new  ILRetArray<complex>(new complex[] { A.GetValue(0) }, 1, 1);
+                }
+                ILSize inDim = A.Size;
+                int[] newDims = inDim.ToIntArray();
+               
+                if (inDim[dim] == 1) return A.C;
+
+                int newLength;
+               
+                complex[] retArr;
+                // build ILSize
+                newLength = inDim.NumberOfElements / newDims[dim];
+                newDims[dim] = 1;
+                retArr = ILMemoryPool.Pool.New< complex>(newLength);
+                ILSize newDimension = new ILSize(newDims);
+                int incOut = newDimension.SequentialIndexDistance(dim);
+                int dimLen = inDim[dim];
+                int nrHigherDims = inDim.NumberOfElements / dimLen;
+                if (dim == 0) {
+                    #region physical along 1st leading dimension
+                    unsafe {
+                        fixed ( complex* pOutArr = retArr)
+                        fixed ( complex* pInArr = A.GetArrayForRead()) {
+                           
+                            complex* lastElement;
+                           
+                            complex* tmpOut = pOutArr;
+                           
+                            complex* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                lastElement = tmpIn + dimLen;
+                                *tmpOut = 0.0;
+                                while (tmpIn < lastElement) {
+                                   
+                                    complex inVal = *(tmpIn++);
+                                   
+                                    /*dummy*/
+                                   
+                                    *tmpOut  +=   (complex) /*dummy*/ (inVal)  ; 
+                                }
+                               
+                                /*dummy*/
+                                tmpOut++;
+                            }
+                        }
+                    }
+                    #endregion
+                } else {
+                    #region physical along abitrary dimension
+                    // sum along abitrary dimension 
+                    unsafe {
+                        fixed ( complex* pOutArr = retArr)
+                        fixed ( complex* pInArr = A.GetArrayForRead()) {
+                           
+                            complex* lastElementOut = newLength + pOutArr - 1;
+                            int inLength = inDim.NumberOfElements - 1;
+                           
+                            complex* lastElementIn = pInArr + inLength;
+                            int inc = inDim.SequentialIndexDistance(dim);
+                           
+                            complex* tmpOut = pOutArr;
+                            int outLength = newLength - 1;
+                           
+                            complex* leadEnd;
+                           
+                            complex* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                leadEnd = tmpIn + dimLen * inc;
+                                *tmpOut = 0.0;
+                                while (tmpIn < leadEnd) {
+                                   
+                                    complex inVal = *(tmpIn);
+                                    tmpIn += inc;
+                                   
+                                    /*dummy*/
+                                   
+                                    *tmpOut  +=  (complex) /*dummy*/ (inVal)  ; //
+                                }
+                               
+                                /*dummy*/
+                                tmpOut += inc;
+                                if (tmpOut > lastElementOut)
+                                    tmpOut = pOutArr + ((tmpOut - pOutArr) - outLength);
+                                if (tmpIn > lastElementIn)
+                                    tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                            }
+                        }
+                    }
+                    #endregion
+                }
+                return new  ILRetArray<complex>(retArr, newDims);
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+   }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/SumMT.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/SumMT.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/SumMT.cs	(revision 9102)
@@ -0,0 +1,703 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading; 
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions;
+ 
+
+
+namespace ILNumerics  {
+    public partial class ILMath {
+
+        /// <summary>
+        /// Sum elements of A along specified dimension
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns>Array, same size as A, but having the 'dim's dimension 
+        /// reduced to the length 1 with the sum of all
+        /// elements along that dimension.</returns>
+        public static  ILRetArray<double>  sum (ILInArray<double> A, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (dim >= A.Size.NumberOfDimensions)
+                    throw new ILArgumentException("dimension parameter out of range!");
+                if (A.IsEmpty)
+                    return  ILRetArray<double>.empty(A.Size);
+                if (A.IsScalar) {
+                    
+                    return new  ILRetArray<double>(new double[] { A.GetValue(0) }, 1, 1);
+                }
+                
+                if (A.S[dim] == 1) return A.C;
+
+                int[] newDims = A.S.ToIntArray();
+                newDims[dim] = 1; 
+                ILSize retDimension = new ILSize(newDims); 
+                 double[] retArr = ILMemoryPool.Pool.New< double>(retDimension.NumberOfElements);
+
+                int inc = A.Size.SequentialIndexDistance(dim);
+                int dimLen = A.Size[dim];
+                int maxRuns = retDimension.NumberOfElements;
+                int modHelp = A.Size.NumberOfElements - 1;
+                int modOut = retDimension.NumberOfElements - 1;
+                int incOut = retDimension.SequentialIndexDistance(dim); 
+                int numelA = A.S.NumberOfElements;
+                
+                double[] aArray = A.GetArrayForRead();
+                if (maxRuns == 1) {
+                    
+                    double tmp = 0;
+                    for (int j = 0; j < dimLen; j++) {
+                        tmp += aArray[j];
+                    }
+                    retArr[0] = tmp;
+                } else {
+                    #region may run parallel 
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                    if (Settings.s_maxNumberThreads > 1 && maxRuns > 1 
+                        && numelA / 2 >= Settings.s_minParallelElement1Count) {
+
+                        if (maxRuns >= Settings.s_maxNumberThreads
+                            && numelA / Settings.s_maxNumberThreads > Settings.s_minParallelElement1Count) {
+                            workItemLength = maxRuns / workItemCount;
+                        } else {
+                            workItemLength = maxRuns / 2;
+                            workItemCount = 2;
+                        }
+                        
+                    } else {
+                        workItemLength = maxRuns;
+                        workItemCount = 1;
+                    }
+                    Action<object> action = (data) => {
+                        Tuple<int, int> range = (Tuple<int, int>)data;
+                        int from = range.Item1, to = range.Item2;
+                        for (int c = from; c < to; c++) {
+                            int pos = (int)(((long)dimLen * c * inc) % modHelp);
+                            long posOut = ((long)c * incOut);
+                            if (posOut > modOut)
+                                posOut = ((posOut - 1) % modOut) + 1;
+                            
+                            double tmp = 0;
+                            int end = pos + dimLen * inc;
+                            for (int j = pos; j < end; j += inc) {
+                                tmp += aArray[j];
+                            }
+                            retArr[posOut] = tmp;
+                        }
+                        System.Threading.Interlocked.Decrement(ref workerCount);
+                    };
+                    for (; i < workItemCount - 1; i++) {
+                        Interlocked.Increment(ref workerCount);
+
+                        ILThreadPool.QueueUserWorkItem(i,action, Tuple.Create(i * workItemLength, (i + 1) * workItemLength));
+                    }
+                    action(Tuple.Create(i * workItemLength, maxRuns));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                    #endregion
+                }
+                return new  ILRetArray<double>(retArr, newDims);
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// Sum elements of A along specified dimension
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns>Array, same size as A, but having the 'dim's dimension 
+        /// reduced to the length 1 with the sum of all
+        /// elements along that dimension.</returns>
+        public static  ILRetArray<Int64>  sum (ILInArray<Int64> A, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (dim >= A.Size.NumberOfDimensions)
+                    throw new ILArgumentException("dimension parameter out of range!");
+                if (A.IsEmpty)
+                    return  ILRetArray<Int64>.empty(A.Size);
+                if (A.IsScalar) {
+                   
+                    return new  ILRetArray<Int64>(new Int64[] { A.GetValue(0) }, 1, 1);
+                }
+               
+                if (A.S[dim] == 1) return A.C;
+
+                int[] newDims = A.S.ToIntArray();
+                newDims[dim] = 1; 
+                ILSize retDimension = new ILSize(newDims); 
+                Int64[] retArr = ILMemoryPool.Pool.New< Int64>(retDimension.NumberOfElements);
+
+                int inc = A.Size.SequentialIndexDistance(dim);
+                int dimLen = A.Size[dim];
+                int maxRuns = retDimension.NumberOfElements;
+                int modHelp = A.Size.NumberOfElements - 1;
+                int modOut = retDimension.NumberOfElements - 1;
+                int incOut = retDimension.SequentialIndexDistance(dim); 
+                int numelA = A.S.NumberOfElements;
+               
+                Int64[] aArray = A.GetArrayForRead();
+                if (maxRuns == 1) {
+                   
+                    Int64 tmp = 0;
+                    for (int j = 0; j < dimLen; j++) {
+                        tmp += aArray[j];
+                    }
+                    retArr[0] = tmp;
+                } else {
+                    #region may run parallel 
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                    if (Settings.s_maxNumberThreads > 1 && maxRuns > 1 
+                        && numelA / 2 >= Settings.s_minParallelElement1Count) {
+
+                        if (maxRuns >= Settings.s_maxNumberThreads
+                            && numelA / Settings.s_maxNumberThreads > Settings.s_minParallelElement1Count) {
+                            workItemLength = maxRuns / workItemCount;
+                        } else {
+                            workItemLength = maxRuns / 2;
+                            workItemCount = 2;
+                        }
+                        
+                    } else {
+                        workItemLength = maxRuns;
+                        workItemCount = 1;
+                    }
+                    Action<object> action = (data) => {
+                        Tuple<int, int> range = (Tuple<int, int>)data;
+                        int from = range.Item1, to = range.Item2;
+                        for (int c = from; c < to; c++) {
+                            int pos = (int)(((long)dimLen * c * inc) % modHelp);
+                            long posOut = ((long)c * incOut);
+                            if (posOut > modOut)
+                                posOut = ((posOut - 1) % modOut) + 1;
+                           
+                            Int64 tmp = 0;
+                            int end = pos + dimLen * inc;
+                            for (int j = pos; j < end; j += inc) {
+                                tmp += aArray[j];
+                            }
+                            retArr[posOut] = tmp;
+                        }
+                        System.Threading.Interlocked.Decrement(ref workerCount);
+                    };
+                    for (; i < workItemCount - 1; i++) {
+                        Interlocked.Increment(ref workerCount);
+
+                        ILThreadPool.QueueUserWorkItem(i,action, Tuple.Create(i * workItemLength, (i + 1) * workItemLength));
+                    }
+                    action(Tuple.Create(i * workItemLength, maxRuns));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                    #endregion
+                }
+                return new  ILRetArray<Int64>(retArr, newDims);
+            }
+        }
+        /// <summary>
+        /// Sum elements of A along specified dimension
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns>Array, same size as A, but having the 'dim's dimension 
+        /// reduced to the length 1 with the sum of all
+        /// elements along that dimension.</returns>
+        public static  ILRetArray<Int32>  sum (ILInArray<Int32> A, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (dim >= A.Size.NumberOfDimensions)
+                    throw new ILArgumentException("dimension parameter out of range!");
+                if (A.IsEmpty)
+                    return  ILRetArray<Int32>.empty(A.Size);
+                if (A.IsScalar) {
+                   
+                    return new  ILRetArray<Int32>(new Int32[] { A.GetValue(0) }, 1, 1);
+                }
+               
+                if (A.S[dim] == 1) return A.C;
+
+                int[] newDims = A.S.ToIntArray();
+                newDims[dim] = 1; 
+                ILSize retDimension = new ILSize(newDims); 
+                Int32[] retArr = ILMemoryPool.Pool.New< Int32>(retDimension.NumberOfElements);
+
+                int inc = A.Size.SequentialIndexDistance(dim);
+                int dimLen = A.Size[dim];
+                int maxRuns = retDimension.NumberOfElements;
+                int modHelp = A.Size.NumberOfElements - 1;
+                int modOut = retDimension.NumberOfElements - 1;
+                int incOut = retDimension.SequentialIndexDistance(dim); 
+                int numelA = A.S.NumberOfElements;
+               
+                Int32[] aArray = A.GetArrayForRead();
+                if (maxRuns == 1) {
+                   
+                    Int32 tmp = 0;
+                    for (int j = 0; j < dimLen; j++) {
+                        tmp += aArray[j];
+                    }
+                    retArr[0] = tmp;
+                } else {
+                    #region may run parallel 
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                    if (Settings.s_maxNumberThreads > 1 && maxRuns > 1 
+                        && numelA / 2 >= Settings.s_minParallelElement1Count) {
+
+                        if (maxRuns >= Settings.s_maxNumberThreads
+                            && numelA / Settings.s_maxNumberThreads > Settings.s_minParallelElement1Count) {
+                            workItemLength = maxRuns / workItemCount;
+                        } else {
+                            workItemLength = maxRuns / 2;
+                            workItemCount = 2;
+                        }
+                        
+                    } else {
+                        workItemLength = maxRuns;
+                        workItemCount = 1;
+                    }
+                    Action<object> action = (data) => {
+                        Tuple<int, int> range = (Tuple<int, int>)data;
+                        int from = range.Item1, to = range.Item2;
+                        for (int c = from; c < to; c++) {
+                            int pos = (int)(((long)dimLen * c * inc) % modHelp);
+                            long posOut = ((long)c * incOut);
+                            if (posOut > modOut)
+                                posOut = ((posOut - 1) % modOut) + 1;
+                           
+                            Int32 tmp = 0;
+                            int end = pos + dimLen * inc;
+                            for (int j = pos; j < end; j += inc) {
+                                tmp += aArray[j];
+                            }
+                            retArr[posOut] = tmp;
+                        }
+                        System.Threading.Interlocked.Decrement(ref workerCount);
+                    };
+                    for (; i < workItemCount - 1; i++) {
+                        Interlocked.Increment(ref workerCount);
+
+                        ILThreadPool.QueueUserWorkItem(i,action, Tuple.Create(i * workItemLength, (i + 1) * workItemLength));
+                    }
+                    action(Tuple.Create(i * workItemLength, maxRuns));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                    #endregion
+                }
+                return new  ILRetArray<Int32>(retArr, newDims);
+            }
+        }
+        /// <summary>
+        /// Sum elements of A along specified dimension
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns>Array, same size as A, but having the 'dim's dimension 
+        /// reduced to the length 1 with the sum of all
+        /// elements along that dimension.</returns>
+        public static  ILRetArray<byte>  sum (ILInArray<byte> A, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (dim >= A.Size.NumberOfDimensions)
+                    throw new ILArgumentException("dimension parameter out of range!");
+                if (A.IsEmpty)
+                    return  ILRetArray<byte>.empty(A.Size);
+                if (A.IsScalar) {
+                   
+                    return new  ILRetArray<byte>(new byte[] { A.GetValue(0) }, 1, 1);
+                }
+               
+                if (A.S[dim] == 1) return A.C;
+
+                int[] newDims = A.S.ToIntArray();
+                newDims[dim] = 1; 
+                ILSize retDimension = new ILSize(newDims); 
+                byte[] retArr = ILMemoryPool.Pool.New< byte>(retDimension.NumberOfElements);
+
+                int inc = A.Size.SequentialIndexDistance(dim);
+                int dimLen = A.Size[dim];
+                int maxRuns = retDimension.NumberOfElements;
+                int modHelp = A.Size.NumberOfElements - 1;
+                int modOut = retDimension.NumberOfElements - 1;
+                int incOut = retDimension.SequentialIndexDistance(dim); 
+                int numelA = A.S.NumberOfElements;
+               
+                byte[] aArray = A.GetArrayForRead();
+                if (maxRuns == 1) {
+                   
+                    byte tmp = 0;
+                    for (int j = 0; j < dimLen; j++) {
+                        tmp += aArray[j];
+                    }
+                    retArr[0] = tmp;
+                } else {
+                    #region may run parallel 
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                    if (Settings.s_maxNumberThreads > 1 && maxRuns > 1 
+                        && numelA / 2 >= Settings.s_minParallelElement1Count) {
+
+                        if (maxRuns >= Settings.s_maxNumberThreads
+                            && numelA / Settings.s_maxNumberThreads > Settings.s_minParallelElement1Count) {
+                            workItemLength = maxRuns / workItemCount;
+                        } else {
+                            workItemLength = maxRuns / 2;
+                            workItemCount = 2;
+                        }
+                        
+                    } else {
+                        workItemLength = maxRuns;
+                        workItemCount = 1;
+                    }
+                    Action<object> action = (data) => {
+                        Tuple<int, int> range = (Tuple<int, int>)data;
+                        int from = range.Item1, to = range.Item2;
+                        for (int c = from; c < to; c++) {
+                            int pos = (int)(((long)dimLen * c * inc) % modHelp);
+                            long posOut = ((long)c * incOut);
+                            if (posOut > modOut)
+                                posOut = ((posOut - 1) % modOut) + 1;
+                           
+                            byte tmp = 0;
+                            int end = pos + dimLen * inc;
+                            for (int j = pos; j < end; j += inc) {
+                                tmp += aArray[j];
+                            }
+                            retArr[posOut] = tmp;
+                        }
+                        System.Threading.Interlocked.Decrement(ref workerCount);
+                    };
+                    for (; i < workItemCount - 1; i++) {
+                        Interlocked.Increment(ref workerCount);
+
+                        ILThreadPool.QueueUserWorkItem(i,action, Tuple.Create(i * workItemLength, (i + 1) * workItemLength));
+                    }
+                    action(Tuple.Create(i * workItemLength, maxRuns));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                    #endregion
+                }
+                return new  ILRetArray<byte>(retArr, newDims);
+            }
+        }
+        /// <summary>
+        /// Sum elements of A along specified dimension
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns>Array, same size as A, but having the 'dim's dimension 
+        /// reduced to the length 1 with the sum of all
+        /// elements along that dimension.</returns>
+        public static  ILRetArray<fcomplex>  sum (ILInArray<fcomplex> A, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (dim >= A.Size.NumberOfDimensions)
+                    throw new ILArgumentException("dimension parameter out of range!");
+                if (A.IsEmpty)
+                    return  ILRetArray<fcomplex>.empty(A.Size);
+                if (A.IsScalar) {
+                   
+                    return new  ILRetArray<fcomplex>(new fcomplex[] { A.GetValue(0) }, 1, 1);
+                }
+               
+                if (A.S[dim] == 1) return A.C;
+
+                int[] newDims = A.S.ToIntArray();
+                newDims[dim] = 1; 
+                ILSize retDimension = new ILSize(newDims); 
+                fcomplex[] retArr = ILMemoryPool.Pool.New< fcomplex>(retDimension.NumberOfElements);
+
+                int inc = A.Size.SequentialIndexDistance(dim);
+                int dimLen = A.Size[dim];
+                int maxRuns = retDimension.NumberOfElements;
+                int modHelp = A.Size.NumberOfElements - 1;
+                int modOut = retDimension.NumberOfElements - 1;
+                int incOut = retDimension.SequentialIndexDistance(dim); 
+                int numelA = A.S.NumberOfElements;
+               
+                fcomplex[] aArray = A.GetArrayForRead();
+                if (maxRuns == 1) {
+                   
+                    fcomplex tmp = 0;
+                    for (int j = 0; j < dimLen; j++) {
+                        tmp += aArray[j];
+                    }
+                    retArr[0] = tmp;
+                } else {
+                    #region may run parallel 
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                    if (Settings.s_maxNumberThreads > 1 && maxRuns > 1 
+                        && numelA / 2 >= Settings.s_minParallelElement1Count) {
+
+                        if (maxRuns >= Settings.s_maxNumberThreads
+                            && numelA / Settings.s_maxNumberThreads > Settings.s_minParallelElement1Count) {
+                            workItemLength = maxRuns / workItemCount;
+                        } else {
+                            workItemLength = maxRuns / 2;
+                            workItemCount = 2;
+                        }
+                        
+                    } else {
+                        workItemLength = maxRuns;
+                        workItemCount = 1;
+                    }
+                    Action<object> action = (data) => {
+                        Tuple<int, int> range = (Tuple<int, int>)data;
+                        int from = range.Item1, to = range.Item2;
+                        for (int c = from; c < to; c++) {
+                            int pos = (int)(((long)dimLen * c * inc) % modHelp);
+                            long posOut = ((long)c * incOut);
+                            if (posOut > modOut)
+                                posOut = ((posOut - 1) % modOut) + 1;
+                           
+                            fcomplex tmp = 0;
+                            int end = pos + dimLen * inc;
+                            for (int j = pos; j < end; j += inc) {
+                                tmp += aArray[j];
+                            }
+                            retArr[posOut] = tmp;
+                        }
+                        System.Threading.Interlocked.Decrement(ref workerCount);
+                    };
+                    for (; i < workItemCount - 1; i++) {
+                        Interlocked.Increment(ref workerCount);
+
+                        ILThreadPool.QueueUserWorkItem(i,action, Tuple.Create(i * workItemLength, (i + 1) * workItemLength));
+                    }
+                    action(Tuple.Create(i * workItemLength, maxRuns));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                    #endregion
+                }
+                return new  ILRetArray<fcomplex>(retArr, newDims);
+            }
+        }
+        /// <summary>
+        /// Sum elements of A along specified dimension
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns>Array, same size as A, but having the 'dim's dimension 
+        /// reduced to the length 1 with the sum of all
+        /// elements along that dimension.</returns>
+        public static  ILRetArray<float>  sum (ILInArray<float> A, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (dim >= A.Size.NumberOfDimensions)
+                    throw new ILArgumentException("dimension parameter out of range!");
+                if (A.IsEmpty)
+                    return  ILRetArray<float>.empty(A.Size);
+                if (A.IsScalar) {
+                   
+                    return new  ILRetArray<float>(new float[] { A.GetValue(0) }, 1, 1);
+                }
+               
+                if (A.S[dim] == 1) return A.C;
+
+                int[] newDims = A.S.ToIntArray();
+                newDims[dim] = 1; 
+                ILSize retDimension = new ILSize(newDims); 
+                float[] retArr = ILMemoryPool.Pool.New< float>(retDimension.NumberOfElements);
+
+                int inc = A.Size.SequentialIndexDistance(dim);
+                int dimLen = A.Size[dim];
+                int maxRuns = retDimension.NumberOfElements;
+                int modHelp = A.Size.NumberOfElements - 1;
+                int modOut = retDimension.NumberOfElements - 1;
+                int incOut = retDimension.SequentialIndexDistance(dim); 
+                int numelA = A.S.NumberOfElements;
+               
+                float[] aArray = A.GetArrayForRead();
+                if (maxRuns == 1) {
+                   
+                    float tmp = 0;
+                    for (int j = 0; j < dimLen; j++) {
+                        tmp += aArray[j];
+                    }
+                    retArr[0] = tmp;
+                } else {
+                    #region may run parallel 
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                    if (Settings.s_maxNumberThreads > 1 && maxRuns > 1 
+                        && numelA / 2 >= Settings.s_minParallelElement1Count) {
+
+                        if (maxRuns >= Settings.s_maxNumberThreads
+                            && numelA / Settings.s_maxNumberThreads > Settings.s_minParallelElement1Count) {
+                            workItemLength = maxRuns / workItemCount;
+                        } else {
+                            workItemLength = maxRuns / 2;
+                            workItemCount = 2;
+                        }
+                        
+                    } else {
+                        workItemLength = maxRuns;
+                        workItemCount = 1;
+                    }
+                    Action<object> action = (data) => {
+                        Tuple<int, int> range = (Tuple<int, int>)data;
+                        int from = range.Item1, to = range.Item2;
+                        for (int c = from; c < to; c++) {
+                            int pos = (int)(((long)dimLen * c * inc) % modHelp);
+                            long posOut = ((long)c * incOut);
+                            if (posOut > modOut)
+                                posOut = ((posOut - 1) % modOut) + 1;
+                           
+                            float tmp = 0;
+                            int end = pos + dimLen * inc;
+                            for (int j = pos; j < end; j += inc) {
+                                tmp += aArray[j];
+                            }
+                            retArr[posOut] = tmp;
+                        }
+                        System.Threading.Interlocked.Decrement(ref workerCount);
+                    };
+                    for (; i < workItemCount - 1; i++) {
+                        Interlocked.Increment(ref workerCount);
+
+                        ILThreadPool.QueueUserWorkItem(i,action, Tuple.Create(i * workItemLength, (i + 1) * workItemLength));
+                    }
+                    action(Tuple.Create(i * workItemLength, maxRuns));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                    #endregion
+                }
+                return new  ILRetArray<float>(retArr, newDims);
+            }
+        }
+        /// <summary>
+        /// Sum elements of A along specified dimension
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns>Array, same size as A, but having the 'dim's dimension 
+        /// reduced to the length 1 with the sum of all
+        /// elements along that dimension.</returns>
+        public static  ILRetArray<complex>  sum (ILInArray<complex> A, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (dim >= A.Size.NumberOfDimensions)
+                    throw new ILArgumentException("dimension parameter out of range!");
+                if (A.IsEmpty)
+                    return  ILRetArray<complex>.empty(A.Size);
+                if (A.IsScalar) {
+                   
+                    return new  ILRetArray<complex>(new complex[] { A.GetValue(0) }, 1, 1);
+                }
+               
+                if (A.S[dim] == 1) return A.C;
+
+                int[] newDims = A.S.ToIntArray();
+                newDims[dim] = 1; 
+                ILSize retDimension = new ILSize(newDims); 
+                complex[] retArr = ILMemoryPool.Pool.New< complex>(retDimension.NumberOfElements);
+
+                int inc = A.Size.SequentialIndexDistance(dim);
+                int dimLen = A.Size[dim];
+                int maxRuns = retDimension.NumberOfElements;
+                int modHelp = A.Size.NumberOfElements - 1;
+                int modOut = retDimension.NumberOfElements - 1;
+                int incOut = retDimension.SequentialIndexDistance(dim); 
+                int numelA = A.S.NumberOfElements;
+               
+                complex[] aArray = A.GetArrayForRead();
+                if (maxRuns == 1) {
+                   
+                    complex tmp = 0;
+                    for (int j = 0; j < dimLen; j++) {
+                        tmp += aArray[j];
+                    }
+                    retArr[0] = tmp;
+                } else {
+                    #region may run parallel 
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                    if (Settings.s_maxNumberThreads > 1 && maxRuns > 1 
+                        && numelA / 2 >= Settings.s_minParallelElement1Count) {
+
+                        if (maxRuns >= Settings.s_maxNumberThreads
+                            && numelA / Settings.s_maxNumberThreads > Settings.s_minParallelElement1Count) {
+                            workItemLength = maxRuns / workItemCount;
+                        } else {
+                            workItemLength = maxRuns / 2;
+                            workItemCount = 2;
+                        }
+                        
+                    } else {
+                        workItemLength = maxRuns;
+                        workItemCount = 1;
+                    }
+                    Action<object> action = (data) => {
+                        Tuple<int, int> range = (Tuple<int, int>)data;
+                        int from = range.Item1, to = range.Item2;
+                        for (int c = from; c < to; c++) {
+                            int pos = (int)(((long)dimLen * c * inc) % modHelp);
+                            long posOut = ((long)c * incOut);
+                            if (posOut > modOut)
+                                posOut = ((posOut - 1) % modOut) + 1;
+                           
+                            complex tmp = 0;
+                            int end = pos + dimLen * inc;
+                            for (int j = pos; j < end; j += inc) {
+                                tmp += aArray[j];
+                            }
+                            retArr[posOut] = tmp;
+                        }
+                        System.Threading.Interlocked.Decrement(ref workerCount);
+                    };
+                    for (; i < workItemCount - 1; i++) {
+                        Interlocked.Increment(ref workerCount);
+
+                        ILThreadPool.QueueUserWorkItem(i,action, Tuple.Create(i * workItemLength, (i + 1) * workItemLength));
+                    }
+                    action(Tuple.Create(i * workItemLength, maxRuns));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                    #endregion
+                }
+                return new  ILRetArray<complex>(retArr, newDims);
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+   }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/Svd.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/Svd.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/Svd.cs	(revision 9102)
@@ -0,0 +1,691 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions;
+
+
+namespace ILNumerics {
+    public partial class ILMath {
+
+        /// <summary>
+        /// Singular value decomposition 
+        /// </summary>
+        /// <param name="A">Input matrix A</param>
+        /// <returns>Vector with min(M,N) singular values of A as column vector</returns>
+        public static ILRetArray< double > svd(ILInArray< double > A) {
+            return svd(A,null, null, false, false);
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// Singular value decomposition 
+        /// </summary>
+        /// <param name="A">Input matrix A</param>
+        /// <returns>Vector with min(M,N) singular values of A as column vector</returns>
+        public static ILRetArray< float > svd(ILInArray< float > A) {
+            return svd(A,null, null, false, false);
+        }
+        /// <summary>
+        /// Singular value decomposition 
+        /// </summary>
+        /// <param name="A">Input matrix A</param>
+        /// <returns>Vector with min(M,N) singular values of A as column vector</returns>
+        public static ILRetArray< float > svd(ILInArray< fcomplex > A) {
+            return svd(A,null, null, false, false);
+        }
+        /// <summary>
+        /// Singular value decomposition 
+        /// </summary>
+        /// <param name="A">Input matrix A</param>
+        /// <returns>Vector with min(M,N) singular values of A as column vector</returns>
+        public static ILRetArray< double > svd(ILInArray< complex > A) {
+            return svd(A,null, null, false, false);
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+
+        /// <summary>
+        /// Singular value decomposition 
+        /// </summary>
+        /// <param name="A">Input matrix</param>
+        /// <param name="U">[Output] Left singular vectors of A as columns of matrix U. 
+        /// Setting this parameter to a non-null value signals the need of returning those values.</param>
+        /// <returns>Singluar values as diagonal matrix of same size and type as A</returns>
+        public static ILRetArray< double > svd(ILInArray< double > A, ILOutArray< double > U) {
+            return svd(A, U, null , false,false);
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// Singular value decomposition 
+        /// </summary>
+        /// <param name="A">Input matrix</param>
+        /// <param name="U">[Output] Left singular vectors of A as columns of matrix U. 
+        /// Setting this parameter to a non-null value signals the need of returning those values.</param>
+        /// <returns>Singluar values as diagonal matrix of same size and type as A</returns>
+        public static ILRetArray< float > svd(ILInArray< float > A, ILOutArray< float > U) {
+            return svd(A, U, null , false,false);
+        }
+        /// <summary>
+        /// Singular value decomposition 
+        /// </summary>
+        /// <param name="A">Input matrix</param>
+        /// <param name="U">[Output] Left singular vectors of A as columns of matrix U. 
+        /// Setting this parameter to a non-null value signals the need of returning those values.</param>
+        /// <returns>Singluar values as diagonal matrix of same size and type as A</returns>
+        public static ILRetArray< float > svd(ILInArray< fcomplex > A, ILOutArray< fcomplex > U) {
+            return svd(A, U, null , false,false);
+        }
+        /// <summary>
+        /// Singular value decomposition 
+        /// </summary>
+        /// <param name="A">Input matrix</param>
+        /// <param name="U">[Output] Left singular vectors of A as columns of matrix U. 
+        /// Setting this parameter to a non-null value signals the need of returning those values.</param>
+        /// <returns>Singluar values as diagonal matrix of same size and type as A</returns>
+        public static ILRetArray< double > svd(ILInArray< complex > A, ILOutArray< complex > U) {
+            return svd(A, U, null , false,false);
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+
+        /// <summary>
+        /// Singular value decomposition 
+        /// </summary>
+        /// <param name="A">Input matrix</param>
+        /// <param name="outU">[Output] Left singular vectors of A as columns of matrix outU. 
+        /// Setting this parameter to a non-null value (e.g. 'empty') signals the need of returning those values.</param>
+        /// <param name="small">If true: return only first min(M,N) columns of outU will be 
+        /// of size [min(M,N),min(M,N)]</param>
+        /// <returns>Singluar values as diagonal matrix of same size and type as A</returns>
+        public static ILRetArray< double > svd(ILInArray< double > A, ILOutArray< double > outU, bool small) {
+            return svd(A, outU, null, small,false);
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// Singular value decomposition 
+        /// </summary>
+        /// <param name="A">Input matrix</param>
+        /// <param name="outU">[Output] Left singular vectors of A as columns of matrix outU. 
+        /// Setting this parameter to a non-null value (e.g. 'empty') signals the need of returning those values.</param>
+        /// <param name="small">If true: return only first min(M,N) columns of outU will be 
+        /// of size [min(M,N),min(M,N)]</param>
+        /// <returns>Singluar values as diagonal matrix of same size and type as A</returns>
+        public static ILRetArray< float > svd(ILInArray< float > A, ILOutArray< float > outU, bool small) {
+            return svd(A, outU, null, small,false);
+        }
+        /// <summary>
+        /// Singular value decomposition 
+        /// </summary>
+        /// <param name="A">Input matrix</param>
+        /// <param name="outU">[Output] Left singular vectors of A as columns of matrix outU. 
+        /// Setting this parameter to a non-null value (e.g. 'empty') signals the need of returning those values.</param>
+        /// <param name="small">If true: return only first min(M,N) columns of outU will be 
+        /// of size [min(M,N),min(M,N)]</param>
+        /// <returns>Singluar values as diagonal matrix of same size and type as A</returns>
+        public static ILRetArray< float > svd(ILInArray< fcomplex > A, ILOutArray< fcomplex > outU, bool small) {
+            return svd(A, outU, null, small,false);
+        }
+        /// <summary>
+        /// Singular value decomposition 
+        /// </summary>
+        /// <param name="A">Input matrix</param>
+        /// <param name="outU">[Output] Left singular vectors of A as columns of matrix outU. 
+        /// Setting this parameter to a non-null value (e.g. 'empty') signals the need of returning those values.</param>
+        /// <param name="small">If true: return only first min(M,N) columns of outU will be 
+        /// of size [min(M,N),min(M,N)]</param>
+        /// <returns>Singluar values as diagonal matrix of same size and type as A</returns>
+        public static ILRetArray< double > svd(ILInArray< complex > A, ILOutArray< complex > outU, bool small) {
+            return svd(A, outU, null, small,false);
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+       
+
+        /// <summary>
+        /// Singular value decomposition 
+        /// </summary>
+        /// <param name="A">Input matrix</param>
+        /// <param name="outU">[Output] Left singular vectors of A as columns of matrix U. 
+        /// Setting this parameter to a non-null value signals the need of returning those values.</param>
+        /// <param name="outV">[Output] Right singular vectors of X as rows of matrix V.
+        /// This parameter must not be null. It might be an empty array on input.</param>
+        /// <returns>Singluar values as diagonal matrix of same size and type as A</returns>
+        public static ILRetArray< double > svd(ILInArray< double > A, ILOutArray< double > outU, ILOutArray< double > outV) {
+            return svd(A, outU, outV, false,false);
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// Singular value decomposition 
+        /// </summary>
+        /// <param name="A">Input matrix</param>
+        /// <param name="outU">[Output] Left singular vectors of A as columns of matrix U. 
+        /// Setting this parameter to a non-null value signals the need of returning those values.</param>
+        /// <param name="outV">[Output] Right singular vectors of X as rows of matrix V.
+        /// This parameter must not be null. It might be an empty array on input.</param>
+        /// <returns>Singluar values as diagonal matrix of same size and type as A</returns>
+        public static ILRetArray< float > svd(ILInArray< float > A, ILOutArray< float > outU, ILOutArray< float > outV) {
+            return svd(A, outU, outV, false,false);
+        }
+        /// <summary>
+        /// Singular value decomposition 
+        /// </summary>
+        /// <param name="A">Input matrix</param>
+        /// <param name="outU">[Output] Left singular vectors of A as columns of matrix U. 
+        /// Setting this parameter to a non-null value signals the need of returning those values.</param>
+        /// <param name="outV">[Output] Right singular vectors of X as rows of matrix V.
+        /// This parameter must not be null. It might be an empty array on input.</param>
+        /// <returns>Singluar values as diagonal matrix of same size and type as A</returns>
+        public static ILRetArray< float > svd(ILInArray< fcomplex > A, ILOutArray< fcomplex > outU, ILOutArray< fcomplex > outV) {
+            return svd(A, outU, outV, false,false);
+        }
+        /// <summary>
+        /// Singular value decomposition 
+        /// </summary>
+        /// <param name="A">Input matrix</param>
+        /// <param name="outU">[Output] Left singular vectors of A as columns of matrix U. 
+        /// Setting this parameter to a non-null value signals the need of returning those values.</param>
+        /// <param name="outV">[Output] Right singular vectors of X as rows of matrix V.
+        /// This parameter must not be null. It might be an empty array on input.</param>
+        /// <returns>Singluar values as diagonal matrix of same size and type as A</returns>
+        public static ILRetArray< double > svd(ILInArray< complex > A, ILOutArray< complex > outU, ILOutArray< complex > outV) {
+            return svd(A, outU, outV, false,false);
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+
+        /// <summary>
+        /// singular value decomposition 
+        /// </summary>
+        /// <param name="A">Input matrix</param>
+        /// <param name="outU">[Output] Left singular vectors of A as columns of matrix outU. 
+        /// Setting this parameter to a non-null value signals the need of returning those values.</param>
+        /// <param name="outV">[Output] Right singular vectors of X as rows of matrix outV.
+        /// This parameter must not be null. It might be an empty array on input.</param>
+        /// <param name="small">If true: return only first min(M,N) columns of outU and S (returned) will be 
+        /// of size [min(M,N),min(M,N)]</param>
+        /// <param name="discardFiniteTest">If true: the matrix given will not be checked for infinte or NaN values. If such elements 
+        /// exist nevertheless, this may result in failing convergence or error. In worst case 
+        /// the function may hang inside the Lapack lib! Use with care! </param>
+        /// <returns>Singular values as diagonal matrix of same size and type as A</returns>
+        public static ILRetArray< double> svd( ILInArray< double> A, ILOutArray< double> outU, 
+                                                                ILOutArray< double> outV, bool small, bool discardFiniteTest ) {
+            if (object.Equals(A,null))
+                throw new ILArgumentException("input matrix X must not be null"); 
+            using (ILScope.Enter(A)) {
+                
+                if (!A.IsMatrix)
+                    throw new ILArgumentSizeException("svd is defined for matrices only");
+                // early exit for small matrices
+                if (A.Size[1] < 4 && A.Size[0] == A.Size[1]) {
+                    switch (A.Size[0]) {
+                        case 1:
+                            if (!Object.Equals(outU, null))
+                                outU.a = ( double)1.0;
+                            if (!Object.Equals(outV, null))
+                                outV.a = ( double)1.0;
+                            return abs(A);
+                        //case 2:
+                        //    return -1; 
+                        //case 3: 
+                        //    return -1; 
+                    }
+                }
+                if (!discardFiniteTest && !allall(isfinite(A)))
+                    throw new ILArgumentException("svd: input must have only finite elements");
+                if (Lapack == null)
+                    throw new ILMathException("no Lapack package available");
+                // parameter evaluation
+                int M = A.Size[0]; int N = A.Size[1];
+                int minMN = (M < N) ? M : N;
+                int LDU = M; int LDVT = N;
+                int LDA = M, lenDU = 0, lenVT = 0;
+                
+                double[] dS = ILMemoryPool.Pool.New<  double>(minMN);
+                char jobz = (small) ? 'S' : 'A';
+                
+                double[] dU = null;
+                
+                double[] dVT = null;
+                int info = 0;
+                if (!Object.Equals(outU, null) || !Object.Equals(outV, null)) {
+                    // need to return U and VT 
+                    if (small) {
+                        lenDU = M * minMN; 
+                        dU = ILMemoryPool.Pool.New<  double>(lenDU);
+                        lenVT = N * minMN; 
+                        dVT = ILMemoryPool.Pool.New<  double>(lenVT);
+                    } else {
+                        lenDU = M * M; 
+                        dU = ILMemoryPool.Pool.New<  double>(lenDU);
+                        lenVT = N * N; 
+                        dVT = ILMemoryPool.Pool.New<  double>(lenVT);
+                    }
+                } else {
+                    jobz = 'N';
+                }
+
+                // must create copy of input ! 
+                
+                double[] dInput = A.C.GetArrayForWrite();
+                /*!HC:lapack_dgesdd*/
+                Lapack.dgesdd(jobz, M, N, dInput, LDA, dS, dU, LDU, dVT, LDVT, ref info);
+                if (info < 0)
+                    throw new ILArgumentException("the " + (-info).ToString() + "th argument to SVD was invalid");
+                if (info > 0)
+                    throw new ILArgumentException("svd was not converging");
+                ILArray< double> ret = empty<double>(ILSize.Empty00);
+                if (info == 0) {
+                    // success
+                    if (!Object.Equals(outU, null) || !Object.Equals(outV, null)) {
+                        if (small) {
+                            ret.a = zeros< double>(new ILSize(minMN, minMN));
+                        } else {
+                            ret.a = zeros< double>(new ILSize(M, N));
+                        }
+                        for (int i = 0; i < minMN; i++) {
+                            ret.SetValue(dS[i], i, i);
+                        }
+                        ILMemoryPool.Pool.Free(dS); 
+                        if (!Object.Equals(outU, null)) {
+                            outU.a = array< double>(dU, M, lenDU / M);
+                        } else {
+                            ILMemoryPool.Pool.Free(dU); 
+                        }
+                        if (!Object.Equals(outV, null)) {
+                            
+                            outV.a = array< double>(dVT, N, lenVT / N).T;
+                        } else {
+                            ILMemoryPool.Pool.Free(dVT); 
+                        }
+                    } else {
+                        ret.a = array< double>(dS,minMN, 1);
+                    }
+                }
+                return ret;
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// singular value decomposition 
+        /// </summary>
+        /// <param name="A">Input matrix</param>
+        /// <param name="outU">[Output] Left singular vectors of A as columns of matrix outU. 
+        /// Setting this parameter to a non-null value signals the need of returning those values.</param>
+        /// <param name="outV">[Output] Right singular vectors of X as rows of matrix outV.
+        /// This parameter must not be null. It might be an empty array on input.</param>
+        /// <param name="small">If true: return only first min(M,N) columns of outU and S (returned) will be 
+        /// of size [min(M,N),min(M,N)]</param>
+        /// <param name="discardFiniteTest">If true: the matrix given will not be checked for infinte or NaN values. If such elements 
+        /// exist nevertheless, this may result in failing convergence or error. In worst case 
+        /// the function may hang inside the Lapack lib! Use with care! </param>
+        /// <returns>Singular values as diagonal matrix of same size and type as A</returns>
+        public static ILRetArray< float> svd( ILInArray< float> A, ILOutArray< float> outU, 
+                                                                ILOutArray< float> outV, bool small, bool discardFiniteTest ) {
+            if (object.Equals(A,null))
+                throw new ILArgumentException("input matrix X must not be null"); 
+            using (ILScope.Enter(A)) {
+                
+                if (!A.IsMatrix)
+                    throw new ILArgumentSizeException("svd is defined for matrices only");
+                // early exit for small matrices
+                if (A.Size[1] < 4 && A.Size[0] == A.Size[1]) {
+                    switch (A.Size[0]) {
+                        case 1:
+                            if (!Object.Equals(outU, null))
+                                outU.a = ( float)1.0;
+                            if (!Object.Equals(outV, null))
+                                outV.a = ( float)1.0;
+                            return abs(A);
+                        //case 2:
+                        //    return -1; 
+                        //case 3: 
+                        //    return -1; 
+                    }
+                }
+                if (!discardFiniteTest && !allall(isfinite(A)))
+                    throw new ILArgumentException("svd: input must have only finite elements");
+                if (Lapack == null)
+                    throw new ILMathException("no Lapack package available");
+                // parameter evaluation
+                int M = A.Size[0]; int N = A.Size[1];
+                int minMN = (M < N) ? M : N;
+                int LDU = M; int LDVT = N;
+                int LDA = M, lenDU = 0, lenVT = 0;
+               
+                float[] dS = ILMemoryPool.Pool.New<  float>(minMN);
+                char jobz = (small) ? 'S' : 'A';
+               
+                float[] dU = null;
+               
+                float[] dVT = null;
+                int info = 0;
+                if (!Object.Equals(outU, null) || !Object.Equals(outV, null)) {
+                    // need to return U and VT 
+                    if (small) {
+                        lenDU = M * minMN; 
+                        dU = ILMemoryPool.Pool.New<  float>(lenDU);
+                        lenVT = N * minMN; 
+                        dVT = ILMemoryPool.Pool.New<  float>(lenVT);
+                    } else {
+                        lenDU = M * M; 
+                        dU = ILMemoryPool.Pool.New<  float>(lenDU);
+                        lenVT = N * N; 
+                        dVT = ILMemoryPool.Pool.New<  float>(lenVT);
+                    }
+                } else {
+                    jobz = 'N';
+                }
+
+                // must create copy of input ! 
+               
+                float[] dInput = A.C.GetArrayForWrite();
+                Lapack.sgesdd(jobz, M, N, dInput, LDA, dS, dU, LDU, dVT, LDVT, ref info);
+                if (info < 0)
+                    throw new ILArgumentException("the " + (-info).ToString() + "th argument to SVD was invalid");
+                if (info > 0)
+                    throw new ILArgumentException("svd was not converging");
+                ILArray< float> ret = empty<float>(ILSize.Empty00);
+                if (info == 0) {
+                    // success
+                    if (!Object.Equals(outU, null) || !Object.Equals(outV, null)) {
+                        if (small) {
+                            ret.a = zeros< float>(new ILSize(minMN, minMN));
+                        } else {
+                            ret.a = zeros< float>(new ILSize(M, N));
+                        }
+                        for (int i = 0; i < minMN; i++) {
+                            ret.SetValue(dS[i], i, i);
+                        }
+                        ILMemoryPool.Pool.Free(dS); 
+                        if (!Object.Equals(outU, null)) {
+                            outU.a = array< float>(dU, M, lenDU / M);
+                        } else {
+                            ILMemoryPool.Pool.Free(dU); 
+                        }
+                        if (!Object.Equals(outV, null)) {
+                            outV.a = new  ILRetArray<float> (dVT,N,lenVT / N).T;
+                        } else {
+                            ILMemoryPool.Pool.Free(dVT); 
+                        }
+                    } else {
+                        ret.a = array< float>(dS,minMN, 1);
+                    }
+                }
+                return ret;
+            }
+        }
+        /// <summary>
+        /// singular value decomposition 
+        /// </summary>
+        /// <param name="A">Input matrix</param>
+        /// <param name="outU">[Output] Left singular vectors of A as columns of matrix outU. 
+        /// Setting this parameter to a non-null value signals the need of returning those values.</param>
+        /// <param name="outV">[Output] Right singular vectors of X as rows of matrix outV.
+        /// This parameter must not be null. It might be an empty array on input.</param>
+        /// <param name="small">If true: return only first min(M,N) columns of outU and S (returned) will be 
+        /// of size [min(M,N),min(M,N)]</param>
+        /// <param name="discardFiniteTest">If true: the matrix given will not be checked for infinte or NaN values. If such elements 
+        /// exist nevertheless, this may result in failing convergence or error. In worst case 
+        /// the function may hang inside the Lapack lib! Use with care! </param>
+        /// <returns>Singular values as diagonal matrix of same size and type as A</returns>
+        public static ILRetArray< float> svd( ILInArray< fcomplex> A, ILOutArray< fcomplex> outU, 
+                                                                ILOutArray< fcomplex> outV, bool small, bool discardFiniteTest ) {
+            if (object.Equals(A,null))
+                throw new ILArgumentException("input matrix X must not be null"); 
+            using (ILScope.Enter(A)) {
+                
+                if (!A.IsMatrix)
+                    throw new ILArgumentSizeException("svd is defined for matrices only");
+                // early exit for small matrices
+                if (A.Size[1] < 4 && A.Size[0] == A.Size[1]) {
+                    switch (A.Size[0]) {
+                        case 1:
+                            if (!Object.Equals(outU, null))
+                                outU.a = ( fcomplex)1.0;
+                            if (!Object.Equals(outV, null))
+                                outV.a = ( fcomplex)1.0;
+                            return abs(A);
+                        //case 2:
+                        //    return -1; 
+                        //case 3: 
+                        //    return -1; 
+                    }
+                }
+                if (!discardFiniteTest && !allall(isfinite(A)))
+                    throw new ILArgumentException("svd: input must have only finite elements");
+                if (Lapack == null)
+                    throw new ILMathException("no Lapack package available");
+                // parameter evaluation
+                int M = A.Size[0]; int N = A.Size[1];
+                int minMN = (M < N) ? M : N;
+                int LDU = M; int LDVT = N;
+                int LDA = M, lenDU = 0, lenVT = 0;
+               
+                float[] dS = ILMemoryPool.Pool.New<  float>(minMN);
+                char jobz = (small) ? 'S' : 'A';
+               
+                fcomplex[] dU = null;
+               
+                fcomplex[] dVT = null;
+                int info = 0;
+                if (!Object.Equals(outU, null) || !Object.Equals(outV, null)) {
+                    // need to return U and VT 
+                    if (small) {
+                        lenDU = M * minMN; 
+                        dU = ILMemoryPool.Pool.New<  fcomplex>(lenDU);
+                        lenVT = N * minMN; 
+                        dVT = ILMemoryPool.Pool.New<  fcomplex>(lenVT);
+                    } else {
+                        lenDU = M * M; 
+                        dU = ILMemoryPool.Pool.New<  fcomplex>(lenDU);
+                        lenVT = N * N; 
+                        dVT = ILMemoryPool.Pool.New<  fcomplex>(lenVT);
+                    }
+                } else {
+                    jobz = 'N';
+                }
+
+                // must create copy of input ! 
+               
+                fcomplex[] dInput = A.C.GetArrayForWrite();
+                Lapack.cgesdd(jobz, M, N, dInput, LDA, dS, dU, LDU, dVT, LDVT, ref info);
+                if (info < 0)
+                    throw new ILArgumentException("the " + (-info).ToString() + "th argument to SVD was invalid");
+                if (info > 0)
+                    throw new ILArgumentException("svd was not converging");
+                ILArray< float> ret = empty<float>(ILSize.Empty00);
+                if (info == 0) {
+                    // success
+                    if (!Object.Equals(outU, null) || !Object.Equals(outV, null)) {
+                        if (small) {
+                            ret.a = zeros< float>(new ILSize(minMN, minMN));
+                        } else {
+                            ret.a = zeros< float>(new ILSize(M, N));
+                        }
+                        for (int i = 0; i < minMN; i++) {
+                            ret.SetValue(dS[i], i, i);
+                        }
+                        ILMemoryPool.Pool.Free(dS); 
+                        if (!Object.Equals(outU, null)) {
+                            outU.a = array< fcomplex>(dU, M, lenDU / M);
+                        } else {
+                            ILMemoryPool.Pool.Free(dU); 
+                        }
+                        if (!Object.Equals(outV, null)) {
+                            outV.a = conj(new  ILRetArray<fcomplex> (dVT,N,lenVT / N).T);
+                        } else {
+                            ILMemoryPool.Pool.Free(dVT); 
+                        }
+                    } else {
+                        ret.a = array< float>(dS,minMN, 1);
+                    }
+                }
+                return ret;
+            }
+        }
+        /// <summary>
+        /// singular value decomposition 
+        /// </summary>
+        /// <param name="A">Input matrix</param>
+        /// <param name="outU">[Output] Left singular vectors of A as columns of matrix outU. 
+        /// Setting this parameter to a non-null value signals the need of returning those values.</param>
+        /// <param name="outV">[Output] Right singular vectors of X as rows of matrix outV.
+        /// This parameter must not be null. It might be an empty array on input.</param>
+        /// <param name="small">If true: return only first min(M,N) columns of outU and S (returned) will be 
+        /// of size [min(M,N),min(M,N)]</param>
+        /// <param name="discardFiniteTest">If true: the matrix given will not be checked for infinte or NaN values. If such elements 
+        /// exist nevertheless, this may result in failing convergence or error. In worst case 
+        /// the function may hang inside the Lapack lib! Use with care! </param>
+        /// <returns>Singular values as diagonal matrix of same size and type as A</returns>
+        public static ILRetArray< double> svd( ILInArray< complex> A, ILOutArray< complex> outU, 
+                                                                ILOutArray< complex> outV, bool small, bool discardFiniteTest ) {
+            if (object.Equals(A,null))
+                throw new ILArgumentException("input matrix X must not be null"); 
+            using (ILScope.Enter(A)) {
+                
+                if (!A.IsMatrix)
+                    throw new ILArgumentSizeException("svd is defined for matrices only");
+                // early exit for small matrices
+                if (A.Size[1] < 4 && A.Size[0] == A.Size[1]) {
+                    switch (A.Size[0]) {
+                        case 1:
+                            if (!Object.Equals(outU, null))
+                                outU.a = ( complex)1.0;
+                            if (!Object.Equals(outV, null))
+                                outV.a = ( complex)1.0;
+                            return abs(A);
+                        //case 2:
+                        //    return -1; 
+                        //case 3: 
+                        //    return -1; 
+                    }
+                }
+                if (!discardFiniteTest && !allall(isfinite(A)))
+                    throw new ILArgumentException("svd: input must have only finite elements");
+                if (Lapack == null)
+                    throw new ILMathException("no Lapack package available");
+                // parameter evaluation
+                int M = A.Size[0]; int N = A.Size[1];
+                int minMN = (M < N) ? M : N;
+                int LDU = M; int LDVT = N;
+                int LDA = M, lenDU = 0, lenVT = 0;
+               
+                double[] dS = ILMemoryPool.Pool.New<  double>(minMN);
+                char jobz = (small) ? 'S' : 'A';
+               
+                complex[] dU = null;
+               
+                complex[] dVT = null;
+                int info = 0;
+                if (!Object.Equals(outU, null) || !Object.Equals(outV, null)) {
+                    // need to return U and VT 
+                    if (small) {
+                        lenDU = M * minMN; 
+                        dU = ILMemoryPool.Pool.New<  complex>(lenDU);
+                        lenVT = N * minMN; 
+                        dVT = ILMemoryPool.Pool.New<  complex>(lenVT);
+                    } else {
+                        lenDU = M * M; 
+                        dU = ILMemoryPool.Pool.New<  complex>(lenDU);
+                        lenVT = N * N; 
+                        dVT = ILMemoryPool.Pool.New<  complex>(lenVT);
+                    }
+                } else {
+                    jobz = 'N';
+                }
+
+                // must create copy of input ! 
+               
+                complex[] dInput = A.C.GetArrayForWrite();
+                Lapack.zgesdd(jobz, M, N, dInput, LDA, dS, dU, LDU, dVT, LDVT, ref info);
+                if (info < 0)
+                    throw new ILArgumentException("the " + (-info).ToString() + "th argument to SVD was invalid");
+                if (info > 0)
+                    throw new ILArgumentException("svd was not converging");
+                ILArray< double> ret = empty<double>(ILSize.Empty00);
+                if (info == 0) {
+                    // success
+                    if (!Object.Equals(outU, null) || !Object.Equals(outV, null)) {
+                        if (small) {
+                            ret.a = zeros< double>(new ILSize(minMN, minMN));
+                        } else {
+                            ret.a = zeros< double>(new ILSize(M, N));
+                        }
+                        for (int i = 0; i < minMN; i++) {
+                            ret.SetValue(dS[i], i, i);
+                        }
+                        ILMemoryPool.Pool.Free(dS); 
+                        if (!Object.Equals(outU, null)) {
+                            outU.a = array< complex>(dU, M, lenDU / M);
+                        } else {
+                            ILMemoryPool.Pool.Free(dU); 
+                        }
+                        if (!Object.Equals(outV, null)) {
+                            outV.a = conj(new  ILRetArray<complex> (dVT,N,lenVT / N).T);
+                        } else {
+                            ILMemoryPool.Pool.Free(dVT); 
+                        }
+                    } else {
+                        ret.a = array< double>(dS,minMN, 1);
+                    }
+                }
+                return ret;
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+   }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/Vertcat.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/Vertcat.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/Vertcat.cs	(revision 9102)
@@ -0,0 +1,168 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions; 
+
+
+
+namespace ILNumerics {
+    public partial class ILMath {
+
+
+        /// <summary>
+        /// Vertical array concatenation 
+        /// </summary>
+        /// <param name="arrays">Arrays to be concatenated with each other. All
+        /// arrays must be of the same inner type. The dimensions of all arrays 
+        /// must match - except for the first dimension (index 0).</param>
+        /// <returns>Larger array having all arrays in 'arrays' placed beneath each other (along dimension 0).
+        /// </returns>
+        public static ILRetArray<double> vertcat(params ILInArray<double>[] arrays) {
+            return vertcat<double>(arrays); 
+        }
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// Vertical array concatenation 
+        /// </summary>
+        /// <param name="arrays">Arrays to be concatenated with each other. All
+        /// arrays must be of the same inner type. The dimensions of all arrays 
+        /// must match - except for the first dimension (index 0).</param>
+        /// <returns>Larger array having all arrays in 'arrays' placed beneath each other (along dimension 0).
+        /// </returns>
+        public static ILRetArray<fcomplex> vertcat(params ILInArray<fcomplex>[] arrays) {
+            return vertcat<fcomplex>(arrays); 
+        }
+
+        /// <summary>
+        /// Vertical array concatenation 
+        /// </summary>
+        /// <param name="arrays">Arrays to be concatenated with each other. All
+        /// arrays must be of the same inner type. The dimensions of all arrays 
+        /// must match - except for the first dimension (index 0).</param>
+        /// <returns>Larger array having all arrays in 'arrays' placed beneath each other (along dimension 0).
+        /// </returns>
+        public static ILRetArray<complex> vertcat(params ILInArray<complex>[] arrays) {
+            return vertcat<complex>(arrays); 
+        }
+
+        /// <summary>
+        /// Vertical array concatenation 
+        /// </summary>
+        /// <param name="arrays">Arrays to be concatenated with each other. All
+        /// arrays must be of the same inner type. The dimensions of all arrays 
+        /// must match - except for the first dimension (index 0).</param>
+        /// <returns>Larger array having all arrays in 'arrays' placed beneath each other (along dimension 0).
+        /// </returns>
+        public static ILRetArray<byte> vertcat(params ILInArray<byte>[] arrays) {
+            return vertcat<byte>(arrays); 
+        }
+
+        /// <summary>
+        /// Vertical array concatenation 
+        /// </summary>
+        /// <param name="arrays">Arrays to be concatenated with each other. All
+        /// arrays must be of the same inner type. The dimensions of all arrays 
+        /// must match - except for the first dimension (index 0).</param>
+        /// <returns>Larger array having all arrays in 'arrays' placed beneath each other (along dimension 0).
+        /// </returns>
+        public static ILRetArray<Int64> vertcat(params ILInArray<Int64>[] arrays) {
+            return vertcat<Int64>(arrays); 
+        }
+
+        /// <summary>
+        /// Vertical array concatenation 
+        /// </summary>
+        /// <param name="arrays">Arrays to be concatenated with each other. All
+        /// arrays must be of the same inner type. The dimensions of all arrays 
+        /// must match - except for the first dimension (index 0).</param>
+        /// <returns>Larger array having all arrays in 'arrays' placed beneath each other (along dimension 0).
+        /// </returns>
+        public static ILRetArray<Int32> vertcat(params ILInArray<Int32>[] arrays) {
+            return vertcat<Int32>(arrays); 
+        }
+
+        /// <summary>
+        /// Vertical array concatenation 
+        /// </summary>
+        /// <param name="arrays">Arrays to be concatenated with each other. All
+        /// arrays must be of the same inner type. The dimensions of all arrays 
+        /// must match - except for the first dimension (index 0).</param>
+        /// <returns>Larger array having all arrays in 'arrays' placed beneath each other (along dimension 0).
+        /// </returns>
+        public static ILRetArray<float> vertcat(params ILInArray<float>[] arrays) {
+            return vertcat<float>(arrays); 
+        }
+
+
+#endregion HYCALPER AUTO GENERATED CODE
+       /// <summary>
+        /// Vertical array concatenation 
+        /// </summary>
+        /// <param name="arrays">Arrays to be concatenated with each other. All
+        /// arrays must be of the same inner type. The dimensions of all arrays 
+        /// must match - except for the first dimension (index 0).</param>
+        /// <returns>Larger array having all arrays in 'arrays' placed beneath each other.
+        /// </returns>
+        public static ILRetArray<T> vertcat<T>(params ILInArray<T>[] arrays) {
+            if (arrays == null) 
+                throw new ILArgumentException("input argument must not be null!"); 
+            if (arrays.Length == 0 || object.Equals(arrays[0],null)) 
+                return empty<T>(ILSize.Empty00);
+            using (ILScope.Enter(arrays)) {
+                if (arrays.Length == 1)
+                    return arrays[0].C;
+                ILDenseStorage<T> ret = arrays[0].Storage.Concat(arrays[1].Storage, 0);
+                for (int i = 2; i < arrays.Length; i++) {
+                    ILDenseStorage<T> tmp = ret.Concat(arrays[i].Storage, 0);
+                    ret.Dispose();
+                    ret = tmp;
+                }
+                return new ILRetArray<T>(ret);
+            }
+        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/abs.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/abs.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/abs.cs	(revision 9102)
@@ -0,0 +1,815 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics;
+using ILNumerics.Exceptions;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+
+
+namespace ILNumerics {
+    public partial class ILMath {
+        /// <summary>Absolute values of array elements</summary>
+        /// <param name="A">Input Array</param>
+        /// <returns>Absolute values of array elements</returns>
+        /// <remarks><para>If the Input Array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static ILRetArray<byte> abs(ILInArray<byte> A) {
+            using (ILScope.Enter(A)) {
+                return A.C;
+            }
+        }
+
+
+                        
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>Absolute values of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Absolute values of array elements</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<double>  abs (ILInArray< double > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<double>(A.Size); 
+                ILSize inDim = A.Size;
+                double[] arrA = A.GetArrayForRead(); 
+                double [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)){
+                    retArr = ILMemoryPool.Pool.New<double>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<double> retStorage = new ILDenseStorage<double>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    double* cp = ((double*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  Math.Abs(cp[0]  )  /*dummy*/;
+                            cp[1] =  Math.Abs(cp[1]  )  /*dummy*/;
+                            cp[2] =  Math.Abs(cp[2]  )  /*dummy*/;
+                            cp[3] =  Math.Abs(cp[3]  )  /*dummy*/;
+                            cp[4] =  Math.Abs(cp[4]  )  /*dummy*/;
+                            cp[5] =  Math.Abs(cp[5]  )  /*dummy*/;
+                            cp[6] =  Math.Abs(cp[6]  )  /*dummy*/;
+                            cp[7] =  Math.Abs(cp[7]  )  /*dummy*/;
+                            cp[8] =  Math.Abs(cp[8]  )  /*dummy*/;
+                            cp[9] =  Math.Abs(cp[9]  )  /*dummy*/;
+                            cp[10] =  Math.Abs(cp[10]  )  /*dummy*/;
+                            cp[11] =  Math.Abs(cp[11]  )  /*dummy*/;
+                            cp[12] =  Math.Abs(cp[12]  )  /*dummy*/;
+                            cp[13] =  Math.Abs(cp[13]  )  /*dummy*/;
+                            cp[14] =  Math.Abs(cp[14]  )  /*dummy*/;
+                            cp[15] =  Math.Abs(cp[15]  )  /*dummy*/;
+                            cp[16] =  Math.Abs(cp[16]  )  /*dummy*/;
+                            cp[17] =  Math.Abs(cp[17]  )  /*dummy*/;
+                            cp[18] =  Math.Abs(cp[18]  )  /*dummy*/;
+                            cp[19] =  Math.Abs(cp[19]  )  /*dummy*/;
+                            cp[20] =  Math.Abs(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Math.Abs(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        double* ap = ((double*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  Math.Abs(ap[0]  )  /*dummy*/;
+                            cp[1] =  Math.Abs(ap[1]  )  /*dummy*/;
+                            cp[2] =  Math.Abs(ap[2]  )  /*dummy*/;
+                            cp[3] =  Math.Abs(ap[3]  )  /*dummy*/;
+                            cp[4] =  Math.Abs(ap[4]  )  /*dummy*/;
+                            cp[5] =  Math.Abs(ap[5]  )  /*dummy*/;
+                            cp[6] =  Math.Abs(ap[6]  )  /*dummy*/;
+                            cp[7] =  Math.Abs(ap[7]  )  /*dummy*/;
+                            cp[8] =  Math.Abs(ap[8]  )  /*dummy*/;
+                            cp[9] =  Math.Abs(ap[9]  )  /*dummy*/;
+                            cp[10] =  Math.Abs(ap[10]  )  /*dummy*/;
+                            cp[11] =  Math.Abs(ap[11]  )  /*dummy*/;
+                            cp[12] =  Math.Abs(ap[12]  )  /*dummy*/;
+                            cp[13] =  Math.Abs(ap[13]  )  /*dummy*/;
+                            cp[14] =  Math.Abs(ap[14]  )  /*dummy*/;
+                            cp[15] =  Math.Abs(ap[15]  )  /*dummy*/;
+                            cp[16] =  Math.Abs(ap[16]  )  /*dummy*/;
+                            cp[17] =  Math.Abs(ap[17]  )  /*dummy*/;
+                            cp[18] =  Math.Abs(ap[18]  )  /*dummy*/;
+                            cp[19] =  Math.Abs(ap[19]  )  /*dummy*/;
+                            cp[20] =  Math.Abs(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Math.Abs(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( double* arrAP = arrA)
+                fixed ( double* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<double>(retStorage);
+            }
+        }
+        /// <summary>Absolute values of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Absolute values of array elements</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<float>  abs (ILInArray< float > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<float>(A.Size); 
+                ILSize inDim = A.Size;
+                float[] arrA = A.GetArrayForRead(); 
+                float [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)){
+                    retArr = ILMemoryPool.Pool.New<float>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<float> retStorage = new ILDenseStorage<float>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    float* cp = ((float*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  Math.Abs(cp[0]  )  /*dummy*/;
+                            cp[1] =  Math.Abs(cp[1]  )  /*dummy*/;
+                            cp[2] =  Math.Abs(cp[2]  )  /*dummy*/;
+                            cp[3] =  Math.Abs(cp[3]  )  /*dummy*/;
+                            cp[4] =  Math.Abs(cp[4]  )  /*dummy*/;
+                            cp[5] =  Math.Abs(cp[5]  )  /*dummy*/;
+                            cp[6] =  Math.Abs(cp[6]  )  /*dummy*/;
+                            cp[7] =  Math.Abs(cp[7]  )  /*dummy*/;
+                            cp[8] =  Math.Abs(cp[8]  )  /*dummy*/;
+                            cp[9] =  Math.Abs(cp[9]  )  /*dummy*/;
+                            cp[10] =  Math.Abs(cp[10]  )  /*dummy*/;
+                            cp[11] =  Math.Abs(cp[11]  )  /*dummy*/;
+                            cp[12] =  Math.Abs(cp[12]  )  /*dummy*/;
+                            cp[13] =  Math.Abs(cp[13]  )  /*dummy*/;
+                            cp[14] =  Math.Abs(cp[14]  )  /*dummy*/;
+                            cp[15] =  Math.Abs(cp[15]  )  /*dummy*/;
+                            cp[16] =  Math.Abs(cp[16]  )  /*dummy*/;
+                            cp[17] =  Math.Abs(cp[17]  )  /*dummy*/;
+                            cp[18] =  Math.Abs(cp[18]  )  /*dummy*/;
+                            cp[19] =  Math.Abs(cp[19]  )  /*dummy*/;
+                            cp[20] =  Math.Abs(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Math.Abs(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        float* ap = ((float*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  Math.Abs(ap[0]  )  /*dummy*/;
+                            cp[1] =  Math.Abs(ap[1]  )  /*dummy*/;
+                            cp[2] =  Math.Abs(ap[2]  )  /*dummy*/;
+                            cp[3] =  Math.Abs(ap[3]  )  /*dummy*/;
+                            cp[4] =  Math.Abs(ap[4]  )  /*dummy*/;
+                            cp[5] =  Math.Abs(ap[5]  )  /*dummy*/;
+                            cp[6] =  Math.Abs(ap[6]  )  /*dummy*/;
+                            cp[7] =  Math.Abs(ap[7]  )  /*dummy*/;
+                            cp[8] =  Math.Abs(ap[8]  )  /*dummy*/;
+                            cp[9] =  Math.Abs(ap[9]  )  /*dummy*/;
+                            cp[10] =  Math.Abs(ap[10]  )  /*dummy*/;
+                            cp[11] =  Math.Abs(ap[11]  )  /*dummy*/;
+                            cp[12] =  Math.Abs(ap[12]  )  /*dummy*/;
+                            cp[13] =  Math.Abs(ap[13]  )  /*dummy*/;
+                            cp[14] =  Math.Abs(ap[14]  )  /*dummy*/;
+                            cp[15] =  Math.Abs(ap[15]  )  /*dummy*/;
+                            cp[16] =  Math.Abs(ap[16]  )  /*dummy*/;
+                            cp[17] =  Math.Abs(ap[17]  )  /*dummy*/;
+                            cp[18] =  Math.Abs(ap[18]  )  /*dummy*/;
+                            cp[19] =  Math.Abs(ap[19]  )  /*dummy*/;
+                            cp[20] =  Math.Abs(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Math.Abs(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( float* arrAP = arrA)
+                fixed ( float* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<float>(retStorage);
+            }
+        }
+        /// <summary>Magnitude of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Magnitude of array elements</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<float>  abs (ILInArray< fcomplex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<float>(A.Size); 
+                ILSize inDim = A.Size;
+                fcomplex[] arrA = A.GetArrayForRead(); 
+                float [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (true){
+                    retArr = ILMemoryPool.Pool.New<float>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<float> retStorage = new ILDenseStorage<float>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    float* cp = ((float*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  fcomplex.Abs(cp[0]  )  /*dummy*/;
+                            cp[1] =  fcomplex.Abs(cp[1]  )  /*dummy*/;
+                            cp[2] =  fcomplex.Abs(cp[2]  )  /*dummy*/;
+                            cp[3] =  fcomplex.Abs(cp[3]  )  /*dummy*/;
+                            cp[4] =  fcomplex.Abs(cp[4]  )  /*dummy*/;
+                            cp[5] =  fcomplex.Abs(cp[5]  )  /*dummy*/;
+                            cp[6] =  fcomplex.Abs(cp[6]  )  /*dummy*/;
+                            cp[7] =  fcomplex.Abs(cp[7]  )  /*dummy*/;
+                            cp[8] =  fcomplex.Abs(cp[8]  )  /*dummy*/;
+                            cp[9] =  fcomplex.Abs(cp[9]  )  /*dummy*/;
+                            cp[10] =  fcomplex.Abs(cp[10]  )  /*dummy*/;
+                            cp[11] =  fcomplex.Abs(cp[11]  )  /*dummy*/;
+                            cp[12] =  fcomplex.Abs(cp[12]  )  /*dummy*/;
+                            cp[13] =  fcomplex.Abs(cp[13]  )  /*dummy*/;
+                            cp[14] =  fcomplex.Abs(cp[14]  )  /*dummy*/;
+                            cp[15] =  fcomplex.Abs(cp[15]  )  /*dummy*/;
+                            cp[16] =  fcomplex.Abs(cp[16]  )  /*dummy*/;
+                            cp[17] =  fcomplex.Abs(cp[17]  )  /*dummy*/;
+                            cp[18] =  fcomplex.Abs(cp[18]  )  /*dummy*/;
+                            cp[19] =  fcomplex.Abs(cp[19]  )  /*dummy*/;
+                            cp[20] =  fcomplex.Abs(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.Abs(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        fcomplex* ap = ((fcomplex*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  fcomplex.Abs(ap[0]  )  /*dummy*/;
+                            cp[1] =  fcomplex.Abs(ap[1]  )  /*dummy*/;
+                            cp[2] =  fcomplex.Abs(ap[2]  )  /*dummy*/;
+                            cp[3] =  fcomplex.Abs(ap[3]  )  /*dummy*/;
+                            cp[4] =  fcomplex.Abs(ap[4]  )  /*dummy*/;
+                            cp[5] =  fcomplex.Abs(ap[5]  )  /*dummy*/;
+                            cp[6] =  fcomplex.Abs(ap[6]  )  /*dummy*/;
+                            cp[7] =  fcomplex.Abs(ap[7]  )  /*dummy*/;
+                            cp[8] =  fcomplex.Abs(ap[8]  )  /*dummy*/;
+                            cp[9] =  fcomplex.Abs(ap[9]  )  /*dummy*/;
+                            cp[10] =  fcomplex.Abs(ap[10]  )  /*dummy*/;
+                            cp[11] =  fcomplex.Abs(ap[11]  )  /*dummy*/;
+                            cp[12] =  fcomplex.Abs(ap[12]  )  /*dummy*/;
+                            cp[13] =  fcomplex.Abs(ap[13]  )  /*dummy*/;
+                            cp[14] =  fcomplex.Abs(ap[14]  )  /*dummy*/;
+                            cp[15] =  fcomplex.Abs(ap[15]  )  /*dummy*/;
+                            cp[16] =  fcomplex.Abs(ap[16]  )  /*dummy*/;
+                            cp[17] =  fcomplex.Abs(ap[17]  )  /*dummy*/;
+                            cp[18] =  fcomplex.Abs(ap[18]  )  /*dummy*/;
+                            cp[19] =  fcomplex.Abs(ap[19]  )  /*dummy*/;
+                            cp[20] =  fcomplex.Abs(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.Abs(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( fcomplex* arrAP = arrA)
+                fixed ( float* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<float>(retStorage);
+            }
+        }
+        /// <summary>Magnitude of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Magnitude of array elements</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<double>  abs (ILInArray< complex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<double>(A.Size); 
+                ILSize inDim = A.Size;
+                complex[] arrA = A.GetArrayForRead(); 
+                double [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (true){
+                    retArr = ILMemoryPool.Pool.New<double>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<double> retStorage = new ILDenseStorage<double>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    double* cp = ((double*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  complex.Abs(cp[0]  )  /*dummy*/;
+                            cp[1] =  complex.Abs(cp[1]  )  /*dummy*/;
+                            cp[2] =  complex.Abs(cp[2]  )  /*dummy*/;
+                            cp[3] =  complex.Abs(cp[3]  )  /*dummy*/;
+                            cp[4] =  complex.Abs(cp[4]  )  /*dummy*/;
+                            cp[5] =  complex.Abs(cp[5]  )  /*dummy*/;
+                            cp[6] =  complex.Abs(cp[6]  )  /*dummy*/;
+                            cp[7] =  complex.Abs(cp[7]  )  /*dummy*/;
+                            cp[8] =  complex.Abs(cp[8]  )  /*dummy*/;
+                            cp[9] =  complex.Abs(cp[9]  )  /*dummy*/;
+                            cp[10] =  complex.Abs(cp[10]  )  /*dummy*/;
+                            cp[11] =  complex.Abs(cp[11]  )  /*dummy*/;
+                            cp[12] =  complex.Abs(cp[12]  )  /*dummy*/;
+                            cp[13] =  complex.Abs(cp[13]  )  /*dummy*/;
+                            cp[14] =  complex.Abs(cp[14]  )  /*dummy*/;
+                            cp[15] =  complex.Abs(cp[15]  )  /*dummy*/;
+                            cp[16] =  complex.Abs(cp[16]  )  /*dummy*/;
+                            cp[17] =  complex.Abs(cp[17]  )  /*dummy*/;
+                            cp[18] =  complex.Abs(cp[18]  )  /*dummy*/;
+                            cp[19] =  complex.Abs(cp[19]  )  /*dummy*/;
+                            cp[20] =  complex.Abs(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.Abs(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        complex* ap = ((complex*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  complex.Abs(ap[0]  )  /*dummy*/;
+                            cp[1] =  complex.Abs(ap[1]  )  /*dummy*/;
+                            cp[2] =  complex.Abs(ap[2]  )  /*dummy*/;
+                            cp[3] =  complex.Abs(ap[3]  )  /*dummy*/;
+                            cp[4] =  complex.Abs(ap[4]  )  /*dummy*/;
+                            cp[5] =  complex.Abs(ap[5]  )  /*dummy*/;
+                            cp[6] =  complex.Abs(ap[6]  )  /*dummy*/;
+                            cp[7] =  complex.Abs(ap[7]  )  /*dummy*/;
+                            cp[8] =  complex.Abs(ap[8]  )  /*dummy*/;
+                            cp[9] =  complex.Abs(ap[9]  )  /*dummy*/;
+                            cp[10] =  complex.Abs(ap[10]  )  /*dummy*/;
+                            cp[11] =  complex.Abs(ap[11]  )  /*dummy*/;
+                            cp[12] =  complex.Abs(ap[12]  )  /*dummy*/;
+                            cp[13] =  complex.Abs(ap[13]  )  /*dummy*/;
+                            cp[14] =  complex.Abs(ap[14]  )  /*dummy*/;
+                            cp[15] =  complex.Abs(ap[15]  )  /*dummy*/;
+                            cp[16] =  complex.Abs(ap[16]  )  /*dummy*/;
+                            cp[17] =  complex.Abs(ap[17]  )  /*dummy*/;
+                            cp[18] =  complex.Abs(ap[18]  )  /*dummy*/;
+                            cp[19] =  complex.Abs(ap[19]  )  /*dummy*/;
+                            cp[20] =  complex.Abs(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.Abs(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( complex* arrAP = arrA)
+                fixed ( double* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<double>(retStorage);
+            }
+        }
+        /// <summary>Absolute values of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Absolute values of array elements</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<Int64>  abs (ILInArray< Int64 > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<Int64>(A.Size); 
+                ILSize inDim = A.Size;
+                Int64[] arrA = A.GetArrayForRead(); 
+                Int64 [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)){
+                    retArr = ILMemoryPool.Pool.New<Int64>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<Int64> retStorage = new ILDenseStorage<Int64>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    Int64* cp = ((Int64*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  Math.Abs(cp[0]  )  /*dummy*/;
+                            cp[1] =  Math.Abs(cp[1]  )  /*dummy*/;
+                            cp[2] =  Math.Abs(cp[2]  )  /*dummy*/;
+                            cp[3] =  Math.Abs(cp[3]  )  /*dummy*/;
+                            cp[4] =  Math.Abs(cp[4]  )  /*dummy*/;
+                            cp[5] =  Math.Abs(cp[5]  )  /*dummy*/;
+                            cp[6] =  Math.Abs(cp[6]  )  /*dummy*/;
+                            cp[7] =  Math.Abs(cp[7]  )  /*dummy*/;
+                            cp[8] =  Math.Abs(cp[8]  )  /*dummy*/;
+                            cp[9] =  Math.Abs(cp[9]  )  /*dummy*/;
+                            cp[10] =  Math.Abs(cp[10]  )  /*dummy*/;
+                            cp[11] =  Math.Abs(cp[11]  )  /*dummy*/;
+                            cp[12] =  Math.Abs(cp[12]  )  /*dummy*/;
+                            cp[13] =  Math.Abs(cp[13]  )  /*dummy*/;
+                            cp[14] =  Math.Abs(cp[14]  )  /*dummy*/;
+                            cp[15] =  Math.Abs(cp[15]  )  /*dummy*/;
+                            cp[16] =  Math.Abs(cp[16]  )  /*dummy*/;
+                            cp[17] =  Math.Abs(cp[17]  )  /*dummy*/;
+                            cp[18] =  Math.Abs(cp[18]  )  /*dummy*/;
+                            cp[19] =  Math.Abs(cp[19]  )  /*dummy*/;
+                            cp[20] =  Math.Abs(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Math.Abs(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        Int64* ap = ((Int64*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  Math.Abs(ap[0]  )  /*dummy*/;
+                            cp[1] =  Math.Abs(ap[1]  )  /*dummy*/;
+                            cp[2] =  Math.Abs(ap[2]  )  /*dummy*/;
+                            cp[3] =  Math.Abs(ap[3]  )  /*dummy*/;
+                            cp[4] =  Math.Abs(ap[4]  )  /*dummy*/;
+                            cp[5] =  Math.Abs(ap[5]  )  /*dummy*/;
+                            cp[6] =  Math.Abs(ap[6]  )  /*dummy*/;
+                            cp[7] =  Math.Abs(ap[7]  )  /*dummy*/;
+                            cp[8] =  Math.Abs(ap[8]  )  /*dummy*/;
+                            cp[9] =  Math.Abs(ap[9]  )  /*dummy*/;
+                            cp[10] =  Math.Abs(ap[10]  )  /*dummy*/;
+                            cp[11] =  Math.Abs(ap[11]  )  /*dummy*/;
+                            cp[12] =  Math.Abs(ap[12]  )  /*dummy*/;
+                            cp[13] =  Math.Abs(ap[13]  )  /*dummy*/;
+                            cp[14] =  Math.Abs(ap[14]  )  /*dummy*/;
+                            cp[15] =  Math.Abs(ap[15]  )  /*dummy*/;
+                            cp[16] =  Math.Abs(ap[16]  )  /*dummy*/;
+                            cp[17] =  Math.Abs(ap[17]  )  /*dummy*/;
+                            cp[18] =  Math.Abs(ap[18]  )  /*dummy*/;
+                            cp[19] =  Math.Abs(ap[19]  )  /*dummy*/;
+                            cp[20] =  Math.Abs(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Math.Abs(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( Int64* arrAP = arrA)
+                fixed ( Int64* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<Int64>(retStorage);
+            }
+        }
+        /// <summary>Absolute values of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Absolute values of array elements</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<Int32>  abs (ILInArray< Int32 > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<Int32>(A.Size); 
+                ILSize inDim = A.Size;
+                Int32[] arrA = A.GetArrayForRead(); 
+                Int32 [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)){
+                    retArr = ILMemoryPool.Pool.New<Int32>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<Int32> retStorage = new ILDenseStorage<Int32>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    Int32* cp = ((Int32*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  Math.Abs(cp[0]  )  /*dummy*/;
+                            cp[1] =  Math.Abs(cp[1]  )  /*dummy*/;
+                            cp[2] =  Math.Abs(cp[2]  )  /*dummy*/;
+                            cp[3] =  Math.Abs(cp[3]  )  /*dummy*/;
+                            cp[4] =  Math.Abs(cp[4]  )  /*dummy*/;
+                            cp[5] =  Math.Abs(cp[5]  )  /*dummy*/;
+                            cp[6] =  Math.Abs(cp[6]  )  /*dummy*/;
+                            cp[7] =  Math.Abs(cp[7]  )  /*dummy*/;
+                            cp[8] =  Math.Abs(cp[8]  )  /*dummy*/;
+                            cp[9] =  Math.Abs(cp[9]  )  /*dummy*/;
+                            cp[10] =  Math.Abs(cp[10]  )  /*dummy*/;
+                            cp[11] =  Math.Abs(cp[11]  )  /*dummy*/;
+                            cp[12] =  Math.Abs(cp[12]  )  /*dummy*/;
+                            cp[13] =  Math.Abs(cp[13]  )  /*dummy*/;
+                            cp[14] =  Math.Abs(cp[14]  )  /*dummy*/;
+                            cp[15] =  Math.Abs(cp[15]  )  /*dummy*/;
+                            cp[16] =  Math.Abs(cp[16]  )  /*dummy*/;
+                            cp[17] =  Math.Abs(cp[17]  )  /*dummy*/;
+                            cp[18] =  Math.Abs(cp[18]  )  /*dummy*/;
+                            cp[19] =  Math.Abs(cp[19]  )  /*dummy*/;
+                            cp[20] =  Math.Abs(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Math.Abs(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        Int32* ap = ((Int32*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  Math.Abs(ap[0]  )  /*dummy*/;
+                            cp[1] =  Math.Abs(ap[1]  )  /*dummy*/;
+                            cp[2] =  Math.Abs(ap[2]  )  /*dummy*/;
+                            cp[3] =  Math.Abs(ap[3]  )  /*dummy*/;
+                            cp[4] =  Math.Abs(ap[4]  )  /*dummy*/;
+                            cp[5] =  Math.Abs(ap[5]  )  /*dummy*/;
+                            cp[6] =  Math.Abs(ap[6]  )  /*dummy*/;
+                            cp[7] =  Math.Abs(ap[7]  )  /*dummy*/;
+                            cp[8] =  Math.Abs(ap[8]  )  /*dummy*/;
+                            cp[9] =  Math.Abs(ap[9]  )  /*dummy*/;
+                            cp[10] =  Math.Abs(ap[10]  )  /*dummy*/;
+                            cp[11] =  Math.Abs(ap[11]  )  /*dummy*/;
+                            cp[12] =  Math.Abs(ap[12]  )  /*dummy*/;
+                            cp[13] =  Math.Abs(ap[13]  )  /*dummy*/;
+                            cp[14] =  Math.Abs(ap[14]  )  /*dummy*/;
+                            cp[15] =  Math.Abs(ap[15]  )  /*dummy*/;
+                            cp[16] =  Math.Abs(ap[16]  )  /*dummy*/;
+                            cp[17] =  Math.Abs(ap[17]  )  /*dummy*/;
+                            cp[18] =  Math.Abs(ap[18]  )  /*dummy*/;
+                            cp[19] =  Math.Abs(ap[19]  )  /*dummy*/;
+                            cp[20] =  Math.Abs(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Math.Abs(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( Int32* arrAP = arrA)
+                fixed ( Int32* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<Int32>(retStorage);
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/acos.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/acos.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/acos.cs	(revision 9102)
@@ -0,0 +1,803 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics;
+using ILNumerics.Exceptions;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+
+
+namespace ILNumerics {
+    public partial class ILMath {
+
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>Arccosine of array elements - complex output</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Arccosine of array elements - complex output</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<complex>  acosc (ILInArray< double > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<complex>(A.Size); 
+                ILSize inDim = A.Size;
+                double[] arrA = A.GetArrayForRead(); 
+                complex [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (true){
+                    retArr = ILMemoryPool.Pool.New<complex>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<complex> retStorage = new ILDenseStorage<complex>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    complex* cp = ((complex*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  complex.Acos(cp[0]  )  /*dummy*/;
+                            cp[1] =  complex.Acos(cp[1]  )  /*dummy*/;
+                            cp[2] =  complex.Acos(cp[2]  )  /*dummy*/;
+                            cp[3] =  complex.Acos(cp[3]  )  /*dummy*/;
+                            cp[4] =  complex.Acos(cp[4]  )  /*dummy*/;
+                            cp[5] =  complex.Acos(cp[5]  )  /*dummy*/;
+                            cp[6] =  complex.Acos(cp[6]  )  /*dummy*/;
+                            cp[7] =  complex.Acos(cp[7]  )  /*dummy*/;
+                            cp[8] =  complex.Acos(cp[8]  )  /*dummy*/;
+                            cp[9] =  complex.Acos(cp[9]  )  /*dummy*/;
+                            cp[10] =  complex.Acos(cp[10]  )  /*dummy*/;
+                            cp[11] =  complex.Acos(cp[11]  )  /*dummy*/;
+                            cp[12] =  complex.Acos(cp[12]  )  /*dummy*/;
+                            cp[13] =  complex.Acos(cp[13]  )  /*dummy*/;
+                            cp[14] =  complex.Acos(cp[14]  )  /*dummy*/;
+                            cp[15] =  complex.Acos(cp[15]  )  /*dummy*/;
+                            cp[16] =  complex.Acos(cp[16]  )  /*dummy*/;
+                            cp[17] =  complex.Acos(cp[17]  )  /*dummy*/;
+                            cp[18] =  complex.Acos(cp[18]  )  /*dummy*/;
+                            cp[19] =  complex.Acos(cp[19]  )  /*dummy*/;
+                            cp[20] =  complex.Acos(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.Acos(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        double* ap = ((double*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  complex.Acos(ap[0]  )  /*dummy*/;
+                            cp[1] =  complex.Acos(ap[1]  )  /*dummy*/;
+                            cp[2] =  complex.Acos(ap[2]  )  /*dummy*/;
+                            cp[3] =  complex.Acos(ap[3]  )  /*dummy*/;
+                            cp[4] =  complex.Acos(ap[4]  )  /*dummy*/;
+                            cp[5] =  complex.Acos(ap[5]  )  /*dummy*/;
+                            cp[6] =  complex.Acos(ap[6]  )  /*dummy*/;
+                            cp[7] =  complex.Acos(ap[7]  )  /*dummy*/;
+                            cp[8] =  complex.Acos(ap[8]  )  /*dummy*/;
+                            cp[9] =  complex.Acos(ap[9]  )  /*dummy*/;
+                            cp[10] =  complex.Acos(ap[10]  )  /*dummy*/;
+                            cp[11] =  complex.Acos(ap[11]  )  /*dummy*/;
+                            cp[12] =  complex.Acos(ap[12]  )  /*dummy*/;
+                            cp[13] =  complex.Acos(ap[13]  )  /*dummy*/;
+                            cp[14] =  complex.Acos(ap[14]  )  /*dummy*/;
+                            cp[15] =  complex.Acos(ap[15]  )  /*dummy*/;
+                            cp[16] =  complex.Acos(ap[16]  )  /*dummy*/;
+                            cp[17] =  complex.Acos(ap[17]  )  /*dummy*/;
+                            cp[18] =  complex.Acos(ap[18]  )  /*dummy*/;
+                            cp[19] =  complex.Acos(ap[19]  )  /*dummy*/;
+                            cp[20] =  complex.Acos(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.Acos(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( double* arrAP = arrA)
+                fixed ( complex* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<complex>(retStorage);
+            }
+        }
+        /// <summary>Arccosine of array elements - complex output</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Arccosine of array elements - complex output</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<fcomplex>  acosc (ILInArray< float > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<fcomplex>(A.Size); 
+                ILSize inDim = A.Size;
+                float[] arrA = A.GetArrayForRead(); 
+                fcomplex [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (true){
+                    retArr = ILMemoryPool.Pool.New<fcomplex>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<fcomplex> retStorage = new ILDenseStorage<fcomplex>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    fcomplex* cp = ((fcomplex*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  fcomplex.Acos(cp[0]  )  /*dummy*/;
+                            cp[1] =  fcomplex.Acos(cp[1]  )  /*dummy*/;
+                            cp[2] =  fcomplex.Acos(cp[2]  )  /*dummy*/;
+                            cp[3] =  fcomplex.Acos(cp[3]  )  /*dummy*/;
+                            cp[4] =  fcomplex.Acos(cp[4]  )  /*dummy*/;
+                            cp[5] =  fcomplex.Acos(cp[5]  )  /*dummy*/;
+                            cp[6] =  fcomplex.Acos(cp[6]  )  /*dummy*/;
+                            cp[7] =  fcomplex.Acos(cp[7]  )  /*dummy*/;
+                            cp[8] =  fcomplex.Acos(cp[8]  )  /*dummy*/;
+                            cp[9] =  fcomplex.Acos(cp[9]  )  /*dummy*/;
+                            cp[10] =  fcomplex.Acos(cp[10]  )  /*dummy*/;
+                            cp[11] =  fcomplex.Acos(cp[11]  )  /*dummy*/;
+                            cp[12] =  fcomplex.Acos(cp[12]  )  /*dummy*/;
+                            cp[13] =  fcomplex.Acos(cp[13]  )  /*dummy*/;
+                            cp[14] =  fcomplex.Acos(cp[14]  )  /*dummy*/;
+                            cp[15] =  fcomplex.Acos(cp[15]  )  /*dummy*/;
+                            cp[16] =  fcomplex.Acos(cp[16]  )  /*dummy*/;
+                            cp[17] =  fcomplex.Acos(cp[17]  )  /*dummy*/;
+                            cp[18] =  fcomplex.Acos(cp[18]  )  /*dummy*/;
+                            cp[19] =  fcomplex.Acos(cp[19]  )  /*dummy*/;
+                            cp[20] =  fcomplex.Acos(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.Acos(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        float* ap = ((float*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  fcomplex.Acos(ap[0]  )  /*dummy*/;
+                            cp[1] =  fcomplex.Acos(ap[1]  )  /*dummy*/;
+                            cp[2] =  fcomplex.Acos(ap[2]  )  /*dummy*/;
+                            cp[3] =  fcomplex.Acos(ap[3]  )  /*dummy*/;
+                            cp[4] =  fcomplex.Acos(ap[4]  )  /*dummy*/;
+                            cp[5] =  fcomplex.Acos(ap[5]  )  /*dummy*/;
+                            cp[6] =  fcomplex.Acos(ap[6]  )  /*dummy*/;
+                            cp[7] =  fcomplex.Acos(ap[7]  )  /*dummy*/;
+                            cp[8] =  fcomplex.Acos(ap[8]  )  /*dummy*/;
+                            cp[9] =  fcomplex.Acos(ap[9]  )  /*dummy*/;
+                            cp[10] =  fcomplex.Acos(ap[10]  )  /*dummy*/;
+                            cp[11] =  fcomplex.Acos(ap[11]  )  /*dummy*/;
+                            cp[12] =  fcomplex.Acos(ap[12]  )  /*dummy*/;
+                            cp[13] =  fcomplex.Acos(ap[13]  )  /*dummy*/;
+                            cp[14] =  fcomplex.Acos(ap[14]  )  /*dummy*/;
+                            cp[15] =  fcomplex.Acos(ap[15]  )  /*dummy*/;
+                            cp[16] =  fcomplex.Acos(ap[16]  )  /*dummy*/;
+                            cp[17] =  fcomplex.Acos(ap[17]  )  /*dummy*/;
+                            cp[18] =  fcomplex.Acos(ap[18]  )  /*dummy*/;
+                            cp[19] =  fcomplex.Acos(ap[19]  )  /*dummy*/;
+                            cp[20] =  fcomplex.Acos(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.Acos(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( float* arrAP = arrA)
+                fixed ( fcomplex* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<fcomplex>(retStorage);
+            }
+        }
+        /// <summary>Arccosine values of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Arccosine of array elements</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<complex>  acos (ILInArray< complex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<complex>(A.Size); 
+                ILSize inDim = A.Size;
+                complex[] arrA = A.GetArrayForRead(); 
+                complex [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<complex>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<complex> retStorage = new ILDenseStorage<complex>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    complex* cp = ((complex*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  complex.Acos(cp[0]  )  /*dummy*/;
+                            cp[1] =  complex.Acos(cp[1]  )  /*dummy*/;
+                            cp[2] =  complex.Acos(cp[2]  )  /*dummy*/;
+                            cp[3] =  complex.Acos(cp[3]  )  /*dummy*/;
+                            cp[4] =  complex.Acos(cp[4]  )  /*dummy*/;
+                            cp[5] =  complex.Acos(cp[5]  )  /*dummy*/;
+                            cp[6] =  complex.Acos(cp[6]  )  /*dummy*/;
+                            cp[7] =  complex.Acos(cp[7]  )  /*dummy*/;
+                            cp[8] =  complex.Acos(cp[8]  )  /*dummy*/;
+                            cp[9] =  complex.Acos(cp[9]  )  /*dummy*/;
+                            cp[10] =  complex.Acos(cp[10]  )  /*dummy*/;
+                            cp[11] =  complex.Acos(cp[11]  )  /*dummy*/;
+                            cp[12] =  complex.Acos(cp[12]  )  /*dummy*/;
+                            cp[13] =  complex.Acos(cp[13]  )  /*dummy*/;
+                            cp[14] =  complex.Acos(cp[14]  )  /*dummy*/;
+                            cp[15] =  complex.Acos(cp[15]  )  /*dummy*/;
+                            cp[16] =  complex.Acos(cp[16]  )  /*dummy*/;
+                            cp[17] =  complex.Acos(cp[17]  )  /*dummy*/;
+                            cp[18] =  complex.Acos(cp[18]  )  /*dummy*/;
+                            cp[19] =  complex.Acos(cp[19]  )  /*dummy*/;
+                            cp[20] =  complex.Acos(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.Acos(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        complex* ap = ((complex*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  complex.Acos(ap[0]  )  /*dummy*/;
+                            cp[1] =  complex.Acos(ap[1]  )  /*dummy*/;
+                            cp[2] =  complex.Acos(ap[2]  )  /*dummy*/;
+                            cp[3] =  complex.Acos(ap[3]  )  /*dummy*/;
+                            cp[4] =  complex.Acos(ap[4]  )  /*dummy*/;
+                            cp[5] =  complex.Acos(ap[5]  )  /*dummy*/;
+                            cp[6] =  complex.Acos(ap[6]  )  /*dummy*/;
+                            cp[7] =  complex.Acos(ap[7]  )  /*dummy*/;
+                            cp[8] =  complex.Acos(ap[8]  )  /*dummy*/;
+                            cp[9] =  complex.Acos(ap[9]  )  /*dummy*/;
+                            cp[10] =  complex.Acos(ap[10]  )  /*dummy*/;
+                            cp[11] =  complex.Acos(ap[11]  )  /*dummy*/;
+                            cp[12] =  complex.Acos(ap[12]  )  /*dummy*/;
+                            cp[13] =  complex.Acos(ap[13]  )  /*dummy*/;
+                            cp[14] =  complex.Acos(ap[14]  )  /*dummy*/;
+                            cp[15] =  complex.Acos(ap[15]  )  /*dummy*/;
+                            cp[16] =  complex.Acos(ap[16]  )  /*dummy*/;
+                            cp[17] =  complex.Acos(ap[17]  )  /*dummy*/;
+                            cp[18] =  complex.Acos(ap[18]  )  /*dummy*/;
+                            cp[19] =  complex.Acos(ap[19]  )  /*dummy*/;
+                            cp[20] =  complex.Acos(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.Acos(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( complex* arrAP = arrA)
+                fixed ( complex* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<complex>(retStorage);
+            }
+        }
+        /// <summary>Arccosine values of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Arccosine of array elements</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<fcomplex>  acos (ILInArray< fcomplex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<fcomplex>(A.Size); 
+                ILSize inDim = A.Size;
+                fcomplex[] arrA = A.GetArrayForRead(); 
+                fcomplex [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<fcomplex>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<fcomplex> retStorage = new ILDenseStorage<fcomplex>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    fcomplex* cp = ((fcomplex*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  fcomplex.Acos(cp[0]  )  /*dummy*/;
+                            cp[1] =  fcomplex.Acos(cp[1]  )  /*dummy*/;
+                            cp[2] =  fcomplex.Acos(cp[2]  )  /*dummy*/;
+                            cp[3] =  fcomplex.Acos(cp[3]  )  /*dummy*/;
+                            cp[4] =  fcomplex.Acos(cp[4]  )  /*dummy*/;
+                            cp[5] =  fcomplex.Acos(cp[5]  )  /*dummy*/;
+                            cp[6] =  fcomplex.Acos(cp[6]  )  /*dummy*/;
+                            cp[7] =  fcomplex.Acos(cp[7]  )  /*dummy*/;
+                            cp[8] =  fcomplex.Acos(cp[8]  )  /*dummy*/;
+                            cp[9] =  fcomplex.Acos(cp[9]  )  /*dummy*/;
+                            cp[10] =  fcomplex.Acos(cp[10]  )  /*dummy*/;
+                            cp[11] =  fcomplex.Acos(cp[11]  )  /*dummy*/;
+                            cp[12] =  fcomplex.Acos(cp[12]  )  /*dummy*/;
+                            cp[13] =  fcomplex.Acos(cp[13]  )  /*dummy*/;
+                            cp[14] =  fcomplex.Acos(cp[14]  )  /*dummy*/;
+                            cp[15] =  fcomplex.Acos(cp[15]  )  /*dummy*/;
+                            cp[16] =  fcomplex.Acos(cp[16]  )  /*dummy*/;
+                            cp[17] =  fcomplex.Acos(cp[17]  )  /*dummy*/;
+                            cp[18] =  fcomplex.Acos(cp[18]  )  /*dummy*/;
+                            cp[19] =  fcomplex.Acos(cp[19]  )  /*dummy*/;
+                            cp[20] =  fcomplex.Acos(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.Acos(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        fcomplex* ap = ((fcomplex*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  fcomplex.Acos(ap[0]  )  /*dummy*/;
+                            cp[1] =  fcomplex.Acos(ap[1]  )  /*dummy*/;
+                            cp[2] =  fcomplex.Acos(ap[2]  )  /*dummy*/;
+                            cp[3] =  fcomplex.Acos(ap[3]  )  /*dummy*/;
+                            cp[4] =  fcomplex.Acos(ap[4]  )  /*dummy*/;
+                            cp[5] =  fcomplex.Acos(ap[5]  )  /*dummy*/;
+                            cp[6] =  fcomplex.Acos(ap[6]  )  /*dummy*/;
+                            cp[7] =  fcomplex.Acos(ap[7]  )  /*dummy*/;
+                            cp[8] =  fcomplex.Acos(ap[8]  )  /*dummy*/;
+                            cp[9] =  fcomplex.Acos(ap[9]  )  /*dummy*/;
+                            cp[10] =  fcomplex.Acos(ap[10]  )  /*dummy*/;
+                            cp[11] =  fcomplex.Acos(ap[11]  )  /*dummy*/;
+                            cp[12] =  fcomplex.Acos(ap[12]  )  /*dummy*/;
+                            cp[13] =  fcomplex.Acos(ap[13]  )  /*dummy*/;
+                            cp[14] =  fcomplex.Acos(ap[14]  )  /*dummy*/;
+                            cp[15] =  fcomplex.Acos(ap[15]  )  /*dummy*/;
+                            cp[16] =  fcomplex.Acos(ap[16]  )  /*dummy*/;
+                            cp[17] =  fcomplex.Acos(ap[17]  )  /*dummy*/;
+                            cp[18] =  fcomplex.Acos(ap[18]  )  /*dummy*/;
+                            cp[19] =  fcomplex.Acos(ap[19]  )  /*dummy*/;
+                            cp[20] =  fcomplex.Acos(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.Acos(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( fcomplex* arrAP = arrA)
+                fixed ( fcomplex* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<fcomplex>(retStorage);
+            }
+        }
+        /// <summary>Arccosine of array elements - real output</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Arccosine of array elements - real output</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<float>  acos (ILInArray< float > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<float>(A.Size); 
+                ILSize inDim = A.Size;
+                float[] arrA = A.GetArrayForRead(); 
+                float [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<float>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<float> retStorage = new ILDenseStorage<float>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    float* cp = ((float*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  (float)Math.Acos(cp[0]  )  /*dummy*/;
+                            cp[1] =  (float)Math.Acos(cp[1]  )  /*dummy*/;
+                            cp[2] =  (float)Math.Acos(cp[2]  )  /*dummy*/;
+                            cp[3] =  (float)Math.Acos(cp[3]  )  /*dummy*/;
+                            cp[4] =  (float)Math.Acos(cp[4]  )  /*dummy*/;
+                            cp[5] =  (float)Math.Acos(cp[5]  )  /*dummy*/;
+                            cp[6] =  (float)Math.Acos(cp[6]  )  /*dummy*/;
+                            cp[7] =  (float)Math.Acos(cp[7]  )  /*dummy*/;
+                            cp[8] =  (float)Math.Acos(cp[8]  )  /*dummy*/;
+                            cp[9] =  (float)Math.Acos(cp[9]  )  /*dummy*/;
+                            cp[10] =  (float)Math.Acos(cp[10]  )  /*dummy*/;
+                            cp[11] =  (float)Math.Acos(cp[11]  )  /*dummy*/;
+                            cp[12] =  (float)Math.Acos(cp[12]  )  /*dummy*/;
+                            cp[13] =  (float)Math.Acos(cp[13]  )  /*dummy*/;
+                            cp[14] =  (float)Math.Acos(cp[14]  )  /*dummy*/;
+                            cp[15] =  (float)Math.Acos(cp[15]  )  /*dummy*/;
+                            cp[16] =  (float)Math.Acos(cp[16]  )  /*dummy*/;
+                            cp[17] =  (float)Math.Acos(cp[17]  )  /*dummy*/;
+                            cp[18] =  (float)Math.Acos(cp[18]  )  /*dummy*/;
+                            cp[19] =  (float)Math.Acos(cp[19]  )  /*dummy*/;
+                            cp[20] =  (float)Math.Acos(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  (float)Math.Acos(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        float* ap = ((float*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  (float)Math.Acos(ap[0]  )  /*dummy*/;
+                            cp[1] =  (float)Math.Acos(ap[1]  )  /*dummy*/;
+                            cp[2] =  (float)Math.Acos(ap[2]  )  /*dummy*/;
+                            cp[3] =  (float)Math.Acos(ap[3]  )  /*dummy*/;
+                            cp[4] =  (float)Math.Acos(ap[4]  )  /*dummy*/;
+                            cp[5] =  (float)Math.Acos(ap[5]  )  /*dummy*/;
+                            cp[6] =  (float)Math.Acos(ap[6]  )  /*dummy*/;
+                            cp[7] =  (float)Math.Acos(ap[7]  )  /*dummy*/;
+                            cp[8] =  (float)Math.Acos(ap[8]  )  /*dummy*/;
+                            cp[9] =  (float)Math.Acos(ap[9]  )  /*dummy*/;
+                            cp[10] =  (float)Math.Acos(ap[10]  )  /*dummy*/;
+                            cp[11] =  (float)Math.Acos(ap[11]  )  /*dummy*/;
+                            cp[12] =  (float)Math.Acos(ap[12]  )  /*dummy*/;
+                            cp[13] =  (float)Math.Acos(ap[13]  )  /*dummy*/;
+                            cp[14] =  (float)Math.Acos(ap[14]  )  /*dummy*/;
+                            cp[15] =  (float)Math.Acos(ap[15]  )  /*dummy*/;
+                            cp[16] =  (float)Math.Acos(ap[16]  )  /*dummy*/;
+                            cp[17] =  (float)Math.Acos(ap[17]  )  /*dummy*/;
+                            cp[18] =  (float)Math.Acos(ap[18]  )  /*dummy*/;
+                            cp[19] =  (float)Math.Acos(ap[19]  )  /*dummy*/;
+                            cp[20] =  (float)Math.Acos(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  (float)Math.Acos(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( float* arrAP = arrA)
+                fixed ( float* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<float>(retStorage);
+            }
+        }
+        /// <summary>Arccosine of array elements - real output</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Arccosine of array elements - real output</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<double>  acos (ILInArray< double > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<double>(A.Size); 
+                ILSize inDim = A.Size;
+                double[] arrA = A.GetArrayForRead(); 
+                double [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<double>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<double> retStorage = new ILDenseStorage<double>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    double* cp = ((double*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  Math.Acos(cp[0]  )  /*dummy*/;
+                            cp[1] =  Math.Acos(cp[1]  )  /*dummy*/;
+                            cp[2] =  Math.Acos(cp[2]  )  /*dummy*/;
+                            cp[3] =  Math.Acos(cp[3]  )  /*dummy*/;
+                            cp[4] =  Math.Acos(cp[4]  )  /*dummy*/;
+                            cp[5] =  Math.Acos(cp[5]  )  /*dummy*/;
+                            cp[6] =  Math.Acos(cp[6]  )  /*dummy*/;
+                            cp[7] =  Math.Acos(cp[7]  )  /*dummy*/;
+                            cp[8] =  Math.Acos(cp[8]  )  /*dummy*/;
+                            cp[9] =  Math.Acos(cp[9]  )  /*dummy*/;
+                            cp[10] =  Math.Acos(cp[10]  )  /*dummy*/;
+                            cp[11] =  Math.Acos(cp[11]  )  /*dummy*/;
+                            cp[12] =  Math.Acos(cp[12]  )  /*dummy*/;
+                            cp[13] =  Math.Acos(cp[13]  )  /*dummy*/;
+                            cp[14] =  Math.Acos(cp[14]  )  /*dummy*/;
+                            cp[15] =  Math.Acos(cp[15]  )  /*dummy*/;
+                            cp[16] =  Math.Acos(cp[16]  )  /*dummy*/;
+                            cp[17] =  Math.Acos(cp[17]  )  /*dummy*/;
+                            cp[18] =  Math.Acos(cp[18]  )  /*dummy*/;
+                            cp[19] =  Math.Acos(cp[19]  )  /*dummy*/;
+                            cp[20] =  Math.Acos(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Math.Acos(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        double* ap = ((double*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  Math.Acos(ap[0]  )  /*dummy*/;
+                            cp[1] =  Math.Acos(ap[1]  )  /*dummy*/;
+                            cp[2] =  Math.Acos(ap[2]  )  /*dummy*/;
+                            cp[3] =  Math.Acos(ap[3]  )  /*dummy*/;
+                            cp[4] =  Math.Acos(ap[4]  )  /*dummy*/;
+                            cp[5] =  Math.Acos(ap[5]  )  /*dummy*/;
+                            cp[6] =  Math.Acos(ap[6]  )  /*dummy*/;
+                            cp[7] =  Math.Acos(ap[7]  )  /*dummy*/;
+                            cp[8] =  Math.Acos(ap[8]  )  /*dummy*/;
+                            cp[9] =  Math.Acos(ap[9]  )  /*dummy*/;
+                            cp[10] =  Math.Acos(ap[10]  )  /*dummy*/;
+                            cp[11] =  Math.Acos(ap[11]  )  /*dummy*/;
+                            cp[12] =  Math.Acos(ap[12]  )  /*dummy*/;
+                            cp[13] =  Math.Acos(ap[13]  )  /*dummy*/;
+                            cp[14] =  Math.Acos(ap[14]  )  /*dummy*/;
+                            cp[15] =  Math.Acos(ap[15]  )  /*dummy*/;
+                            cp[16] =  Math.Acos(ap[16]  )  /*dummy*/;
+                            cp[17] =  Math.Acos(ap[17]  )  /*dummy*/;
+                            cp[18] =  Math.Acos(ap[18]  )  /*dummy*/;
+                            cp[19] =  Math.Acos(ap[19]  )  /*dummy*/;
+                            cp[20] =  Math.Acos(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Math.Acos(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( double* arrAP = arrA)
+                fixed ( double* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<double>(retStorage);
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+   }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/all.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/all.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/all.cs	(revision 9102)
@@ -0,0 +1,779 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions; 
+       
+namespace ILNumerics  {
+    public partial class ILMath {
+
+        
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>Determine, if all elements are nonzero</summary>
+        /// <param name="A">Input array</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns><para>Array of same size as A, having specified or first non-singleton dimension reduced to 1, if all elements along that dimension are nonzero, '0' else. </para></returns>
+        public static  ILRetLogical  all (ILInArray<double> A, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (dim >= A.Size.NumberOfDimensions)
+                    throw new ILArgumentException("dimension parameter out of range!");
+                if (A.IsEmpty)
+                    return new  ILRetLogical(A.Size);
+                if (A.IsScalar) {
+                    return new ILRetLogical (new byte [1]{(A.GetValue(0) == 0.0)?(byte)0:(byte)1},1,1);
+                }
+                ILSize inDim = A.Size;
+                int[] newDims = inDim.ToIntArray();
+                int tmpCount = 0; 
+
+                int newLength;
+               
+                byte[] retArr;
+                // build ILSize
+                newLength = inDim.NumberOfElements / newDims[dim];
+                newDims[dim] = 1;
+                retArr = ILMemoryPool.Pool.New< byte>(newLength);
+                ILSize newDimension = new ILSize(newDims);
+                int incOut = newDimension.SequentialIndexDistance(dim);
+                int dimLen = inDim[dim];
+                int nrHigherDims = inDim.NumberOfElements / dimLen;
+                if (dim == 0) {
+                    #region physical along 1st leading dimension
+                    unsafe {
+                        fixed ( byte* pOutArr = retArr)
+                        fixed ( double* pInArr = A.GetArrayForRead()) {
+                           
+                            double* lastElement;
+                           
+                            byte* tmpOut = pOutArr;
+                           
+                            double* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                lastElement = tmpIn + dimLen;
+                                
+                                while (tmpIn < lastElement) {
+                                   
+                                    double inVal = *(tmpIn++);
+                                   
+                                    /*dummy*/
+                                   
+                                    tmpCount  +=   ( /*dummy*/ (inVal)   == 0.0)?0:1; 
+                                }
+                                *tmpOut = (tmpCount == dimLen)? (byte)1:(byte)0; tmpCount = 0; 
+                                tmpOut++;
+                            }
+                        }
+                    }
+                    #endregion
+                } else {
+                    #region physical along abitrary dimension
+                    // sum along abitrary dimension 
+                    unsafe {
+                        fixed ( byte* pOutArr = retArr)
+                        fixed ( double* pInArr = A.GetArrayForRead()) {
+                           
+                            byte* lastElementOut = newLength + pOutArr - 1;
+                            int inLength = inDim.NumberOfElements - 1;
+                           
+                            double* lastElementIn = pInArr + inLength;
+                            int inc = inDim.SequentialIndexDistance(dim);
+                           
+                            byte* tmpOut = pOutArr;
+                            int outLength = newLength - 1;
+                           
+                            double* leadEnd;
+                           
+                            double* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                leadEnd = tmpIn + dimLen * inc;
+                                
+                                while (tmpIn < leadEnd) {
+                                   
+                                    double inVal = *(tmpIn);
+                                    tmpIn += inc;
+                                   
+                                    /*dummy*/
+                                   
+                                    tmpCount  +=  ( /*dummy*/ (inVal)   == 0.0)?0:1; //
+                                }
+                                *tmpOut = (tmpCount == dimLen)? (byte)1:(byte)0; tmpCount = 0; 
+                                tmpOut += inc;
+                                if (tmpOut > lastElementOut)
+                                    tmpOut = pOutArr + ((tmpOut - pOutArr) - outLength);
+                                if (tmpIn > lastElementIn)
+                                    tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                            }
+                        }
+                    }
+                    #endregion
+                }
+                return new  ILRetLogical(retArr, newDims);
+            }
+        }
+        /// <summary>Determine, if all elements are nonzero</summary>
+        /// <param name="A">Input array</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns><para>Array of same size as A, having specified or first non-singleton dimension reduced to 1, if all elements along that dimension are nonzero, '0' else. </para></returns>
+        public static  ILRetLogical  all (ILInArray<Int64> A, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (dim >= A.Size.NumberOfDimensions)
+                    throw new ILArgumentException("dimension parameter out of range!");
+                if (A.IsEmpty)
+                    return new  ILRetLogical(A.Size);
+                if (A.IsScalar) {
+                    return new ILRetLogical (new byte [1]{(A.GetValue(0) == 0)?(byte)0:(byte)1},1,1);
+                }
+                ILSize inDim = A.Size;
+                int[] newDims = inDim.ToIntArray();
+                int tmpCount = 0; 
+
+                int newLength;
+               
+                byte[] retArr;
+                // build ILSize
+                newLength = inDim.NumberOfElements / newDims[dim];
+                newDims[dim] = 1;
+                retArr = ILMemoryPool.Pool.New< byte>(newLength);
+                ILSize newDimension = new ILSize(newDims);
+                int incOut = newDimension.SequentialIndexDistance(dim);
+                int dimLen = inDim[dim];
+                int nrHigherDims = inDim.NumberOfElements / dimLen;
+                if (dim == 0) {
+                    #region physical along 1st leading dimension
+                    unsafe {
+                        fixed ( byte* pOutArr = retArr)
+                        fixed ( Int64* pInArr = A.GetArrayForRead()) {
+                           
+                            Int64* lastElement;
+                           
+                            byte* tmpOut = pOutArr;
+                           
+                            Int64* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                lastElement = tmpIn + dimLen;
+                                
+                                while (tmpIn < lastElement) {
+                                   
+                                    Int64 inVal = *(tmpIn++);
+                                   
+                                    /*dummy*/
+                                   
+                                    tmpCount  +=   ( /*dummy*/ (inVal)   == 0)?0:1; 
+                                }
+                                *tmpOut = (tmpCount == dimLen)? (byte)1:(byte)0; tmpCount = 0; 
+                                tmpOut++;
+                            }
+                        }
+                    }
+                    #endregion
+                } else {
+                    #region physical along abitrary dimension
+                    // sum along abitrary dimension 
+                    unsafe {
+                        fixed ( byte* pOutArr = retArr)
+                        fixed ( Int64* pInArr = A.GetArrayForRead()) {
+                           
+                            byte* lastElementOut = newLength + pOutArr - 1;
+                            int inLength = inDim.NumberOfElements - 1;
+                           
+                            Int64* lastElementIn = pInArr + inLength;
+                            int inc = inDim.SequentialIndexDistance(dim);
+                           
+                            byte* tmpOut = pOutArr;
+                            int outLength = newLength - 1;
+                           
+                            Int64* leadEnd;
+                           
+                            Int64* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                leadEnd = tmpIn + dimLen * inc;
+                                
+                                while (tmpIn < leadEnd) {
+                                   
+                                    Int64 inVal = *(tmpIn);
+                                    tmpIn += inc;
+                                   
+                                    /*dummy*/
+                                   
+                                    tmpCount  +=  ( /*dummy*/ (inVal)   == 0)?0:1; //
+                                }
+                                *tmpOut = (tmpCount == dimLen)? (byte)1:(byte)0; tmpCount = 0; 
+                                tmpOut += inc;
+                                if (tmpOut > lastElementOut)
+                                    tmpOut = pOutArr + ((tmpOut - pOutArr) - outLength);
+                                if (tmpIn > lastElementIn)
+                                    tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                            }
+                        }
+                    }
+                    #endregion
+                }
+                return new  ILRetLogical(retArr, newDims);
+            }
+        }
+        /// <summary>Determine, if all elements are nonzero</summary>
+        /// <param name="A">Input array</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns><para>Array of same size as A, having specified or first non-singleton dimension reduced to 1, if all elements along that dimension are nonzero, '0' else. </para></returns>
+        public static  ILRetLogical  all (ILInArray<Int32> A, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (dim >= A.Size.NumberOfDimensions)
+                    throw new ILArgumentException("dimension parameter out of range!");
+                if (A.IsEmpty)
+                    return new  ILRetLogical(A.Size);
+                if (A.IsScalar) {
+                    return new ILRetLogical (new byte [1]{(A.GetValue(0) == 0)?(byte)0:(byte)1},1,1);
+                }
+                ILSize inDim = A.Size;
+                int[] newDims = inDim.ToIntArray();
+                int tmpCount = 0; 
+
+                int newLength;
+               
+                byte[] retArr;
+                // build ILSize
+                newLength = inDim.NumberOfElements / newDims[dim];
+                newDims[dim] = 1;
+                retArr = ILMemoryPool.Pool.New< byte>(newLength);
+                ILSize newDimension = new ILSize(newDims);
+                int incOut = newDimension.SequentialIndexDistance(dim);
+                int dimLen = inDim[dim];
+                int nrHigherDims = inDim.NumberOfElements / dimLen;
+                if (dim == 0) {
+                    #region physical along 1st leading dimension
+                    unsafe {
+                        fixed ( byte* pOutArr = retArr)
+                        fixed ( Int32* pInArr = A.GetArrayForRead()) {
+                           
+                            Int32* lastElement;
+                           
+                            byte* tmpOut = pOutArr;
+                           
+                            Int32* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                lastElement = tmpIn + dimLen;
+                                
+                                while (tmpIn < lastElement) {
+                                   
+                                    Int32 inVal = *(tmpIn++);
+                                   
+                                    /*dummy*/
+                                   
+                                    tmpCount  +=   ( /*dummy*/ (inVal)   == 0)?0:1; 
+                                }
+                                *tmpOut = (tmpCount == dimLen)? (byte)1:(byte)0; tmpCount = 0; 
+                                tmpOut++;
+                            }
+                        }
+                    }
+                    #endregion
+                } else {
+                    #region physical along abitrary dimension
+                    // sum along abitrary dimension 
+                    unsafe {
+                        fixed ( byte* pOutArr = retArr)
+                        fixed ( Int32* pInArr = A.GetArrayForRead()) {
+                           
+                            byte* lastElementOut = newLength + pOutArr - 1;
+                            int inLength = inDim.NumberOfElements - 1;
+                           
+                            Int32* lastElementIn = pInArr + inLength;
+                            int inc = inDim.SequentialIndexDistance(dim);
+                           
+                            byte* tmpOut = pOutArr;
+                            int outLength = newLength - 1;
+                           
+                            Int32* leadEnd;
+                           
+                            Int32* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                leadEnd = tmpIn + dimLen * inc;
+                                
+                                while (tmpIn < leadEnd) {
+                                   
+                                    Int32 inVal = *(tmpIn);
+                                    tmpIn += inc;
+                                   
+                                    /*dummy*/
+                                   
+                                    tmpCount  +=  ( /*dummy*/ (inVal)   == 0)?0:1; //
+                                }
+                                *tmpOut = (tmpCount == dimLen)? (byte)1:(byte)0; tmpCount = 0; 
+                                tmpOut += inc;
+                                if (tmpOut > lastElementOut)
+                                    tmpOut = pOutArr + ((tmpOut - pOutArr) - outLength);
+                                if (tmpIn > lastElementIn)
+                                    tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                            }
+                        }
+                    }
+                    #endregion
+                }
+                return new  ILRetLogical(retArr, newDims);
+            }
+        }
+        /// <summary>Determine, if all elements are nonzero</summary>
+        /// <param name="A">Input array</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns><para>Array of same size as A, having specified or first non-singleton dimension reduced to 1, if all elements along that dimension are nonzero, '0' else. </para></returns>
+        public static  ILRetLogical  all (ILInArray<byte> A, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (dim >= A.Size.NumberOfDimensions)
+                    throw new ILArgumentException("dimension parameter out of range!");
+                if (A.IsEmpty)
+                    return new  ILRetLogical(A.Size);
+                if (A.IsScalar) {
+                    return new ILRetLogical (new byte [1]{(A.GetValue(0) == 0)?(byte)0:(byte)1},1,1);
+                }
+                ILSize inDim = A.Size;
+                int[] newDims = inDim.ToIntArray();
+                int tmpCount = 0; 
+
+                int newLength;
+               
+                byte[] retArr;
+                // build ILSize
+                newLength = inDim.NumberOfElements / newDims[dim];
+                newDims[dim] = 1;
+                retArr = ILMemoryPool.Pool.New< byte>(newLength);
+                ILSize newDimension = new ILSize(newDims);
+                int incOut = newDimension.SequentialIndexDistance(dim);
+                int dimLen = inDim[dim];
+                int nrHigherDims = inDim.NumberOfElements / dimLen;
+                if (dim == 0) {
+                    #region physical along 1st leading dimension
+                    unsafe {
+                        fixed ( byte* pOutArr = retArr)
+                        fixed ( byte* pInArr = A.GetArrayForRead()) {
+                           
+                            byte* lastElement;
+                           
+                            byte* tmpOut = pOutArr;
+                           
+                            byte* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                lastElement = tmpIn + dimLen;
+                                
+                                while (tmpIn < lastElement) {
+                                   
+                                    byte inVal = *(tmpIn++);
+                                   
+                                    /*dummy*/
+                                   
+                                    tmpCount  +=   ( /*dummy*/ (inVal)   == 0)?0:1; 
+                                }
+                                *tmpOut = (tmpCount == dimLen)? (byte)1:(byte)0; tmpCount = 0; 
+                                tmpOut++;
+                            }
+                        }
+                    }
+                    #endregion
+                } else {
+                    #region physical along abitrary dimension
+                    // sum along abitrary dimension 
+                    unsafe {
+                        fixed ( byte* pOutArr = retArr)
+                        fixed ( byte* pInArr = A.GetArrayForRead()) {
+                           
+                            byte* lastElementOut = newLength + pOutArr - 1;
+                            int inLength = inDim.NumberOfElements - 1;
+                           
+                            byte* lastElementIn = pInArr + inLength;
+                            int inc = inDim.SequentialIndexDistance(dim);
+                           
+                            byte* tmpOut = pOutArr;
+                            int outLength = newLength - 1;
+                           
+                            byte* leadEnd;
+                           
+                            byte* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                leadEnd = tmpIn + dimLen * inc;
+                                
+                                while (tmpIn < leadEnd) {
+                                   
+                                    byte inVal = *(tmpIn);
+                                    tmpIn += inc;
+                                   
+                                    /*dummy*/
+                                   
+                                    tmpCount  +=  ( /*dummy*/ (inVal)   == 0)?0:1; //
+                                }
+                                *tmpOut = (tmpCount == dimLen)? (byte)1:(byte)0; tmpCount = 0; 
+                                tmpOut += inc;
+                                if (tmpOut > lastElementOut)
+                                    tmpOut = pOutArr + ((tmpOut - pOutArr) - outLength);
+                                if (tmpIn > lastElementIn)
+                                    tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                            }
+                        }
+                    }
+                    #endregion
+                }
+                return new  ILRetLogical(retArr, newDims);
+            }
+        }
+        /// <summary>Determine, if all elements are nonzero</summary>
+        /// <param name="A">Input array</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns><para>Array of same size as A, having specified or first non-singleton dimension reduced to 1, if all elements along that dimension are nonzero, '0' else. </para></returns>
+        public static  ILRetLogical  all (ILInArray<fcomplex> A, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (dim >= A.Size.NumberOfDimensions)
+                    throw new ILArgumentException("dimension parameter out of range!");
+                if (A.IsEmpty)
+                    return new  ILRetLogical(A.Size);
+                if (A.IsScalar) {
+                    return new ILRetLogical (new byte [1]{(A.GetValue(0).iszero())?(byte)1:(byte)0},1,1);
+                }
+                ILSize inDim = A.Size;
+                int[] newDims = inDim.ToIntArray();
+                int tmpCount = 0; 
+
+                int newLength;
+               
+                byte[] retArr;
+                // build ILSize
+                newLength = inDim.NumberOfElements / newDims[dim];
+                newDims[dim] = 1;
+                retArr = ILMemoryPool.Pool.New< byte>(newLength);
+                ILSize newDimension = new ILSize(newDims);
+                int incOut = newDimension.SequentialIndexDistance(dim);
+                int dimLen = inDim[dim];
+                int nrHigherDims = inDim.NumberOfElements / dimLen;
+                if (dim == 0) {
+                    #region physical along 1st leading dimension
+                    unsafe {
+                        fixed ( byte* pOutArr = retArr)
+                        fixed ( fcomplex* pInArr = A.GetArrayForRead()) {
+                           
+                            fcomplex* lastElement;
+                           
+                            byte* tmpOut = pOutArr;
+                           
+                            fcomplex* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                lastElement = tmpIn + dimLen;
+                                
+                                while (tmpIn < lastElement) {
+                                   
+                                    fcomplex inVal = *(tmpIn++);
+                                   
+                                    /*dummy*/
+                                   
+                                    tmpCount  +=   ( /*dummy*/ (inVal)  .iszero())?0:1;  
+                                }
+                                *tmpOut = (tmpCount == dimLen)? (byte)1:(byte)0; tmpCount = 0; 
+                                tmpOut++;
+                            }
+                        }
+                    }
+                    #endregion
+                } else {
+                    #region physical along abitrary dimension
+                    // sum along abitrary dimension 
+                    unsafe {
+                        fixed ( byte* pOutArr = retArr)
+                        fixed ( fcomplex* pInArr = A.GetArrayForRead()) {
+                           
+                            byte* lastElementOut = newLength + pOutArr - 1;
+                            int inLength = inDim.NumberOfElements - 1;
+                           
+                            fcomplex* lastElementIn = pInArr + inLength;
+                            int inc = inDim.SequentialIndexDistance(dim);
+                           
+                            byte* tmpOut = pOutArr;
+                            int outLength = newLength - 1;
+                           
+                            fcomplex* leadEnd;
+                           
+                            fcomplex* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                leadEnd = tmpIn + dimLen * inc;
+                                
+                                while (tmpIn < leadEnd) {
+                                   
+                                    fcomplex inVal = *(tmpIn);
+                                    tmpIn += inc;
+                                   
+                                    /*dummy*/
+                                   
+                                    tmpCount  +=  ( /*dummy*/ (inVal)  .iszero())?0:1;  //
+                                }
+                                *tmpOut = (tmpCount == dimLen)? (byte)1:(byte)0; tmpCount = 0; 
+                                tmpOut += inc;
+                                if (tmpOut > lastElementOut)
+                                    tmpOut = pOutArr + ((tmpOut - pOutArr) - outLength);
+                                if (tmpIn > lastElementIn)
+                                    tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                            }
+                        }
+                    }
+                    #endregion
+                }
+                return new  ILRetLogical(retArr, newDims);
+            }
+        }
+        /// <summary>Determine, if all elements are nonzero</summary>
+        /// <param name="A">Input array</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns><para>Array of same size as A, having specified or first non-singleton dimension reduced to 1, if any elements along that dimension are nonzero, '0' else. </para></returns>
+        public static  ILRetLogical  all (ILInArray<float> A, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (dim >= A.Size.NumberOfDimensions)
+                    throw new ILArgumentException("dimension parameter out of range!");
+                if (A.IsEmpty)
+                    return new  ILRetLogical(A.Size);
+                if (A.IsScalar) {
+                    return new ILRetLogical (new byte [1]{(A.GetValue(0) == 0.0f)?(byte)0:(byte)1},1,1);
+                }
+                ILSize inDim = A.Size;
+                int[] newDims = inDim.ToIntArray();
+                int tmpCount = 0; 
+
+                int newLength;
+               
+                byte[] retArr;
+                // build ILSize
+                newLength = inDim.NumberOfElements / newDims[dim];
+                newDims[dim] = 1;
+                retArr = ILMemoryPool.Pool.New< byte>(newLength);
+                ILSize newDimension = new ILSize(newDims);
+                int incOut = newDimension.SequentialIndexDistance(dim);
+                int dimLen = inDim[dim];
+                int nrHigherDims = inDim.NumberOfElements / dimLen;
+                if (dim == 0) {
+                    #region physical along 1st leading dimension
+                    unsafe {
+                        fixed ( byte* pOutArr = retArr)
+                        fixed ( float* pInArr = A.GetArrayForRead()) {
+                           
+                            float* lastElement;
+                           
+                            byte* tmpOut = pOutArr;
+                           
+                            float* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                lastElement = tmpIn + dimLen;
+                                
+                                while (tmpIn < lastElement) {
+                                   
+                                    float inVal = *(tmpIn++);
+                                   
+                                    /*dummy*/
+                                   
+                                    tmpCount  +=   ( /*dummy*/ (inVal)   == 0.0f)?0:1; 
+                                }
+                                *tmpOut = (tmpCount == dimLen)? (byte)1:(byte)0; tmpCount = 0; 
+                                tmpOut++;
+                            }
+                        }
+                    }
+                    #endregion
+                } else {
+                    #region physical along abitrary dimension
+                    // sum along abitrary dimension 
+                    unsafe {
+                        fixed ( byte* pOutArr = retArr)
+                        fixed ( float* pInArr = A.GetArrayForRead()) {
+                           
+                            byte* lastElementOut = newLength + pOutArr - 1;
+                            int inLength = inDim.NumberOfElements - 1;
+                           
+                            float* lastElementIn = pInArr + inLength;
+                            int inc = inDim.SequentialIndexDistance(dim);
+                           
+                            byte* tmpOut = pOutArr;
+                            int outLength = newLength - 1;
+                           
+                            float* leadEnd;
+                           
+                            float* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                leadEnd = tmpIn + dimLen * inc;
+                                
+                                while (tmpIn < leadEnd) {
+                                   
+                                    float inVal = *(tmpIn);
+                                    tmpIn += inc;
+                                   
+                                    /*dummy*/
+                                   
+                                    tmpCount  +=  ( /*dummy*/ (inVal)   == 0.0f)?0:1; //
+                                }
+                                *tmpOut = (tmpCount == dimLen)? (byte)1:(byte)0; tmpCount = 0; 
+                                tmpOut += inc;
+                                if (tmpOut > lastElementOut)
+                                    tmpOut = pOutArr + ((tmpOut - pOutArr) - outLength);
+                                if (tmpIn > lastElementIn)
+                                    tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                            }
+                        }
+                    }
+                    #endregion
+                }
+                return new  ILRetLogical(retArr, newDims);
+            }
+        }
+        /// <summary>Determine, if all elements are nonzero</summary>
+        /// <param name="A">Input array</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns><para>Array of same size as A, having specified or first non-singleton dimension reduced to 1, if any elements along that dimension are nonzero, '0' else. </para></returns>
+        public static  ILRetLogical  all (ILInArray<complex> A, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (dim >= A.Size.NumberOfDimensions)
+                    throw new ILArgumentException("dimension parameter out of range!");
+                if (A.IsEmpty)
+                    return new  ILRetLogical(A.Size);
+                if (A.IsScalar) {
+                    return new ILRetLogical (new byte [1]{(A.GetValue(0).iszero())?(byte)0:(byte)1},1,1);
+                }
+                ILSize inDim = A.Size;
+                int[] newDims = inDim.ToIntArray();
+                int tmpCount = 0; 
+
+                int newLength;
+               
+                byte[] retArr;
+                // build ILSize
+                newLength = inDim.NumberOfElements / newDims[dim];
+                newDims[dim] = 1;
+                retArr = ILMemoryPool.Pool.New< byte>(newLength);
+                ILSize newDimension = new ILSize(newDims);
+                int incOut = newDimension.SequentialIndexDistance(dim);
+                int dimLen = inDim[dim];
+                int nrHigherDims = inDim.NumberOfElements / dimLen;
+                if (dim == 0) {
+                    #region physical along 1st leading dimension
+                    unsafe {
+                        fixed ( byte* pOutArr = retArr)
+                        fixed ( complex* pInArr = A.GetArrayForRead()) {
+                           
+                            complex* lastElement;
+                           
+                            byte* tmpOut = pOutArr;
+                           
+                            complex* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                lastElement = tmpIn + dimLen;
+                                
+                                while (tmpIn < lastElement) {
+                                   
+                                    complex inVal = *(tmpIn++);
+                                   
+                                    /*dummy*/
+                                   
+                                    tmpCount  +=   ( /*dummy*/ (inVal)  .iszero())?0:1;  
+                                }
+                                *tmpOut = (tmpCount == dimLen)? (byte)1:(byte)0; tmpCount = 0; 
+                                tmpOut++;
+                            }
+                        }
+                    }
+                    #endregion
+                } else {
+                    #region physical along abitrary dimension
+                    // sum along abitrary dimension 
+                    unsafe {
+                        fixed ( byte* pOutArr = retArr)
+                        fixed ( complex* pInArr = A.GetArrayForRead()) {
+                           
+                            byte* lastElementOut = newLength + pOutArr - 1;
+                            int inLength = inDim.NumberOfElements - 1;
+                           
+                            complex* lastElementIn = pInArr + inLength;
+                            int inc = inDim.SequentialIndexDistance(dim);
+                           
+                            byte* tmpOut = pOutArr;
+                            int outLength = newLength - 1;
+                           
+                            complex* leadEnd;
+                           
+                            complex* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                leadEnd = tmpIn + dimLen * inc;
+                                
+                                while (tmpIn < leadEnd) {
+                                   
+                                    complex inVal = *(tmpIn);
+                                    tmpIn += inc;
+                                   
+                                    /*dummy*/
+                                   
+                                    tmpCount  +=  ( /*dummy*/ (inVal)  .iszero())?0:1;  //
+                                }
+                                *tmpOut = (tmpCount == dimLen)? (byte)1:(byte)0; tmpCount = 0; 
+                                tmpOut += inc;
+                                if (tmpOut > lastElementOut)
+                                    tmpOut = pOutArr + ((tmpOut - pOutArr) - outLength);
+                                if (tmpIn > lastElementIn)
+                                    tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                            }
+                        }
+                    }
+                    #endregion
+                }
+                return new  ILRetLogical(retArr, newDims);
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+   }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/allall.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/allall.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/allall.cs	(revision 9102)
@@ -0,0 +1,274 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions; 
+
+namespace ILNumerics  {
+    public partial class ILMath {
+
+        /// <summary>Determine if array has nonzero elements in all dimensions</summary>
+        /// <param name="A">Input Array</param>
+        /// <returns>Scalar logical array</returns>
+        /// <remarks><para>The function evaluates all elements of A in all dimensions. It returnes 'true' (1) if
+        /// all elements are found to be non-zero, false otherwise.</para>
+        /// <para>If A is empty, a scalar logical 'false' (0) is returned. </para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If A was null.</exception>
+        /// <seealso cref="ILNumerics.ILMath.all(ILInArray{double},int)"/>
+        public static ILRetLogical allall (ILInArray<double> A) {
+            if (object.Equals(A,null))
+                throw new ILArgumentException("A must not be null!");
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    return new ILRetLogical(ILSize.Empty00); 
+                } 
+                byte retArr = 1; 
+                unsafe {
+                    fixed ( double * inArrStart = A.GetArrayForRead()) {
+                         double * inArrWalk = inArrStart; 
+                         double * inArrEnd = inArrStart + A.Size.NumberOfElements; 
+                        while (inArrWalk < inArrEnd) {
+                            if ( *inArrWalk++ == 0) {
+                                retArr = 0; 
+                                break; 
+                            }
+                        }
+                    }
+                }
+                return new ILRetLogical (new byte [1] {retArr},1,1);
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>Determine if array has nonzero elements in all dimensions</summary>
+        /// <param name="A">Input Array</param>
+        /// <returns>Scalar logical array</returns>
+        /// <remarks><para>The function evaluates all elements of A in all dimensions. It returnes 'true' (1) if
+        /// all elements are found to be non-zero, false otherwise.</para>
+        /// <para>If A is empty, a scalar logical 'false' (0) is returned. </para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If A was null.</exception>
+        /// <seealso cref="ILNumerics.ILMath.all(ILInArray{double},int)"/>
+        public static ILRetLogical allall (ILInArray<Int64> A) {
+            if (object.Equals(A,null))
+                throw new ILArgumentException("A must not be null!");
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    return new ILRetLogical(ILSize.Empty00); 
+                } 
+                byte retArr = 1; 
+                unsafe {
+                    fixed ( Int64 * inArrStart = A.GetArrayForRead()) {
+                        Int64 * inArrWalk = inArrStart; 
+                        Int64 * inArrEnd = inArrStart + A.Size.NumberOfElements; 
+                        while (inArrWalk < inArrEnd) {
+                            if ( *inArrWalk++ == 0) {
+                                retArr = 0; 
+                                break; 
+                            }
+                        }
+                    }
+                }
+                return new ILRetLogical (new byte [1] {retArr},1,1);
+            }
+        }
+        /// <summary>Determine if array has nonzero elements in all dimensions</summary>
+        /// <param name="A">Input Array</param>
+        /// <returns>Scalar logical array</returns>
+        /// <remarks><para>The function evaluates all elements of A in all dimensions. It returnes 'true' (1) if
+        /// all elements are found to be non-zero, false otherwise.</para>
+        /// <para>If A is empty, a scalar logical 'false' (0) is returned. </para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If A was null.</exception>
+        /// <seealso cref="ILNumerics.ILMath.all(ILInArray{double},int)"/>
+        public static ILRetLogical allall (ILInArray<Int32> A) {
+            if (object.Equals(A,null))
+                throw new ILArgumentException("A must not be null!");
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    return new ILRetLogical(ILSize.Empty00); 
+                } 
+                byte retArr = 1; 
+                unsafe {
+                    fixed ( Int32 * inArrStart = A.GetArrayForRead()) {
+                        Int32 * inArrWalk = inArrStart; 
+                        Int32 * inArrEnd = inArrStart + A.Size.NumberOfElements; 
+                        while (inArrWalk < inArrEnd) {
+                            if ( *inArrWalk++ == 0) {
+                                retArr = 0; 
+                                break; 
+                            }
+                        }
+                    }
+                }
+                return new ILRetLogical (new byte [1] {retArr},1,1);
+            }
+        }
+        /// <summary>Determine if array has nonzero elements in all dimensions</summary>
+        /// <param name="A">Input Array</param>
+        /// <returns>Scalar logical array</returns>
+        /// <remarks><para>The function evaluates all elements of A in all dimensions. It returnes 'true' (1) if
+        /// all elements are found to be non-zero, false otherwise.</para>
+        /// <para>If A is empty, a scalar logical 'false' (0) is returned. </para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If A was null.</exception>
+        /// <seealso cref="ILNumerics.ILMath.all(ILInArray{double},int)"/>
+        public static ILRetLogical allall (ILInArray<byte> A) {
+            if (object.Equals(A,null))
+                throw new ILArgumentException("A must not be null!");
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    return new ILRetLogical(ILSize.Empty00); 
+                } 
+                byte retArr = 1; 
+                unsafe {
+                    fixed ( byte * inArrStart = A.GetArrayForRead()) {
+                        byte * inArrWalk = inArrStart; 
+                        byte * inArrEnd = inArrStart + A.Size.NumberOfElements; 
+                        while (inArrWalk < inArrEnd) {
+                            if ( *inArrWalk++ == 0) {
+                                retArr = 0; 
+                                break; 
+                            }
+                        }
+                    }
+                }
+                return new ILRetLogical (new byte [1] {retArr},1,1);
+            }
+        }
+        /// <summary>Determine if array has nonzero elements in all dimensions</summary>
+        /// <param name="A">Input Array</param>
+        /// <returns>Scalar logical array</returns>
+        /// <remarks><para>The function evaluates all elements of A in all dimensions. It returnes 'true' (1) if
+        /// all elements are found to be non-zero, false otherwise.</para>
+        /// <para>If A is empty, a scalar logical 'false' (0) is returned. </para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If A was null.</exception>
+        /// <seealso cref="ILNumerics.ILMath.all(ILInArray{double},int)"/>
+        public static ILRetLogical allall (ILInArray<fcomplex> A) {
+            if (object.Equals(A,null))
+                throw new ILArgumentException("A must not be null!");
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    return new ILRetLogical(ILSize.Empty00); 
+                } 
+                byte retArr = 1; 
+                unsafe {
+                    fixed ( fcomplex * inArrStart = A.GetArrayForRead()) {
+                        fcomplex * inArrWalk = inArrStart; 
+                        fcomplex * inArrEnd = inArrStart + A.Size.NumberOfElements; 
+                        while (inArrWalk < inArrEnd) {
+                            if ( *inArrWalk++ == 0) {
+                                retArr = 0; 
+                                break; 
+                            }
+                        }
+                    }
+                }
+                return new ILRetLogical (new byte [1] {retArr},1,1);
+            }
+        }
+        /// <summary>Determine if array has nonzero elements in all dimensions</summary>
+        /// <param name="A">Input Array</param>
+        /// <returns>Scalar logical array</returns>
+        /// <remarks><para>The function evaluates all elements of A in all dimensions. It returnes 'true' (1) if
+        /// all elements are found to be non-zero, false otherwise.</para>
+        /// <para>If A is empty, a scalar logical 'false' (0) is returned. </para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If A was null.</exception>
+        /// <seealso cref="ILNumerics.ILMath.all(ILInArray{double},int)"/>
+        public static ILRetLogical allall (ILInArray<float> A) {
+            if (object.Equals(A,null))
+                throw new ILArgumentException("A must not be null!");
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    return new ILRetLogical(ILSize.Empty00); 
+                } 
+                byte retArr = 1; 
+                unsafe {
+                    fixed ( float * inArrStart = A.GetArrayForRead()) {
+                        float * inArrWalk = inArrStart; 
+                        float * inArrEnd = inArrStart + A.Size.NumberOfElements; 
+                        while (inArrWalk < inArrEnd) {
+                            if ( *inArrWalk++ == 0) {
+                                retArr = 0; 
+                                break; 
+                            }
+                        }
+                    }
+                }
+                return new ILRetLogical (new byte [1] {retArr},1,1);
+            }
+        }
+        /// <summary>Determine if array has nonzero elements in all dimensions</summary>
+        /// <param name="A">Input Array</param>
+        /// <returns>Scalar logical array</returns>
+        /// <remarks><para>The function evaluates all elements of A in all dimensions. It returnes 'true' (1) if
+        /// all elements are found to be non-zero, false otherwise.</para>
+        /// <para>If A is empty, a scalar logical 'false' (0) is returned. </para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If A was null.</exception>
+        /// <seealso cref="ILNumerics.ILMath.all(ILInArray{double},int)"/>
+        public static ILRetLogical allall (ILInArray<complex> A) {
+            if (object.Equals(A,null))
+                throw new ILArgumentException("A must not be null!");
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    return new ILRetLogical(ILSize.Empty00); 
+                } 
+                byte retArr = 1; 
+                unsafe {
+                    fixed ( complex * inArrStart = A.GetArrayForRead()) {
+                        complex * inArrWalk = inArrStart; 
+                        complex * inArrEnd = inArrStart + A.Size.NumberOfElements; 
+                        while (inArrWalk < inArrEnd) {
+                            if ( *inArrWalk++ == 0) {
+                                retArr = 0; 
+                                break; 
+                            }
+                        }
+                    }
+                }
+                return new ILRetLogical (new byte [1] {retArr},1,1);
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/and.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/and.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/and.cs	(revision 9102)
@@ -0,0 +1,1912 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.InteropServices; 
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Native;
+using ILNumerics.Exceptions;
+
+
+
+namespace ILNumerics {
+
+    public partial class ILMath {
+
+
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>Elementwise logical 'and' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array with the elementwise result of logical 'and' for all elements in A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  and(ILInArray<Int64> A, ILInArray<Int64> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                Int64[] arrA = A.GetArrayForRead();
+               
+                Int64[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0) != 0 && B.GetValue(0) != 0) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  andEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    Int64 scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            Int64* ap = ((Int64*)range.Item3 + range.Item1);
+                            Int64* bp = ((Int64*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                                *cp = (*ap != 0 && *bp != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((Int64*)range.Item3 + range.Item1);
+                            scalar = *((Int64*)range.Item4);
+                            while (cp < cLast) {
+                                *cp = (scalar != 0 && *ap != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((Int64*)range.Item3);
+                            bp = ((Int64*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                                *cp = (scalar != 0 && *bp != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (Int64* arrAP = arrA)
+                fixed (Int64* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  andEx(ILInArray<Int64> A, ILInArray<Int64> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                Int64[] arrA = A.GetArrayForRead();
+               
+                Int64[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    Int64* ap;
+                   
+                    Int64* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (Int64*)range.Item3;
+                                bp = (Int64*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap != 0 && *bp != 0) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (Int64*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (Int64*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap != 0 && *bp != 0) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( Int64* arrAP = arrA)
+                fixed ( Int64* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'and' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array with the elementwise result of logical 'and' for all elements in A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  and(ILInArray<Int32> A, ILInArray<Int32> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                Int32[] arrA = A.GetArrayForRead();
+               
+                Int32[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0) != 0 && B.GetValue(0) != 0) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  andEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    Int32 scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            Int32* ap = ((Int32*)range.Item3 + range.Item1);
+                            Int32* bp = ((Int32*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                                *cp = (*ap != 0 && *bp != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((Int32*)range.Item3 + range.Item1);
+                            scalar = *((Int32*)range.Item4);
+                            while (cp < cLast) {
+                                *cp = (scalar != 0 && *ap != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((Int32*)range.Item3);
+                            bp = ((Int32*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                                *cp = (scalar != 0 && *bp != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (Int32* arrAP = arrA)
+                fixed (Int32* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  andEx(ILInArray<Int32> A, ILInArray<Int32> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                Int32[] arrA = A.GetArrayForRead();
+               
+                Int32[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    Int32* ap;
+                   
+                    Int32* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (Int32*)range.Item3;
+                                bp = (Int32*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap != 0 && *bp != 0) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (Int32*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (Int32*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap != 0 && *bp != 0) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( Int32* arrAP = arrA)
+                fixed ( Int32* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'and' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array with the elementwise result of logical 'and' for all elements in A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  and(ILInArray<float> A, ILInArray<float> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                float[] arrA = A.GetArrayForRead();
+               
+                float[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0) != 0 && B.GetValue(0) != 0) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  andEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    float scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            float* ap = ((float*)range.Item3 + range.Item1);
+                            float* bp = ((float*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                                *cp = (*ap != 0 && *bp != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((float*)range.Item3 + range.Item1);
+                            scalar = *((float*)range.Item4);
+                            while (cp < cLast) {
+                                *cp = (scalar != 0 && *ap != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((float*)range.Item3);
+                            bp = ((float*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                                *cp = (scalar != 0 && *bp != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (float* arrAP = arrA)
+                fixed (float* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  andEx(ILInArray<float> A, ILInArray<float> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                float[] arrA = A.GetArrayForRead();
+               
+                float[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    float* ap;
+                   
+                    float* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (float*)range.Item3;
+                                bp = (float*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap != 0 && *bp != 0) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (float*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (float*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap != 0 && *bp != 0) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( float* arrAP = arrA)
+                fixed ( float* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'and' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array with the elementwise result of logical 'and' for all elements in A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  and(ILInArray<fcomplex> A, ILInArray<fcomplex> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                fcomplex[] arrA = A.GetArrayForRead();
+               
+                fcomplex[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0) != 0 && B.GetValue(0) != 0) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  andEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    fcomplex scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            fcomplex* ap = ((fcomplex*)range.Item3 + range.Item1);
+                            fcomplex* bp = ((fcomplex*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                                *cp = (*ap != 0 && *bp != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((fcomplex*)range.Item3 + range.Item1);
+                            scalar = *((fcomplex*)range.Item4);
+                            while (cp < cLast) {
+                                *cp = (scalar != 0 && *ap != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((fcomplex*)range.Item3);
+                            bp = ((fcomplex*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                                *cp = (scalar != 0 && *bp != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (fcomplex* arrAP = arrA)
+                fixed (fcomplex* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  andEx(ILInArray<fcomplex> A, ILInArray<fcomplex> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                fcomplex[] arrA = A.GetArrayForRead();
+               
+                fcomplex[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    fcomplex* ap;
+                   
+                    fcomplex* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (fcomplex*)range.Item3;
+                                bp = (fcomplex*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap != 0 && *bp != 0) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (fcomplex*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (fcomplex*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap != 0 && *bp != 0) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( fcomplex* arrAP = arrA)
+                fixed ( fcomplex* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'and' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array with the elementwise result of logical 'and' for all elements in A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  and(ILInArray<complex> A, ILInArray<complex> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                complex[] arrA = A.GetArrayForRead();
+               
+                complex[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0) != 0 && B.GetValue(0) != 0) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  andEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    complex scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            complex* ap = ((complex*)range.Item3 + range.Item1);
+                            complex* bp = ((complex*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                                *cp = (*ap != 0 && *bp != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((complex*)range.Item3 + range.Item1);
+                            scalar = *((complex*)range.Item4);
+                            while (cp < cLast) {
+                                *cp = (scalar != 0 && *ap != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((complex*)range.Item3);
+                            bp = ((complex*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                                *cp = (scalar != 0 && *bp != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (complex* arrAP = arrA)
+                fixed (complex* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  andEx(ILInArray<complex> A, ILInArray<complex> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                complex[] arrA = A.GetArrayForRead();
+               
+                complex[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    complex* ap;
+                   
+                    complex* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (complex*)range.Item3;
+                                bp = (complex*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap != 0 && *bp != 0) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (complex*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (complex*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap != 0 && *bp != 0) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( complex* arrAP = arrA)
+                fixed ( complex* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'and' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array with the elementwise result of logical 'and' for all elements in A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  and(ILInArray<byte> A, ILInArray<byte> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                byte[] arrA = A.GetArrayForRead();
+               
+                byte[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0) != 0 && B.GetValue(0) != 0) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  andEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    byte scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            byte* ap = ((byte*)range.Item3 + range.Item1);
+                            byte* bp = ((byte*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                                *cp = (*ap != 0 && *bp != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((byte*)range.Item3 + range.Item1);
+                            scalar = *((byte*)range.Item4);
+                            while (cp < cLast) {
+                                *cp = (scalar != 0 && *ap != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((byte*)range.Item3);
+                            bp = ((byte*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                                *cp = (scalar != 0 && *bp != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (byte* arrAP = arrA)
+                fixed (byte* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  andEx(ILInArray<byte> A, ILInArray<byte> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                byte[] arrA = A.GetArrayForRead();
+               
+                byte[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    byte* ap;
+                   
+                    byte* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (byte*)range.Item3;
+                                bp = (byte*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap != 0 && *bp != 0) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (byte*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (byte*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap != 0 && *bp != 0) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( byte* arrAP = arrA)
+                fixed ( byte* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'and' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array with the elementwise result of logical 'and' for all elements in A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  and(ILInArray<double> A, ILInArray<double> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                double[] arrA = A.GetArrayForRead();
+               
+                double[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0) != 0 && B.GetValue(0) != 0) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  andEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    double scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            double* ap = ((double*)range.Item3 + range.Item1);
+                            double* bp = ((double*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                                *cp = (*ap != 0 && *bp != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((double*)range.Item3 + range.Item1);
+                            scalar = *((double*)range.Item4);
+                            while (cp < cLast) {
+                                *cp = (scalar != 0 && *ap != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((double*)range.Item3);
+                            bp = ((double*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                                *cp = (scalar != 0 && *bp != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (double* arrAP = arrA)
+                fixed (double* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  andEx(ILInArray<double> A, ILInArray<double> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                double[] arrA = A.GetArrayForRead();
+               
+                double[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    double* ap;
+                   
+                    double* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (double*)range.Item3;
+                                bp = (double*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap != 0 && *bp != 0) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (double*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (double*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap != 0 && *bp != 0) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( double* arrAP = arrA)
+                fixed ( double* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/any.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/any.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/any.cs	(revision 9102)
@@ -0,0 +1,766 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions; 
+       
+namespace ILNumerics  {
+    public partial class ILMath {
+
+
+        
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>Determine, if any elements are nonzero</summary>
+        /// <param name="A">Input array</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns><para>Array of same size as A, having the specified or first non-singleton dimension reduced to 1, if any elements along that dimension are non-zero, '0' else. </para></returns>
+        public static  ILRetLogical  any (ILInArray<double> A, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (dim >= A.Size.NumberOfDimensions)
+                    throw new ILArgumentException("dimension parameter out of range!");
+                if (A.IsEmpty)
+                    return new  ILRetLogical(A.Size);
+                if (A.IsScalar) {
+                    return new ILRetLogical (new byte [1]{(A.GetValue(0) == 0.0 || double.IsNaN(A.GetValue(0)))?(byte)0:(byte)1},1,1);
+                }
+                ILSize inDim = A.Size;
+                int[] newDims = inDim.ToIntArray();
+                int tmpCount = 0; 
+
+                int newLength;
+               
+                byte[] retArr;
+                // build ILSize
+                newLength = inDim.NumberOfElements / newDims[dim];
+                newDims[dim] = 1;
+                retArr = ILMemoryPool.Pool.New< byte>(newLength);
+                ILSize newDimension = new ILSize(newDims);
+                int incOut = newDimension.SequentialIndexDistance(dim);
+                int dimLen = inDim[dim];
+                int nrHigherDims = inDim.NumberOfElements / dimLen;
+                if (dim == 0) {
+                    #region physical along 1st leading dimension
+                    unsafe {
+                        fixed ( byte* pOutArr = retArr)
+                        fixed ( double* pInArr = A.GetArrayForRead()) {
+                           
+                            double* lastElement;
+                           
+                            byte* tmpOut = pOutArr;
+                           
+                            double* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                lastElement = tmpIn + dimLen;
+                                
+                                while (tmpIn < lastElement) {
+                                   
+                                    double inVal = *(tmpIn++);
+                                    if (double.IsNaN(inVal)) continue; 
+                                   
+                                    tmpCount  +=   ( /*dummy*/ (inVal)   == 0.0)?0:1; 
+                                }
+                                *tmpOut = (tmpCount == 0)? (byte)0:(byte)1; tmpCount = 0; 
+                                tmpOut++;
+                            }
+                        }
+                    }
+                    #endregion
+                } else {
+                    #region physical along abitrary dimension
+                    // sum along abitrary dimension 
+                    unsafe {
+                        fixed ( byte* pOutArr = retArr)
+                        fixed ( double* pInArr = A.GetArrayForRead()) {
+                           
+                            byte* lastElementOut = newLength + pOutArr - 1;
+                            int inLength = inDim.NumberOfElements - 1;
+                           
+                            double* lastElementIn = pInArr + inLength;
+                            int inc = inDim.SequentialIndexDistance(dim);
+                           
+                            byte* tmpOut = pOutArr;
+                            int outLength = newLength - 1;
+                           
+                            double* leadEnd;
+                           
+                            double* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                leadEnd = tmpIn + dimLen * inc;
+                                
+                                while (tmpIn < leadEnd) {
+                                   
+                                    double inVal = *(tmpIn);
+                                    tmpIn += inc;
+                                    if (double.IsNaN(inVal)) continue; 
+                                   
+                                    tmpCount  +=  ( /*dummy*/ (inVal)   == 0.0)?0:1; //
+                                }
+                                *tmpOut = (tmpCount == 0)? (byte)0:(byte)1; tmpCount = 0; 
+                                tmpOut += inc;
+                                if (tmpOut > lastElementOut)
+                                    tmpOut = pOutArr + ((tmpOut - pOutArr) - outLength);
+                                if (tmpIn > lastElementIn)
+                                    tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                            }
+                        }
+                    }
+                    #endregion
+                }
+                return new  ILRetLogical(retArr, newDims);
+            }
+        }
+        /// <summary>Determine, if any elements are nonzero</summary>
+        /// <param name="A">Input array</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns><para>Array of same size as A, having the specified or first non-singleton dimension reduced to 1, if any elements along that dimension are non-zero, '0' else. </para></returns>
+        public static  ILRetLogical  any (ILInArray<Int64> A, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (dim >= A.Size.NumberOfDimensions)
+                    throw new ILArgumentException("dimension parameter out of range!");
+                if (A.IsEmpty)
+                    return new  ILRetLogical(A.Size);
+                if (A.IsScalar) {
+                    return new ILRetLogical (new byte [1]{(A.GetValue(0) == 0)?(byte)0:(byte)1},1,1);
+                }
+                ILSize inDim = A.Size;
+                int[] newDims = inDim.ToIntArray();
+                int tmpCount = 0; 
+
+                int newLength;
+               
+                byte[] retArr;
+                // build ILSize
+                newLength = inDim.NumberOfElements / newDims[dim];
+                newDims[dim] = 1;
+                retArr = ILMemoryPool.Pool.New< byte>(newLength);
+                ILSize newDimension = new ILSize(newDims);
+                int incOut = newDimension.SequentialIndexDistance(dim);
+                int dimLen = inDim[dim];
+                int nrHigherDims = inDim.NumberOfElements / dimLen;
+                if (dim == 0) {
+                    #region physical along 1st leading dimension
+                    unsafe {
+                        fixed ( byte* pOutArr = retArr)
+                        fixed ( Int64* pInArr = A.GetArrayForRead()) {
+                           
+                            Int64* lastElement;
+                           
+                            byte* tmpOut = pOutArr;
+                           
+                            Int64* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                lastElement = tmpIn + dimLen;
+                                
+                                while (tmpIn < lastElement) {
+                                   
+                                    Int64 inVal = *(tmpIn++);
+                                    
+                                   
+                                    tmpCount  +=   ( /*dummy*/ (inVal)   == 0)?0:1; 
+                                }
+                                *tmpOut = (tmpCount == 0)? (byte)0:(byte)1; tmpCount = 0; 
+                                tmpOut++;
+                            }
+                        }
+                    }
+                    #endregion
+                } else {
+                    #region physical along abitrary dimension
+                    // sum along abitrary dimension 
+                    unsafe {
+                        fixed ( byte* pOutArr = retArr)
+                        fixed ( Int64* pInArr = A.GetArrayForRead()) {
+                           
+                            byte* lastElementOut = newLength + pOutArr - 1;
+                            int inLength = inDim.NumberOfElements - 1;
+                           
+                            Int64* lastElementIn = pInArr + inLength;
+                            int inc = inDim.SequentialIndexDistance(dim);
+                           
+                            byte* tmpOut = pOutArr;
+                            int outLength = newLength - 1;
+                           
+                            Int64* leadEnd;
+                           
+                            Int64* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                leadEnd = tmpIn + dimLen * inc;
+                                
+                                while (tmpIn < leadEnd) {
+                                   
+                                    Int64 inVal = *(tmpIn);
+                                    tmpIn += inc;
+                                    
+                                   
+                                    tmpCount  +=  ( /*dummy*/ (inVal)   == 0)?0:1; //
+                                }
+                                *tmpOut = (tmpCount == 0)? (byte)0:(byte)1; tmpCount = 0; 
+                                tmpOut += inc;
+                                if (tmpOut > lastElementOut)
+                                    tmpOut = pOutArr + ((tmpOut - pOutArr) - outLength);
+                                if (tmpIn > lastElementIn)
+                                    tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                            }
+                        }
+                    }
+                    #endregion
+                }
+                return new  ILRetLogical(retArr, newDims);
+            }
+        }
+        /// <summary>Determine, if any elements are nonzero</summary>
+        /// <param name="A">Input array</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns><para>Array of same size as A, having the specified or first non-singleton dimension reduced to 1, if any elements along that dimension are non-zero, '0' else. </para></returns>
+        public static  ILRetLogical  any (ILInArray<Int32> A, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (dim >= A.Size.NumberOfDimensions)
+                    throw new ILArgumentException("dimension parameter out of range!");
+                if (A.IsEmpty)
+                    return new  ILRetLogical(A.Size);
+                if (A.IsScalar) {
+                    return new ILRetLogical (new byte [1]{(A.GetValue(0) == 0)?(byte)0:(byte)1},1,1);
+                }
+                ILSize inDim = A.Size;
+                int[] newDims = inDim.ToIntArray();
+                int tmpCount = 0; 
+
+                int newLength;
+               
+                byte[] retArr;
+                // build ILSize
+                newLength = inDim.NumberOfElements / newDims[dim];
+                newDims[dim] = 1;
+                retArr = ILMemoryPool.Pool.New< byte>(newLength);
+                ILSize newDimension = new ILSize(newDims);
+                int incOut = newDimension.SequentialIndexDistance(dim);
+                int dimLen = inDim[dim];
+                int nrHigherDims = inDim.NumberOfElements / dimLen;
+                if (dim == 0) {
+                    #region physical along 1st leading dimension
+                    unsafe {
+                        fixed ( byte* pOutArr = retArr)
+                        fixed ( Int32* pInArr = A.GetArrayForRead()) {
+                           
+                            Int32* lastElement;
+                           
+                            byte* tmpOut = pOutArr;
+                           
+                            Int32* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                lastElement = tmpIn + dimLen;
+                                
+                                while (tmpIn < lastElement) {
+                                   
+                                    Int32 inVal = *(tmpIn++);
+                                    
+                                   
+                                    tmpCount  +=   ( /*dummy*/ (inVal)   == 0)?0:1; 
+                                }
+                                *tmpOut = (tmpCount == 0)? (byte)0:(byte)1; tmpCount = 0; 
+                                tmpOut++;
+                            }
+                        }
+                    }
+                    #endregion
+                } else {
+                    #region physical along abitrary dimension
+                    // sum along abitrary dimension 
+                    unsafe {
+                        fixed ( byte* pOutArr = retArr)
+                        fixed ( Int32* pInArr = A.GetArrayForRead()) {
+                           
+                            byte* lastElementOut = newLength + pOutArr - 1;
+                            int inLength = inDim.NumberOfElements - 1;
+                           
+                            Int32* lastElementIn = pInArr + inLength;
+                            int inc = inDim.SequentialIndexDistance(dim);
+                           
+                            byte* tmpOut = pOutArr;
+                            int outLength = newLength - 1;
+                           
+                            Int32* leadEnd;
+                           
+                            Int32* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                leadEnd = tmpIn + dimLen * inc;
+                                
+                                while (tmpIn < leadEnd) {
+                                   
+                                    Int32 inVal = *(tmpIn);
+                                    tmpIn += inc;
+                                    
+                                   
+                                    tmpCount  +=  ( /*dummy*/ (inVal)   == 0)?0:1; //
+                                }
+                                *tmpOut = (tmpCount == 0)? (byte)0:(byte)1; tmpCount = 0; 
+                                tmpOut += inc;
+                                if (tmpOut > lastElementOut)
+                                    tmpOut = pOutArr + ((tmpOut - pOutArr) - outLength);
+                                if (tmpIn > lastElementIn)
+                                    tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                            }
+                        }
+                    }
+                    #endregion
+                }
+                return new  ILRetLogical(retArr, newDims);
+            }
+        }
+        /// <summary>Determine, if any elements are nonzero</summary>
+        /// <param name="A">Input array</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns><para>Array of same size as A, having the specified or first non-singleton dimension reduced to 1, if any elements along that dimension are non-zero, '0' else. </para></returns>
+        public static  ILRetLogical  any (ILInArray<byte> A, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (dim >= A.Size.NumberOfDimensions)
+                    throw new ILArgumentException("dimension parameter out of range!");
+                if (A.IsEmpty)
+                    return new  ILRetLogical(A.Size);
+                if (A.IsScalar) {
+                    return new ILRetLogical (new byte [1]{(A.GetValue(0) == 0)?(byte)0:(byte)1},1,1);
+                }
+                ILSize inDim = A.Size;
+                int[] newDims = inDim.ToIntArray();
+                int tmpCount = 0; 
+
+                int newLength;
+               
+                byte[] retArr;
+                // build ILSize
+                newLength = inDim.NumberOfElements / newDims[dim];
+                newDims[dim] = 1;
+                retArr = ILMemoryPool.Pool.New< byte>(newLength);
+                ILSize newDimension = new ILSize(newDims);
+                int incOut = newDimension.SequentialIndexDistance(dim);
+                int dimLen = inDim[dim];
+                int nrHigherDims = inDim.NumberOfElements / dimLen;
+                if (dim == 0) {
+                    #region physical along 1st leading dimension
+                    unsafe {
+                        fixed ( byte* pOutArr = retArr)
+                        fixed ( byte* pInArr = A.GetArrayForRead()) {
+                           
+                            byte* lastElement;
+                           
+                            byte* tmpOut = pOutArr;
+                           
+                            byte* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                lastElement = tmpIn + dimLen;
+                                
+                                while (tmpIn < lastElement) {
+                                   
+                                    byte inVal = *(tmpIn++);
+                                    
+                                   
+                                    tmpCount  +=   ( /*dummy*/ (inVal)   == 0)?0:1; 
+                                }
+                                *tmpOut = (tmpCount == 0)? (byte)0:(byte)1; tmpCount = 0; 
+                                tmpOut++;
+                            }
+                        }
+                    }
+                    #endregion
+                } else {
+                    #region physical along abitrary dimension
+                    // sum along abitrary dimension 
+                    unsafe {
+                        fixed ( byte* pOutArr = retArr)
+                        fixed ( byte* pInArr = A.GetArrayForRead()) {
+                           
+                            byte* lastElementOut = newLength + pOutArr - 1;
+                            int inLength = inDim.NumberOfElements - 1;
+                           
+                            byte* lastElementIn = pInArr + inLength;
+                            int inc = inDim.SequentialIndexDistance(dim);
+                           
+                            byte* tmpOut = pOutArr;
+                            int outLength = newLength - 1;
+                           
+                            byte* leadEnd;
+                           
+                            byte* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                leadEnd = tmpIn + dimLen * inc;
+                                
+                                while (tmpIn < leadEnd) {
+                                   
+                                    byte inVal = *(tmpIn);
+                                    tmpIn += inc;
+                                    
+                                   
+                                    tmpCount  +=  ( /*dummy*/ (inVal)   == 0)?0:1; //
+                                }
+                                *tmpOut = (tmpCount == 0)? (byte)0:(byte)1; tmpCount = 0; 
+                                tmpOut += inc;
+                                if (tmpOut > lastElementOut)
+                                    tmpOut = pOutArr + ((tmpOut - pOutArr) - outLength);
+                                if (tmpIn > lastElementIn)
+                                    tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                            }
+                        }
+                    }
+                    #endregion
+                }
+                return new  ILRetLogical(retArr, newDims);
+            }
+        }
+        /// <summary>Determine, if any elements are nonzero</summary>
+        /// <param name="A">Input array</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns><para>Array of same size as A, having the specified or first non-singleton dimension reduced to 1, if any elements along that dimension are non-zero, '0' else. </para></returns>
+        public static  ILRetLogical  any (ILInArray<fcomplex> A, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (dim >= A.Size.NumberOfDimensions)
+                    throw new ILArgumentException("dimension parameter out of range!");
+                if (A.IsEmpty)
+                    return new  ILRetLogical(A.Size);
+                if (A.IsScalar) {
+                    return new ILRetLogical (new byte [1]{(A.GetValue(0).iszero() || fcomplex.IsNaN(A.GetValue(0)))?(byte)1:(byte)0},1,1);
+                }
+                ILSize inDim = A.Size;
+                int[] newDims = inDim.ToIntArray();
+                int tmpCount = 0; 
+
+                int newLength;
+               
+                byte[] retArr;
+                // build ILSize
+                newLength = inDim.NumberOfElements / newDims[dim];
+                newDims[dim] = 1;
+                retArr = ILMemoryPool.Pool.New< byte>(newLength);
+                ILSize newDimension = new ILSize(newDims);
+                int incOut = newDimension.SequentialIndexDistance(dim);
+                int dimLen = inDim[dim];
+                int nrHigherDims = inDim.NumberOfElements / dimLen;
+                if (dim == 0) {
+                    #region physical along 1st leading dimension
+                    unsafe {
+                        fixed ( byte* pOutArr = retArr)
+                        fixed ( fcomplex* pInArr = A.GetArrayForRead()) {
+                           
+                            fcomplex* lastElement;
+                           
+                            byte* tmpOut = pOutArr;
+                           
+                            fcomplex* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                lastElement = tmpIn + dimLen;
+                                
+                                while (tmpIn < lastElement) {
+                                   
+                                    fcomplex inVal = *(tmpIn++);
+                                    if (fcomplex.IsNaN(inVal)) continue; 
+                                   
+                                    tmpCount  +=   ( /*dummy*/ (inVal)  .iszero())?0:1;  
+                                }
+                                *tmpOut = (tmpCount == 0)? (byte)0:(byte)1; tmpCount = 0; 
+                                tmpOut++;
+                            }
+                        }
+                    }
+                    #endregion
+                } else {
+                    #region physical along abitrary dimension
+                    // sum along abitrary dimension 
+                    unsafe {
+                        fixed ( byte* pOutArr = retArr)
+                        fixed ( fcomplex* pInArr = A.GetArrayForRead()) {
+                           
+                            byte* lastElementOut = newLength + pOutArr - 1;
+                            int inLength = inDim.NumberOfElements - 1;
+                           
+                            fcomplex* lastElementIn = pInArr + inLength;
+                            int inc = inDim.SequentialIndexDistance(dim);
+                           
+                            byte* tmpOut = pOutArr;
+                            int outLength = newLength - 1;
+                           
+                            fcomplex* leadEnd;
+                           
+                            fcomplex* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                leadEnd = tmpIn + dimLen * inc;
+                                
+                                while (tmpIn < leadEnd) {
+                                   
+                                    fcomplex inVal = *(tmpIn);
+                                    tmpIn += inc;
+                                    if (fcomplex.IsNaN(inVal)) continue; 
+                                   
+                                    tmpCount  +=  ( /*dummy*/ (inVal)  .iszero())?0:1;  //
+                                }
+                                *tmpOut = (tmpCount == 0)? (byte)0:(byte)1; tmpCount = 0; 
+                                tmpOut += inc;
+                                if (tmpOut > lastElementOut)
+                                    tmpOut = pOutArr + ((tmpOut - pOutArr) - outLength);
+                                if (tmpIn > lastElementIn)
+                                    tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                            }
+                        }
+                    }
+                    #endregion
+                }
+                return new  ILRetLogical(retArr, newDims);
+            }
+        }
+        /// <summary>Determine, if any elements are nonzero</summary>
+        /// <param name="A">Input array</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns><para>Array of same size as A, having the specified or first non-singleton dimension reduced to 1, if any elements along that dimension are non-zero, '0' else. </para></returns>
+        public static  ILRetLogical  any (ILInArray<float> A, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (dim >= A.Size.NumberOfDimensions)
+                    throw new ILArgumentException("dimension parameter out of range!");
+                if (A.IsEmpty)
+                    return new  ILRetLogical(A.Size);
+                if (A.IsScalar) {
+                    return new ILRetLogical (new byte [1]{(A.GetValue(0) == 0.0f || float.IsNaN(A.GetValue(0)))?(byte)0:(byte)1},1,1);
+                }
+                ILSize inDim = A.Size;
+                int[] newDims = inDim.ToIntArray();
+                int tmpCount = 0; 
+
+                int newLength;
+               
+                byte[] retArr;
+                // build ILSize
+                newLength = inDim.NumberOfElements / newDims[dim];
+                newDims[dim] = 1;
+                retArr = ILMemoryPool.Pool.New< byte>(newLength);
+                ILSize newDimension = new ILSize(newDims);
+                int incOut = newDimension.SequentialIndexDistance(dim);
+                int dimLen = inDim[dim];
+                int nrHigherDims = inDim.NumberOfElements / dimLen;
+                if (dim == 0) {
+                    #region physical along 1st leading dimension
+                    unsafe {
+                        fixed ( byte* pOutArr = retArr)
+                        fixed ( float* pInArr = A.GetArrayForRead()) {
+                           
+                            float* lastElement;
+                           
+                            byte* tmpOut = pOutArr;
+                           
+                            float* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                lastElement = tmpIn + dimLen;
+                                
+                                while (tmpIn < lastElement) {
+                                   
+                                    float inVal = *(tmpIn++);
+                                    if (float.IsNaN(inVal)) continue; 
+                                   
+                                    tmpCount  +=   ( /*dummy*/ (inVal)   == 0.0f)?0:1; 
+                                }
+                                *tmpOut = (tmpCount == 0)? (byte)0:(byte)1; tmpCount = 0; 
+                                tmpOut++;
+                            }
+                        }
+                    }
+                    #endregion
+                } else {
+                    #region physical along abitrary dimension
+                    // sum along abitrary dimension 
+                    unsafe {
+                        fixed ( byte* pOutArr = retArr)
+                        fixed ( float* pInArr = A.GetArrayForRead()) {
+                           
+                            byte* lastElementOut = newLength + pOutArr - 1;
+                            int inLength = inDim.NumberOfElements - 1;
+                           
+                            float* lastElementIn = pInArr + inLength;
+                            int inc = inDim.SequentialIndexDistance(dim);
+                           
+                            byte* tmpOut = pOutArr;
+                            int outLength = newLength - 1;
+                           
+                            float* leadEnd;
+                           
+                            float* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                leadEnd = tmpIn + dimLen * inc;
+                                
+                                while (tmpIn < leadEnd) {
+                                   
+                                    float inVal = *(tmpIn);
+                                    tmpIn += inc;
+                                    if (float.IsNaN(inVal)) continue; 
+                                   
+                                    tmpCount  +=  ( /*dummy*/ (inVal)   == 0.0f)?0:1; //
+                                }
+                                *tmpOut = (tmpCount == 0)? (byte)0:(byte)1; tmpCount = 0; 
+                                tmpOut += inc;
+                                if (tmpOut > lastElementOut)
+                                    tmpOut = pOutArr + ((tmpOut - pOutArr) - outLength);
+                                if (tmpIn > lastElementIn)
+                                    tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                            }
+                        }
+                    }
+                    #endregion
+                }
+                return new  ILRetLogical(retArr, newDims);
+            }
+        }
+        /// <summary>Determine, if any elements are nonzero</summary>
+        /// <param name="A">Input array</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns><para>Array of same size as A, having the specified or first non-singleton dimension reduced to 1, if any elements along that dimension are non-zero, '0' else. </para></returns>
+        public static  ILRetLogical  any (ILInArray<complex> A, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (dim >= A.Size.NumberOfDimensions)
+                    throw new ILArgumentException("dimension parameter out of range!");
+                if (A.IsEmpty)
+                    return new  ILRetLogical(A.Size);
+                if (A.IsScalar) {
+                    return new ILRetLogical (new byte [1]{(A.GetValue(0).iszero() || complex.IsNaN(A.GetValue(0)))?(byte)0:(byte)1},1,1);
+                }
+                ILSize inDim = A.Size;
+                int[] newDims = inDim.ToIntArray();
+                int tmpCount = 0; 
+
+                int newLength;
+               
+                byte[] retArr;
+                // build ILSize
+                newLength = inDim.NumberOfElements / newDims[dim];
+                newDims[dim] = 1;
+                retArr = ILMemoryPool.Pool.New< byte>(newLength);
+                ILSize newDimension = new ILSize(newDims);
+                int incOut = newDimension.SequentialIndexDistance(dim);
+                int dimLen = inDim[dim];
+                int nrHigherDims = inDim.NumberOfElements / dimLen;
+                if (dim == 0) {
+                    #region physical along 1st leading dimension
+                    unsafe {
+                        fixed ( byte* pOutArr = retArr)
+                        fixed ( complex* pInArr = A.GetArrayForRead()) {
+                           
+                            complex* lastElement;
+                           
+                            byte* tmpOut = pOutArr;
+                           
+                            complex* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                lastElement = tmpIn + dimLen;
+                                
+                                while (tmpIn < lastElement) {
+                                   
+                                    complex inVal = *(tmpIn++);
+                                    if (complex.IsNaN(inVal)) continue; 
+                                   
+                                    tmpCount  +=   ( /*dummy*/ (inVal)  .iszero())?0:1;  
+                                }
+                                *tmpOut = (tmpCount == 0)? (byte)0:(byte)1; tmpCount = 0; 
+                                tmpOut++;
+                            }
+                        }
+                    }
+                    #endregion
+                } else {
+                    #region physical along abitrary dimension
+                    // sum along abitrary dimension 
+                    unsafe {
+                        fixed ( byte* pOutArr = retArr)
+                        fixed ( complex* pInArr = A.GetArrayForRead()) {
+                           
+                            byte* lastElementOut = newLength + pOutArr - 1;
+                            int inLength = inDim.NumberOfElements - 1;
+                           
+                            complex* lastElementIn = pInArr + inLength;
+                            int inc = inDim.SequentialIndexDistance(dim);
+                           
+                            byte* tmpOut = pOutArr;
+                            int outLength = newLength - 1;
+                           
+                            complex* leadEnd;
+                           
+                            complex* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                leadEnd = tmpIn + dimLen * inc;
+                                
+                                while (tmpIn < leadEnd) {
+                                   
+                                    complex inVal = *(tmpIn);
+                                    tmpIn += inc;
+                                    if (complex.IsNaN(inVal)) continue; 
+                                   
+                                    tmpCount  +=  ( /*dummy*/ (inVal)  .iszero())?0:1;  //
+                                }
+                                *tmpOut = (tmpCount == 0)? (byte)0:(byte)1; tmpCount = 0; 
+                                tmpOut += inc;
+                                if (tmpOut > lastElementOut)
+                                    tmpOut = pOutArr + ((tmpOut - pOutArr) - outLength);
+                                if (tmpIn > lastElementIn)
+                                    tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                            }
+                        }
+                    }
+                    #endregion
+                }
+                return new  ILRetLogical(retArr, newDims);
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+   }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/anyall.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/anyall.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/anyall.cs	(revision 9102)
@@ -0,0 +1,298 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions; 
+
+
+namespace ILNumerics  {
+
+    public partial class ILMath {
+
+
+        /// <summary>
+        /// Determine if array has any nonzero elements
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Scalar logical array</returns>
+        /// <remarks><para>The function evaluates all elements of A in all dimensions. It returnes 'true' (1) if
+        /// <b>any</b> elements are found to be non-zero, false, if all elements are zero.</para>
+        /// <para>If A is empty, a scalar logical 'false' (0) is returned.</para>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If A was null.</exception>
+        /// <seealso cref="ILNumerics.ILMath.all(ILInArray{double},int)"/>
+        public static ILRetLogical anyall (ILInArray<double> A) {
+            if (object.Equals(A,null))
+                throw new ILArgumentException("A must not be null!");
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    return new ILRetLogical(ILSize.Empty00); 
+                } 
+                byte retArr = 0; 
+                unsafe {
+                    fixed ( double * inArrStart = A.GetArrayForRead()) {
+                         double * inArrWalk = inArrStart; 
+                         double * inArrEnd = inArrStart + A.Size.NumberOfElements; 
+                        while (inArrWalk < inArrEnd) {
+                            if ( *inArrWalk++ != 0) {
+                                retArr = 1; 
+                                break; 
+                            }
+                        }
+                    }
+                }
+                return new ILRetLogical (new byte [1]{retArr},1,1);
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// Determine if array has any nonzero elements
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Scalar logical array</returns>
+        /// <remarks><para>The function evaluates all elements of A in all dimensions. It returnes 'true' (1) if
+        /// <b>any</b> elements are found to be non-zero, false, if all elements are zero.</para>
+        /// <para>If A is empty, a scalar logical 'false' (0) is returned.</para>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If A was null.</exception>
+        /// <seealso cref="ILNumerics.ILMath.all(ILInArray{double},int)"/>
+        public static ILRetLogical anyall (ILInArray<Int64> A) {
+            if (object.Equals(A,null))
+                throw new ILArgumentException("A must not be null!");
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    return new ILRetLogical(ILSize.Empty00); 
+                } 
+                byte retArr = 0; 
+                unsafe {
+                    fixed ( Int64 * inArrStart = A.GetArrayForRead()) {
+                        Int64 * inArrWalk = inArrStart; 
+                        Int64 * inArrEnd = inArrStart + A.Size.NumberOfElements; 
+                        while (inArrWalk < inArrEnd) {
+                            if ( *inArrWalk++ != 0) {
+                                retArr = 1; 
+                                break; 
+                            }
+                        }
+                    }
+                }
+                return new ILRetLogical (new byte [1]{retArr},1,1);
+            }
+        }
+        /// <summary>
+        /// Determine if array has any nonzero elements
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Scalar logical array</returns>
+        /// <remarks><para>The function evaluates all elements of A in all dimensions. It returnes 'true' (1) if
+        /// <b>any</b> elements are found to be non-zero, false, if all elements are zero.</para>
+        /// <para>If A is empty, a scalar logical 'false' (0) is returned.</para>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If A was null.</exception>
+        /// <seealso cref="ILNumerics.ILMath.all(ILInArray{double},int)"/>
+        public static ILRetLogical anyall (ILInArray<Int32> A) {
+            if (object.Equals(A,null))
+                throw new ILArgumentException("A must not be null!");
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    return new ILRetLogical(ILSize.Empty00); 
+                } 
+                byte retArr = 0; 
+                unsafe {
+                    fixed ( Int32 * inArrStart = A.GetArrayForRead()) {
+                        Int32 * inArrWalk = inArrStart; 
+                        Int32 * inArrEnd = inArrStart + A.Size.NumberOfElements; 
+                        while (inArrWalk < inArrEnd) {
+                            if ( *inArrWalk++ != 0) {
+                                retArr = 1; 
+                                break; 
+                            }
+                        }
+                    }
+                }
+                return new ILRetLogical (new byte [1]{retArr},1,1);
+            }
+        }
+        /// <summary>
+        /// Determine if array has any nonzero elements
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Scalar logical array</returns>
+        /// <remarks><para>The function evaluates all elements of A in all dimensions. It returnes 'true' (1) if
+        /// <b>any</b> elements are found to be non-zero, false, if all elements are zero.</para>
+        /// <para>If A is empty, a scalar logical 'false' (0) is returned.</para>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If A was null.</exception>
+        /// <seealso cref="ILNumerics.ILMath.all(ILInArray{double},int)"/>
+        public static ILRetLogical anyall (ILInArray<byte> A) {
+            if (object.Equals(A,null))
+                throw new ILArgumentException("A must not be null!");
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    return new ILRetLogical(ILSize.Empty00); 
+                } 
+                byte retArr = 0; 
+                unsafe {
+                    fixed ( byte * inArrStart = A.GetArrayForRead()) {
+                        byte * inArrWalk = inArrStart; 
+                        byte * inArrEnd = inArrStart + A.Size.NumberOfElements; 
+                        while (inArrWalk < inArrEnd) {
+                            if ( *inArrWalk++ != 0) {
+                                retArr = 1; 
+                                break; 
+                            }
+                        }
+                    }
+                }
+                return new ILRetLogical (new byte [1]{retArr},1,1);
+            }
+        }
+        /// <summary>
+        /// Determine if array has any nonzero elements
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Scalar logical array</returns>
+        /// <remarks><para>The function evaluates all elements of A in all dimensions. It returnes 'true' (1) if
+        /// <b>any</b> elements are found to be non-zero, false, if all elements are zero.</para>
+        /// <para>If A is empty, a scalar logical 'false' (0) is returned.</para>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If A was null.</exception>
+        /// <seealso cref="ILNumerics.ILMath.all(ILInArray{double},int)"/>
+        public static ILRetLogical anyall (ILInArray<fcomplex> A) {
+            if (object.Equals(A,null))
+                throw new ILArgumentException("A must not be null!");
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    return new ILRetLogical(ILSize.Empty00); 
+                } 
+                byte retArr = 0; 
+                unsafe {
+                    fixed ( fcomplex * inArrStart = A.GetArrayForRead()) {
+                        fcomplex * inArrWalk = inArrStart; 
+                        fcomplex * inArrEnd = inArrStart + A.Size.NumberOfElements; 
+                        while (inArrWalk < inArrEnd) {
+                            if ( *inArrWalk++ != 0) {
+                                retArr = 1; 
+                                break; 
+                            }
+                        }
+                    }
+                }
+                return new ILRetLogical (new byte [1]{retArr},1,1);
+            }
+        }
+        /// <summary>
+        /// Determine if array has any nonzero elements
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Scalar logical array</returns>
+        /// <remarks><para>The function evaluates all elements of A in all dimensions. It returnes 'true' (1) if
+        /// <b>any</b> elements are found to be non-zero, false, if all elements are zero.</para>
+        /// <para>If A is empty, a scalar logical 'false' (0) is returned.</para>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If A was null.</exception>
+        /// <seealso cref="ILNumerics.ILMath.all(ILInArray{double},int)"/>
+        public static ILRetLogical anyall (ILInArray<float> A) {
+            if (object.Equals(A,null))
+                throw new ILArgumentException("A must not be null!");
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    return new ILRetLogical(ILSize.Empty00); 
+                } 
+                byte retArr = 0; 
+                unsafe {
+                    fixed ( float * inArrStart = A.GetArrayForRead()) {
+                        float * inArrWalk = inArrStart; 
+                        float * inArrEnd = inArrStart + A.Size.NumberOfElements; 
+                        while (inArrWalk < inArrEnd) {
+                            if ( *inArrWalk++ != 0) {
+                                retArr = 1; 
+                                break; 
+                            }
+                        }
+                    }
+                }
+                return new ILRetLogical (new byte [1]{retArr},1,1);
+            }
+        }
+        /// <summary>
+        /// Determine if array has any nonzero elements
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Scalar logical array</returns>
+        /// <remarks><para>The function evaluates all elements of A in all dimensions. It returnes 'true' (1) if
+        /// <b>any</b> elements are found to be non-zero, false, if all elements are zero.</para>
+        /// <para>If A is empty, a scalar logical 'false' (0) is returned.</para>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If A was null.</exception>
+        /// <seealso cref="ILNumerics.ILMath.all(ILInArray{double},int)"/>
+        public static ILRetLogical anyall (ILInArray<complex> A) {
+            if (object.Equals(A,null))
+                throw new ILArgumentException("A must not be null!");
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    return new ILRetLogical(ILSize.Empty00); 
+                } 
+                byte retArr = 0; 
+                unsafe {
+                    fixed ( complex * inArrStart = A.GetArrayForRead()) {
+                        complex * inArrWalk = inArrStart; 
+                        complex * inArrEnd = inArrStart + A.Size.NumberOfElements; 
+                        while (inArrWalk < inArrEnd) {
+                            if ( *inArrWalk++ != 0) {
+                                retArr = 1; 
+                                break; 
+                            }
+                        }
+                    }
+                }
+                return new ILRetLogical (new byte [1]{retArr},1,1);
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/apply.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/apply.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/apply.cs	(revision 9102)
@@ -0,0 +1,2776 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics;
+using ILNumerics.Exceptions;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+
+
+namespace ILNumerics {
+    public partial class ILMath {
+
+
+        /// <summary>Apply an arbitrary function to two arrays</summary>
+        /// <param name="func">A function c = f(a,b), which will be applied to elements in A and B</param>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>The combination of A and B. The result and size depends on the inputs:<list type="table">
+        /// <item>
+        ///     <term>size(A) == size(B)</term>
+        ///     <description>Same size as A/B, elementwise combination of A and B.</description>
+        /// </item>
+        /// <item>
+        ///     <term>isscalar(A) || isscalar(B)</term>
+        ///     <description>Same size as A or B, whichever is not a scalar, the scalar value being applied to each element 
+        ///     (i.e. if the non-scalar input is empty, the result is empty).</description>
+        /// </item>
+        /// <item>
+        ///     <term>All other cases</term>
+        ///     <description>If A or B is a colum vector and the other parameter is an array with a matching column length, the vector is used to operate on all columns of the array. 
+        /// Similarly, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length.</description>
+        /// </item>
+        /// </list></returns>
+        /// <remarks><para>The <c>apply</c> function is also implemented for input if e.g. sizes (mxn) and (mx1). 
+        /// In this case the vector argument will be combined to each column, resulting in an (mxn) array. 
+        /// This feature is, however, officiallny not supported.</para></remarks>
+        public unsafe static ILRetArray<double> apply(Func<double, double, double> func, ILInArray<double> A, ILInArray<double> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                
+                double[] retArr;
+                
+                double[] arrA = A.GetArrayForRead();
+                
+                double[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size;
+                    if (B.IsScalar) {
+
+                        return new ILRetArray<double>(new double[1] { func(A.GetValue(0), B.GetValue(0)) }, A.Size);
+                    } else if (B.IsEmpty) {
+                        return ILRetArray<double>.empty(outDims);
+                    } else {
+                        outLen = outDims.NumberOfElements;
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New<double>(outLen);
+                            mode = BinOpItMode.SAN;
+                        } else {
+                            mode = BinOpItMode.SAI;
+                        }
+                    }
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return ILRetArray<double>.empty(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New<double>(outLen);
+                            mode = BinOpItMode.ASN;
+                        } else {
+                            mode = BinOpItMode.ASI;
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return applyEx(func,A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        if (A.TryGetStorage4InplaceOp(out retArr))
+                            mode = BinOpItMode.AAIA;
+                        else if (B.TryGetStorage4InplaceOp(out retArr)) {
+                            mode = BinOpItMode.AAIB;
+                        } else {
+                            retArr = ILMemoryPool.Pool.New<double>(outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<double> retStorage = new ILDenseStorage<double>(retArr, outDims);
+                int i = 0, workerCount = 1; 
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    
+                    double* cLast, cp = (double*)range.Item5 + range.Item1;
+                    
+                    double scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                            
+                            double* bp = ((double*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp =   func(*cp, *bp++);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                            
+                            double* ap = ((double*)range.Item3 + range.Item1);
+                            while (cp < cLast) {
+
+                                *cp = func(*ap++, *cp);
+                                cp++;
+
+                            }
+                            //ap = ((double*)range.Item3 + range.Item1);
+                            //for (int i2 = range.Item2; i2-- > 0; ) {
+                            //    *(cp + i2) = *(ap + i2) - *(cp + i2);
+                            //}
+                            //int ie = range.Item1 + range.Item2-1;
+                            //double[] locRetArr = retArr;
+                            //for (int i2 = range.Item1; i2 < locRetArr.Length; i2++) {
+                            //    locRetArr[i2] = arrA[i2] - locRetArr[i2];
+                            //    if (i2 >= ie) break; 
+                            //}
+
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((double*)range.Item3 + range.Item1);
+                            bp = ((double*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp++ =   func(*ap++, *bp++);
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((double*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp =   func(*cp, scalar);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((double*)range.Item3 + range.Item1);
+                            scalar = *((double*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp++ =   func(*ap++, scalar);
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((double*)range.Item3);
+                            while (cp < cLast) {
+                               
+                                *cp =   func(scalar, *cp);
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((double*)range.Item3);
+                            bp = ((double*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp++ =   func(scalar, *bp++);
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work 
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                
+                // retStorage.PendingEvents = new System.Threading.CountdownEvent(workItemCount); 
+
+                fixed ( double* arrAP = arrA)
+                fixed ( double* arrBP = arrB)
+                fixed ( double* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range 
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    System.Threading.SpinWait.SpinUntil(() => {
+                        return workerCount <= 0;
+                    });
+                    //while (workerCount > 0) ; 
+                }
+
+                #endregion
+                return new ILRetArray<double>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<double> applyEx(Func<double, double, double> applyFunc, ILInArray<double> A, ILInArray<double> B) {
+            #region parameter checking
+            if (isnull(A) || isnull(B))
+                return empty<double>(ILSize.Empty00);
+            if (A.IsEmpty) {
+                return empty<double>(B.S);
+            } else if (B.IsEmpty) {
+                return empty<double>(A.S);
+            }
+            //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+            //    return add(A,B);
+            int dim = -1;
+            for (int _L = 0; _L < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); _L++) {
+                if (A.S[_L] != B.S[_L]) {
+                    if (dim >= 0 || (A.S[_L] != 1 && B.S[_L] != 1)) {
+                        throw new ILArgumentException("A and B must have the same size except for one singleton dimension in A or B");
+                    }
+                    dim = _L;
+                }
+            }
+            if (dim > 1)
+                throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+            #endregion
+
+            #region parameter preparation
+
+            
+            double[] retArr;
+
+            
+            double[] arrA = A.GetArrayForRead();
+
+            
+            double[] arrB = B.GetArrayForRead();
+            ILSize outDims;
+            BinOptItExMode mode;
+            int arrInc = 0;
+            int arrStepInc = 0;
+            int dimLen = 0;
+            if (A.IsVector) {
+                outDims = B.S;
+                if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<double>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                } else {
+                    mode = BinOptItExMode.VAI;
+                }
+                dimLen = A.Length;
+            } else if (B.IsVector) {
+                outDims = A.S;
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<double>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                } else {
+                    mode = BinOptItExMode.AVI;
+                }
+                dimLen = B.Length;
+            } else {
+                throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+            }
+            arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+            arrStepInc = outDims.SequentialIndexDistance(dim);
+            #endregion
+
+            #region worker loops definition
+            ILDenseStorage<double> retStorage = new ILDenseStorage<double>(retArr, outDims);
+            int workerCount = 1;
+            Action<object> worker = data => {
+                // expects: iStart, iLen, ap, bp, cp
+                Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                    (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                
+                double* ap;
+                
+                double* bp;
+                
+                double* cp;
+                switch (mode) {
+                    case BinOptItExMode.VAN:
+                        for (int s = 0; s < range.Item2; s++) {
+                            ap = (double*)range.Item3;
+                            bp = (double*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                            cp = (double*)range.Item5 + range.Item1 + s * arrStepInc;
+                            for (int l = 0; l < dimLen; l++) {
+
+                                *cp = applyFunc(*ap, *bp);
+                                ap++;
+                                bp += arrInc;
+                                cp += arrInc;
+                            }
+                        }
+                        break;
+                    case BinOptItExMode.VAI:
+                        for (int s = 0; s < range.Item2; s++) {
+                            ap = (double*)range.Item3;
+                            cp = (double*)range.Item5 + range.Item1 + s * arrStepInc;
+                            for (int l = 0; l < dimLen; l++) {
+
+                                *cp = applyFunc(*ap, *cp);
+                                ap++;
+                                cp += arrInc;
+                            }
+                        }
+                        break;
+                    case BinOptItExMode.AVN:
+                        for (int s = 0; s < range.Item2; s++) {
+                            ap = (double*)range.Item3 + range.Item1 + s * arrStepInc;
+                            bp = (double*)range.Item4;
+                            cp = (double*)range.Item5 + range.Item1 + s * arrStepInc;
+                            for (int l = 0; l < dimLen; l++) {
+
+                                *cp = applyFunc(*ap, *bp);
+                                ap += arrInc;
+                                bp++;
+                                cp += arrInc;
+                            }
+                        }
+                        break;
+                    case BinOptItExMode.AVI:
+                        for (int s = 0; s < range.Item2; s++) {
+                            bp = (double*)range.Item4;
+                            cp = (double*)range.Item5 + range.Item1 + s * arrStepInc;
+                            for (int l = 0; l < dimLen; l++) {
+
+                                *cp = applyFunc(*cp, *bp);
+                                bp++;
+                                cp += arrInc;
+                            }
+                        }
+                        break;
+                }
+                System.Threading.Interlocked.Decrement(ref workerCount);
+            };
+            #endregion
+
+            #region work distribution
+            int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+            int outLen = outDims.NumberOfElements;
+            if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                    workItemLength = outLen / dimLen / workItemCount;
+                    //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                } else {
+                    workItemLength = outLen / dimLen / 2;
+                    workItemCount = 2;
+                }
+            } else {
+                workItemLength = outLen / dimLen;
+                workItemCount = 1;
+            }
+
+            fixed (double* arrAP = arrA)
+            fixed (double* arrBP = arrB)
+            fixed (double* retArrP = retArr) {
+
+                for (; i < workItemCount - 1; i++) {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                        = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                           (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                    System.Threading.Interlocked.Increment(ref workerCount);
+                    ILThreadPool.QueueUserWorkItem(i, worker, range);
+                }
+                // the last (or may the only) chunk is done right here
+                //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                            (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                ILThreadPool.Wait4Workers(ref workerCount);
+            }
+            #endregion
+
+            return new ILRetArray<double>(retStorage);
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>Apply an arbitrary function to two arrays</summary>
+        /// <param name="func">A function c = f(a,b), which will be applied to elements in A and B</param>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>The combination of A and B. The result and size depends on the inputs:<list type="table">
+        /// <item>
+        ///     <term>size(A) == size(B)</term>
+        ///     <description>Same size as A/B, elementwise combination of A and B.</description>
+        /// </item>
+        /// <item>
+        ///     <term>isscalar(A) || isscalar(B)</term>
+        ///     <description>Same size as A or B, whichever is not a scalar, the scalar value being applied to each element 
+        ///     (i.e. if the non-scalar input is empty, the result is empty).</description>
+        /// </item>
+        /// <item>
+        ///     <term>All other cases</term>
+        ///     <description>If A or B is a colum vector and the other parameter is an array with a matching column length, the vector is used to operate on all columns of the array. 
+        /// Similarly, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length.</description>
+        /// </item>
+        /// </list></returns>
+        /// <remarks><para>The <c>apply</c> function is also implemented for input if e.g. sizes (mxn) and (mx1). 
+        /// In this case the vector argument will be combined to each column, resulting in an (mxn) array. 
+        /// This feature is, however, officiallny not supported.</para></remarks>
+        public unsafe static ILRetArray<float> apply(Func<float, float, float> func, ILInArray<float> A, ILInArray<float> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+               
+                float[] retArr;
+               
+                float[] arrA = A.GetArrayForRead();
+               
+                float[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size;
+                    if (B.IsScalar) {
+
+                        return new ILRetArray<float>(new float[1] { func(A.GetValue(0), B.GetValue(0)) }, A.Size);
+                    } else if (B.IsEmpty) {
+                        return ILRetArray<float>.empty(outDims);
+                    } else {
+                        outLen = outDims.NumberOfElements;
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New<float>(outLen);
+                            mode = BinOpItMode.SAN;
+                        } else {
+                            mode = BinOpItMode.SAI;
+                        }
+                    }
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return ILRetArray<float>.empty(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New<float>(outLen);
+                            mode = BinOpItMode.ASN;
+                        } else {
+                            mode = BinOpItMode.ASI;
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return applyEx(func,A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        if (A.TryGetStorage4InplaceOp(out retArr))
+                            mode = BinOpItMode.AAIA;
+                        else if (B.TryGetStorage4InplaceOp(out retArr)) {
+                            mode = BinOpItMode.AAIB;
+                        } else {
+                            retArr = ILMemoryPool.Pool.New<float>(outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<float> retStorage = new ILDenseStorage<float>(retArr, outDims);
+                int i = 0, workerCount = 1; 
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                   
+                    float* cLast, cp = (float*)range.Item5 + range.Item1;
+                   
+                    float scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           
+                            float* bp = ((float*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp =   func(*cp, *bp++);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           
+                            float* ap = ((float*)range.Item3 + range.Item1);
+                            while (cp < cLast) {
+
+                                *cp = func(*ap++, *cp);
+                                cp++;
+
+                            }
+                            //ap = ((double*)range.Item3 + range.Item1);
+                            //for (int i2 = range.Item2; i2-- > 0; ) {
+                            //    *(cp + i2) = *(ap + i2) - *(cp + i2);
+                            //}
+                            //int ie = range.Item1 + range.Item2-1;
+                            //double[] locRetArr = retArr;
+                            //for (int i2 = range.Item1; i2 < locRetArr.Length; i2++) {
+                            //    locRetArr[i2] = arrA[i2] - locRetArr[i2];
+                            //    if (i2 >= ie) break; 
+                            //}
+
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((float*)range.Item3 + range.Item1);
+                            bp = ((float*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp++ =   func(*ap++, *bp++);
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((float*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp =   func(*cp, scalar);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((float*)range.Item3 + range.Item1);
+                            scalar = *((float*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp++ =   func(*ap++, scalar);
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((float*)range.Item3);
+                            while (cp < cLast) {
+                               
+                                *cp =   func(scalar, *cp);
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((float*)range.Item3);
+                            bp = ((float*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp++ =   func(scalar, *bp++);
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work 
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                
+                // retStorage.PendingEvents = new System.Threading.CountdownEvent(workItemCount); 
+
+                fixed ( float* arrAP = arrA)
+                fixed ( float* arrBP = arrB)
+                fixed ( float* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range 
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    System.Threading.SpinWait.SpinUntil(() => {
+                        return workerCount <= 0;
+                    });
+                    //while (workerCount > 0) ; 
+                }
+
+                #endregion
+                return new ILRetArray<float>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<float> applyEx(Func<float, float, float> applyFunc, ILInArray<float> A, ILInArray<float> B) {
+            #region parameter checking
+            if (isnull(A) || isnull(B))
+                return empty<float>(ILSize.Empty00);
+            if (A.IsEmpty) {
+                return empty<float>(B.S);
+            } else if (B.IsEmpty) {
+                return empty<float>(A.S);
+            }
+            //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+            //    return add(A,B);
+            int dim = -1;
+            for (int _L = 0; _L < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); _L++) {
+                if (A.S[_L] != B.S[_L]) {
+                    if (dim >= 0 || (A.S[_L] != 1 && B.S[_L] != 1)) {
+                        throw new ILArgumentException("A and B must have the same size except for one singleton dimension in A or B");
+                    }
+                    dim = _L;
+                }
+            }
+            if (dim > 1)
+                throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+            #endregion
+
+            #region parameter preparation
+
+           
+            float[] retArr;
+
+           
+            float[] arrA = A.GetArrayForRead();
+
+           
+            float[] arrB = B.GetArrayForRead();
+            ILSize outDims;
+            BinOptItExMode mode;
+            int arrInc = 0;
+            int arrStepInc = 0;
+            int dimLen = 0;
+            if (A.IsVector) {
+                outDims = B.S;
+                if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<float>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                } else {
+                    mode = BinOptItExMode.VAI;
+                }
+                dimLen = A.Length;
+            } else if (B.IsVector) {
+                outDims = A.S;
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<float>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                } else {
+                    mode = BinOptItExMode.AVI;
+                }
+                dimLen = B.Length;
+            } else {
+                throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+            }
+            arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+            arrStepInc = outDims.SequentialIndexDistance(dim);
+            #endregion
+
+            #region worker loops definition
+            ILDenseStorage<float> retStorage = new ILDenseStorage<float>(retArr, outDims);
+            int workerCount = 1;
+            Action<object> worker = data => {
+                // expects: iStart, iLen, ap, bp, cp
+                Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                    (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+               
+                float* ap;
+               
+                float* bp;
+               
+                float* cp;
+                switch (mode) {
+                    case BinOptItExMode.VAN:
+                        for (int s = 0; s < range.Item2; s++) {
+                            ap = (float*)range.Item3;
+                            bp = (float*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                            cp = (float*)range.Item5 + range.Item1 + s * arrStepInc;
+                            for (int l = 0; l < dimLen; l++) {
+
+                                *cp = applyFunc(*ap, *bp);
+                                ap++;
+                                bp += arrInc;
+                                cp += arrInc;
+                            }
+                        }
+                        break;
+                    case BinOptItExMode.VAI:
+                        for (int s = 0; s < range.Item2; s++) {
+                            ap = (float*)range.Item3;
+                            cp = (float*)range.Item5 + range.Item1 + s * arrStepInc;
+                            for (int l = 0; l < dimLen; l++) {
+
+                                *cp = applyFunc(*ap, *cp);
+                                ap++;
+                                cp += arrInc;
+                            }
+                        }
+                        break;
+                    case BinOptItExMode.AVN:
+                        for (int s = 0; s < range.Item2; s++) {
+                            ap = (float*)range.Item3 + range.Item1 + s * arrStepInc;
+                            bp = (float*)range.Item4;
+                            cp = (float*)range.Item5 + range.Item1 + s * arrStepInc;
+                            for (int l = 0; l < dimLen; l++) {
+
+                                *cp = applyFunc(*ap, *bp);
+                                ap += arrInc;
+                                bp++;
+                                cp += arrInc;
+                            }
+                        }
+                        break;
+                    case BinOptItExMode.AVI:
+                        for (int s = 0; s < range.Item2; s++) {
+                            bp = (float*)range.Item4;
+                            cp = (float*)range.Item5 + range.Item1 + s * arrStepInc;
+                            for (int l = 0; l < dimLen; l++) {
+
+                                *cp = applyFunc(*cp, *bp);
+                                bp++;
+                                cp += arrInc;
+                            }
+                        }
+                        break;
+                }
+                System.Threading.Interlocked.Decrement(ref workerCount);
+            };
+            #endregion
+
+            #region work distribution
+            int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+            int outLen = outDims.NumberOfElements;
+            if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                    workItemLength = outLen / dimLen / workItemCount;
+                    //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                } else {
+                    workItemLength = outLen / dimLen / 2;
+                    workItemCount = 2;
+                }
+            } else {
+                workItemLength = outLen / dimLen;
+                workItemCount = 1;
+            }
+
+            fixed (float* arrAP = arrA)
+            fixed (float* arrBP = arrB)
+            fixed (float* retArrP = retArr) {
+
+                for (; i < workItemCount - 1; i++) {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                        = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                           (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                    System.Threading.Interlocked.Increment(ref workerCount);
+                    ILThreadPool.QueueUserWorkItem(i, worker, range);
+                }
+                // the last (or may the only) chunk is done right here
+                //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                            (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                ILThreadPool.Wait4Workers(ref workerCount);
+            }
+            #endregion
+
+            return new ILRetArray<float>(retStorage);
+        }
+        /// <summary>Apply an arbitrary function to two arrays</summary>
+        /// <param name="func">A function c = f(a,b), which will be applied to elements in A and B</param>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>The combination of A and B. The result and size depends on the inputs:<list type="table">
+        /// <item>
+        ///     <term>size(A) == size(B)</term>
+        ///     <description>Same size as A/B, elementwise combination of A and B.</description>
+        /// </item>
+        /// <item>
+        ///     <term>isscalar(A) || isscalar(B)</term>
+        ///     <description>Same size as A or B, whichever is not a scalar, the scalar value being applied to each element 
+        ///     (i.e. if the non-scalar input is empty, the result is empty).</description>
+        /// </item>
+        /// <item>
+        ///     <term>All other cases</term>
+        ///     <description>If A or B is a colum vector and the other parameter is an array with a matching column length, the vector is used to operate on all columns of the array. 
+        /// Similarly, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length.</description>
+        /// </item>
+        /// </list></returns>
+        /// <remarks><para>The <c>apply</c> function is also implemented for input if e.g. sizes (mxn) and (mx1). 
+        /// In this case the vector argument will be combined to each column, resulting in an (mxn) array. 
+        /// This feature is, however, officiallny not supported.</para></remarks>
+        public unsafe static ILRetArray<fcomplex> apply(Func<fcomplex, fcomplex, fcomplex> func, ILInArray<fcomplex> A, ILInArray<fcomplex> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+               
+                fcomplex[] retArr;
+               
+                fcomplex[] arrA = A.GetArrayForRead();
+               
+                fcomplex[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size;
+                    if (B.IsScalar) {
+
+                        return new ILRetArray<fcomplex>(new fcomplex[1] { func(A.GetValue(0), B.GetValue(0)) }, A.Size);
+                    } else if (B.IsEmpty) {
+                        return ILRetArray<fcomplex>.empty(outDims);
+                    } else {
+                        outLen = outDims.NumberOfElements;
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New<fcomplex>(outLen);
+                            mode = BinOpItMode.SAN;
+                        } else {
+                            mode = BinOpItMode.SAI;
+                        }
+                    }
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return ILRetArray<fcomplex>.empty(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New<fcomplex>(outLen);
+                            mode = BinOpItMode.ASN;
+                        } else {
+                            mode = BinOpItMode.ASI;
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return applyEx(func,A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        if (A.TryGetStorage4InplaceOp(out retArr))
+                            mode = BinOpItMode.AAIA;
+                        else if (B.TryGetStorage4InplaceOp(out retArr)) {
+                            mode = BinOpItMode.AAIB;
+                        } else {
+                            retArr = ILMemoryPool.Pool.New<fcomplex>(outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<fcomplex> retStorage = new ILDenseStorage<fcomplex>(retArr, outDims);
+                int i = 0, workerCount = 1; 
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                   
+                    fcomplex* cLast, cp = (fcomplex*)range.Item5 + range.Item1;
+                   
+                    fcomplex scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           
+                            fcomplex* bp = ((fcomplex*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp =   func(*cp, *bp++);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           
+                            fcomplex* ap = ((fcomplex*)range.Item3 + range.Item1);
+                            while (cp < cLast) {
+
+                                *cp = func(*ap++, *cp);
+                                cp++;
+
+                            }
+                            //ap = ((double*)range.Item3 + range.Item1);
+                            //for (int i2 = range.Item2; i2-- > 0; ) {
+                            //    *(cp + i2) = *(ap + i2) - *(cp + i2);
+                            //}
+                            //int ie = range.Item1 + range.Item2-1;
+                            //double[] locRetArr = retArr;
+                            //for (int i2 = range.Item1; i2 < locRetArr.Length; i2++) {
+                            //    locRetArr[i2] = arrA[i2] - locRetArr[i2];
+                            //    if (i2 >= ie) break; 
+                            //}
+
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((fcomplex*)range.Item3 + range.Item1);
+                            bp = ((fcomplex*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp++ =   func(*ap++, *bp++);
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((fcomplex*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp =   func(*cp, scalar);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((fcomplex*)range.Item3 + range.Item1);
+                            scalar = *((fcomplex*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp++ =   func(*ap++, scalar);
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((fcomplex*)range.Item3);
+                            while (cp < cLast) {
+                               
+                                *cp =   func(scalar, *cp);
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((fcomplex*)range.Item3);
+                            bp = ((fcomplex*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp++ =   func(scalar, *bp++);
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work 
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                
+                // retStorage.PendingEvents = new System.Threading.CountdownEvent(workItemCount); 
+
+                fixed ( fcomplex* arrAP = arrA)
+                fixed ( fcomplex* arrBP = arrB)
+                fixed ( fcomplex* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range 
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    System.Threading.SpinWait.SpinUntil(() => {
+                        return workerCount <= 0;
+                    });
+                    //while (workerCount > 0) ; 
+                }
+
+                #endregion
+                return new ILRetArray<fcomplex>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<fcomplex> applyEx(Func<fcomplex, fcomplex, fcomplex> applyFunc, ILInArray<fcomplex> A, ILInArray<fcomplex> B) {
+            #region parameter checking
+            if (isnull(A) || isnull(B))
+                return empty<fcomplex>(ILSize.Empty00);
+            if (A.IsEmpty) {
+                return empty<fcomplex>(B.S);
+            } else if (B.IsEmpty) {
+                return empty<fcomplex>(A.S);
+            }
+            //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+            //    return add(A,B);
+            int dim = -1;
+            for (int _L = 0; _L < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); _L++) {
+                if (A.S[_L] != B.S[_L]) {
+                    if (dim >= 0 || (A.S[_L] != 1 && B.S[_L] != 1)) {
+                        throw new ILArgumentException("A and B must have the same size except for one singleton dimension in A or B");
+                    }
+                    dim = _L;
+                }
+            }
+            if (dim > 1)
+                throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+            #endregion
+
+            #region parameter preparation
+
+           
+            fcomplex[] retArr;
+
+           
+            fcomplex[] arrA = A.GetArrayForRead();
+
+           
+            fcomplex[] arrB = B.GetArrayForRead();
+            ILSize outDims;
+            BinOptItExMode mode;
+            int arrInc = 0;
+            int arrStepInc = 0;
+            int dimLen = 0;
+            if (A.IsVector) {
+                outDims = B.S;
+                if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<fcomplex>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                } else {
+                    mode = BinOptItExMode.VAI;
+                }
+                dimLen = A.Length;
+            } else if (B.IsVector) {
+                outDims = A.S;
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<fcomplex>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                } else {
+                    mode = BinOptItExMode.AVI;
+                }
+                dimLen = B.Length;
+            } else {
+                throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+            }
+            arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+            arrStepInc = outDims.SequentialIndexDistance(dim);
+            #endregion
+
+            #region worker loops definition
+            ILDenseStorage<fcomplex> retStorage = new ILDenseStorage<fcomplex>(retArr, outDims);
+            int workerCount = 1;
+            Action<object> worker = data => {
+                // expects: iStart, iLen, ap, bp, cp
+                Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                    (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+               
+                fcomplex* ap;
+               
+                fcomplex* bp;
+               
+                fcomplex* cp;
+                switch (mode) {
+                    case BinOptItExMode.VAN:
+                        for (int s = 0; s < range.Item2; s++) {
+                            ap = (fcomplex*)range.Item3;
+                            bp = (fcomplex*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                            cp = (fcomplex*)range.Item5 + range.Item1 + s * arrStepInc;
+                            for (int l = 0; l < dimLen; l++) {
+
+                                *cp = applyFunc(*ap, *bp);
+                                ap++;
+                                bp += arrInc;
+                                cp += arrInc;
+                            }
+                        }
+                        break;
+                    case BinOptItExMode.VAI:
+                        for (int s = 0; s < range.Item2; s++) {
+                            ap = (fcomplex*)range.Item3;
+                            cp = (fcomplex*)range.Item5 + range.Item1 + s * arrStepInc;
+                            for (int l = 0; l < dimLen; l++) {
+
+                                *cp = applyFunc(*ap, *cp);
+                                ap++;
+                                cp += arrInc;
+                            }
+                        }
+                        break;
+                    case BinOptItExMode.AVN:
+                        for (int s = 0; s < range.Item2; s++) {
+                            ap = (fcomplex*)range.Item3 + range.Item1 + s * arrStepInc;
+                            bp = (fcomplex*)range.Item4;
+                            cp = (fcomplex*)range.Item5 + range.Item1 + s * arrStepInc;
+                            for (int l = 0; l < dimLen; l++) {
+
+                                *cp = applyFunc(*ap, *bp);
+                                ap += arrInc;
+                                bp++;
+                                cp += arrInc;
+                            }
+                        }
+                        break;
+                    case BinOptItExMode.AVI:
+                        for (int s = 0; s < range.Item2; s++) {
+                            bp = (fcomplex*)range.Item4;
+                            cp = (fcomplex*)range.Item5 + range.Item1 + s * arrStepInc;
+                            for (int l = 0; l < dimLen; l++) {
+
+                                *cp = applyFunc(*cp, *bp);
+                                bp++;
+                                cp += arrInc;
+                            }
+                        }
+                        break;
+                }
+                System.Threading.Interlocked.Decrement(ref workerCount);
+            };
+            #endregion
+
+            #region work distribution
+            int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+            int outLen = outDims.NumberOfElements;
+            if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                    workItemLength = outLen / dimLen / workItemCount;
+                    //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                } else {
+                    workItemLength = outLen / dimLen / 2;
+                    workItemCount = 2;
+                }
+            } else {
+                workItemLength = outLen / dimLen;
+                workItemCount = 1;
+            }
+
+            fixed (fcomplex* arrAP = arrA)
+            fixed (fcomplex* arrBP = arrB)
+            fixed (fcomplex* retArrP = retArr) {
+
+                for (; i < workItemCount - 1; i++) {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                        = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                           (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                    System.Threading.Interlocked.Increment(ref workerCount);
+                    ILThreadPool.QueueUserWorkItem(i, worker, range);
+                }
+                // the last (or may the only) chunk is done right here
+                //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                            (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                ILThreadPool.Wait4Workers(ref workerCount);
+            }
+            #endregion
+
+            return new ILRetArray<fcomplex>(retStorage);
+        }
+        /// <summary>Apply an arbitrary function to two arrays</summary>
+        /// <param name="func">A function c = f(a,b), which will be applied to elements in A and B</param>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>The combination of A and B. The result and size depends on the inputs:<list type="table">
+        /// <item>
+        ///     <term>size(A) == size(B)</term>
+        ///     <description>Same size as A/B, elementwise combination of A and B.</description>
+        /// </item>
+        /// <item>
+        ///     <term>isscalar(A) || isscalar(B)</term>
+        ///     <description>Same size as A or B, whichever is not a scalar, the scalar value being applied to each element 
+        ///     (i.e. if the non-scalar input is empty, the result is empty).</description>
+        /// </item>
+        /// <item>
+        ///     <term>All other cases</term>
+        ///     <description>If A or B is a colum vector and the other parameter is an array with a matching column length, the vector is used to operate on all columns of the array. 
+        /// Similarly, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length.</description>
+        /// </item>
+        /// </list></returns>
+        /// <remarks><para>The <c>apply</c> function is also implemented for input if e.g. sizes (mxn) and (mx1). 
+        /// In this case the vector argument will be combined to each column, resulting in an (mxn) array. 
+        /// This feature is, however, officiallny not supported.</para></remarks>
+        public unsafe static ILRetArray<complex> apply(Func<complex, complex, complex> func, ILInArray<complex> A, ILInArray<complex> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+               
+                complex[] retArr;
+               
+                complex[] arrA = A.GetArrayForRead();
+               
+                complex[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size;
+                    if (B.IsScalar) {
+
+                        return new ILRetArray<complex>(new complex[1] { func(A.GetValue(0), B.GetValue(0)) }, A.Size);
+                    } else if (B.IsEmpty) {
+                        return ILRetArray<complex>.empty(outDims);
+                    } else {
+                        outLen = outDims.NumberOfElements;
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New<complex>(outLen);
+                            mode = BinOpItMode.SAN;
+                        } else {
+                            mode = BinOpItMode.SAI;
+                        }
+                    }
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return ILRetArray<complex>.empty(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New<complex>(outLen);
+                            mode = BinOpItMode.ASN;
+                        } else {
+                            mode = BinOpItMode.ASI;
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return applyEx(func,A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        if (A.TryGetStorage4InplaceOp(out retArr))
+                            mode = BinOpItMode.AAIA;
+                        else if (B.TryGetStorage4InplaceOp(out retArr)) {
+                            mode = BinOpItMode.AAIB;
+                        } else {
+                            retArr = ILMemoryPool.Pool.New<complex>(outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<complex> retStorage = new ILDenseStorage<complex>(retArr, outDims);
+                int i = 0, workerCount = 1; 
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                   
+                    complex* cLast, cp = (complex*)range.Item5 + range.Item1;
+                   
+                    complex scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           
+                            complex* bp = ((complex*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp =   func(*cp, *bp++);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           
+                            complex* ap = ((complex*)range.Item3 + range.Item1);
+                            while (cp < cLast) {
+
+                                *cp = func(*ap++, *cp);
+                                cp++;
+
+                            }
+                            //ap = ((double*)range.Item3 + range.Item1);
+                            //for (int i2 = range.Item2; i2-- > 0; ) {
+                            //    *(cp + i2) = *(ap + i2) - *(cp + i2);
+                            //}
+                            //int ie = range.Item1 + range.Item2-1;
+                            //double[] locRetArr = retArr;
+                            //for (int i2 = range.Item1; i2 < locRetArr.Length; i2++) {
+                            //    locRetArr[i2] = arrA[i2] - locRetArr[i2];
+                            //    if (i2 >= ie) break; 
+                            //}
+
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((complex*)range.Item3 + range.Item1);
+                            bp = ((complex*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp++ =   func(*ap++, *bp++);
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((complex*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp =   func(*cp, scalar);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((complex*)range.Item3 + range.Item1);
+                            scalar = *((complex*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp++ =   func(*ap++, scalar);
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((complex*)range.Item3);
+                            while (cp < cLast) {
+                               
+                                *cp =   func(scalar, *cp);
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((complex*)range.Item3);
+                            bp = ((complex*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp++ =   func(scalar, *bp++);
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work 
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                
+                // retStorage.PendingEvents = new System.Threading.CountdownEvent(workItemCount); 
+
+                fixed ( complex* arrAP = arrA)
+                fixed ( complex* arrBP = arrB)
+                fixed ( complex* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range 
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    System.Threading.SpinWait.SpinUntil(() => {
+                        return workerCount <= 0;
+                    });
+                    //while (workerCount > 0) ; 
+                }
+
+                #endregion
+                return new ILRetArray<complex>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<complex> applyEx(Func<complex, complex, complex> applyFunc, ILInArray<complex> A, ILInArray<complex> B) {
+            #region parameter checking
+            if (isnull(A) || isnull(B))
+                return empty<complex>(ILSize.Empty00);
+            if (A.IsEmpty) {
+                return empty<complex>(B.S);
+            } else if (B.IsEmpty) {
+                return empty<complex>(A.S);
+            }
+            //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+            //    return add(A,B);
+            int dim = -1;
+            for (int _L = 0; _L < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); _L++) {
+                if (A.S[_L] != B.S[_L]) {
+                    if (dim >= 0 || (A.S[_L] != 1 && B.S[_L] != 1)) {
+                        throw new ILArgumentException("A and B must have the same size except for one singleton dimension in A or B");
+                    }
+                    dim = _L;
+                }
+            }
+            if (dim > 1)
+                throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+            #endregion
+
+            #region parameter preparation
+
+           
+            complex[] retArr;
+
+           
+            complex[] arrA = A.GetArrayForRead();
+
+           
+            complex[] arrB = B.GetArrayForRead();
+            ILSize outDims;
+            BinOptItExMode mode;
+            int arrInc = 0;
+            int arrStepInc = 0;
+            int dimLen = 0;
+            if (A.IsVector) {
+                outDims = B.S;
+                if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<complex>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                } else {
+                    mode = BinOptItExMode.VAI;
+                }
+                dimLen = A.Length;
+            } else if (B.IsVector) {
+                outDims = A.S;
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<complex>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                } else {
+                    mode = BinOptItExMode.AVI;
+                }
+                dimLen = B.Length;
+            } else {
+                throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+            }
+            arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+            arrStepInc = outDims.SequentialIndexDistance(dim);
+            #endregion
+
+            #region worker loops definition
+            ILDenseStorage<complex> retStorage = new ILDenseStorage<complex>(retArr, outDims);
+            int workerCount = 1;
+            Action<object> worker = data => {
+                // expects: iStart, iLen, ap, bp, cp
+                Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                    (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+               
+                complex* ap;
+               
+                complex* bp;
+               
+                complex* cp;
+                switch (mode) {
+                    case BinOptItExMode.VAN:
+                        for (int s = 0; s < range.Item2; s++) {
+                            ap = (complex*)range.Item3;
+                            bp = (complex*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                            cp = (complex*)range.Item5 + range.Item1 + s * arrStepInc;
+                            for (int l = 0; l < dimLen; l++) {
+
+                                *cp = applyFunc(*ap, *bp);
+                                ap++;
+                                bp += arrInc;
+                                cp += arrInc;
+                            }
+                        }
+                        break;
+                    case BinOptItExMode.VAI:
+                        for (int s = 0; s < range.Item2; s++) {
+                            ap = (complex*)range.Item3;
+                            cp = (complex*)range.Item5 + range.Item1 + s * arrStepInc;
+                            for (int l = 0; l < dimLen; l++) {
+
+                                *cp = applyFunc(*ap, *cp);
+                                ap++;
+                                cp += arrInc;
+                            }
+                        }
+                        break;
+                    case BinOptItExMode.AVN:
+                        for (int s = 0; s < range.Item2; s++) {
+                            ap = (complex*)range.Item3 + range.Item1 + s * arrStepInc;
+                            bp = (complex*)range.Item4;
+                            cp = (complex*)range.Item5 + range.Item1 + s * arrStepInc;
+                            for (int l = 0; l < dimLen; l++) {
+
+                                *cp = applyFunc(*ap, *bp);
+                                ap += arrInc;
+                                bp++;
+                                cp += arrInc;
+                            }
+                        }
+                        break;
+                    case BinOptItExMode.AVI:
+                        for (int s = 0; s < range.Item2; s++) {
+                            bp = (complex*)range.Item4;
+                            cp = (complex*)range.Item5 + range.Item1 + s * arrStepInc;
+                            for (int l = 0; l < dimLen; l++) {
+
+                                *cp = applyFunc(*cp, *bp);
+                                bp++;
+                                cp += arrInc;
+                            }
+                        }
+                        break;
+                }
+                System.Threading.Interlocked.Decrement(ref workerCount);
+            };
+            #endregion
+
+            #region work distribution
+            int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+            int outLen = outDims.NumberOfElements;
+            if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                    workItemLength = outLen / dimLen / workItemCount;
+                    //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                } else {
+                    workItemLength = outLen / dimLen / 2;
+                    workItemCount = 2;
+                }
+            } else {
+                workItemLength = outLen / dimLen;
+                workItemCount = 1;
+            }
+
+            fixed (complex* arrAP = arrA)
+            fixed (complex* arrBP = arrB)
+            fixed (complex* retArrP = retArr) {
+
+                for (; i < workItemCount - 1; i++) {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                        = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                           (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                    System.Threading.Interlocked.Increment(ref workerCount);
+                    ILThreadPool.QueueUserWorkItem(i, worker, range);
+                }
+                // the last (or may the only) chunk is done right here
+                //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                            (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                ILThreadPool.Wait4Workers(ref workerCount);
+            }
+            #endregion
+
+            return new ILRetArray<complex>(retStorage);
+        }
+        /// <summary>Apply an arbitrary function to two arrays</summary>
+        /// <param name="func">A function c = f(a,b), which will be applied to elements in A and B</param>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>The combination of A and B. The result and size depends on the inputs:<list type="table">
+        /// <item>
+        ///     <term>size(A) == size(B)</term>
+        ///     <description>Same size as A/B, elementwise combination of A and B.</description>
+        /// </item>
+        /// <item>
+        ///     <term>isscalar(A) || isscalar(B)</term>
+        ///     <description>Same size as A or B, whichever is not a scalar, the scalar value being applied to each element 
+        ///     (i.e. if the non-scalar input is empty, the result is empty).</description>
+        /// </item>
+        /// <item>
+        ///     <term>All other cases</term>
+        ///     <description>If A or B is a colum vector and the other parameter is an array with a matching column length, the vector is used to operate on all columns of the array. 
+        /// Similarly, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length.</description>
+        /// </item>
+        /// </list></returns>
+        /// <remarks><para>The <c>apply</c> function is also implemented for input if e.g. sizes (mxn) and (mx1). 
+        /// In this case the vector argument will be combined to each column, resulting in an (mxn) array. 
+        /// This feature is, however, officiallny not supported.</para></remarks>
+        public unsafe static ILRetArray<Int64> apply(Func<Int64, Int64, Int64> func, ILInArray<Int64> A, ILInArray<Int64> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+               
+                Int64[] retArr;
+               
+                Int64[] arrA = A.GetArrayForRead();
+               
+                Int64[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size;
+                    if (B.IsScalar) {
+
+                        return new ILRetArray<Int64>(new Int64[1] { func(A.GetValue(0), B.GetValue(0)) }, A.Size);
+                    } else if (B.IsEmpty) {
+                        return ILRetArray<Int64>.empty(outDims);
+                    } else {
+                        outLen = outDims.NumberOfElements;
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New<Int64>(outLen);
+                            mode = BinOpItMode.SAN;
+                        } else {
+                            mode = BinOpItMode.SAI;
+                        }
+                    }
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return ILRetArray<Int64>.empty(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New<Int64>(outLen);
+                            mode = BinOpItMode.ASN;
+                        } else {
+                            mode = BinOpItMode.ASI;
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return applyEx(func,A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        if (A.TryGetStorage4InplaceOp(out retArr))
+                            mode = BinOpItMode.AAIA;
+                        else if (B.TryGetStorage4InplaceOp(out retArr)) {
+                            mode = BinOpItMode.AAIB;
+                        } else {
+                            retArr = ILMemoryPool.Pool.New<Int64>(outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<Int64> retStorage = new ILDenseStorage<Int64>(retArr, outDims);
+                int i = 0, workerCount = 1; 
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                   
+                    Int64* cLast, cp = (Int64*)range.Item5 + range.Item1;
+                   
+                    Int64 scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           
+                            Int64* bp = ((Int64*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp =   func(*cp, *bp++);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           
+                            Int64* ap = ((Int64*)range.Item3 + range.Item1);
+                            while (cp < cLast) {
+
+                                *cp = func(*ap++, *cp);
+                                cp++;
+
+                            }
+                            //ap = ((double*)range.Item3 + range.Item1);
+                            //for (int i2 = range.Item2; i2-- > 0; ) {
+                            //    *(cp + i2) = *(ap + i2) - *(cp + i2);
+                            //}
+                            //int ie = range.Item1 + range.Item2-1;
+                            //double[] locRetArr = retArr;
+                            //for (int i2 = range.Item1; i2 < locRetArr.Length; i2++) {
+                            //    locRetArr[i2] = arrA[i2] - locRetArr[i2];
+                            //    if (i2 >= ie) break; 
+                            //}
+
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((Int64*)range.Item3 + range.Item1);
+                            bp = ((Int64*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp++ =   func(*ap++, *bp++);
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((Int64*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp =   func(*cp, scalar);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((Int64*)range.Item3 + range.Item1);
+                            scalar = *((Int64*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp++ =   func(*ap++, scalar);
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((Int64*)range.Item3);
+                            while (cp < cLast) {
+                               
+                                *cp =   func(scalar, *cp);
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((Int64*)range.Item3);
+                            bp = ((Int64*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp++ =   func(scalar, *bp++);
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work 
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                
+                // retStorage.PendingEvents = new System.Threading.CountdownEvent(workItemCount); 
+
+                fixed ( Int64* arrAP = arrA)
+                fixed ( Int64* arrBP = arrB)
+                fixed ( Int64* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range 
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    System.Threading.SpinWait.SpinUntil(() => {
+                        return workerCount <= 0;
+                    });
+                    //while (workerCount > 0) ; 
+                }
+
+                #endregion
+                return new ILRetArray<Int64>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<Int64> applyEx(Func<Int64, Int64, Int64> applyFunc, ILInArray<Int64> A, ILInArray<Int64> B) {
+            #region parameter checking
+            if (isnull(A) || isnull(B))
+                return empty<Int64>(ILSize.Empty00);
+            if (A.IsEmpty) {
+                return empty<Int64>(B.S);
+            } else if (B.IsEmpty) {
+                return empty<Int64>(A.S);
+            }
+            //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+            //    return add(A,B);
+            int dim = -1;
+            for (int _L = 0; _L < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); _L++) {
+                if (A.S[_L] != B.S[_L]) {
+                    if (dim >= 0 || (A.S[_L] != 1 && B.S[_L] != 1)) {
+                        throw new ILArgumentException("A and B must have the same size except for one singleton dimension in A or B");
+                    }
+                    dim = _L;
+                }
+            }
+            if (dim > 1)
+                throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+            #endregion
+
+            #region parameter preparation
+
+           
+            Int64[] retArr;
+
+           
+            Int64[] arrA = A.GetArrayForRead();
+
+           
+            Int64[] arrB = B.GetArrayForRead();
+            ILSize outDims;
+            BinOptItExMode mode;
+            int arrInc = 0;
+            int arrStepInc = 0;
+            int dimLen = 0;
+            if (A.IsVector) {
+                outDims = B.S;
+                if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<Int64>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                } else {
+                    mode = BinOptItExMode.VAI;
+                }
+                dimLen = A.Length;
+            } else if (B.IsVector) {
+                outDims = A.S;
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<Int64>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                } else {
+                    mode = BinOptItExMode.AVI;
+                }
+                dimLen = B.Length;
+            } else {
+                throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+            }
+            arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+            arrStepInc = outDims.SequentialIndexDistance(dim);
+            #endregion
+
+            #region worker loops definition
+            ILDenseStorage<Int64> retStorage = new ILDenseStorage<Int64>(retArr, outDims);
+            int workerCount = 1;
+            Action<object> worker = data => {
+                // expects: iStart, iLen, ap, bp, cp
+                Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                    (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+               
+                Int64* ap;
+               
+                Int64* bp;
+               
+                Int64* cp;
+                switch (mode) {
+                    case BinOptItExMode.VAN:
+                        for (int s = 0; s < range.Item2; s++) {
+                            ap = (Int64*)range.Item3;
+                            bp = (Int64*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                            cp = (Int64*)range.Item5 + range.Item1 + s * arrStepInc;
+                            for (int l = 0; l < dimLen; l++) {
+
+                                *cp = applyFunc(*ap, *bp);
+                                ap++;
+                                bp += arrInc;
+                                cp += arrInc;
+                            }
+                        }
+                        break;
+                    case BinOptItExMode.VAI:
+                        for (int s = 0; s < range.Item2; s++) {
+                            ap = (Int64*)range.Item3;
+                            cp = (Int64*)range.Item5 + range.Item1 + s * arrStepInc;
+                            for (int l = 0; l < dimLen; l++) {
+
+                                *cp = applyFunc(*ap, *cp);
+                                ap++;
+                                cp += arrInc;
+                            }
+                        }
+                        break;
+                    case BinOptItExMode.AVN:
+                        for (int s = 0; s < range.Item2; s++) {
+                            ap = (Int64*)range.Item3 + range.Item1 + s * arrStepInc;
+                            bp = (Int64*)range.Item4;
+                            cp = (Int64*)range.Item5 + range.Item1 + s * arrStepInc;
+                            for (int l = 0; l < dimLen; l++) {
+
+                                *cp = applyFunc(*ap, *bp);
+                                ap += arrInc;
+                                bp++;
+                                cp += arrInc;
+                            }
+                        }
+                        break;
+                    case BinOptItExMode.AVI:
+                        for (int s = 0; s < range.Item2; s++) {
+                            bp = (Int64*)range.Item4;
+                            cp = (Int64*)range.Item5 + range.Item1 + s * arrStepInc;
+                            for (int l = 0; l < dimLen; l++) {
+
+                                *cp = applyFunc(*cp, *bp);
+                                bp++;
+                                cp += arrInc;
+                            }
+                        }
+                        break;
+                }
+                System.Threading.Interlocked.Decrement(ref workerCount);
+            };
+            #endregion
+
+            #region work distribution
+            int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+            int outLen = outDims.NumberOfElements;
+            if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                    workItemLength = outLen / dimLen / workItemCount;
+                    //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                } else {
+                    workItemLength = outLen / dimLen / 2;
+                    workItemCount = 2;
+                }
+            } else {
+                workItemLength = outLen / dimLen;
+                workItemCount = 1;
+            }
+
+            fixed (Int64* arrAP = arrA)
+            fixed (Int64* arrBP = arrB)
+            fixed (Int64* retArrP = retArr) {
+
+                for (; i < workItemCount - 1; i++) {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                        = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                           (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                    System.Threading.Interlocked.Increment(ref workerCount);
+                    ILThreadPool.QueueUserWorkItem(i, worker, range);
+                }
+                // the last (or may the only) chunk is done right here
+                //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                            (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                ILThreadPool.Wait4Workers(ref workerCount);
+            }
+            #endregion
+
+            return new ILRetArray<Int64>(retStorage);
+        }
+        /// <summary>Apply an arbitrary function to two arrays</summary>
+        /// <param name="func">A function c = f(a,b), which will be applied to elements in A and B</param>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>The combination of A and B. The result and size depends on the inputs:<list type="table">
+        /// <item>
+        ///     <term>size(A) == size(B)</term>
+        ///     <description>Same size as A/B, elementwise combination of A and B.</description>
+        /// </item>
+        /// <item>
+        ///     <term>isscalar(A) || isscalar(B)</term>
+        ///     <description>Same size as A or B, whichever is not a scalar, the scalar value being applied to each element 
+        ///     (i.e. if the non-scalar input is empty, the result is empty).</description>
+        /// </item>
+        /// <item>
+        ///     <term>All other cases</term>
+        ///     <description>If A or B is a colum vector and the other parameter is an array with a matching column length, the vector is used to operate on all columns of the array. 
+        /// Similarly, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length.</description>
+        /// </item>
+        /// </list></returns>
+        /// <remarks><para>The <c>apply</c> function is also implemented for input if e.g. sizes (mxn) and (mx1). 
+        /// In this case the vector argument will be combined to each column, resulting in an (mxn) array. 
+        /// This feature is, however, officiallny not supported.</para></remarks>
+        public unsafe static ILRetArray<Int32> apply(Func<Int32, Int32, Int32> func, ILInArray<Int32> A, ILInArray<Int32> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+               
+                Int32[] retArr;
+               
+                Int32[] arrA = A.GetArrayForRead();
+               
+                Int32[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size;
+                    if (B.IsScalar) {
+
+                        return new ILRetArray<Int32>(new Int32[1] { func(A.GetValue(0), B.GetValue(0)) }, A.Size);
+                    } else if (B.IsEmpty) {
+                        return ILRetArray<Int32>.empty(outDims);
+                    } else {
+                        outLen = outDims.NumberOfElements;
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New<Int32>(outLen);
+                            mode = BinOpItMode.SAN;
+                        } else {
+                            mode = BinOpItMode.SAI;
+                        }
+                    }
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return ILRetArray<Int32>.empty(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New<Int32>(outLen);
+                            mode = BinOpItMode.ASN;
+                        } else {
+                            mode = BinOpItMode.ASI;
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return applyEx(func,A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        if (A.TryGetStorage4InplaceOp(out retArr))
+                            mode = BinOpItMode.AAIA;
+                        else if (B.TryGetStorage4InplaceOp(out retArr)) {
+                            mode = BinOpItMode.AAIB;
+                        } else {
+                            retArr = ILMemoryPool.Pool.New<Int32>(outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<Int32> retStorage = new ILDenseStorage<Int32>(retArr, outDims);
+                int i = 0, workerCount = 1; 
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                   
+                    Int32* cLast, cp = (Int32*)range.Item5 + range.Item1;
+                   
+                    Int32 scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           
+                            Int32* bp = ((Int32*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp =   func(*cp, *bp++);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           
+                            Int32* ap = ((Int32*)range.Item3 + range.Item1);
+                            while (cp < cLast) {
+
+                                *cp = func(*ap++, *cp);
+                                cp++;
+
+                            }
+                            //ap = ((double*)range.Item3 + range.Item1);
+                            //for (int i2 = range.Item2; i2-- > 0; ) {
+                            //    *(cp + i2) = *(ap + i2) - *(cp + i2);
+                            //}
+                            //int ie = range.Item1 + range.Item2-1;
+                            //double[] locRetArr = retArr;
+                            //for (int i2 = range.Item1; i2 < locRetArr.Length; i2++) {
+                            //    locRetArr[i2] = arrA[i2] - locRetArr[i2];
+                            //    if (i2 >= ie) break; 
+                            //}
+
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((Int32*)range.Item3 + range.Item1);
+                            bp = ((Int32*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp++ =   func(*ap++, *bp++);
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((Int32*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp =   func(*cp, scalar);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((Int32*)range.Item3 + range.Item1);
+                            scalar = *((Int32*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp++ =   func(*ap++, scalar);
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((Int32*)range.Item3);
+                            while (cp < cLast) {
+                               
+                                *cp =   func(scalar, *cp);
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((Int32*)range.Item3);
+                            bp = ((Int32*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp++ =   func(scalar, *bp++);
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work 
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                
+                // retStorage.PendingEvents = new System.Threading.CountdownEvent(workItemCount); 
+
+                fixed ( Int32* arrAP = arrA)
+                fixed ( Int32* arrBP = arrB)
+                fixed ( Int32* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range 
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    System.Threading.SpinWait.SpinUntil(() => {
+                        return workerCount <= 0;
+                    });
+                    //while (workerCount > 0) ; 
+                }
+
+                #endregion
+                return new ILRetArray<Int32>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<Int32> applyEx(Func<Int32, Int32, Int32> applyFunc, ILInArray<Int32> A, ILInArray<Int32> B) {
+            #region parameter checking
+            if (isnull(A) || isnull(B))
+                return empty<Int32>(ILSize.Empty00);
+            if (A.IsEmpty) {
+                return empty<Int32>(B.S);
+            } else if (B.IsEmpty) {
+                return empty<Int32>(A.S);
+            }
+            //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+            //    return add(A,B);
+            int dim = -1;
+            for (int _L = 0; _L < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); _L++) {
+                if (A.S[_L] != B.S[_L]) {
+                    if (dim >= 0 || (A.S[_L] != 1 && B.S[_L] != 1)) {
+                        throw new ILArgumentException("A and B must have the same size except for one singleton dimension in A or B");
+                    }
+                    dim = _L;
+                }
+            }
+            if (dim > 1)
+                throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+            #endregion
+
+            #region parameter preparation
+
+           
+            Int32[] retArr;
+
+           
+            Int32[] arrA = A.GetArrayForRead();
+
+           
+            Int32[] arrB = B.GetArrayForRead();
+            ILSize outDims;
+            BinOptItExMode mode;
+            int arrInc = 0;
+            int arrStepInc = 0;
+            int dimLen = 0;
+            if (A.IsVector) {
+                outDims = B.S;
+                if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<Int32>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                } else {
+                    mode = BinOptItExMode.VAI;
+                }
+                dimLen = A.Length;
+            } else if (B.IsVector) {
+                outDims = A.S;
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<Int32>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                } else {
+                    mode = BinOptItExMode.AVI;
+                }
+                dimLen = B.Length;
+            } else {
+                throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+            }
+            arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+            arrStepInc = outDims.SequentialIndexDistance(dim);
+            #endregion
+
+            #region worker loops definition
+            ILDenseStorage<Int32> retStorage = new ILDenseStorage<Int32>(retArr, outDims);
+            int workerCount = 1;
+            Action<object> worker = data => {
+                // expects: iStart, iLen, ap, bp, cp
+                Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                    (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+               
+                Int32* ap;
+               
+                Int32* bp;
+               
+                Int32* cp;
+                switch (mode) {
+                    case BinOptItExMode.VAN:
+                        for (int s = 0; s < range.Item2; s++) {
+                            ap = (Int32*)range.Item3;
+                            bp = (Int32*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                            cp = (Int32*)range.Item5 + range.Item1 + s * arrStepInc;
+                            for (int l = 0; l < dimLen; l++) {
+
+                                *cp = applyFunc(*ap, *bp);
+                                ap++;
+                                bp += arrInc;
+                                cp += arrInc;
+                            }
+                        }
+                        break;
+                    case BinOptItExMode.VAI:
+                        for (int s = 0; s < range.Item2; s++) {
+                            ap = (Int32*)range.Item3;
+                            cp = (Int32*)range.Item5 + range.Item1 + s * arrStepInc;
+                            for (int l = 0; l < dimLen; l++) {
+
+                                *cp = applyFunc(*ap, *cp);
+                                ap++;
+                                cp += arrInc;
+                            }
+                        }
+                        break;
+                    case BinOptItExMode.AVN:
+                        for (int s = 0; s < range.Item2; s++) {
+                            ap = (Int32*)range.Item3 + range.Item1 + s * arrStepInc;
+                            bp = (Int32*)range.Item4;
+                            cp = (Int32*)range.Item5 + range.Item1 + s * arrStepInc;
+                            for (int l = 0; l < dimLen; l++) {
+
+                                *cp = applyFunc(*ap, *bp);
+                                ap += arrInc;
+                                bp++;
+                                cp += arrInc;
+                            }
+                        }
+                        break;
+                    case BinOptItExMode.AVI:
+                        for (int s = 0; s < range.Item2; s++) {
+                            bp = (Int32*)range.Item4;
+                            cp = (Int32*)range.Item5 + range.Item1 + s * arrStepInc;
+                            for (int l = 0; l < dimLen; l++) {
+
+                                *cp = applyFunc(*cp, *bp);
+                                bp++;
+                                cp += arrInc;
+                            }
+                        }
+                        break;
+                }
+                System.Threading.Interlocked.Decrement(ref workerCount);
+            };
+            #endregion
+
+            #region work distribution
+            int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+            int outLen = outDims.NumberOfElements;
+            if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                    workItemLength = outLen / dimLen / workItemCount;
+                    //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                } else {
+                    workItemLength = outLen / dimLen / 2;
+                    workItemCount = 2;
+                }
+            } else {
+                workItemLength = outLen / dimLen;
+                workItemCount = 1;
+            }
+
+            fixed (Int32* arrAP = arrA)
+            fixed (Int32* arrBP = arrB)
+            fixed (Int32* retArrP = retArr) {
+
+                for (; i < workItemCount - 1; i++) {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                        = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                           (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                    System.Threading.Interlocked.Increment(ref workerCount);
+                    ILThreadPool.QueueUserWorkItem(i, worker, range);
+                }
+                // the last (or may the only) chunk is done right here
+                //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                            (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                ILThreadPool.Wait4Workers(ref workerCount);
+            }
+            #endregion
+
+            return new ILRetArray<Int32>(retStorage);
+        }
+        /// <summary>Apply an arbitrary function to two arrays</summary>
+        /// <param name="func">A function c = f(a,b), which will be applied to elements in A and B</param>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>The combination of A and B. The result and size depends on the inputs:<list type="table">
+        /// <item>
+        ///     <term>size(A) == size(B)</term>
+        ///     <description>Same size as A/B, elementwise combination of A and B.</description>
+        /// </item>
+        /// <item>
+        ///     <term>isscalar(A) || isscalar(B)</term>
+        ///     <description>Same size as A or B, whichever is not a scalar, the scalar value being applied to each element 
+        ///     (i.e. if the non-scalar input is empty, the result is empty).</description>
+        /// </item>
+        /// <item>
+        ///     <term>All other cases</term>
+        ///     <description>If A or B is a colum vector and the other parameter is an array with a matching column length, the vector is used to operate on all columns of the array. 
+        /// Similarly, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length.</description>
+        /// </item>
+        /// </list></returns>
+        /// <remarks><para>The <c>apply</c> function is also implemented for input if e.g. sizes (mxn) and (mx1). 
+        /// In this case the vector argument will be combined to each column, resulting in an (mxn) array. 
+        /// This feature is, however, officiallny not supported.</para></remarks>
+        public unsafe static ILRetArray<byte> apply(Func<byte, byte, byte> func, ILInArray<byte> A, ILInArray<byte> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+               
+                byte[] retArr;
+               
+                byte[] arrA = A.GetArrayForRead();
+               
+                byte[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size;
+                    if (B.IsScalar) {
+
+                        return new ILRetArray<byte>(new byte[1] { func(A.GetValue(0), B.GetValue(0)) }, A.Size);
+                    } else if (B.IsEmpty) {
+                        return ILRetArray<byte>.empty(outDims);
+                    } else {
+                        outLen = outDims.NumberOfElements;
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                            mode = BinOpItMode.SAN;
+                        } else {
+                            mode = BinOpItMode.SAI;
+                        }
+                    }
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return ILRetArray<byte>.empty(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                            mode = BinOpItMode.ASN;
+                        } else {
+                            mode = BinOpItMode.ASI;
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return applyEx(func,A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        if (A.TryGetStorage4InplaceOp(out retArr))
+                            mode = BinOpItMode.AAIA;
+                        else if (B.TryGetStorage4InplaceOp(out retArr)) {
+                            mode = BinOpItMode.AAIB;
+                        } else {
+                            retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<byte> retStorage = new ILDenseStorage<byte>(retArr, outDims);
+                int i = 0, workerCount = 1; 
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                   
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                   
+                    byte scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           
+                            byte* bp = ((byte*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp =   func(*cp, *bp++);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           
+                            byte* ap = ((byte*)range.Item3 + range.Item1);
+                            while (cp < cLast) {
+
+                                *cp = func(*ap++, *cp);
+                                cp++;
+
+                            }
+                            //ap = ((double*)range.Item3 + range.Item1);
+                            //for (int i2 = range.Item2; i2-- > 0; ) {
+                            //    *(cp + i2) = *(ap + i2) - *(cp + i2);
+                            //}
+                            //int ie = range.Item1 + range.Item2-1;
+                            //double[] locRetArr = retArr;
+                            //for (int i2 = range.Item1; i2 < locRetArr.Length; i2++) {
+                            //    locRetArr[i2] = arrA[i2] - locRetArr[i2];
+                            //    if (i2 >= ie) break; 
+                            //}
+
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((byte*)range.Item3 + range.Item1);
+                            bp = ((byte*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp++ =   func(*ap++, *bp++);
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((byte*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp =   func(*cp, scalar);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((byte*)range.Item3 + range.Item1);
+                            scalar = *((byte*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp++ =   func(*ap++, scalar);
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((byte*)range.Item3);
+                            while (cp < cLast) {
+                               
+                                *cp =   func(scalar, *cp);
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((byte*)range.Item3);
+                            bp = ((byte*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp++ =   func(scalar, *bp++);
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work 
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                
+                // retStorage.PendingEvents = new System.Threading.CountdownEvent(workItemCount); 
+
+                fixed ( byte* arrAP = arrA)
+                fixed ( byte* arrBP = arrB)
+                fixed ( byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range 
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    System.Threading.SpinWait.SpinUntil(() => {
+                        return workerCount <= 0;
+                    });
+                    //while (workerCount > 0) ; 
+                }
+
+                #endregion
+                return new ILRetArray<byte>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<byte> applyEx(Func<byte, byte, byte> applyFunc, ILInArray<byte> A, ILInArray<byte> B) {
+            #region parameter checking
+            if (isnull(A) || isnull(B))
+                return empty<byte>(ILSize.Empty00);
+            if (A.IsEmpty) {
+                return empty<byte>(B.S);
+            } else if (B.IsEmpty) {
+                return empty<byte>(A.S);
+            }
+            //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+            //    return add(A,B);
+            int dim = -1;
+            for (int _L = 0; _L < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); _L++) {
+                if (A.S[_L] != B.S[_L]) {
+                    if (dim >= 0 || (A.S[_L] != 1 && B.S[_L] != 1)) {
+                        throw new ILArgumentException("A and B must have the same size except for one singleton dimension in A or B");
+                    }
+                    dim = _L;
+                }
+            }
+            if (dim > 1)
+                throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+            #endregion
+
+            #region parameter preparation
+
+           
+            byte[] retArr;
+
+           
+            byte[] arrA = A.GetArrayForRead();
+
+           
+            byte[] arrB = B.GetArrayForRead();
+            ILSize outDims;
+            BinOptItExMode mode;
+            int arrInc = 0;
+            int arrStepInc = 0;
+            int dimLen = 0;
+            if (A.IsVector) {
+                outDims = B.S;
+                if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                } else {
+                    mode = BinOptItExMode.VAI;
+                }
+                dimLen = A.Length;
+            } else if (B.IsVector) {
+                outDims = A.S;
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                } else {
+                    mode = BinOptItExMode.AVI;
+                }
+                dimLen = B.Length;
+            } else {
+                throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+            }
+            arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+            arrStepInc = outDims.SequentialIndexDistance(dim);
+            #endregion
+
+            #region worker loops definition
+            ILDenseStorage<byte> retStorage = new ILDenseStorage<byte>(retArr, outDims);
+            int workerCount = 1;
+            Action<object> worker = data => {
+                // expects: iStart, iLen, ap, bp, cp
+                Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                    (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+               
+                byte* ap;
+               
+                byte* bp;
+               
+                byte* cp;
+                switch (mode) {
+                    case BinOptItExMode.VAN:
+                        for (int s = 0; s < range.Item2; s++) {
+                            ap = (byte*)range.Item3;
+                            bp = (byte*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                            cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                            for (int l = 0; l < dimLen; l++) {
+
+                                *cp = applyFunc(*ap, *bp);
+                                ap++;
+                                bp += arrInc;
+                                cp += arrInc;
+                            }
+                        }
+                        break;
+                    case BinOptItExMode.VAI:
+                        for (int s = 0; s < range.Item2; s++) {
+                            ap = (byte*)range.Item3;
+                            cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                            for (int l = 0; l < dimLen; l++) {
+
+                                *cp = applyFunc(*ap, *cp);
+                                ap++;
+                                cp += arrInc;
+                            }
+                        }
+                        break;
+                    case BinOptItExMode.AVN:
+                        for (int s = 0; s < range.Item2; s++) {
+                            ap = (byte*)range.Item3 + range.Item1 + s * arrStepInc;
+                            bp = (byte*)range.Item4;
+                            cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                            for (int l = 0; l < dimLen; l++) {
+
+                                *cp = applyFunc(*ap, *bp);
+                                ap += arrInc;
+                                bp++;
+                                cp += arrInc;
+                            }
+                        }
+                        break;
+                    case BinOptItExMode.AVI:
+                        for (int s = 0; s < range.Item2; s++) {
+                            bp = (byte*)range.Item4;
+                            cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                            for (int l = 0; l < dimLen; l++) {
+
+                                *cp = applyFunc(*cp, *bp);
+                                bp++;
+                                cp += arrInc;
+                            }
+                        }
+                        break;
+                }
+                System.Threading.Interlocked.Decrement(ref workerCount);
+            };
+            #endregion
+
+            #region work distribution
+            int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+            int outLen = outDims.NumberOfElements;
+            if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                    workItemLength = outLen / dimLen / workItemCount;
+                    //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                } else {
+                    workItemLength = outLen / dimLen / 2;
+                    workItemCount = 2;
+                }
+            } else {
+                workItemLength = outLen / dimLen;
+                workItemCount = 1;
+            }
+
+            fixed (byte* arrAP = arrA)
+            fixed (byte* arrBP = arrB)
+            fixed (byte* retArrP = retArr) {
+
+                for (; i < workItemCount - 1; i++) {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                        = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                           (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                    System.Threading.Interlocked.Increment(ref workerCount);
+                    ILThreadPool.QueueUserWorkItem(i, worker, range);
+                }
+                // the last (or may the only) chunk is done right here
+                //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                            (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                ILThreadPool.Wait4Workers(ref workerCount);
+            }
+            #endregion
+
+            return new ILRetArray<byte>(retStorage);
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/array.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/array.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/array.cs	(revision 9102)
@@ -0,0 +1,205 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.InteropServices; 
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Native;
+using ILNumerics.Exceptions;
+
+namespace ILNumerics {
+
+    public partial class ILMath {
+
+        /// <summary>
+        /// Create new array, fill elements with constant value
+        /// </summary>
+        /// <typeparam name="T">Element type</typeparam>
+        /// <param name="value">Constant value for all elements</param>
+        /// <param name="size">Size of new array</param>
+        /// <returns>New array according to size with all elements set to 'value'</returns>
+        public static ILRetArray<T> array<T>(T value, ILSize size) {
+            T[] newData = ILMemoryPool.Pool.New<T>(size.NumberOfElements);
+            int i = 0, itemLength, itemCount, workerCount = 1;
+            if (Settings.s_maxNumberThreads > 2 &&
+                size.NumberOfElements >= ILNumerics.Settings.s_minParallelElement1Count / 2) {
+                if (size.NumberOfElements >= ILNumerics.Settings.s_minParallelElement1Count / Settings.s_maxNumberThreads) {
+                    itemCount = Settings.s_maxNumberThreads;
+                    itemLength = size.NumberOfElements / Settings.s_maxNumberThreads;
+                } else {
+                    itemCount = 2;
+                    itemLength = size.NumberOfElements / 2;
+                }
+            } else {
+                itemCount = 1;
+                itemLength = size.NumberOfElements;
+            }
+            Action<object> worker = (data) => {
+                Tuple<int, int> range = (Tuple<int, int>)data;
+                int start = range.Item1, endEx = range.Item2;
+                for (int c = start; c < endEx; c++) {
+                    newData[c] = value;
+                }
+                System.Threading.Interlocked.Decrement(ref workerCount);
+            };
+            for (i = 0; i < workerCount - 1; i++) {
+                System.Threading.Interlocked.Increment(ref workerCount);
+                Tuple<int, int> range = Tuple.Create(i * itemLength, (i + 1) * itemLength);
+                ILThreadPool.QueueUserWorkItem(i, worker, range);
+            }
+            worker(Tuple.Create(i * itemLength, size.NumberOfElements));
+            System.Threading.SpinWait.SpinUntil(() => { return workerCount <= 0; });
+            ILRetArray<T> ret = new ILRetArray<T>(newData, size);
+            return ret;
+        }
+        /// <summary>
+        /// Create new array, fill element with constant value
+        /// </summary>
+        /// <typeparam name="T">Element type</typeparam>
+        /// <param name="value">Constant value for all elements</param>
+        /// <param name="size">Size of new array</param>
+        /// <returns>New array according to size with all elements set to 'value'</returns>
+        public static ILRetArray<T> array<T>(T value, params int[] size) {
+            return array<T>(value, new ILSize(size));
+        }
+        /// <summary>
+        /// Create array, given elements and size
+        /// </summary>
+        /// <typeparam name="T">Element type</typeparam>
+        /// <param name="elements">System.Array of predefined elements</param>
+        /// <param name="size">Size of every dimension for the new array, must correspond to the number of elements in <paramref name="elements"/>.</param>
+        /// <returns>Newly created array</returns>
+        /// <remarks><para>The System.Array given as <paramref name="elements"/>is taken 
+        /// as storage for the new array without copy. Make sure not to reference that 
+        /// System.Array directly afterwards.</para>
+        /// <para>In order to prevent for memory leaks on long runnning algorithms, <c>System.Array</c>s should 
+        /// not get created via the 'new' keyword - but fetched from the ILMemoryPool. </para></remarks>
+        public static ILRetArray<T> array<T>(T[] elements, params int[] size) {
+            ILSize newDimensions = new ILSize(size);
+            ILRetArray<T> ret = new ILRetArray<T>(elements, newDimensions);
+            return ret;
+        }
+        /// <summary>
+        /// Create array, given elements and size
+        /// </summary>
+        /// <typeparam name="T">Element type</typeparam>
+        /// <param name="elements">System.Array of predefined elements</param>
+        /// <param name="size">Size of the new array, must correspond to the number of elements in <paramref name="elements"/>.</param>
+        /// <returns>Newly created array</returns>
+        /// <remarks><para>The System.Array given as <paramref name="elements"/>is taken 
+        /// as storage for the new array without copy. Make sure not to reference that 
+        /// System.Array directly afterwards.</para>
+        /// <para>In order to prevent for memory leaks on long runnning algorithms, <c>System.Array</c>s should 
+        /// not get created via the 'new' keyword - but fetched from the ILMemoryPool. 
+        /// </para></remarks>
+        public static ILRetArray<T> array<T>(T[] elements, ILSize size) {
+            ILRetArray<T> ret = new ILRetArray<T>(elements, size);
+            return ret;
+        }
+        /// <summary>
+        /// Create array, given elements and size
+        /// </summary>
+        /// <typeparam name="T">Element type</typeparam>
+        /// <param name="elements">Variable argument list with elements</param>
+        /// <param name="size">Size of the new array, must correspond to the number of elements in <paramref name="elements"/>.</param>
+        /// <returns>Newly created array</returns>
+        /// <remarks><para>The elements given as <paramref name="elements"/> are used 
+        /// for the new array without copy. For <typeparamref name="T"/> being a reference type, make sure not to reference any  
+        /// elements directly afterwards.</para>
+        /// </remarks>
+        public static ILRetArray<T> array<T>(ILSize size, params T[] elements) {
+            ILRetArray<T> ret = new ILRetArray<T>(elements, size);
+            return ret;
+        }
+        /// <summary>
+        /// Create column vector from given elements 
+        /// </summary>
+        /// <typeparam name="T">Element type</typeparam>
+        /// <param name="elements">List of elements</param>
+        /// <returns>Newly created vector with elements given</returns>
+        /// <remarks><para>If an System.Array was given as params argument, the array is directly taken 
+        /// as storage for the new array without copy. Make sure not to reference the 
+        /// System.Array directly afterwards!</para>
+        /// <para>In order to prevent for memory leaks on long runnning algorithms, <c>System.Array</c>s should 
+        /// not get created via the 'new' keyword - but fetched from the ILMemoryPool.</para>
+        /// <para>The shape of the vector created is controlled by the setting switch <see cref="ILNumerics.Settings.CreateRowVectorsByDefault"/>.
+        /// This switch defaults to <c>false</c> which will cause the creation of a column vector. </para></remarks>
+        /// <see cref="ILNumerics.ILMath.row{T}(T[])"/>
+        /// <see cref="ILNumerics.ILMath.column{T}(T[])"/>
+        public static ILRetArray<T> array<T>(params T[] elements) {
+            ILSize newDimensions;
+            if (Settings.CreateRowVectorsByDefault) {
+                newDimensions = new ILSize(1, elements.Length);
+            } else {
+                newDimensions = new ILSize(elements.Length, 1);
+            }
+            ILRetArray<T> ret = new ILRetArray<T>(elements, newDimensions);
+            return ret;
+        }
+
+        /// <summary>
+        /// Create row vector
+        /// </summary>
+        /// <typeparam name="T">Element type</typeparam>
+        /// <param name="elements">Elements of the row vector</param>
+        /// <returns>New row vector</returns>
+        public static ILRetArray<T> row<T>(params T[] elements) {
+            if (elements == null || elements.Length == 0) {
+                return empty<T>(ILSize.Empty00);
+            }
+            return new ILRetArray<T>(elements, new ILSize(1, elements.Length));
+        }
+        /// <summary>
+        /// Create column vector
+        /// </summary>
+        /// <typeparam name="T">Element type</typeparam>
+        /// <param name="elements">Elements of the column vector</param>
+        /// <returns>New column vector</returns>
+        public static ILRetArray<T> column<T>(params T[] elements) {
+            if (elements == null || elements.Length == 0) {
+                return empty<T>(ILSize.Empty00);
+            }
+            return new ILRetArray<T>(elements, new ILSize(elements.Length, 1));
+        }
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/asin.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/asin.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/asin.cs	(revision 9102)
@@ -0,0 +1,806 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics;
+using ILNumerics.Exceptions;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+
+
+
+namespace ILNumerics {
+
+    public partial class ILMath {
+
+
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>Arcsine of array elements - complex output</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Arcsine of array elements - complex output</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<fcomplex>  asinc (ILInArray< float > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<fcomplex>(A.Size); 
+                ILSize inDim = A.Size;
+                float[] arrA = A.GetArrayForRead(); 
+                fcomplex [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (true){
+                    retArr = ILMemoryPool.Pool.New<fcomplex>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<fcomplex> retStorage = new ILDenseStorage<fcomplex>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    fcomplex* cp = ((fcomplex*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  fcomplex.Asin(cp[0]  )  /*dummy*/;
+                            cp[1] =  fcomplex.Asin(cp[1]  )  /*dummy*/;
+                            cp[2] =  fcomplex.Asin(cp[2]  )  /*dummy*/;
+                            cp[3] =  fcomplex.Asin(cp[3]  )  /*dummy*/;
+                            cp[4] =  fcomplex.Asin(cp[4]  )  /*dummy*/;
+                            cp[5] =  fcomplex.Asin(cp[5]  )  /*dummy*/;
+                            cp[6] =  fcomplex.Asin(cp[6]  )  /*dummy*/;
+                            cp[7] =  fcomplex.Asin(cp[7]  )  /*dummy*/;
+                            cp[8] =  fcomplex.Asin(cp[8]  )  /*dummy*/;
+                            cp[9] =  fcomplex.Asin(cp[9]  )  /*dummy*/;
+                            cp[10] =  fcomplex.Asin(cp[10]  )  /*dummy*/;
+                            cp[11] =  fcomplex.Asin(cp[11]  )  /*dummy*/;
+                            cp[12] =  fcomplex.Asin(cp[12]  )  /*dummy*/;
+                            cp[13] =  fcomplex.Asin(cp[13]  )  /*dummy*/;
+                            cp[14] =  fcomplex.Asin(cp[14]  )  /*dummy*/;
+                            cp[15] =  fcomplex.Asin(cp[15]  )  /*dummy*/;
+                            cp[16] =  fcomplex.Asin(cp[16]  )  /*dummy*/;
+                            cp[17] =  fcomplex.Asin(cp[17]  )  /*dummy*/;
+                            cp[18] =  fcomplex.Asin(cp[18]  )  /*dummy*/;
+                            cp[19] =  fcomplex.Asin(cp[19]  )  /*dummy*/;
+                            cp[20] =  fcomplex.Asin(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.Asin(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        float* ap = ((float*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  fcomplex.Asin(ap[0]  )  /*dummy*/;
+                            cp[1] =  fcomplex.Asin(ap[1]  )  /*dummy*/;
+                            cp[2] =  fcomplex.Asin(ap[2]  )  /*dummy*/;
+                            cp[3] =  fcomplex.Asin(ap[3]  )  /*dummy*/;
+                            cp[4] =  fcomplex.Asin(ap[4]  )  /*dummy*/;
+                            cp[5] =  fcomplex.Asin(ap[5]  )  /*dummy*/;
+                            cp[6] =  fcomplex.Asin(ap[6]  )  /*dummy*/;
+                            cp[7] =  fcomplex.Asin(ap[7]  )  /*dummy*/;
+                            cp[8] =  fcomplex.Asin(ap[8]  )  /*dummy*/;
+                            cp[9] =  fcomplex.Asin(ap[9]  )  /*dummy*/;
+                            cp[10] =  fcomplex.Asin(ap[10]  )  /*dummy*/;
+                            cp[11] =  fcomplex.Asin(ap[11]  )  /*dummy*/;
+                            cp[12] =  fcomplex.Asin(ap[12]  )  /*dummy*/;
+                            cp[13] =  fcomplex.Asin(ap[13]  )  /*dummy*/;
+                            cp[14] =  fcomplex.Asin(ap[14]  )  /*dummy*/;
+                            cp[15] =  fcomplex.Asin(ap[15]  )  /*dummy*/;
+                            cp[16] =  fcomplex.Asin(ap[16]  )  /*dummy*/;
+                            cp[17] =  fcomplex.Asin(ap[17]  )  /*dummy*/;
+                            cp[18] =  fcomplex.Asin(ap[18]  )  /*dummy*/;
+                            cp[19] =  fcomplex.Asin(ap[19]  )  /*dummy*/;
+                            cp[20] =  fcomplex.Asin(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.Asin(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( float* arrAP = arrA)
+                fixed ( fcomplex* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<fcomplex>(retStorage);
+            }
+        }
+        /// <summary>Arcsine of array elements - complex output</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Arcsine of array elements - complex output</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<complex>  asinc (ILInArray< double > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<complex>(A.Size); 
+                ILSize inDim = A.Size;
+                double[] arrA = A.GetArrayForRead(); 
+                complex [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (true){
+                    retArr = ILMemoryPool.Pool.New<complex>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<complex> retStorage = new ILDenseStorage<complex>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    complex* cp = ((complex*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  complex.Asin(cp[0]  )  /*dummy*/;
+                            cp[1] =  complex.Asin(cp[1]  )  /*dummy*/;
+                            cp[2] =  complex.Asin(cp[2]  )  /*dummy*/;
+                            cp[3] =  complex.Asin(cp[3]  )  /*dummy*/;
+                            cp[4] =  complex.Asin(cp[4]  )  /*dummy*/;
+                            cp[5] =  complex.Asin(cp[5]  )  /*dummy*/;
+                            cp[6] =  complex.Asin(cp[6]  )  /*dummy*/;
+                            cp[7] =  complex.Asin(cp[7]  )  /*dummy*/;
+                            cp[8] =  complex.Asin(cp[8]  )  /*dummy*/;
+                            cp[9] =  complex.Asin(cp[9]  )  /*dummy*/;
+                            cp[10] =  complex.Asin(cp[10]  )  /*dummy*/;
+                            cp[11] =  complex.Asin(cp[11]  )  /*dummy*/;
+                            cp[12] =  complex.Asin(cp[12]  )  /*dummy*/;
+                            cp[13] =  complex.Asin(cp[13]  )  /*dummy*/;
+                            cp[14] =  complex.Asin(cp[14]  )  /*dummy*/;
+                            cp[15] =  complex.Asin(cp[15]  )  /*dummy*/;
+                            cp[16] =  complex.Asin(cp[16]  )  /*dummy*/;
+                            cp[17] =  complex.Asin(cp[17]  )  /*dummy*/;
+                            cp[18] =  complex.Asin(cp[18]  )  /*dummy*/;
+                            cp[19] =  complex.Asin(cp[19]  )  /*dummy*/;
+                            cp[20] =  complex.Asin(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.Asin(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        double* ap = ((double*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  complex.Asin(ap[0]  )  /*dummy*/;
+                            cp[1] =  complex.Asin(ap[1]  )  /*dummy*/;
+                            cp[2] =  complex.Asin(ap[2]  )  /*dummy*/;
+                            cp[3] =  complex.Asin(ap[3]  )  /*dummy*/;
+                            cp[4] =  complex.Asin(ap[4]  )  /*dummy*/;
+                            cp[5] =  complex.Asin(ap[5]  )  /*dummy*/;
+                            cp[6] =  complex.Asin(ap[6]  )  /*dummy*/;
+                            cp[7] =  complex.Asin(ap[7]  )  /*dummy*/;
+                            cp[8] =  complex.Asin(ap[8]  )  /*dummy*/;
+                            cp[9] =  complex.Asin(ap[9]  )  /*dummy*/;
+                            cp[10] =  complex.Asin(ap[10]  )  /*dummy*/;
+                            cp[11] =  complex.Asin(ap[11]  )  /*dummy*/;
+                            cp[12] =  complex.Asin(ap[12]  )  /*dummy*/;
+                            cp[13] =  complex.Asin(ap[13]  )  /*dummy*/;
+                            cp[14] =  complex.Asin(ap[14]  )  /*dummy*/;
+                            cp[15] =  complex.Asin(ap[15]  )  /*dummy*/;
+                            cp[16] =  complex.Asin(ap[16]  )  /*dummy*/;
+                            cp[17] =  complex.Asin(ap[17]  )  /*dummy*/;
+                            cp[18] =  complex.Asin(ap[18]  )  /*dummy*/;
+                            cp[19] =  complex.Asin(ap[19]  )  /*dummy*/;
+                            cp[20] =  complex.Asin(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.Asin(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( double* arrAP = arrA)
+                fixed ( complex* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<complex>(retStorage);
+            }
+        }
+        /// <summary>Arcsine values of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Arcsine of array elements</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<complex>  asin (ILInArray< complex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<complex>(A.Size); 
+                ILSize inDim = A.Size;
+                complex[] arrA = A.GetArrayForRead(); 
+                complex [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<complex>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<complex> retStorage = new ILDenseStorage<complex>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    complex* cp = ((complex*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  complex.Asin(cp[0]  )  /*dummy*/;
+                            cp[1] =  complex.Asin(cp[1]  )  /*dummy*/;
+                            cp[2] =  complex.Asin(cp[2]  )  /*dummy*/;
+                            cp[3] =  complex.Asin(cp[3]  )  /*dummy*/;
+                            cp[4] =  complex.Asin(cp[4]  )  /*dummy*/;
+                            cp[5] =  complex.Asin(cp[5]  )  /*dummy*/;
+                            cp[6] =  complex.Asin(cp[6]  )  /*dummy*/;
+                            cp[7] =  complex.Asin(cp[7]  )  /*dummy*/;
+                            cp[8] =  complex.Asin(cp[8]  )  /*dummy*/;
+                            cp[9] =  complex.Asin(cp[9]  )  /*dummy*/;
+                            cp[10] =  complex.Asin(cp[10]  )  /*dummy*/;
+                            cp[11] =  complex.Asin(cp[11]  )  /*dummy*/;
+                            cp[12] =  complex.Asin(cp[12]  )  /*dummy*/;
+                            cp[13] =  complex.Asin(cp[13]  )  /*dummy*/;
+                            cp[14] =  complex.Asin(cp[14]  )  /*dummy*/;
+                            cp[15] =  complex.Asin(cp[15]  )  /*dummy*/;
+                            cp[16] =  complex.Asin(cp[16]  )  /*dummy*/;
+                            cp[17] =  complex.Asin(cp[17]  )  /*dummy*/;
+                            cp[18] =  complex.Asin(cp[18]  )  /*dummy*/;
+                            cp[19] =  complex.Asin(cp[19]  )  /*dummy*/;
+                            cp[20] =  complex.Asin(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.Asin(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        complex* ap = ((complex*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  complex.Asin(ap[0]  )  /*dummy*/;
+                            cp[1] =  complex.Asin(ap[1]  )  /*dummy*/;
+                            cp[2] =  complex.Asin(ap[2]  )  /*dummy*/;
+                            cp[3] =  complex.Asin(ap[3]  )  /*dummy*/;
+                            cp[4] =  complex.Asin(ap[4]  )  /*dummy*/;
+                            cp[5] =  complex.Asin(ap[5]  )  /*dummy*/;
+                            cp[6] =  complex.Asin(ap[6]  )  /*dummy*/;
+                            cp[7] =  complex.Asin(ap[7]  )  /*dummy*/;
+                            cp[8] =  complex.Asin(ap[8]  )  /*dummy*/;
+                            cp[9] =  complex.Asin(ap[9]  )  /*dummy*/;
+                            cp[10] =  complex.Asin(ap[10]  )  /*dummy*/;
+                            cp[11] =  complex.Asin(ap[11]  )  /*dummy*/;
+                            cp[12] =  complex.Asin(ap[12]  )  /*dummy*/;
+                            cp[13] =  complex.Asin(ap[13]  )  /*dummy*/;
+                            cp[14] =  complex.Asin(ap[14]  )  /*dummy*/;
+                            cp[15] =  complex.Asin(ap[15]  )  /*dummy*/;
+                            cp[16] =  complex.Asin(ap[16]  )  /*dummy*/;
+                            cp[17] =  complex.Asin(ap[17]  )  /*dummy*/;
+                            cp[18] =  complex.Asin(ap[18]  )  /*dummy*/;
+                            cp[19] =  complex.Asin(ap[19]  )  /*dummy*/;
+                            cp[20] =  complex.Asin(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.Asin(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( complex* arrAP = arrA)
+                fixed ( complex* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<complex>(retStorage);
+            }
+        }
+        /// <summary>Arcsine values of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Arcsine of array elements</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<fcomplex>  asin (ILInArray< fcomplex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<fcomplex>(A.Size); 
+                ILSize inDim = A.Size;
+                fcomplex[] arrA = A.GetArrayForRead(); 
+                fcomplex [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<fcomplex>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<fcomplex> retStorage = new ILDenseStorage<fcomplex>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    fcomplex* cp = ((fcomplex*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  fcomplex.Asin(cp[0]  )  /*dummy*/;
+                            cp[1] =  fcomplex.Asin(cp[1]  )  /*dummy*/;
+                            cp[2] =  fcomplex.Asin(cp[2]  )  /*dummy*/;
+                            cp[3] =  fcomplex.Asin(cp[3]  )  /*dummy*/;
+                            cp[4] =  fcomplex.Asin(cp[4]  )  /*dummy*/;
+                            cp[5] =  fcomplex.Asin(cp[5]  )  /*dummy*/;
+                            cp[6] =  fcomplex.Asin(cp[6]  )  /*dummy*/;
+                            cp[7] =  fcomplex.Asin(cp[7]  )  /*dummy*/;
+                            cp[8] =  fcomplex.Asin(cp[8]  )  /*dummy*/;
+                            cp[9] =  fcomplex.Asin(cp[9]  )  /*dummy*/;
+                            cp[10] =  fcomplex.Asin(cp[10]  )  /*dummy*/;
+                            cp[11] =  fcomplex.Asin(cp[11]  )  /*dummy*/;
+                            cp[12] =  fcomplex.Asin(cp[12]  )  /*dummy*/;
+                            cp[13] =  fcomplex.Asin(cp[13]  )  /*dummy*/;
+                            cp[14] =  fcomplex.Asin(cp[14]  )  /*dummy*/;
+                            cp[15] =  fcomplex.Asin(cp[15]  )  /*dummy*/;
+                            cp[16] =  fcomplex.Asin(cp[16]  )  /*dummy*/;
+                            cp[17] =  fcomplex.Asin(cp[17]  )  /*dummy*/;
+                            cp[18] =  fcomplex.Asin(cp[18]  )  /*dummy*/;
+                            cp[19] =  fcomplex.Asin(cp[19]  )  /*dummy*/;
+                            cp[20] =  fcomplex.Asin(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.Asin(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        fcomplex* ap = ((fcomplex*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  fcomplex.Asin(ap[0]  )  /*dummy*/;
+                            cp[1] =  fcomplex.Asin(ap[1]  )  /*dummy*/;
+                            cp[2] =  fcomplex.Asin(ap[2]  )  /*dummy*/;
+                            cp[3] =  fcomplex.Asin(ap[3]  )  /*dummy*/;
+                            cp[4] =  fcomplex.Asin(ap[4]  )  /*dummy*/;
+                            cp[5] =  fcomplex.Asin(ap[5]  )  /*dummy*/;
+                            cp[6] =  fcomplex.Asin(ap[6]  )  /*dummy*/;
+                            cp[7] =  fcomplex.Asin(ap[7]  )  /*dummy*/;
+                            cp[8] =  fcomplex.Asin(ap[8]  )  /*dummy*/;
+                            cp[9] =  fcomplex.Asin(ap[9]  )  /*dummy*/;
+                            cp[10] =  fcomplex.Asin(ap[10]  )  /*dummy*/;
+                            cp[11] =  fcomplex.Asin(ap[11]  )  /*dummy*/;
+                            cp[12] =  fcomplex.Asin(ap[12]  )  /*dummy*/;
+                            cp[13] =  fcomplex.Asin(ap[13]  )  /*dummy*/;
+                            cp[14] =  fcomplex.Asin(ap[14]  )  /*dummy*/;
+                            cp[15] =  fcomplex.Asin(ap[15]  )  /*dummy*/;
+                            cp[16] =  fcomplex.Asin(ap[16]  )  /*dummy*/;
+                            cp[17] =  fcomplex.Asin(ap[17]  )  /*dummy*/;
+                            cp[18] =  fcomplex.Asin(ap[18]  )  /*dummy*/;
+                            cp[19] =  fcomplex.Asin(ap[19]  )  /*dummy*/;
+                            cp[20] =  fcomplex.Asin(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.Asin(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( fcomplex* arrAP = arrA)
+                fixed ( fcomplex* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<fcomplex>(retStorage);
+            }
+        }
+        /// <summary>Arcsine of array elements - real output</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Arcsine of array elements - real output</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<float>  asin (ILInArray< float > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<float>(A.Size); 
+                ILSize inDim = A.Size;
+                float[] arrA = A.GetArrayForRead(); 
+                float [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<float>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<float> retStorage = new ILDenseStorage<float>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    float* cp = ((float*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  (float)Math.Asin(cp[0]  )  /*dummy*/;
+                            cp[1] =  (float)Math.Asin(cp[1]  )  /*dummy*/;
+                            cp[2] =  (float)Math.Asin(cp[2]  )  /*dummy*/;
+                            cp[3] =  (float)Math.Asin(cp[3]  )  /*dummy*/;
+                            cp[4] =  (float)Math.Asin(cp[4]  )  /*dummy*/;
+                            cp[5] =  (float)Math.Asin(cp[5]  )  /*dummy*/;
+                            cp[6] =  (float)Math.Asin(cp[6]  )  /*dummy*/;
+                            cp[7] =  (float)Math.Asin(cp[7]  )  /*dummy*/;
+                            cp[8] =  (float)Math.Asin(cp[8]  )  /*dummy*/;
+                            cp[9] =  (float)Math.Asin(cp[9]  )  /*dummy*/;
+                            cp[10] =  (float)Math.Asin(cp[10]  )  /*dummy*/;
+                            cp[11] =  (float)Math.Asin(cp[11]  )  /*dummy*/;
+                            cp[12] =  (float)Math.Asin(cp[12]  )  /*dummy*/;
+                            cp[13] =  (float)Math.Asin(cp[13]  )  /*dummy*/;
+                            cp[14] =  (float)Math.Asin(cp[14]  )  /*dummy*/;
+                            cp[15] =  (float)Math.Asin(cp[15]  )  /*dummy*/;
+                            cp[16] =  (float)Math.Asin(cp[16]  )  /*dummy*/;
+                            cp[17] =  (float)Math.Asin(cp[17]  )  /*dummy*/;
+                            cp[18] =  (float)Math.Asin(cp[18]  )  /*dummy*/;
+                            cp[19] =  (float)Math.Asin(cp[19]  )  /*dummy*/;
+                            cp[20] =  (float)Math.Asin(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  (float)Math.Asin(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        float* ap = ((float*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  (float)Math.Asin(ap[0]  )  /*dummy*/;
+                            cp[1] =  (float)Math.Asin(ap[1]  )  /*dummy*/;
+                            cp[2] =  (float)Math.Asin(ap[2]  )  /*dummy*/;
+                            cp[3] =  (float)Math.Asin(ap[3]  )  /*dummy*/;
+                            cp[4] =  (float)Math.Asin(ap[4]  )  /*dummy*/;
+                            cp[5] =  (float)Math.Asin(ap[5]  )  /*dummy*/;
+                            cp[6] =  (float)Math.Asin(ap[6]  )  /*dummy*/;
+                            cp[7] =  (float)Math.Asin(ap[7]  )  /*dummy*/;
+                            cp[8] =  (float)Math.Asin(ap[8]  )  /*dummy*/;
+                            cp[9] =  (float)Math.Asin(ap[9]  )  /*dummy*/;
+                            cp[10] =  (float)Math.Asin(ap[10]  )  /*dummy*/;
+                            cp[11] =  (float)Math.Asin(ap[11]  )  /*dummy*/;
+                            cp[12] =  (float)Math.Asin(ap[12]  )  /*dummy*/;
+                            cp[13] =  (float)Math.Asin(ap[13]  )  /*dummy*/;
+                            cp[14] =  (float)Math.Asin(ap[14]  )  /*dummy*/;
+                            cp[15] =  (float)Math.Asin(ap[15]  )  /*dummy*/;
+                            cp[16] =  (float)Math.Asin(ap[16]  )  /*dummy*/;
+                            cp[17] =  (float)Math.Asin(ap[17]  )  /*dummy*/;
+                            cp[18] =  (float)Math.Asin(ap[18]  )  /*dummy*/;
+                            cp[19] =  (float)Math.Asin(ap[19]  )  /*dummy*/;
+                            cp[20] =  (float)Math.Asin(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  (float)Math.Asin(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( float* arrAP = arrA)
+                fixed ( float* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<float>(retStorage);
+            }
+        }
+        /// <summary>Arcsine of array elements - real output</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Arcsine of array elements - real output</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<double>  asin (ILInArray< double > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<double>(A.Size); 
+                ILSize inDim = A.Size;
+                double[] arrA = A.GetArrayForRead(); 
+                double [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<double>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<double> retStorage = new ILDenseStorage<double>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    double* cp = ((double*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  Math.Asin(cp[0]  )  /*dummy*/;
+                            cp[1] =  Math.Asin(cp[1]  )  /*dummy*/;
+                            cp[2] =  Math.Asin(cp[2]  )  /*dummy*/;
+                            cp[3] =  Math.Asin(cp[3]  )  /*dummy*/;
+                            cp[4] =  Math.Asin(cp[4]  )  /*dummy*/;
+                            cp[5] =  Math.Asin(cp[5]  )  /*dummy*/;
+                            cp[6] =  Math.Asin(cp[6]  )  /*dummy*/;
+                            cp[7] =  Math.Asin(cp[7]  )  /*dummy*/;
+                            cp[8] =  Math.Asin(cp[8]  )  /*dummy*/;
+                            cp[9] =  Math.Asin(cp[9]  )  /*dummy*/;
+                            cp[10] =  Math.Asin(cp[10]  )  /*dummy*/;
+                            cp[11] =  Math.Asin(cp[11]  )  /*dummy*/;
+                            cp[12] =  Math.Asin(cp[12]  )  /*dummy*/;
+                            cp[13] =  Math.Asin(cp[13]  )  /*dummy*/;
+                            cp[14] =  Math.Asin(cp[14]  )  /*dummy*/;
+                            cp[15] =  Math.Asin(cp[15]  )  /*dummy*/;
+                            cp[16] =  Math.Asin(cp[16]  )  /*dummy*/;
+                            cp[17] =  Math.Asin(cp[17]  )  /*dummy*/;
+                            cp[18] =  Math.Asin(cp[18]  )  /*dummy*/;
+                            cp[19] =  Math.Asin(cp[19]  )  /*dummy*/;
+                            cp[20] =  Math.Asin(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Math.Asin(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        double* ap = ((double*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  Math.Asin(ap[0]  )  /*dummy*/;
+                            cp[1] =  Math.Asin(ap[1]  )  /*dummy*/;
+                            cp[2] =  Math.Asin(ap[2]  )  /*dummy*/;
+                            cp[3] =  Math.Asin(ap[3]  )  /*dummy*/;
+                            cp[4] =  Math.Asin(ap[4]  )  /*dummy*/;
+                            cp[5] =  Math.Asin(ap[5]  )  /*dummy*/;
+                            cp[6] =  Math.Asin(ap[6]  )  /*dummy*/;
+                            cp[7] =  Math.Asin(ap[7]  )  /*dummy*/;
+                            cp[8] =  Math.Asin(ap[8]  )  /*dummy*/;
+                            cp[9] =  Math.Asin(ap[9]  )  /*dummy*/;
+                            cp[10] =  Math.Asin(ap[10]  )  /*dummy*/;
+                            cp[11] =  Math.Asin(ap[11]  )  /*dummy*/;
+                            cp[12] =  Math.Asin(ap[12]  )  /*dummy*/;
+                            cp[13] =  Math.Asin(ap[13]  )  /*dummy*/;
+                            cp[14] =  Math.Asin(ap[14]  )  /*dummy*/;
+                            cp[15] =  Math.Asin(ap[15]  )  /*dummy*/;
+                            cp[16] =  Math.Asin(ap[16]  )  /*dummy*/;
+                            cp[17] =  Math.Asin(ap[17]  )  /*dummy*/;
+                            cp[18] =  Math.Asin(ap[18]  )  /*dummy*/;
+                            cp[19] =  Math.Asin(ap[19]  )  /*dummy*/;
+                            cp[20] =  Math.Asin(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Math.Asin(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( double* arrAP = arrA)
+                fixed ( double* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<double>(retStorage);
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+   }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/atan.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/atan.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/atan.cs	(revision 9102)
@@ -0,0 +1,558 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics;
+using ILNumerics.Exceptions; 
+using ILNumerics.Storage; 
+using ILNumerics.Misc; 
+
+
+namespace ILNumerics {
+
+    public partial class ILMath {
+
+
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>Arctangent of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Arctangent of array elements</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<complex>  atan (ILInArray< complex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<complex>(A.Size); 
+                ILSize inDim = A.Size;
+                complex[] arrA = A.GetArrayForRead(); 
+                complex [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<complex>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<complex> retStorage = new ILDenseStorage<complex>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    complex* cp = ((complex*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  complex.Atan(cp[0]  )  /*dummy*/;
+                            cp[1] =  complex.Atan(cp[1]  )  /*dummy*/;
+                            cp[2] =  complex.Atan(cp[2]  )  /*dummy*/;
+                            cp[3] =  complex.Atan(cp[3]  )  /*dummy*/;
+                            cp[4] =  complex.Atan(cp[4]  )  /*dummy*/;
+                            cp[5] =  complex.Atan(cp[5]  )  /*dummy*/;
+                            cp[6] =  complex.Atan(cp[6]  )  /*dummy*/;
+                            cp[7] =  complex.Atan(cp[7]  )  /*dummy*/;
+                            cp[8] =  complex.Atan(cp[8]  )  /*dummy*/;
+                            cp[9] =  complex.Atan(cp[9]  )  /*dummy*/;
+                            cp[10] =  complex.Atan(cp[10]  )  /*dummy*/;
+                            cp[11] =  complex.Atan(cp[11]  )  /*dummy*/;
+                            cp[12] =  complex.Atan(cp[12]  )  /*dummy*/;
+                            cp[13] =  complex.Atan(cp[13]  )  /*dummy*/;
+                            cp[14] =  complex.Atan(cp[14]  )  /*dummy*/;
+                            cp[15] =  complex.Atan(cp[15]  )  /*dummy*/;
+                            cp[16] =  complex.Atan(cp[16]  )  /*dummy*/;
+                            cp[17] =  complex.Atan(cp[17]  )  /*dummy*/;
+                            cp[18] =  complex.Atan(cp[18]  )  /*dummy*/;
+                            cp[19] =  complex.Atan(cp[19]  )  /*dummy*/;
+                            cp[20] =  complex.Atan(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.Atan(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        complex* ap = ((complex*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  complex.Atan(ap[0]  )  /*dummy*/;
+                            cp[1] =  complex.Atan(ap[1]  )  /*dummy*/;
+                            cp[2] =  complex.Atan(ap[2]  )  /*dummy*/;
+                            cp[3] =  complex.Atan(ap[3]  )  /*dummy*/;
+                            cp[4] =  complex.Atan(ap[4]  )  /*dummy*/;
+                            cp[5] =  complex.Atan(ap[5]  )  /*dummy*/;
+                            cp[6] =  complex.Atan(ap[6]  )  /*dummy*/;
+                            cp[7] =  complex.Atan(ap[7]  )  /*dummy*/;
+                            cp[8] =  complex.Atan(ap[8]  )  /*dummy*/;
+                            cp[9] =  complex.Atan(ap[9]  )  /*dummy*/;
+                            cp[10] =  complex.Atan(ap[10]  )  /*dummy*/;
+                            cp[11] =  complex.Atan(ap[11]  )  /*dummy*/;
+                            cp[12] =  complex.Atan(ap[12]  )  /*dummy*/;
+                            cp[13] =  complex.Atan(ap[13]  )  /*dummy*/;
+                            cp[14] =  complex.Atan(ap[14]  )  /*dummy*/;
+                            cp[15] =  complex.Atan(ap[15]  )  /*dummy*/;
+                            cp[16] =  complex.Atan(ap[16]  )  /*dummy*/;
+                            cp[17] =  complex.Atan(ap[17]  )  /*dummy*/;
+                            cp[18] =  complex.Atan(ap[18]  )  /*dummy*/;
+                            cp[19] =  complex.Atan(ap[19]  )  /*dummy*/;
+                            cp[20] =  complex.Atan(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.Atan(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( complex* arrAP = arrA)
+                fixed ( complex* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<complex>(retStorage);
+            }
+        }
+        /// <summary>Arctangent of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Arctangent of array elements</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<fcomplex>  atan (ILInArray< fcomplex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<fcomplex>(A.Size); 
+                ILSize inDim = A.Size;
+                fcomplex[] arrA = A.GetArrayForRead(); 
+                fcomplex [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<fcomplex>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<fcomplex> retStorage = new ILDenseStorage<fcomplex>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    fcomplex* cp = ((fcomplex*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  fcomplex.Atan(cp[0]  )  /*dummy*/;
+                            cp[1] =  fcomplex.Atan(cp[1]  )  /*dummy*/;
+                            cp[2] =  fcomplex.Atan(cp[2]  )  /*dummy*/;
+                            cp[3] =  fcomplex.Atan(cp[3]  )  /*dummy*/;
+                            cp[4] =  fcomplex.Atan(cp[4]  )  /*dummy*/;
+                            cp[5] =  fcomplex.Atan(cp[5]  )  /*dummy*/;
+                            cp[6] =  fcomplex.Atan(cp[6]  )  /*dummy*/;
+                            cp[7] =  fcomplex.Atan(cp[7]  )  /*dummy*/;
+                            cp[8] =  fcomplex.Atan(cp[8]  )  /*dummy*/;
+                            cp[9] =  fcomplex.Atan(cp[9]  )  /*dummy*/;
+                            cp[10] =  fcomplex.Atan(cp[10]  )  /*dummy*/;
+                            cp[11] =  fcomplex.Atan(cp[11]  )  /*dummy*/;
+                            cp[12] =  fcomplex.Atan(cp[12]  )  /*dummy*/;
+                            cp[13] =  fcomplex.Atan(cp[13]  )  /*dummy*/;
+                            cp[14] =  fcomplex.Atan(cp[14]  )  /*dummy*/;
+                            cp[15] =  fcomplex.Atan(cp[15]  )  /*dummy*/;
+                            cp[16] =  fcomplex.Atan(cp[16]  )  /*dummy*/;
+                            cp[17] =  fcomplex.Atan(cp[17]  )  /*dummy*/;
+                            cp[18] =  fcomplex.Atan(cp[18]  )  /*dummy*/;
+                            cp[19] =  fcomplex.Atan(cp[19]  )  /*dummy*/;
+                            cp[20] =  fcomplex.Atan(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.Atan(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        fcomplex* ap = ((fcomplex*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  fcomplex.Atan(ap[0]  )  /*dummy*/;
+                            cp[1] =  fcomplex.Atan(ap[1]  )  /*dummy*/;
+                            cp[2] =  fcomplex.Atan(ap[2]  )  /*dummy*/;
+                            cp[3] =  fcomplex.Atan(ap[3]  )  /*dummy*/;
+                            cp[4] =  fcomplex.Atan(ap[4]  )  /*dummy*/;
+                            cp[5] =  fcomplex.Atan(ap[5]  )  /*dummy*/;
+                            cp[6] =  fcomplex.Atan(ap[6]  )  /*dummy*/;
+                            cp[7] =  fcomplex.Atan(ap[7]  )  /*dummy*/;
+                            cp[8] =  fcomplex.Atan(ap[8]  )  /*dummy*/;
+                            cp[9] =  fcomplex.Atan(ap[9]  )  /*dummy*/;
+                            cp[10] =  fcomplex.Atan(ap[10]  )  /*dummy*/;
+                            cp[11] =  fcomplex.Atan(ap[11]  )  /*dummy*/;
+                            cp[12] =  fcomplex.Atan(ap[12]  )  /*dummy*/;
+                            cp[13] =  fcomplex.Atan(ap[13]  )  /*dummy*/;
+                            cp[14] =  fcomplex.Atan(ap[14]  )  /*dummy*/;
+                            cp[15] =  fcomplex.Atan(ap[15]  )  /*dummy*/;
+                            cp[16] =  fcomplex.Atan(ap[16]  )  /*dummy*/;
+                            cp[17] =  fcomplex.Atan(ap[17]  )  /*dummy*/;
+                            cp[18] =  fcomplex.Atan(ap[18]  )  /*dummy*/;
+                            cp[19] =  fcomplex.Atan(ap[19]  )  /*dummy*/;
+                            cp[20] =  fcomplex.Atan(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.Atan(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( fcomplex* arrAP = arrA)
+                fixed ( fcomplex* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<fcomplex>(retStorage);
+            }
+        }
+        /// <summary>Arctangent of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Arctangent of array elements</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<float>  atan (ILInArray< float > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<float>(A.Size); 
+                ILSize inDim = A.Size;
+                float[] arrA = A.GetArrayForRead(); 
+                float [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<float>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<float> retStorage = new ILDenseStorage<float>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    float* cp = ((float*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  (float)Math.Atan(cp[0]  )  /*dummy*/;
+                            cp[1] =  (float)Math.Atan(cp[1]  )  /*dummy*/;
+                            cp[2] =  (float)Math.Atan(cp[2]  )  /*dummy*/;
+                            cp[3] =  (float)Math.Atan(cp[3]  )  /*dummy*/;
+                            cp[4] =  (float)Math.Atan(cp[4]  )  /*dummy*/;
+                            cp[5] =  (float)Math.Atan(cp[5]  )  /*dummy*/;
+                            cp[6] =  (float)Math.Atan(cp[6]  )  /*dummy*/;
+                            cp[7] =  (float)Math.Atan(cp[7]  )  /*dummy*/;
+                            cp[8] =  (float)Math.Atan(cp[8]  )  /*dummy*/;
+                            cp[9] =  (float)Math.Atan(cp[9]  )  /*dummy*/;
+                            cp[10] =  (float)Math.Atan(cp[10]  )  /*dummy*/;
+                            cp[11] =  (float)Math.Atan(cp[11]  )  /*dummy*/;
+                            cp[12] =  (float)Math.Atan(cp[12]  )  /*dummy*/;
+                            cp[13] =  (float)Math.Atan(cp[13]  )  /*dummy*/;
+                            cp[14] =  (float)Math.Atan(cp[14]  )  /*dummy*/;
+                            cp[15] =  (float)Math.Atan(cp[15]  )  /*dummy*/;
+                            cp[16] =  (float)Math.Atan(cp[16]  )  /*dummy*/;
+                            cp[17] =  (float)Math.Atan(cp[17]  )  /*dummy*/;
+                            cp[18] =  (float)Math.Atan(cp[18]  )  /*dummy*/;
+                            cp[19] =  (float)Math.Atan(cp[19]  )  /*dummy*/;
+                            cp[20] =  (float)Math.Atan(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  (float)Math.Atan(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        float* ap = ((float*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  (float)Math.Atan(ap[0]  )  /*dummy*/;
+                            cp[1] =  (float)Math.Atan(ap[1]  )  /*dummy*/;
+                            cp[2] =  (float)Math.Atan(ap[2]  )  /*dummy*/;
+                            cp[3] =  (float)Math.Atan(ap[3]  )  /*dummy*/;
+                            cp[4] =  (float)Math.Atan(ap[4]  )  /*dummy*/;
+                            cp[5] =  (float)Math.Atan(ap[5]  )  /*dummy*/;
+                            cp[6] =  (float)Math.Atan(ap[6]  )  /*dummy*/;
+                            cp[7] =  (float)Math.Atan(ap[7]  )  /*dummy*/;
+                            cp[8] =  (float)Math.Atan(ap[8]  )  /*dummy*/;
+                            cp[9] =  (float)Math.Atan(ap[9]  )  /*dummy*/;
+                            cp[10] =  (float)Math.Atan(ap[10]  )  /*dummy*/;
+                            cp[11] =  (float)Math.Atan(ap[11]  )  /*dummy*/;
+                            cp[12] =  (float)Math.Atan(ap[12]  )  /*dummy*/;
+                            cp[13] =  (float)Math.Atan(ap[13]  )  /*dummy*/;
+                            cp[14] =  (float)Math.Atan(ap[14]  )  /*dummy*/;
+                            cp[15] =  (float)Math.Atan(ap[15]  )  /*dummy*/;
+                            cp[16] =  (float)Math.Atan(ap[16]  )  /*dummy*/;
+                            cp[17] =  (float)Math.Atan(ap[17]  )  /*dummy*/;
+                            cp[18] =  (float)Math.Atan(ap[18]  )  /*dummy*/;
+                            cp[19] =  (float)Math.Atan(ap[19]  )  /*dummy*/;
+                            cp[20] =  (float)Math.Atan(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  (float)Math.Atan(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( float* arrAP = arrA)
+                fixed ( float* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<float>(retStorage);
+            }
+        }
+        /// <summary>Arctangent of array elements </summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Arctangent of array elements</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<double>  atan (ILInArray< double > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<double>(A.Size); 
+                ILSize inDim = A.Size;
+                double[] arrA = A.GetArrayForRead(); 
+                double [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<double>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<double> retStorage = new ILDenseStorage<double>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    double* cp = ((double*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  Math.Atan(cp[0]  )  /*dummy*/;
+                            cp[1] =  Math.Atan(cp[1]  )  /*dummy*/;
+                            cp[2] =  Math.Atan(cp[2]  )  /*dummy*/;
+                            cp[3] =  Math.Atan(cp[3]  )  /*dummy*/;
+                            cp[4] =  Math.Atan(cp[4]  )  /*dummy*/;
+                            cp[5] =  Math.Atan(cp[5]  )  /*dummy*/;
+                            cp[6] =  Math.Atan(cp[6]  )  /*dummy*/;
+                            cp[7] =  Math.Atan(cp[7]  )  /*dummy*/;
+                            cp[8] =  Math.Atan(cp[8]  )  /*dummy*/;
+                            cp[9] =  Math.Atan(cp[9]  )  /*dummy*/;
+                            cp[10] =  Math.Atan(cp[10]  )  /*dummy*/;
+                            cp[11] =  Math.Atan(cp[11]  )  /*dummy*/;
+                            cp[12] =  Math.Atan(cp[12]  )  /*dummy*/;
+                            cp[13] =  Math.Atan(cp[13]  )  /*dummy*/;
+                            cp[14] =  Math.Atan(cp[14]  )  /*dummy*/;
+                            cp[15] =  Math.Atan(cp[15]  )  /*dummy*/;
+                            cp[16] =  Math.Atan(cp[16]  )  /*dummy*/;
+                            cp[17] =  Math.Atan(cp[17]  )  /*dummy*/;
+                            cp[18] =  Math.Atan(cp[18]  )  /*dummy*/;
+                            cp[19] =  Math.Atan(cp[19]  )  /*dummy*/;
+                            cp[20] =  Math.Atan(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Math.Atan(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        double* ap = ((double*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  Math.Atan(ap[0]  )  /*dummy*/;
+                            cp[1] =  Math.Atan(ap[1]  )  /*dummy*/;
+                            cp[2] =  Math.Atan(ap[2]  )  /*dummy*/;
+                            cp[3] =  Math.Atan(ap[3]  )  /*dummy*/;
+                            cp[4] =  Math.Atan(ap[4]  )  /*dummy*/;
+                            cp[5] =  Math.Atan(ap[5]  )  /*dummy*/;
+                            cp[6] =  Math.Atan(ap[6]  )  /*dummy*/;
+                            cp[7] =  Math.Atan(ap[7]  )  /*dummy*/;
+                            cp[8] =  Math.Atan(ap[8]  )  /*dummy*/;
+                            cp[9] =  Math.Atan(ap[9]  )  /*dummy*/;
+                            cp[10] =  Math.Atan(ap[10]  )  /*dummy*/;
+                            cp[11] =  Math.Atan(ap[11]  )  /*dummy*/;
+                            cp[12] =  Math.Atan(ap[12]  )  /*dummy*/;
+                            cp[13] =  Math.Atan(ap[13]  )  /*dummy*/;
+                            cp[14] =  Math.Atan(ap[14]  )  /*dummy*/;
+                            cp[15] =  Math.Atan(ap[15]  )  /*dummy*/;
+                            cp[16] =  Math.Atan(ap[16]  )  /*dummy*/;
+                            cp[17] =  Math.Atan(ap[17]  )  /*dummy*/;
+                            cp[18] =  Math.Atan(ap[18]  )  /*dummy*/;
+                            cp[19] =  Math.Atan(ap[19]  )  /*dummy*/;
+                            cp[20] =  Math.Atan(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Math.Atan(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( double* arrAP = arrA)
+                fixed ( double* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<double>(retStorage);
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+  
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/atan2.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/atan2.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/atan2.cs	(revision 9102)
@@ -0,0 +1,1501 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using ILNumerics;
+using ILNumerics.Misc;
+using ILNumerics.Storage;
+using ILNumerics.Native;
+using ILNumerics.Exceptions;
+
+
+namespace ILNumerics {
+
+    public partial class ILMath {         
+         
+
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>Arcus tangens of elements</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Array with elementwise arcus tangens of both inputs</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<float>  atan2(ILInArray<float> A, ILInArray<float> B) {
+            using (ILScope.Enter(A,B)) {
+                int outLen; 
+                BinOpItMode mode; 
+                float [] retArr;
+                float [] arrA = A.GetArrayForRead();
+                float[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size; 
+                    if (B.IsScalar) {
+                       
+                        return new  ILRetArray<float> (new  float [1]{  (float)Math.Atan2 (A.GetValue(0)  , B.GetValue(0))}, A.Size);
+                    } else if (B.IsEmpty) {
+                        return  ILRetArray<float>.empty(outDims); 
+                    } else {
+                        outLen = outDims.NumberOfElements; 
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< float > (outLen);
+                            mode = BinOpItMode.SAN; 
+                        } else {
+                            mode = BinOpItMode.SAI; 
+                        }
+                    }
+                } else {
+                    outDims = A.Size; 
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return  ILRetArray<float>.empty(A.Size);  
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< float > (outLen);
+                            mode = BinOpItMode.ASN; 
+                        } else {
+                            mode = BinOpItMode.ASI; 
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  atan2Ex(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (A.TryGetStorage4InplaceOp(out retArr)) 
+                            mode  = BinOpItMode.AAIA; 
+                        else if (B.TryGetStorage4InplaceOp(out retArr)) 
+                            mode = BinOpItMode.AAIB; 
+                        else {
+                            retArr = ILMemoryPool.Pool.New< float > (outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<float> retStorage = new ILDenseStorage<float>(retArr, outDims);
+                int i = 0, workerCount = 1; 
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    float* cp = (float*)range.Item5 + range.Item1;
+                    float scalar;
+                    int j = range.Item2; 
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           float* bp = ((float*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                                cp[0] =   (float)Math.Atan2 (cp[0]  , bp[0]);
+                                cp[1] =   (float)Math.Atan2 (cp[1]  , bp[1]);
+                                cp[2] =   (float)Math.Atan2 (cp[2]  , bp[2]);
+                                cp[3] =   (float)Math.Atan2 (cp[3]  , bp[3]);
+                                cp[4] =   (float)Math.Atan2 (cp[4]  , bp[4]);
+                                cp[5] =   (float)Math.Atan2 (cp[5]  , bp[5]);
+                                cp[6] =   (float)Math.Atan2 (cp[6]  , bp[6]);
+                                cp[7] =   (float)Math.Atan2 (cp[7]  , bp[7]);
+                                cp[8] =   (float)Math.Atan2 (cp[8]  , bp[8]);
+                                cp[9] =   (float)Math.Atan2 (cp[9]  , bp[9]);
+                                cp[10] =   (float)Math.Atan2 (cp[10]  , bp[10]);
+                                cp[11] =   (float)Math.Atan2 (cp[11]  , bp[11]);
+                                cp[12] =   (float)Math.Atan2 (cp[12]  , bp[12]);
+                                cp[13] =   (float)Math.Atan2 (cp[13]  , bp[13]);
+                                cp[14] =   (float)Math.Atan2 (cp[14]  , bp[14]);
+                                cp[15] =   (float)Math.Atan2 (cp[15]  , bp[15]);
+                                cp[16] =   (float)Math.Atan2 (cp[16]  , bp[16]);
+                                cp[17] =   (float)Math.Atan2 (cp[17]  , bp[17]);
+                                cp[18] =   (float)Math.Atan2 (cp[18]  , bp[18]);
+                                cp[19] =   (float)Math.Atan2 (cp[19]  , bp[19]);
+                                cp[20] =   (float)Math.Atan2 (cp[20]  , bp[20]);
+                                cp += 21; bp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (float)Math.Atan2 (*cp  , *bp);
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           float* ap = ((float*)range.Item3 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (float)Math.Atan2 (ap[0]  , cp[0]);
+                                cp[1] =   (float)Math.Atan2 (ap[1]  , cp[1]);
+                                cp[2] =   (float)Math.Atan2 (ap[2]  , cp[2]);
+                                cp[3] =   (float)Math.Atan2 (ap[3]  , cp[3]);
+                                cp[4] =   (float)Math.Atan2 (ap[4]  , cp[4]);
+                                cp[5] =   (float)Math.Atan2 (ap[5]  , cp[5]);
+                                cp[6] =   (float)Math.Atan2 (ap[6]  , cp[6]);
+                                cp[7] =   (float)Math.Atan2 (ap[7]  , cp[7]);
+                                cp[8] =   (float)Math.Atan2 (ap[8]  , cp[8]);
+                                cp[9] =   (float)Math.Atan2 (ap[9]  , cp[9]);
+                                cp[10] =   (float)Math.Atan2 (ap[10]  , cp[10]);
+                                cp[11] =   (float)Math.Atan2 (ap[11]  , cp[11]);
+                                cp[12] =   (float)Math.Atan2 (ap[12]  , cp[12]);
+                                cp[13] =   (float)Math.Atan2 (ap[13]  , cp[13]);
+                                cp[14] =   (float)Math.Atan2 (ap[14]  , cp[14]);
+                                cp[15] =   (float)Math.Atan2 (ap[15]  , cp[15]);
+                                cp[16] =   (float)Math.Atan2 (ap[16]  , cp[16]);
+                                cp[17] =   (float)Math.Atan2 (ap[17]  , cp[17]);
+                                cp[18] =   (float)Math.Atan2 (ap[18]  , cp[18]);
+                                cp[19] =   (float)Math.Atan2 (ap[19]  , cp[19]);
+                                cp[20] =   (float)Math.Atan2 (ap[20]  , cp[20]);
+                                ap += 21; cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (float)Math.Atan2 (*ap  , *cp);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((float*)range.Item3 + range.Item1);
+                            bp = ((float*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (float)Math.Atan2 (ap[0]  , bp[0]);
+                                cp[1] =   (float)Math.Atan2 (ap[1]  , bp[1]);
+                                cp[2] =   (float)Math.Atan2 (ap[2]  , bp[2]);
+                                cp[3] =   (float)Math.Atan2 (ap[3]  , bp[3]);
+                                cp[4] =   (float)Math.Atan2 (ap[4]  , bp[4]);
+                                cp[5] =   (float)Math.Atan2 (ap[5]  , bp[5]);
+                                cp[6] =   (float)Math.Atan2 (ap[6]  , bp[6]);
+                                cp[7] =   (float)Math.Atan2 (ap[7]  , bp[7]);
+                                cp[8] =   (float)Math.Atan2 (ap[8]  , bp[8]);
+                                cp[9] =   (float)Math.Atan2 (ap[9]  , bp[9]);
+                                cp[10] =   (float)Math.Atan2 (ap[10]  , bp[10]);
+                                cp[11] =   (float)Math.Atan2 (ap[11]  , bp[11]);
+                                cp[12] =   (float)Math.Atan2 (ap[12]  , bp[12]);
+                                cp[13] =   (float)Math.Atan2 (ap[13]  , bp[13]);
+                                cp[14] =   (float)Math.Atan2 (ap[14]  , bp[14]);
+                                cp[15] =   (float)Math.Atan2 (ap[15]  , bp[15]);
+                                cp[16] =   (float)Math.Atan2 (ap[16]  , bp[16]);
+                                cp[17] =   (float)Math.Atan2 (ap[17]  , bp[17]);
+                                cp[18] =   (float)Math.Atan2 (ap[18]  , bp[18]);
+                                cp[19] =   (float)Math.Atan2 (ap[19]  , bp[19]);
+                                cp[20] =   (float)Math.Atan2 (ap[20]  , bp[20]);
+                                ap+=21; bp+=21; cp+=21; j-=21;
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (float)Math.Atan2 (*ap  , *bp);
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((float*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =   (float)Math.Atan2 (cp[0]  , scalar);
+                                cp[1] =   (float)Math.Atan2 (cp[1]  , scalar);
+                                cp[2] =   (float)Math.Atan2 (cp[2]  , scalar);
+                                cp[3] =   (float)Math.Atan2 (cp[3]  , scalar);
+                                cp[4] =   (float)Math.Atan2 (cp[4]  , scalar);
+                                cp[5] =   (float)Math.Atan2 (cp[5]  , scalar);
+                                cp[6] =   (float)Math.Atan2 (cp[6]  , scalar);
+                                cp[7] =   (float)Math.Atan2 (cp[7]  , scalar);
+                                cp[8] =   (float)Math.Atan2 (cp[8]  , scalar);
+                                cp[9] =   (float)Math.Atan2 (cp[9]  , scalar);
+                                cp[10] =   (float)Math.Atan2 (cp[10]  , scalar);
+                                cp[11] =   (float)Math.Atan2 (cp[11]  , scalar);
+                                cp[12] =   (float)Math.Atan2 (cp[12]  , scalar);
+                                cp[13] =   (float)Math.Atan2 (cp[13]  , scalar);
+                                cp[14] =   (float)Math.Atan2 (cp[14]  , scalar);
+                                cp[15] =   (float)Math.Atan2 (cp[15]  , scalar);
+                                cp[16] =   (float)Math.Atan2 (cp[16]  , scalar);
+                                cp[17] =   (float)Math.Atan2 (cp[17]  , scalar);
+                                cp[18] =   (float)Math.Atan2 (cp[18]  , scalar);
+                                cp[19] =   (float)Math.Atan2 (cp[19]  , scalar);
+                                cp[20] =   (float)Math.Atan2 (cp[20]  , scalar);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (float)Math.Atan2 (*cp  , scalar);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((float*)range.Item3 + range.Item1);
+                            scalar = *((float*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =   (float)Math.Atan2 (ap[0]  , scalar);
+                                cp[1] =   (float)Math.Atan2 (ap[1]  , scalar);
+                                cp[2] =   (float)Math.Atan2 (ap[2]  , scalar);
+                                cp[3] =   (float)Math.Atan2 (ap[3]  , scalar);
+                                cp[4] =   (float)Math.Atan2 (ap[4]  , scalar);
+                                cp[5] =   (float)Math.Atan2 (ap[5]  , scalar);
+                                cp[6] =   (float)Math.Atan2 (ap[6]  , scalar);
+                                cp[7] =   (float)Math.Atan2 (ap[7]  , scalar);
+                                cp[8] =   (float)Math.Atan2 (ap[8]  , scalar);
+                                cp[9] =   (float)Math.Atan2 (ap[9]  , scalar);
+                                cp[10] =   (float)Math.Atan2 (ap[10]  , scalar);
+                                cp[11] =   (float)Math.Atan2 (ap[11]  , scalar);
+                                cp[12] =   (float)Math.Atan2 (ap[12]  , scalar);
+                                cp[13] =   (float)Math.Atan2 (ap[13]  , scalar);
+                                cp[14] =   (float)Math.Atan2 (ap[14]  , scalar);
+                                cp[15] =   (float)Math.Atan2 (ap[15]  , scalar);
+                                cp[16] =   (float)Math.Atan2 (ap[16]  , scalar);
+                                cp[17] =   (float)Math.Atan2 (ap[17]  , scalar);
+                                cp[18] =   (float)Math.Atan2 (ap[18]  , scalar);
+                                cp[19] =   (float)Math.Atan2 (ap[19]  , scalar);
+                                cp[20] =   (float)Math.Atan2 (ap[20]  , scalar);
+                                ap+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (float)Math.Atan2 (*ap  , scalar);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((float*)range.Item3);
+                            while (j > 20) {
+                               
+                                cp[0] =   (float)Math.Atan2 (scalar  , cp[0]);
+                                cp[1] =   (float)Math.Atan2 (scalar  , cp[1]);
+                                cp[2] =   (float)Math.Atan2 (scalar  , cp[2]);
+                                cp[3] =   (float)Math.Atan2 (scalar  , cp[3]);
+                                cp[4] =   (float)Math.Atan2 (scalar  , cp[4]);
+                                cp[5] =   (float)Math.Atan2 (scalar  , cp[5]);
+                                cp[6] =   (float)Math.Atan2 (scalar  , cp[6]);
+                                cp[7] =   (float)Math.Atan2 (scalar  , cp[7]);
+                                cp[8] =   (float)Math.Atan2 (scalar  , cp[8]);
+                                cp[9] =   (float)Math.Atan2 (scalar  , cp[9]);
+                                cp[10] =   (float)Math.Atan2 (scalar  , cp[10]);
+                                cp[11] =   (float)Math.Atan2 (scalar  , cp[11]);
+                                cp[12] =   (float)Math.Atan2 (scalar  , cp[12]);
+                                cp[13] =   (float)Math.Atan2 (scalar  , cp[13]);
+                                cp[14] =   (float)Math.Atan2 (scalar  , cp[14]);
+                                cp[15] =   (float)Math.Atan2 (scalar  , cp[15]);
+                                cp[16] =   (float)Math.Atan2 (scalar  , cp[16]);
+                                cp[17] =   (float)Math.Atan2 (scalar  , cp[17]);
+                                cp[18] =   (float)Math.Atan2 (scalar  , cp[18]);
+                                cp[19] =   (float)Math.Atan2 (scalar  , cp[19]);
+                                cp[20] =   (float)Math.Atan2 (scalar  , cp[20]);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (float)Math.Atan2 (scalar  , *cp);
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((float*)range.Item3);
+                            bp = ((float*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (float)Math.Atan2 (scalar  , bp[0]);
+                                cp[1] =   (float)Math.Atan2 (scalar  , bp[1]);
+                                cp[2] =   (float)Math.Atan2 (scalar  , bp[2]);
+                                cp[3] =   (float)Math.Atan2 (scalar  , bp[3]);
+                                cp[4] =   (float)Math.Atan2 (scalar  , bp[4]);
+                                cp[5] =   (float)Math.Atan2 (scalar  , bp[5]);
+                                cp[6] =   (float)Math.Atan2 (scalar  , bp[6]);
+                                cp[7] =   (float)Math.Atan2 (scalar  , bp[7]);
+                                cp[8] =   (float)Math.Atan2 (scalar  , bp[8]);
+                                cp[9] =   (float)Math.Atan2 (scalar  , bp[9]);
+                                cp[10] =   (float)Math.Atan2 (scalar  , bp[10]);
+                                cp[11] =   (float)Math.Atan2 (scalar  , bp[11]);
+                                cp[12] =   (float)Math.Atan2 (scalar  , bp[12]);
+                                cp[13] =   (float)Math.Atan2 (scalar  , bp[13]);
+                                cp[14] =   (float)Math.Atan2 (scalar  , bp[14]);
+                                cp[15] =   (float)Math.Atan2 (scalar  , bp[15]);
+                                cp[16] =   (float)Math.Atan2 (scalar  , bp[16]);
+                                cp[17] =   (float)Math.Atan2 (scalar  , bp[17]);
+                                cp[18] =   (float)Math.Atan2 (scalar  , bp[18]);
+                                cp[19] =   (float)Math.Atan2 (scalar  , bp[19]);
+                                cp[20] =   (float)Math.Atan2 (scalar  , bp[20]);
+                                bp+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (float)Math.Atan2 (scalar  , *bp);
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work 
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                
+                fixed ( float* arrAP = arrA)
+                fixed ( float* arrBP = arrB)
+                fixed ( float* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range 
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new  ILRetArray< float>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<float>  atan2Ex(ILInArray<float> A, ILInArray<float> B) {
+            //using (ILScope.Enter(A, B)) { we cannot start a new scope here, since this would prevent A and B to be used implace if applicable
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<float>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<float>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<float>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                dim = -(dim - 1);  // 0 -> 1, 1 -> 0
+                #endregion
+
+                #region parameter preparation
+               
+                float[] retArr;
+               
+                float[] arrA = A.GetArrayForRead();
+               
+                float[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int workItemMultiplierLenA;
+                int workItemMultiplierLenB;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<float>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    workItemMultiplierLenB = outDims[0]; 
+                    workItemMultiplierLenA = dim;  // 0 for column, 1 for row vector
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<float>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    workItemMultiplierLenB = dim;  // 0 for column, 1 for row vector
+                    workItemMultiplierLenA = outDims[0]; 
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one singleton dimension in either A or B");
+                }
+                int itLen = outDims[0]; // (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<float> retStorage = new ILDenseStorage<float>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    float* ap;
+                   
+                    float* bp;
+                   
+                    float* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            if (dim == 0) {
+                                bp = (float*)range.Item3;
+                                cp = (float*)range.Item4; 
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (float*)range.Item2;
+                                    int l = itLen; 
+                                    while (l > 10) {
+                                        cp[0] =   (float)Math.Atan2 (ap[0]  , bp[0]);
+                                        cp[1] =   (float)Math.Atan2 (ap[1]  , bp[1]);
+                                        cp[2] =   (float)Math.Atan2 (ap[2]  , bp[2]);
+                                        cp[3] =   (float)Math.Atan2 (ap[3]  , bp[3]);
+                                        cp[4] =   (float)Math.Atan2 (ap[4]  , bp[4]);
+                                        cp[5] =   (float)Math.Atan2 (ap[5]  , bp[5]);
+                                        cp[6] =   (float)Math.Atan2 (ap[6]  , bp[6]);
+                                        cp[7] =   (float)Math.Atan2 (ap[7]  , bp[7]);
+                                        cp[8] =   (float)Math.Atan2 (ap[8]  , bp[8]);
+                                        cp[9] =   (float)Math.Atan2 (ap[9]  , bp[9]);
+                                        cp[10] =   (float)Math.Atan2 (ap[10]  , bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =   (float)Math.Atan2 (*ap++  , *bp++);
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                ap = (float*)range.Item2;
+                                bp = (float*)range.Item3;
+                                cp = (float*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   float val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (float)Math.Atan2 (val  , bp[0]);
+                                        cp[1] =   (float)Math.Atan2 (val  , bp[1]);
+                                        cp[2] =   (float)Math.Atan2 (val  , bp[2]);
+                                        cp[3] =   (float)Math.Atan2 (val  , bp[3]);
+                                        cp[4] =   (float)Math.Atan2 (val  , bp[4]);
+                                        cp[5] =   (float)Math.Atan2 (val  , bp[5]);
+                                        cp[6] =   (float)Math.Atan2 (val  , bp[6]);
+                                        cp[7] =   (float)Math.Atan2 (val  , bp[7]);
+                                        cp[8] =   (float)Math.Atan2 (val  , bp[8]);
+                                        cp[9] =   (float)Math.Atan2 (val  , bp[9]);
+                                        cp[10] =   (float)Math.Atan2 (val  , bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11; 
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =   (float)Math.Atan2 (val  , *bp++);
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            if (dim == 0) {
+                                cp = (float*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (float*)range.Item2;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (float)Math.Atan2 (ap[0]  , cp[0]);
+                                        cp[1] =   (float)Math.Atan2 (ap[1]  , cp[1]);
+                                        cp[2] =   (float)Math.Atan2 (ap[2]  , cp[2]);
+                                        cp[3] =   (float)Math.Atan2 (ap[3]  , cp[3]);
+                                        cp[4] =   (float)Math.Atan2 (ap[4]  , cp[4]);
+                                        cp[5] =   (float)Math.Atan2 (ap[5]  , cp[5]);
+                                        cp[6] =   (float)Math.Atan2 (ap[6]  , cp[6]);
+                                        cp[7] =   (float)Math.Atan2 (ap[7]  , cp[7]);
+                                        cp[8] =   (float)Math.Atan2 (ap[8]  , cp[8]);
+                                        cp[9] =   (float)Math.Atan2 (ap[9]  , cp[9]);
+                                        cp[10] =   (float)Math.Atan2 (ap[10]  , cp[10]);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (float)Math.Atan2 (*ap++  , *cp);
+                                        cp++; 
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                cp = (float*)range.Item4;
+                                ap = (float*)range.Item2;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    float val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (float)Math.Atan2 (val  , cp[0]);
+                                        cp[1] =   (float)Math.Atan2 (val  , cp[1]);
+                                        cp[2] =   (float)Math.Atan2 (val  , cp[2]);
+                                        cp[3] =   (float)Math.Atan2 (val  , cp[3]);
+                                        cp[4] =   (float)Math.Atan2 (val  , cp[4]);
+                                        cp[5] =   (float)Math.Atan2 (val  , cp[5]);
+                                        cp[6] =   (float)Math.Atan2 (val  , cp[6]);
+                                        cp[7] =   (float)Math.Atan2 (val  , cp[7]);
+                                        cp[8] =   (float)Math.Atan2 (val  , cp[8]);
+                                        cp[9] =   (float)Math.Atan2 (val  , cp[9]);
+                                        cp[10] =   (float)Math.Atan2 (val  , cp[10]);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (float)Math.Atan2 (val  , *cp);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            if (dim == 0) {
+                                ap = (float*)range.Item2;
+                                cp = (float*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (float*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (float)Math.Atan2 (ap[0]  , bp[0]);
+                                        cp[1] =   (float)Math.Atan2 (ap[1]  , bp[1]);
+                                        cp[2] =   (float)Math.Atan2 (ap[2]  , bp[2]);
+                                        cp[3] =   (float)Math.Atan2 (ap[3]  , bp[3]);
+                                        cp[4] =   (float)Math.Atan2 (ap[4]  , bp[4]);
+                                        cp[5] =   (float)Math.Atan2 (ap[5]  , bp[5]);
+                                        cp[6] =   (float)Math.Atan2 (ap[6]  , bp[6]);
+                                        cp[7] =   (float)Math.Atan2 (ap[7]  , bp[7]);
+                                        cp[8] =   (float)Math.Atan2 (ap[8]  , bp[8]);
+                                        cp[9] =   (float)Math.Atan2 (ap[9]  , bp[9]);
+                                        cp[10] =   (float)Math.Atan2 (ap[10]  , bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (float)Math.Atan2 (*ap  , *bp);
+                                        ap++;
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                ap = (float*)range.Item2;
+                                bp = (float*)range.Item3;
+                                cp = (float*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   float val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (float)Math.Atan2 (ap[0]  , val);
+                                        cp[1] =   (float)Math.Atan2 (ap[1]  , val);
+                                        cp[2] =   (float)Math.Atan2 (ap[2]  , val);
+                                        cp[3] =   (float)Math.Atan2 (ap[3]  , val);
+                                        cp[4] =   (float)Math.Atan2 (ap[4]  , val);
+                                        cp[5] =   (float)Math.Atan2 (ap[5]  , val);
+                                        cp[6] =   (float)Math.Atan2 (ap[6]  , val);
+                                        cp[7] =   (float)Math.Atan2 (ap[7]  , val);
+                                        cp[8] =   (float)Math.Atan2 (ap[8]  , val);
+                                        cp[9] =   (float)Math.Atan2 (ap[9]  , val);
+                                        cp[10] =   (float)Math.Atan2 (ap[10]  , val);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (float)Math.Atan2 (*ap  , val);
+                                        ap++;
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            if (dim == 0) {
+                                cp = (float*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (float*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (float)Math.Atan2 (cp[0]  , bp[0]);
+                                        cp[1] =   (float)Math.Atan2 (cp[1]  , bp[1]);
+                                        cp[2] =   (float)Math.Atan2 (cp[2]  , bp[2]);
+                                        cp[3] =   (float)Math.Atan2 (cp[3]  , bp[3]);
+                                        cp[4] =   (float)Math.Atan2 (cp[4]  , bp[4]);
+                                        cp[5] =   (float)Math.Atan2 (cp[5]  , bp[5]);
+                                        cp[6] =   (float)Math.Atan2 (cp[6]  , bp[6]);
+                                        cp[7] =   (float)Math.Atan2 (cp[7]  , bp[7]);
+                                        cp[8] =   (float)Math.Atan2 (cp[8]  , bp[8]);
+                                        cp[9] =   (float)Math.Atan2 (cp[9]  , bp[9]);
+                                        cp[10] =   (float)Math.Atan2 (cp[10]  , bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (float)Math.Atan2 (*cp  , *bp);
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                bp = (float*)range.Item3;
+                                cp = (float*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    float val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (float)Math.Atan2 (cp[0]  , val);
+                                        cp[1] =   (float)Math.Atan2 (cp[1]  , val);
+                                        cp[2] =   (float)Math.Atan2 (cp[2]  , val);
+                                        cp[3] =   (float)Math.Atan2 (cp[3]  , val);
+                                        cp[4] =   (float)Math.Atan2 (cp[4]  , val);
+                                        cp[5] =   (float)Math.Atan2 (cp[5]  , val);
+                                        cp[6] =   (float)Math.Atan2 (cp[6]  , val);
+                                        cp[7] =   (float)Math.Atan2 (cp[7]  , val);
+                                        cp[8] =   (float)Math.Atan2 (cp[8]  , val);
+                                        cp[9] =   (float)Math.Atan2 (cp[9]  , val);
+                                        cp[10] =   (float)Math.Atan2 (cp[10]  , val);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l --> 0) {
+                                        *cp =   (float)Math.Atan2 (*cp  , val);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outDims.NumberOfElements >= Settings.s_minParallelElement1Count
+                    && outDims[1] > 1) {
+                        if (outDims[1] > workItemCount) {
+                        workItemLength = outDims[1] / workItemCount;
+                    } else {
+                        workItemLength = outDims[1] / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outDims[1];
+                    workItemCount = 1;
+                }
+
+                fixed ( float* arrAP = arrA)
+                fixed ( float* arrBP = arrB)
+                fixed ( float* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, IntPtr, IntPtr, IntPtr> range = new Tuple<int, IntPtr, IntPtr, IntPtr>
+                               (workItemLength
+                               , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                               , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                               , (IntPtr)(retArrP + i * outDims[0] * workItemLength)); 
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, IntPtr, IntPtr, IntPtr>
+                                (outDims[1] - i * workItemLength
+                                , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                                , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                                , (IntPtr)(retArrP + i * outDims[0] * workItemLength)));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<float>(retStorage);
+            //}  // no scopes here! it disables implace operations
+        }
+
+        /// <summary>Arcus tangens of elements</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Array with elementwise arcus tangens of both inputs</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<double>  atan2(ILInArray<double> A, ILInArray<double> B) {
+            using (ILScope.Enter(A,B)) {
+                int outLen; 
+                BinOpItMode mode; 
+                double [] retArr;
+                double [] arrA = A.GetArrayForRead();
+                double[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size; 
+                    if (B.IsScalar) {
+                       
+                        return new  ILRetArray<double> (new  double [1]{  Math.Atan2 (A.GetValue(0)  , B.GetValue(0))}, A.Size);
+                    } else if (B.IsEmpty) {
+                        return  ILRetArray<double>.empty(outDims); 
+                    } else {
+                        outLen = outDims.NumberOfElements; 
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< double > (outLen);
+                            mode = BinOpItMode.SAN; 
+                        } else {
+                            mode = BinOpItMode.SAI; 
+                        }
+                    }
+                } else {
+                    outDims = A.Size; 
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return  ILRetArray<double>.empty(A.Size);  
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< double > (outLen);
+                            mode = BinOpItMode.ASN; 
+                        } else {
+                            mode = BinOpItMode.ASI; 
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  atan2Ex(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (A.TryGetStorage4InplaceOp(out retArr)) 
+                            mode  = BinOpItMode.AAIA; 
+                        else if (B.TryGetStorage4InplaceOp(out retArr)) 
+                            mode = BinOpItMode.AAIB; 
+                        else {
+                            retArr = ILMemoryPool.Pool.New< double > (outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<double> retStorage = new ILDenseStorage<double>(retArr, outDims);
+                int i = 0, workerCount = 1; 
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    double* cp = (double*)range.Item5 + range.Item1;
+                    double scalar;
+                    int j = range.Item2; 
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           double* bp = ((double*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                                cp[0] =   Math.Atan2 (cp[0]  , bp[0]);
+                                cp[1] =   Math.Atan2 (cp[1]  , bp[1]);
+                                cp[2] =   Math.Atan2 (cp[2]  , bp[2]);
+                                cp[3] =   Math.Atan2 (cp[3]  , bp[3]);
+                                cp[4] =   Math.Atan2 (cp[4]  , bp[4]);
+                                cp[5] =   Math.Atan2 (cp[5]  , bp[5]);
+                                cp[6] =   Math.Atan2 (cp[6]  , bp[6]);
+                                cp[7] =   Math.Atan2 (cp[7]  , bp[7]);
+                                cp[8] =   Math.Atan2 (cp[8]  , bp[8]);
+                                cp[9] =   Math.Atan2 (cp[9]  , bp[9]);
+                                cp[10] =   Math.Atan2 (cp[10]  , bp[10]);
+                                cp[11] =   Math.Atan2 (cp[11]  , bp[11]);
+                                cp[12] =   Math.Atan2 (cp[12]  , bp[12]);
+                                cp[13] =   Math.Atan2 (cp[13]  , bp[13]);
+                                cp[14] =   Math.Atan2 (cp[14]  , bp[14]);
+                                cp[15] =   Math.Atan2 (cp[15]  , bp[15]);
+                                cp[16] =   Math.Atan2 (cp[16]  , bp[16]);
+                                cp[17] =   Math.Atan2 (cp[17]  , bp[17]);
+                                cp[18] =   Math.Atan2 (cp[18]  , bp[18]);
+                                cp[19] =   Math.Atan2 (cp[19]  , bp[19]);
+                                cp[20] =   Math.Atan2 (cp[20]  , bp[20]);
+                                cp += 21; bp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   Math.Atan2 (*cp  , *bp);
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           double* ap = ((double*)range.Item3 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   Math.Atan2 (ap[0]  , cp[0]);
+                                cp[1] =   Math.Atan2 (ap[1]  , cp[1]);
+                                cp[2] =   Math.Atan2 (ap[2]  , cp[2]);
+                                cp[3] =   Math.Atan2 (ap[3]  , cp[3]);
+                                cp[4] =   Math.Atan2 (ap[4]  , cp[4]);
+                                cp[5] =   Math.Atan2 (ap[5]  , cp[5]);
+                                cp[6] =   Math.Atan2 (ap[6]  , cp[6]);
+                                cp[7] =   Math.Atan2 (ap[7]  , cp[7]);
+                                cp[8] =   Math.Atan2 (ap[8]  , cp[8]);
+                                cp[9] =   Math.Atan2 (ap[9]  , cp[9]);
+                                cp[10] =   Math.Atan2 (ap[10]  , cp[10]);
+                                cp[11] =   Math.Atan2 (ap[11]  , cp[11]);
+                                cp[12] =   Math.Atan2 (ap[12]  , cp[12]);
+                                cp[13] =   Math.Atan2 (ap[13]  , cp[13]);
+                                cp[14] =   Math.Atan2 (ap[14]  , cp[14]);
+                                cp[15] =   Math.Atan2 (ap[15]  , cp[15]);
+                                cp[16] =   Math.Atan2 (ap[16]  , cp[16]);
+                                cp[17] =   Math.Atan2 (ap[17]  , cp[17]);
+                                cp[18] =   Math.Atan2 (ap[18]  , cp[18]);
+                                cp[19] =   Math.Atan2 (ap[19]  , cp[19]);
+                                cp[20] =   Math.Atan2 (ap[20]  , cp[20]);
+                                ap += 21; cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   Math.Atan2 (*ap  , *cp);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((double*)range.Item3 + range.Item1);
+                            bp = ((double*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   Math.Atan2 (ap[0]  , bp[0]);
+                                cp[1] =   Math.Atan2 (ap[1]  , bp[1]);
+                                cp[2] =   Math.Atan2 (ap[2]  , bp[2]);
+                                cp[3] =   Math.Atan2 (ap[3]  , bp[3]);
+                                cp[4] =   Math.Atan2 (ap[4]  , bp[4]);
+                                cp[5] =   Math.Atan2 (ap[5]  , bp[5]);
+                                cp[6] =   Math.Atan2 (ap[6]  , bp[6]);
+                                cp[7] =   Math.Atan2 (ap[7]  , bp[7]);
+                                cp[8] =   Math.Atan2 (ap[8]  , bp[8]);
+                                cp[9] =   Math.Atan2 (ap[9]  , bp[9]);
+                                cp[10] =   Math.Atan2 (ap[10]  , bp[10]);
+                                cp[11] =   Math.Atan2 (ap[11]  , bp[11]);
+                                cp[12] =   Math.Atan2 (ap[12]  , bp[12]);
+                                cp[13] =   Math.Atan2 (ap[13]  , bp[13]);
+                                cp[14] =   Math.Atan2 (ap[14]  , bp[14]);
+                                cp[15] =   Math.Atan2 (ap[15]  , bp[15]);
+                                cp[16] =   Math.Atan2 (ap[16]  , bp[16]);
+                                cp[17] =   Math.Atan2 (ap[17]  , bp[17]);
+                                cp[18] =   Math.Atan2 (ap[18]  , bp[18]);
+                                cp[19] =   Math.Atan2 (ap[19]  , bp[19]);
+                                cp[20] =   Math.Atan2 (ap[20]  , bp[20]);
+                                ap+=21; bp+=21; cp+=21; j-=21;
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   Math.Atan2 (*ap  , *bp);
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((double*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =   Math.Atan2 (cp[0]  , scalar);
+                                cp[1] =   Math.Atan2 (cp[1]  , scalar);
+                                cp[2] =   Math.Atan2 (cp[2]  , scalar);
+                                cp[3] =   Math.Atan2 (cp[3]  , scalar);
+                                cp[4] =   Math.Atan2 (cp[4]  , scalar);
+                                cp[5] =   Math.Atan2 (cp[5]  , scalar);
+                                cp[6] =   Math.Atan2 (cp[6]  , scalar);
+                                cp[7] =   Math.Atan2 (cp[7]  , scalar);
+                                cp[8] =   Math.Atan2 (cp[8]  , scalar);
+                                cp[9] =   Math.Atan2 (cp[9]  , scalar);
+                                cp[10] =   Math.Atan2 (cp[10]  , scalar);
+                                cp[11] =   Math.Atan2 (cp[11]  , scalar);
+                                cp[12] =   Math.Atan2 (cp[12]  , scalar);
+                                cp[13] =   Math.Atan2 (cp[13]  , scalar);
+                                cp[14] =   Math.Atan2 (cp[14]  , scalar);
+                                cp[15] =   Math.Atan2 (cp[15]  , scalar);
+                                cp[16] =   Math.Atan2 (cp[16]  , scalar);
+                                cp[17] =   Math.Atan2 (cp[17]  , scalar);
+                                cp[18] =   Math.Atan2 (cp[18]  , scalar);
+                                cp[19] =   Math.Atan2 (cp[19]  , scalar);
+                                cp[20] =   Math.Atan2 (cp[20]  , scalar);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   Math.Atan2 (*cp  , scalar);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((double*)range.Item3 + range.Item1);
+                            scalar = *((double*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =   Math.Atan2 (ap[0]  , scalar);
+                                cp[1] =   Math.Atan2 (ap[1]  , scalar);
+                                cp[2] =   Math.Atan2 (ap[2]  , scalar);
+                                cp[3] =   Math.Atan2 (ap[3]  , scalar);
+                                cp[4] =   Math.Atan2 (ap[4]  , scalar);
+                                cp[5] =   Math.Atan2 (ap[5]  , scalar);
+                                cp[6] =   Math.Atan2 (ap[6]  , scalar);
+                                cp[7] =   Math.Atan2 (ap[7]  , scalar);
+                                cp[8] =   Math.Atan2 (ap[8]  , scalar);
+                                cp[9] =   Math.Atan2 (ap[9]  , scalar);
+                                cp[10] =   Math.Atan2 (ap[10]  , scalar);
+                                cp[11] =   Math.Atan2 (ap[11]  , scalar);
+                                cp[12] =   Math.Atan2 (ap[12]  , scalar);
+                                cp[13] =   Math.Atan2 (ap[13]  , scalar);
+                                cp[14] =   Math.Atan2 (ap[14]  , scalar);
+                                cp[15] =   Math.Atan2 (ap[15]  , scalar);
+                                cp[16] =   Math.Atan2 (ap[16]  , scalar);
+                                cp[17] =   Math.Atan2 (ap[17]  , scalar);
+                                cp[18] =   Math.Atan2 (ap[18]  , scalar);
+                                cp[19] =   Math.Atan2 (ap[19]  , scalar);
+                                cp[20] =   Math.Atan2 (ap[20]  , scalar);
+                                ap+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   Math.Atan2 (*ap  , scalar);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((double*)range.Item3);
+                            while (j > 20) {
+                               
+                                cp[0] =   Math.Atan2 (scalar  , cp[0]);
+                                cp[1] =   Math.Atan2 (scalar  , cp[1]);
+                                cp[2] =   Math.Atan2 (scalar  , cp[2]);
+                                cp[3] =   Math.Atan2 (scalar  , cp[3]);
+                                cp[4] =   Math.Atan2 (scalar  , cp[4]);
+                                cp[5] =   Math.Atan2 (scalar  , cp[5]);
+                                cp[6] =   Math.Atan2 (scalar  , cp[6]);
+                                cp[7] =   Math.Atan2 (scalar  , cp[7]);
+                                cp[8] =   Math.Atan2 (scalar  , cp[8]);
+                                cp[9] =   Math.Atan2 (scalar  , cp[9]);
+                                cp[10] =   Math.Atan2 (scalar  , cp[10]);
+                                cp[11] =   Math.Atan2 (scalar  , cp[11]);
+                                cp[12] =   Math.Atan2 (scalar  , cp[12]);
+                                cp[13] =   Math.Atan2 (scalar  , cp[13]);
+                                cp[14] =   Math.Atan2 (scalar  , cp[14]);
+                                cp[15] =   Math.Atan2 (scalar  , cp[15]);
+                                cp[16] =   Math.Atan2 (scalar  , cp[16]);
+                                cp[17] =   Math.Atan2 (scalar  , cp[17]);
+                                cp[18] =   Math.Atan2 (scalar  , cp[18]);
+                                cp[19] =   Math.Atan2 (scalar  , cp[19]);
+                                cp[20] =   Math.Atan2 (scalar  , cp[20]);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   Math.Atan2 (scalar  , *cp);
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((double*)range.Item3);
+                            bp = ((double*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   Math.Atan2 (scalar  , bp[0]);
+                                cp[1] =   Math.Atan2 (scalar  , bp[1]);
+                                cp[2] =   Math.Atan2 (scalar  , bp[2]);
+                                cp[3] =   Math.Atan2 (scalar  , bp[3]);
+                                cp[4] =   Math.Atan2 (scalar  , bp[4]);
+                                cp[5] =   Math.Atan2 (scalar  , bp[5]);
+                                cp[6] =   Math.Atan2 (scalar  , bp[6]);
+                                cp[7] =   Math.Atan2 (scalar  , bp[7]);
+                                cp[8] =   Math.Atan2 (scalar  , bp[8]);
+                                cp[9] =   Math.Atan2 (scalar  , bp[9]);
+                                cp[10] =   Math.Atan2 (scalar  , bp[10]);
+                                cp[11] =   Math.Atan2 (scalar  , bp[11]);
+                                cp[12] =   Math.Atan2 (scalar  , bp[12]);
+                                cp[13] =   Math.Atan2 (scalar  , bp[13]);
+                                cp[14] =   Math.Atan2 (scalar  , bp[14]);
+                                cp[15] =   Math.Atan2 (scalar  , bp[15]);
+                                cp[16] =   Math.Atan2 (scalar  , bp[16]);
+                                cp[17] =   Math.Atan2 (scalar  , bp[17]);
+                                cp[18] =   Math.Atan2 (scalar  , bp[18]);
+                                cp[19] =   Math.Atan2 (scalar  , bp[19]);
+                                cp[20] =   Math.Atan2 (scalar  , bp[20]);
+                                bp+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   Math.Atan2 (scalar  , *bp);
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work 
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                
+                fixed ( double* arrAP = arrA)
+                fixed ( double* arrBP = arrB)
+                fixed ( double* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range 
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new  ILRetArray< double>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<double>  atan2Ex(ILInArray<double> A, ILInArray<double> B) {
+            //using (ILScope.Enter(A, B)) { we cannot start a new scope here, since this would prevent A and B to be used implace if applicable
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<double>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<double>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<double>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                dim = -(dim - 1);  // 0 -> 1, 1 -> 0
+                #endregion
+
+                #region parameter preparation
+               
+                double[] retArr;
+               
+                double[] arrA = A.GetArrayForRead();
+               
+                double[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int workItemMultiplierLenA;
+                int workItemMultiplierLenB;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<double>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    workItemMultiplierLenB = outDims[0]; 
+                    workItemMultiplierLenA = dim;  // 0 for column, 1 for row vector
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<double>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    workItemMultiplierLenB = dim;  // 0 for column, 1 for row vector
+                    workItemMultiplierLenA = outDims[0]; 
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one singleton dimension in either A or B");
+                }
+                int itLen = outDims[0]; // (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<double> retStorage = new ILDenseStorage<double>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    double* ap;
+                   
+                    double* bp;
+                   
+                    double* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            if (dim == 0) {
+                                bp = (double*)range.Item3;
+                                cp = (double*)range.Item4; 
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (double*)range.Item2;
+                                    int l = itLen; 
+                                    while (l > 10) {
+                                        cp[0] =   Math.Atan2 (ap[0]  , bp[0]);
+                                        cp[1] =   Math.Atan2 (ap[1]  , bp[1]);
+                                        cp[2] =   Math.Atan2 (ap[2]  , bp[2]);
+                                        cp[3] =   Math.Atan2 (ap[3]  , bp[3]);
+                                        cp[4] =   Math.Atan2 (ap[4]  , bp[4]);
+                                        cp[5] =   Math.Atan2 (ap[5]  , bp[5]);
+                                        cp[6] =   Math.Atan2 (ap[6]  , bp[6]);
+                                        cp[7] =   Math.Atan2 (ap[7]  , bp[7]);
+                                        cp[8] =   Math.Atan2 (ap[8]  , bp[8]);
+                                        cp[9] =   Math.Atan2 (ap[9]  , bp[9]);
+                                        cp[10] =   Math.Atan2 (ap[10]  , bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =   Math.Atan2 (*ap++  , *bp++);
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                ap = (double*)range.Item2;
+                                bp = (double*)range.Item3;
+                                cp = (double*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   double val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   Math.Atan2 (val  , bp[0]);
+                                        cp[1] =   Math.Atan2 (val  , bp[1]);
+                                        cp[2] =   Math.Atan2 (val  , bp[2]);
+                                        cp[3] =   Math.Atan2 (val  , bp[3]);
+                                        cp[4] =   Math.Atan2 (val  , bp[4]);
+                                        cp[5] =   Math.Atan2 (val  , bp[5]);
+                                        cp[6] =   Math.Atan2 (val  , bp[6]);
+                                        cp[7] =   Math.Atan2 (val  , bp[7]);
+                                        cp[8] =   Math.Atan2 (val  , bp[8]);
+                                        cp[9] =   Math.Atan2 (val  , bp[9]);
+                                        cp[10] =   Math.Atan2 (val  , bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11; 
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =   Math.Atan2 (val  , *bp++);
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            if (dim == 0) {
+                                cp = (double*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (double*)range.Item2;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   Math.Atan2 (ap[0]  , cp[0]);
+                                        cp[1] =   Math.Atan2 (ap[1]  , cp[1]);
+                                        cp[2] =   Math.Atan2 (ap[2]  , cp[2]);
+                                        cp[3] =   Math.Atan2 (ap[3]  , cp[3]);
+                                        cp[4] =   Math.Atan2 (ap[4]  , cp[4]);
+                                        cp[5] =   Math.Atan2 (ap[5]  , cp[5]);
+                                        cp[6] =   Math.Atan2 (ap[6]  , cp[6]);
+                                        cp[7] =   Math.Atan2 (ap[7]  , cp[7]);
+                                        cp[8] =   Math.Atan2 (ap[8]  , cp[8]);
+                                        cp[9] =   Math.Atan2 (ap[9]  , cp[9]);
+                                        cp[10] =   Math.Atan2 (ap[10]  , cp[10]);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   Math.Atan2 (*ap++  , *cp);
+                                        cp++; 
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                cp = (double*)range.Item4;
+                                ap = (double*)range.Item2;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    double val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   Math.Atan2 (val  , cp[0]);
+                                        cp[1] =   Math.Atan2 (val  , cp[1]);
+                                        cp[2] =   Math.Atan2 (val  , cp[2]);
+                                        cp[3] =   Math.Atan2 (val  , cp[3]);
+                                        cp[4] =   Math.Atan2 (val  , cp[4]);
+                                        cp[5] =   Math.Atan2 (val  , cp[5]);
+                                        cp[6] =   Math.Atan2 (val  , cp[6]);
+                                        cp[7] =   Math.Atan2 (val  , cp[7]);
+                                        cp[8] =   Math.Atan2 (val  , cp[8]);
+                                        cp[9] =   Math.Atan2 (val  , cp[9]);
+                                        cp[10] =   Math.Atan2 (val  , cp[10]);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   Math.Atan2 (val  , *cp);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            if (dim == 0) {
+                                ap = (double*)range.Item2;
+                                cp = (double*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (double*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   Math.Atan2 (ap[0]  , bp[0]);
+                                        cp[1] =   Math.Atan2 (ap[1]  , bp[1]);
+                                        cp[2] =   Math.Atan2 (ap[2]  , bp[2]);
+                                        cp[3] =   Math.Atan2 (ap[3]  , bp[3]);
+                                        cp[4] =   Math.Atan2 (ap[4]  , bp[4]);
+                                        cp[5] =   Math.Atan2 (ap[5]  , bp[5]);
+                                        cp[6] =   Math.Atan2 (ap[6]  , bp[6]);
+                                        cp[7] =   Math.Atan2 (ap[7]  , bp[7]);
+                                        cp[8] =   Math.Atan2 (ap[8]  , bp[8]);
+                                        cp[9] =   Math.Atan2 (ap[9]  , bp[9]);
+                                        cp[10] =   Math.Atan2 (ap[10]  , bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   Math.Atan2 (*ap  , *bp);
+                                        ap++;
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                ap = (double*)range.Item2;
+                                bp = (double*)range.Item3;
+                                cp = (double*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   double val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   Math.Atan2 (ap[0]  , val);
+                                        cp[1] =   Math.Atan2 (ap[1]  , val);
+                                        cp[2] =   Math.Atan2 (ap[2]  , val);
+                                        cp[3] =   Math.Atan2 (ap[3]  , val);
+                                        cp[4] =   Math.Atan2 (ap[4]  , val);
+                                        cp[5] =   Math.Atan2 (ap[5]  , val);
+                                        cp[6] =   Math.Atan2 (ap[6]  , val);
+                                        cp[7] =   Math.Atan2 (ap[7]  , val);
+                                        cp[8] =   Math.Atan2 (ap[8]  , val);
+                                        cp[9] =   Math.Atan2 (ap[9]  , val);
+                                        cp[10] =   Math.Atan2 (ap[10]  , val);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   Math.Atan2 (*ap  , val);
+                                        ap++;
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            if (dim == 0) {
+                                cp = (double*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (double*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   Math.Atan2 (cp[0]  , bp[0]);
+                                        cp[1] =   Math.Atan2 (cp[1]  , bp[1]);
+                                        cp[2] =   Math.Atan2 (cp[2]  , bp[2]);
+                                        cp[3] =   Math.Atan2 (cp[3]  , bp[3]);
+                                        cp[4] =   Math.Atan2 (cp[4]  , bp[4]);
+                                        cp[5] =   Math.Atan2 (cp[5]  , bp[5]);
+                                        cp[6] =   Math.Atan2 (cp[6]  , bp[6]);
+                                        cp[7] =   Math.Atan2 (cp[7]  , bp[7]);
+                                        cp[8] =   Math.Atan2 (cp[8]  , bp[8]);
+                                        cp[9] =   Math.Atan2 (cp[9]  , bp[9]);
+                                        cp[10] =   Math.Atan2 (cp[10]  , bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   Math.Atan2 (*cp  , *bp);
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                bp = (double*)range.Item3;
+                                cp = (double*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    double val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   Math.Atan2 (cp[0]  , val);
+                                        cp[1] =   Math.Atan2 (cp[1]  , val);
+                                        cp[2] =   Math.Atan2 (cp[2]  , val);
+                                        cp[3] =   Math.Atan2 (cp[3]  , val);
+                                        cp[4] =   Math.Atan2 (cp[4]  , val);
+                                        cp[5] =   Math.Atan2 (cp[5]  , val);
+                                        cp[6] =   Math.Atan2 (cp[6]  , val);
+                                        cp[7] =   Math.Atan2 (cp[7]  , val);
+                                        cp[8] =   Math.Atan2 (cp[8]  , val);
+                                        cp[9] =   Math.Atan2 (cp[9]  , val);
+                                        cp[10] =   Math.Atan2 (cp[10]  , val);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l --> 0) {
+                                        *cp =   Math.Atan2 (*cp  , val);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outDims.NumberOfElements >= Settings.s_minParallelElement1Count
+                    && outDims[1] > 1) {
+                        if (outDims[1] > workItemCount) {
+                        workItemLength = outDims[1] / workItemCount;
+                    } else {
+                        workItemLength = outDims[1] / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outDims[1];
+                    workItemCount = 1;
+                }
+
+                fixed ( double* arrAP = arrA)
+                fixed ( double* arrBP = arrB)
+                fixed ( double* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, IntPtr, IntPtr, IntPtr> range = new Tuple<int, IntPtr, IntPtr, IntPtr>
+                               (workItemLength
+                               , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                               , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                               , (IntPtr)(retArrP + i * outDims[0] * workItemLength)); 
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, IntPtr, IntPtr, IntPtr>
+                                (outDims[1] - i * workItemLength
+                                , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                                , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                                , (IntPtr)(retArrP + i * outDims[0] * workItemLength)));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<double>(retStorage);
+            //}  // no scopes here! it disables implace operations
+        }
+
+
+#endregion HYCALPER AUTO GENERATED CODE
+   
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/cart2pol.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/cart2pol.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/cart2pol.cs	(revision 9102)
@@ -0,0 +1,94 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace ILNumerics {
+
+    // ToDo: DOKU remarks and returns seem outdated...
+    public partial class ILMath {
+
+        /// <summary>
+        /// Transform scalar coordinates into polar (cylindrical) coordinates
+        /// </summary>
+        /// <param name="X">X coordinates</param>
+        /// <param name="Y">Y coordinates</param>
+        /// <param name="Z">Z coordinates (height)</param>
+        /// <param name="outRadius">[Output] Radius if not null on entry</param>
+        /// <param name="outZ">[Output] Z if not null on entry</param>
+        /// <returns>Angles; radius and Z are returned as output parameters, if on entry not null</returns>
+        /// <remarks>Theta, radius and Z must be the same size or either one may be scalar. 
+        /// Polar coordinate arrays returned are of the same size then the input arrays.</remarks>
+        public static ILRetArray<double> cart2pol(ILInArray<double> X, ILInArray<double> Y, ILInArray<double> Z
+                                        ,ILOutArray<double> outRadius, ILOutArray<double> outZ) {
+            using (ILScope.Enter(X,Y,Z)) {    
+                if (!object.Equals(outRadius, null)) 
+                    outRadius.a = sqrt(X * X + Y * Y); 
+                if (!object.Equals(outZ,null)) 
+                    outZ.a = Z.C; 
+                return atan2(Y,X); 
+            }
+        }
+
+        /// <summary>
+        /// Transform scalar coordinates into polar (cylindrical) coordinates
+        /// </summary>
+        /// <param name="X">X coordinates</param>
+        /// <param name="Y">Y coordinates</param>
+        /// <param name="Z">Z coordinates (height)</param>
+        /// <param name="outRadius">[Output] Radius if not null on entry</param>
+        /// <param name="outZ">[Output] Z if not null on entry</param>
+        /// <returns>Angles; radius and Z are returned as output parameters, if on entry not null</returns>
+        /// <remarks>Theta, radius and Z must be the same size or either one may be scalar. 
+        /// Polar coordinate arrays returned are of the same size then the input arrays.</remarks>
+        public static ILRetArray<float> cart2pol(ILInArray<float> X, ILInArray<float> Y, ILInArray<float> Z
+                                        ,ILOutArray<float> outRadius, ILOutArray<float> outZ) {
+            using (ILScope.Enter(X,Y,Z)) {    
+                if (!object.Equals(outRadius, null))
+                    outRadius.a = sqrt(X * X + Y * Y); 
+                if (!object.Equals(outZ,null)) 
+                    outZ.a = Z.C; 
+                return atan2(Y,X); 
+            }
+        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/ccomplex.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/ccomplex.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/ccomplex.cs	(revision 9102)
@@ -0,0 +1,97 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.InteropServices; 
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Native;
+using ILNumerics.Exceptions;
+
+namespace ILNumerics {
+
+    public partial class ILMath {
+
+        /// <summary>
+        /// Create complex array from real and imaginary parts 
+        /// </summary>
+        /// <param name="real">Array with real part elements</param>
+        /// <param name="imag">Array with imaginary part elements</param>
+        /// <returns>Complex array constructed out of real and imaginary parts</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arguments is not the same.</exception>
+        public static ILRetArray<complex> ccomplex(ILInArray<double> real, ILInArray<double> imag) {
+            if (!real.Size.IsSameSize(imag.Size)) 
+                throw new ILArgumentException("fcomplex: input arrays must have the same size!");
+            ILRetArray<complex> ret = new ILRetArray<complex>(real.Size);
+            int nelem = real.Size.NumberOfElements; 
+            complex[] retArr = ret.GetArrayForWrite();
+            double[] realArr = real.GetArrayForRead();
+            double[] imagArr = imag.GetArrayForRead();
+            for (int i = 0; i < nelem; i++) {
+                retArr[i].imag = imagArr[i]; 
+                retArr[i].real = realArr[i]; 
+            }
+            return ret; 
+        }
+        /// <summary>
+        /// Create complex array from real and imaginary parts
+        /// </summary>
+        /// <param name="real">Array with real part elements</param>
+        /// <param name="imag">Array with imaginary part elements</param>
+        /// <returns>Complex array constructed out of real and imaginary parts</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arguments is not the same.</exception>
+        public static ILRetArray<fcomplex> ccomplex(ILInArray<float> real, ILInArray<float> imag) {
+            if (!real.Size.IsSameSize(imag.Size)) 
+                throw new ILArgumentException("fcomplex: input arrays must have the same size!");
+            ILRetArray<fcomplex> ret = new ILRetArray<fcomplex>(real.Size);
+            int nelem = real.Size.NumberOfElements; 
+            fcomplex[] retArr = ret.GetArrayForWrite();
+            float[] realArr = real.GetArrayForRead();
+            float[] imagArr = imag.GetArrayForRead();
+            for (int i = 0; i < nelem; i++) {
+                retArr[i].imag = imagArr[i]; 
+                retArr[i].real = realArr[i]; 
+            }
+            return ret; 
+        }
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/ceil.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/ceil.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/ceil.cs	(revision 9102)
@@ -0,0 +1,559 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics;
+using ILNumerics.Exceptions; 
+using ILNumerics.Storage; 
+using ILNumerics.Misc; 
+
+
+
+namespace ILNumerics {
+
+    public partial class ILMath {
+
+
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>Round towards positive infinity</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Array of same size as A with elements rounded up to next integer value</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<complex>  ceil (ILInArray< complex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<complex>(A.Size); 
+                ILSize inDim = A.Size;
+                complex[] arrA = A.GetArrayForRead(); 
+                complex [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<complex>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<complex> retStorage = new ILDenseStorage<complex>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    complex* cp = ((complex*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  complex.Ceiling(cp[0]  )  /*dummy*/;
+                            cp[1] =  complex.Ceiling(cp[1]  )  /*dummy*/;
+                            cp[2] =  complex.Ceiling(cp[2]  )  /*dummy*/;
+                            cp[3] =  complex.Ceiling(cp[3]  )  /*dummy*/;
+                            cp[4] =  complex.Ceiling(cp[4]  )  /*dummy*/;
+                            cp[5] =  complex.Ceiling(cp[5]  )  /*dummy*/;
+                            cp[6] =  complex.Ceiling(cp[6]  )  /*dummy*/;
+                            cp[7] =  complex.Ceiling(cp[7]  )  /*dummy*/;
+                            cp[8] =  complex.Ceiling(cp[8]  )  /*dummy*/;
+                            cp[9] =  complex.Ceiling(cp[9]  )  /*dummy*/;
+                            cp[10] =  complex.Ceiling(cp[10]  )  /*dummy*/;
+                            cp[11] =  complex.Ceiling(cp[11]  )  /*dummy*/;
+                            cp[12] =  complex.Ceiling(cp[12]  )  /*dummy*/;
+                            cp[13] =  complex.Ceiling(cp[13]  )  /*dummy*/;
+                            cp[14] =  complex.Ceiling(cp[14]  )  /*dummy*/;
+                            cp[15] =  complex.Ceiling(cp[15]  )  /*dummy*/;
+                            cp[16] =  complex.Ceiling(cp[16]  )  /*dummy*/;
+                            cp[17] =  complex.Ceiling(cp[17]  )  /*dummy*/;
+                            cp[18] =  complex.Ceiling(cp[18]  )  /*dummy*/;
+                            cp[19] =  complex.Ceiling(cp[19]  )  /*dummy*/;
+                            cp[20] =  complex.Ceiling(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.Ceiling(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        complex* ap = ((complex*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  complex.Ceiling(ap[0]  )  /*dummy*/;
+                            cp[1] =  complex.Ceiling(ap[1]  )  /*dummy*/;
+                            cp[2] =  complex.Ceiling(ap[2]  )  /*dummy*/;
+                            cp[3] =  complex.Ceiling(ap[3]  )  /*dummy*/;
+                            cp[4] =  complex.Ceiling(ap[4]  )  /*dummy*/;
+                            cp[5] =  complex.Ceiling(ap[5]  )  /*dummy*/;
+                            cp[6] =  complex.Ceiling(ap[6]  )  /*dummy*/;
+                            cp[7] =  complex.Ceiling(ap[7]  )  /*dummy*/;
+                            cp[8] =  complex.Ceiling(ap[8]  )  /*dummy*/;
+                            cp[9] =  complex.Ceiling(ap[9]  )  /*dummy*/;
+                            cp[10] =  complex.Ceiling(ap[10]  )  /*dummy*/;
+                            cp[11] =  complex.Ceiling(ap[11]  )  /*dummy*/;
+                            cp[12] =  complex.Ceiling(ap[12]  )  /*dummy*/;
+                            cp[13] =  complex.Ceiling(ap[13]  )  /*dummy*/;
+                            cp[14] =  complex.Ceiling(ap[14]  )  /*dummy*/;
+                            cp[15] =  complex.Ceiling(ap[15]  )  /*dummy*/;
+                            cp[16] =  complex.Ceiling(ap[16]  )  /*dummy*/;
+                            cp[17] =  complex.Ceiling(ap[17]  )  /*dummy*/;
+                            cp[18] =  complex.Ceiling(ap[18]  )  /*dummy*/;
+                            cp[19] =  complex.Ceiling(ap[19]  )  /*dummy*/;
+                            cp[20] =  complex.Ceiling(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.Ceiling(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( complex* arrAP = arrA)
+                fixed ( complex* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<complex>(retStorage);
+            }
+        }
+        /// <summary>Round towards positive infinity</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Array of same size as A with elements rounded up to next integer value</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<fcomplex>  ceil (ILInArray< fcomplex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<fcomplex>(A.Size); 
+                ILSize inDim = A.Size;
+                fcomplex[] arrA = A.GetArrayForRead(); 
+                fcomplex [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<fcomplex>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<fcomplex> retStorage = new ILDenseStorage<fcomplex>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    fcomplex* cp = ((fcomplex*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  fcomplex.Ceiling(cp[0]  )  /*dummy*/;
+                            cp[1] =  fcomplex.Ceiling(cp[1]  )  /*dummy*/;
+                            cp[2] =  fcomplex.Ceiling(cp[2]  )  /*dummy*/;
+                            cp[3] =  fcomplex.Ceiling(cp[3]  )  /*dummy*/;
+                            cp[4] =  fcomplex.Ceiling(cp[4]  )  /*dummy*/;
+                            cp[5] =  fcomplex.Ceiling(cp[5]  )  /*dummy*/;
+                            cp[6] =  fcomplex.Ceiling(cp[6]  )  /*dummy*/;
+                            cp[7] =  fcomplex.Ceiling(cp[7]  )  /*dummy*/;
+                            cp[8] =  fcomplex.Ceiling(cp[8]  )  /*dummy*/;
+                            cp[9] =  fcomplex.Ceiling(cp[9]  )  /*dummy*/;
+                            cp[10] =  fcomplex.Ceiling(cp[10]  )  /*dummy*/;
+                            cp[11] =  fcomplex.Ceiling(cp[11]  )  /*dummy*/;
+                            cp[12] =  fcomplex.Ceiling(cp[12]  )  /*dummy*/;
+                            cp[13] =  fcomplex.Ceiling(cp[13]  )  /*dummy*/;
+                            cp[14] =  fcomplex.Ceiling(cp[14]  )  /*dummy*/;
+                            cp[15] =  fcomplex.Ceiling(cp[15]  )  /*dummy*/;
+                            cp[16] =  fcomplex.Ceiling(cp[16]  )  /*dummy*/;
+                            cp[17] =  fcomplex.Ceiling(cp[17]  )  /*dummy*/;
+                            cp[18] =  fcomplex.Ceiling(cp[18]  )  /*dummy*/;
+                            cp[19] =  fcomplex.Ceiling(cp[19]  )  /*dummy*/;
+                            cp[20] =  fcomplex.Ceiling(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.Ceiling(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        fcomplex* ap = ((fcomplex*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  fcomplex.Ceiling(ap[0]  )  /*dummy*/;
+                            cp[1] =  fcomplex.Ceiling(ap[1]  )  /*dummy*/;
+                            cp[2] =  fcomplex.Ceiling(ap[2]  )  /*dummy*/;
+                            cp[3] =  fcomplex.Ceiling(ap[3]  )  /*dummy*/;
+                            cp[4] =  fcomplex.Ceiling(ap[4]  )  /*dummy*/;
+                            cp[5] =  fcomplex.Ceiling(ap[5]  )  /*dummy*/;
+                            cp[6] =  fcomplex.Ceiling(ap[6]  )  /*dummy*/;
+                            cp[7] =  fcomplex.Ceiling(ap[7]  )  /*dummy*/;
+                            cp[8] =  fcomplex.Ceiling(ap[8]  )  /*dummy*/;
+                            cp[9] =  fcomplex.Ceiling(ap[9]  )  /*dummy*/;
+                            cp[10] =  fcomplex.Ceiling(ap[10]  )  /*dummy*/;
+                            cp[11] =  fcomplex.Ceiling(ap[11]  )  /*dummy*/;
+                            cp[12] =  fcomplex.Ceiling(ap[12]  )  /*dummy*/;
+                            cp[13] =  fcomplex.Ceiling(ap[13]  )  /*dummy*/;
+                            cp[14] =  fcomplex.Ceiling(ap[14]  )  /*dummy*/;
+                            cp[15] =  fcomplex.Ceiling(ap[15]  )  /*dummy*/;
+                            cp[16] =  fcomplex.Ceiling(ap[16]  )  /*dummy*/;
+                            cp[17] =  fcomplex.Ceiling(ap[17]  )  /*dummy*/;
+                            cp[18] =  fcomplex.Ceiling(ap[18]  )  /*dummy*/;
+                            cp[19] =  fcomplex.Ceiling(ap[19]  )  /*dummy*/;
+                            cp[20] =  fcomplex.Ceiling(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.Ceiling(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( fcomplex* arrAP = arrA)
+                fixed ( fcomplex* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<fcomplex>(retStorage);
+            }
+        }
+        /// <summary>Round towards positive infinity</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Array of same size as A with elements rounded up to next integer value</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<float>  ceil (ILInArray< float > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<float>(A.Size); 
+                ILSize inDim = A.Size;
+                float[] arrA = A.GetArrayForRead(); 
+                float [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<float>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<float> retStorage = new ILDenseStorage<float>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    float* cp = ((float*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  (float)Math.Ceiling(cp[0]  )  /*dummy*/;
+                            cp[1] =  (float)Math.Ceiling(cp[1]  )  /*dummy*/;
+                            cp[2] =  (float)Math.Ceiling(cp[2]  )  /*dummy*/;
+                            cp[3] =  (float)Math.Ceiling(cp[3]  )  /*dummy*/;
+                            cp[4] =  (float)Math.Ceiling(cp[4]  )  /*dummy*/;
+                            cp[5] =  (float)Math.Ceiling(cp[5]  )  /*dummy*/;
+                            cp[6] =  (float)Math.Ceiling(cp[6]  )  /*dummy*/;
+                            cp[7] =  (float)Math.Ceiling(cp[7]  )  /*dummy*/;
+                            cp[8] =  (float)Math.Ceiling(cp[8]  )  /*dummy*/;
+                            cp[9] =  (float)Math.Ceiling(cp[9]  )  /*dummy*/;
+                            cp[10] =  (float)Math.Ceiling(cp[10]  )  /*dummy*/;
+                            cp[11] =  (float)Math.Ceiling(cp[11]  )  /*dummy*/;
+                            cp[12] =  (float)Math.Ceiling(cp[12]  )  /*dummy*/;
+                            cp[13] =  (float)Math.Ceiling(cp[13]  )  /*dummy*/;
+                            cp[14] =  (float)Math.Ceiling(cp[14]  )  /*dummy*/;
+                            cp[15] =  (float)Math.Ceiling(cp[15]  )  /*dummy*/;
+                            cp[16] =  (float)Math.Ceiling(cp[16]  )  /*dummy*/;
+                            cp[17] =  (float)Math.Ceiling(cp[17]  )  /*dummy*/;
+                            cp[18] =  (float)Math.Ceiling(cp[18]  )  /*dummy*/;
+                            cp[19] =  (float)Math.Ceiling(cp[19]  )  /*dummy*/;
+                            cp[20] =  (float)Math.Ceiling(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  (float)Math.Ceiling(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        float* ap = ((float*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  (float)Math.Ceiling(ap[0]  )  /*dummy*/;
+                            cp[1] =  (float)Math.Ceiling(ap[1]  )  /*dummy*/;
+                            cp[2] =  (float)Math.Ceiling(ap[2]  )  /*dummy*/;
+                            cp[3] =  (float)Math.Ceiling(ap[3]  )  /*dummy*/;
+                            cp[4] =  (float)Math.Ceiling(ap[4]  )  /*dummy*/;
+                            cp[5] =  (float)Math.Ceiling(ap[5]  )  /*dummy*/;
+                            cp[6] =  (float)Math.Ceiling(ap[6]  )  /*dummy*/;
+                            cp[7] =  (float)Math.Ceiling(ap[7]  )  /*dummy*/;
+                            cp[8] =  (float)Math.Ceiling(ap[8]  )  /*dummy*/;
+                            cp[9] =  (float)Math.Ceiling(ap[9]  )  /*dummy*/;
+                            cp[10] =  (float)Math.Ceiling(ap[10]  )  /*dummy*/;
+                            cp[11] =  (float)Math.Ceiling(ap[11]  )  /*dummy*/;
+                            cp[12] =  (float)Math.Ceiling(ap[12]  )  /*dummy*/;
+                            cp[13] =  (float)Math.Ceiling(ap[13]  )  /*dummy*/;
+                            cp[14] =  (float)Math.Ceiling(ap[14]  )  /*dummy*/;
+                            cp[15] =  (float)Math.Ceiling(ap[15]  )  /*dummy*/;
+                            cp[16] =  (float)Math.Ceiling(ap[16]  )  /*dummy*/;
+                            cp[17] =  (float)Math.Ceiling(ap[17]  )  /*dummy*/;
+                            cp[18] =  (float)Math.Ceiling(ap[18]  )  /*dummy*/;
+                            cp[19] =  (float)Math.Ceiling(ap[19]  )  /*dummy*/;
+                            cp[20] =  (float)Math.Ceiling(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  (float)Math.Ceiling(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( float* arrAP = arrA)
+                fixed ( float* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<float>(retStorage);
+            }
+        }
+        /// <summary>Round towards positive infinity</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Array of same size as A with elements rounded up to next integer value</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<double>  ceil (ILInArray< double > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<double>(A.Size); 
+                ILSize inDim = A.Size;
+                double[] arrA = A.GetArrayForRead(); 
+                double [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<double>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<double> retStorage = new ILDenseStorage<double>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    double* cp = ((double*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  Math.Ceiling(cp[0]  )  /*dummy*/;
+                            cp[1] =  Math.Ceiling(cp[1]  )  /*dummy*/;
+                            cp[2] =  Math.Ceiling(cp[2]  )  /*dummy*/;
+                            cp[3] =  Math.Ceiling(cp[3]  )  /*dummy*/;
+                            cp[4] =  Math.Ceiling(cp[4]  )  /*dummy*/;
+                            cp[5] =  Math.Ceiling(cp[5]  )  /*dummy*/;
+                            cp[6] =  Math.Ceiling(cp[6]  )  /*dummy*/;
+                            cp[7] =  Math.Ceiling(cp[7]  )  /*dummy*/;
+                            cp[8] =  Math.Ceiling(cp[8]  )  /*dummy*/;
+                            cp[9] =  Math.Ceiling(cp[9]  )  /*dummy*/;
+                            cp[10] =  Math.Ceiling(cp[10]  )  /*dummy*/;
+                            cp[11] =  Math.Ceiling(cp[11]  )  /*dummy*/;
+                            cp[12] =  Math.Ceiling(cp[12]  )  /*dummy*/;
+                            cp[13] =  Math.Ceiling(cp[13]  )  /*dummy*/;
+                            cp[14] =  Math.Ceiling(cp[14]  )  /*dummy*/;
+                            cp[15] =  Math.Ceiling(cp[15]  )  /*dummy*/;
+                            cp[16] =  Math.Ceiling(cp[16]  )  /*dummy*/;
+                            cp[17] =  Math.Ceiling(cp[17]  )  /*dummy*/;
+                            cp[18] =  Math.Ceiling(cp[18]  )  /*dummy*/;
+                            cp[19] =  Math.Ceiling(cp[19]  )  /*dummy*/;
+                            cp[20] =  Math.Ceiling(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Math.Ceiling(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        double* ap = ((double*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  Math.Ceiling(ap[0]  )  /*dummy*/;
+                            cp[1] =  Math.Ceiling(ap[1]  )  /*dummy*/;
+                            cp[2] =  Math.Ceiling(ap[2]  )  /*dummy*/;
+                            cp[3] =  Math.Ceiling(ap[3]  )  /*dummy*/;
+                            cp[4] =  Math.Ceiling(ap[4]  )  /*dummy*/;
+                            cp[5] =  Math.Ceiling(ap[5]  )  /*dummy*/;
+                            cp[6] =  Math.Ceiling(ap[6]  )  /*dummy*/;
+                            cp[7] =  Math.Ceiling(ap[7]  )  /*dummy*/;
+                            cp[8] =  Math.Ceiling(ap[8]  )  /*dummy*/;
+                            cp[9] =  Math.Ceiling(ap[9]  )  /*dummy*/;
+                            cp[10] =  Math.Ceiling(ap[10]  )  /*dummy*/;
+                            cp[11] =  Math.Ceiling(ap[11]  )  /*dummy*/;
+                            cp[12] =  Math.Ceiling(ap[12]  )  /*dummy*/;
+                            cp[13] =  Math.Ceiling(ap[13]  )  /*dummy*/;
+                            cp[14] =  Math.Ceiling(ap[14]  )  /*dummy*/;
+                            cp[15] =  Math.Ceiling(ap[15]  )  /*dummy*/;
+                            cp[16] =  Math.Ceiling(ap[16]  )  /*dummy*/;
+                            cp[17] =  Math.Ceiling(ap[17]  )  /*dummy*/;
+                            cp[18] =  Math.Ceiling(ap[18]  )  /*dummy*/;
+                            cp[19] =  Math.Ceiling(ap[19]  )  /*dummy*/;
+                            cp[20] =  Math.Ceiling(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Math.Ceiling(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( double* arrAP = arrA)
+                fixed ( double* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<double>(retStorage);
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+   
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/cell.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/cell.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/cell.cs	(revision 9102)
@@ -0,0 +1,138 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using ILNumerics.Misc;
+using ILNumerics.Storage; 
+
+namespace ILNumerics {
+    // ToDo: DOKU two overloads undocumented
+    public partial class ILMath {
+
+        /// <summary>
+        /// Create a cell row vector from given arrays 
+        /// </summary>
+        /// <param name="arrays">Arrays to be copied inside the cell</param>
+        /// <returns>Cell vector</returns>
+        /// <remarks><para>The new cell will be created as vector, having the array 'values' given as parameter as cell elements. Those elements will 
+        /// be protected by changes from outside the cell.</para>
+        /// <para>Visit the <a href="http://ilnumerics.net/$Cells.html" target="ILMain">online documentation</a> for cell.</para></remarks>
+        /// <example>
+        /// <para>A common use of the <c>cell</c> function is the concatenation of arrays and constants for subarray definitions, as shown in the following example:</para>
+        /// <code>
+        /// ILArray&lt;double> A = counter(4,3,2); 
+        /// A
+        /// //&lt;Double> [4,3]
+        /// // 1          5          9 
+        /// // 2          6         10 
+        /// // 3          7         11 
+        /// // 4          8         12 
+        /// 
+        /// // extract 1st, 2nd and last row:
+        /// ILArray&lt;double> B = A[cell(0,1,end),full]; 
+        /// B
+        /// //&lt;Double> [3,3]
+        /// // 1          5          9 
+        /// // 2          6         10 
+        /// // 4          8         12 
+        /// </code>
+        /// <para>Here, <c>cell</c> is used to concatenate individual indices determining the rows to select for the subarray. Using a cell here is convenient, because arbitrary types 
+        /// can be stored in cells - integer, floating point types or special placeholders, like expressions (<see cref="ILNumerics.ILMath.end"/> and <see cref="ILNumerics.ILMath.full"/>).</para>
+        /// </example>
+        public static ILRetCell cell(params ILBaseArray[] arrays) {
+            using (ILScope.Enter(arrays)) {
+                if (arrays == null)
+                    return cell(ILSize.Empty00);
+                if (Settings.CreateRowVectorsByDefault) {
+                    return cell(new ILSize(1, arrays.Length), arrays);
+                } else {
+                    return cell(new ILSize(arrays.Length, 1), arrays);
+                }
+            }
+        }
+        /// <summary>
+        /// Create cell, initialize with arrays and size
+        /// </summary>
+        /// <param name="size">Size of the new cell</param>
+        /// <param name="arrays">List of arrays for the cell elements, column major order</param>
+        /// <returns>Cell of specified size, initialized with arrays</returns>
+        /// <remarks>If number of arrays given is smaller than the number of elements given by <paramref name="size"/>, trailing 
+        /// elements in the cell returned will be set to null.
+        /// <para>The <see cref="M:ILNumerics_ILMath_size(params int[])"/> function is convenient for the specification of size descriptors.</para>
+        /// <para>Visit the <a href="http://ilnumerics.net/$Cells.html" target="ILMain">online documentation</a> for cell.</para></remarks>
+        /// <example>
+        /// <code>
+        /// ILArray&lt;double> A = rand(10,20,30); 
+        /// ILCell C = cell(size(3,2),A, A+1, zeros(2,3)); 
+        /// C
+        /// //Cell [3,2]
+        /// // &lt;Double> [10,20,30]          &lt;String>        4th element  
+        /// // &lt;Double> [10,20,30]                                 (null)
+        /// // &lt;Double> [2,3]                                      (null)
+        /// </code>
+        /// </example>
+        public static ILRetCell cell(ILSize size, params ILBaseArray[] arrays) {
+            using (ILScope.Enter(arrays)) {
+                if (object.Equals(arrays, null) || arrays.Length == 0) {
+                    return new ILRetCell(new ILCellStorage(size));
+                }
+                return new ILRetCell(new ILCellStorage(arrays, size));
+            }
+        }
+        /// <summary>
+        /// Create cell, initialize with arrays and size
+        /// </summary>
+        /// <param name="arrays">Predefined array with arrays, directly be used as new cell element storage</param>
+        /// <param name="size">Size of newly created cell</param>
+        /// <returns>Cell with size of <paramref name="size"/> and elements from <paramref name="arrays"/></returns>
+        /// <remarks>The array given in <paramref name="arrays"/> is directly be used for the newly created cell. Make sure, not 
+        /// to reference the system array afterwards. However, arrays  referenced from within the parameter <paramref name="arrays"/> 
+        /// are stored as clone into the new cell. Therefore, those arrays are properly protected from changes by altering any array outside the cell.
+        /// <para>Visit the <a href="http://ilnumerics.net/$Cells.html" target="ILMain">online documentation</a> for cell.</para></remarks>
+        /// <seealso cref="ILNumerics.ILMath.cell(ILNumerics.ILBaseArray[])"/>
+        public static ILRetCell cell(ILBaseArray[] arrays, params int[] size) {
+            using (ILScope.Enter(arrays)) {
+                return cell(new ILSize(size), arrays);
+            }
+        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/check.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/check.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/check.cs	(revision 9102)
@@ -0,0 +1,135 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions;
+
+namespace ILNumerics {
+    public partial class ILMath {
+
+        /// <summary>
+        /// Check if A is a valid parameter
+        /// </summary>
+        /// <typeparam name="T">Element type</typeparam>
+        /// <param name="A">Input parameter</param>
+        /// <param name="ErrorMessage">[optional] Exception message</param>
+        /// <param name="evaluation">[optional] Evaluation function, checks input parameter and transforms it into result, gets only called for A other than null</param>
+        /// <param name="allowNullInput">[optional] Only if A is null -> for true: returns null, false: throws exception. If <paramref name="Default"/> was defined, this parameter is ignored.</param>
+        /// <param name="Default">[optional] If <paramref name="A"/> is null on input, this value is returned. If no default is given (i.e: null), <paramref name="allowNullInput"/> is evaluated.</param>
+        /// <returns>Result of evaluation(A) or A</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If A was null on entry and <paramref name="allowNullInput"/> is false</exception>
+        public static ILRetArray<T> check<T>(ILInArray<T> A, Func<ILInArray<T>, ILRetArray<T>> evaluation = null, bool allowNullInput = false, string ErrorMessage = "", ILInArray<T> Default = null) {
+            using (ILScope.Enter(A,Default)) {
+                if (object.Equals(A, null)) {
+                    if (isnull(Default)) {
+                        if (!allowNullInput)
+                            throw new ILArgumentException("an input parameter was found to be null");
+                        else
+                            return null;
+                    } else {
+                        return Default.C; 
+                    }
+                }
+                if (evaluation == null)
+                    return A;
+                ILRetArray<T> ret = evaluation(A);
+                if (object.Equals(ret, null))
+                    throw new ILArgumentException(String.IsNullOrEmpty(ErrorMessage) ? "invalid input parameter. check the documentation!" : ErrorMessage);
+                else
+                    return ret;
+            }
+        }
+        /// <summary>
+        /// Check if A is a valid parameter
+        /// </summary>
+        /// <param name="A">Input parameter</param>
+        /// <param name="ErrorMessage">[optional] Exception message</param>
+        /// <param name="evaluation">[optional] Evaluation function, checks input parameter and transforms it into result, gets only called for A other than null</param>
+        /// <param name="allowNullInput">[optional] Only if A is null -> for true: returns null, false: throws exception</param>
+        /// <returns>Result of evaluation(A) or A</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If A was null on entry and <paramref name="allowNullInput"/> is false</exception>
+        public static ILRetLogical check(ILInLogical A, Func<ILInLogical, ILRetLogical> evaluation = null, bool allowNullInput = false, string ErrorMessage = "") {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A, null)) {
+                    if (!allowNullInput)
+                        throw new ILArgumentException("an input parameter was found to be null");
+                    else
+                        return null;
+                }
+                if (evaluation == null)
+                    return A;
+                ILRetLogical ret = evaluation(A);
+                if (object.Equals(ret, null))
+                    throw new ILArgumentException(String.IsNullOrEmpty(ErrorMessage) ? "invalid input parameter. check the documentation!" : ErrorMessage);
+                else
+                    return ret;
+            }
+        }
+        /// <summary>
+        /// Check if A is a valid parameter
+        /// </summary>
+        /// <param name="A">Input parameter</param>
+        /// <param name="ErrorMessage">[Optional] Exception message</param>
+        /// <param name="evaluation">[Optional] Evaluation function, checks input parameter and transforms it into result, gets only called for A other than null</param>
+        /// <param name="allowNullInput">[Optional] Only if A is null -> true: returns null, false: throws exception</param>
+        /// <returns>Result of evaluation(A) or A</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If A was null on entry and <paramref name="allowNullInput"/> is false</exception>
+        public static ILRetCell check(ILInCell A, Func<ILInCell, ILRetCell> evaluation = null, bool allowNullInput = false, string ErrorMessage = "") {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A, null)) {
+                    if (!allowNullInput)
+                        throw new ILArgumentException("an input parameter was null");
+                    else
+                        return null;
+                }
+                if (evaluation == null)
+                    return A;
+                ILRetCell ret = evaluation(A);
+                if (object.Equals(ret, null))
+                    throw new ILArgumentException(String.IsNullOrEmpty(ErrorMessage) ? "invalid input parameter. check the documentation!" : ErrorMessage);
+                else
+                    return ret;
+            }
+        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/chol.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/chol.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/chol.cs	(revision 9102)
@@ -0,0 +1,265 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions; 
+
+
+
+namespace ILNumerics {
+
+    public partial class ILMath {
+
+
+        /// <summary>Cholesky factorization</summary>
+        /// <param name="A">Input array A. A must be a symmetric/hermitian matrix. 
+        /// Therefore the upper triangular part of A must be the transpose (complex conjugate for complex input) of the lower triangular part. No check 
+        /// is made for that! <br/> 
+        /// The elements of A will not be altered.</param>
+        /// <param name="throwException">Throw an ILArgumentException if A 
+        /// is found not to be positive definite.</param>
+        /// <returns>Cholesky factorization</returns>
+        /// <remarks><para>If <paramref name="throwException"/> is true and 
+        /// A is found not to be positive definite, an ILArgumentException 
+        /// will be thrown and the operation will be canceled.</para>
+        /// <para>If <paramref name="throwException"/> is false, check the
+        /// return value's dimension to determine the success of the 
+        /// operation (unless you are sure, A was positive definite). 
+        /// If A was found not to be positive definite the matrix returned 
+        /// will be of dimension [k x k] and the result of the cholesky 
+        /// factorization of A[0:k-1;0:k-1]. Here k is the first leading 
+        /// minor of A at which A was found to be not positive definite.</para>
+        /// The factorization is carried out by use of the LAPACK functions 
+        /// DPOTRF, ZPOTRF, SPOTRF or CPOTRF respectively. </remarks>
+        public static ILRetArray<double> chol(ILInArray<double> A, bool throwException = true) {
+            using (ILScope.Enter(A)) {
+                if (!A.IsMatrix)
+                    throw new ILArgumentSizeException("chol is defined for matrices only!");
+                int n = A.Size[0], info = 0; 
+                if (A.Size[1] != n) 
+                    throw new ILArgumentException("chol: input matrix must be square!");
+                ILDenseStorage<double> ret = A.Storage.copyUpperTriangle(n);
+                /*!HC:lapack_*potrf*/ Lapack.dpotrf ('U', n, ret.GetArrayForRead(), n, ref info); 
+                if (info < 0 ) {
+                    throw new ILArgumentException("chol: illegal parameter error.");
+                } else if (info > 0) {
+                    // not pos.definite 
+                    if (! throwException) {
+                        if (info > 1) {
+                            int newDim = info - 1;
+                            ret = A.Storage.copyUpperTriangle(newDim); 
+                            /*!HC:lapack_*potrf*/  Lapack.dpotrf ('U',newDim,ret.GetArrayForRead(), newDim, ref info);
+                            if (info != 0) 
+                                throw new ILArgumentException("chol: the original matrix given was not pos. definit. An attempt to decompose the submatrix of order " + (newDim + 1).ToString() + " failed."); 
+                            return new ILRetArray<double>(ret); 
+                        } else {
+                            return empty<double>(ILSize.Empty00); 
+                        } 
+                    } else {
+                        throw new ILArgumentException("chol: the matrix given is not positive definite!"); 
+                    }
+                }
+                return new ILRetArray<double>(ret);
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>Cholesky factorization</summary>
+        /// <param name="A">Input array A. A must be a symmetric/hermitian matrix. 
+        /// Therefore the upper triangular part of A must be the transpose (complex conjugate for complex input) of the lower triangular part. No check 
+        /// is made for that! <br/> 
+        /// The elements of A will not be altered.</param>
+        /// <param name="throwException">Throw an ILArgumentException if A 
+        /// is found not to be positive definite.</param>
+        /// <returns>Cholesky factorization</returns>
+        /// <remarks><para>If <paramref name="throwException"/> is true and 
+        /// A is found not to be positive definite, an ILArgumentException 
+        /// will be thrown and the operation will be canceled.</para>
+        /// <para>If <paramref name="throwException"/> is false, check the
+        /// return value's dimension to determine the success of the 
+        /// operation (unless you are sure, A was positive definite). 
+        /// If A was found not to be positive definite the matrix returned 
+        /// will be of dimension [k x k] and the result of the cholesky 
+        /// factorization of A[0:k-1;0:k-1]. Here k is the first leading 
+        /// minor of A at which A was found to be not positive definite.</para>
+        /// The factorization is carried out by use of the LAPACK functions 
+        /// DPOTRF, ZPOTRF, SPOTRF or CPOTRF respectively. </remarks>
+        public static ILRetArray<float> chol(ILInArray<float> A, bool throwException = true) {
+            using (ILScope.Enter(A)) {
+                if (!A.IsMatrix)
+                    throw new ILArgumentSizeException("chol is defined for matrices only!");
+                int n = A.Size[0], info = 0; 
+                if (A.Size[1] != n) 
+                    throw new ILArgumentException("chol: input matrix must be square!");
+                ILDenseStorage<float> ret = A.Storage.copyUpperTriangle(n);
+                Lapack.spotrf ('U', n, ret.GetArrayForRead(), n, ref info); 
+                if (info < 0 ) {
+                    throw new ILArgumentException("chol: illegal parameter error.");
+                } else if (info > 0) {
+                    // not pos.definite 
+                    if (! throwException) {
+                        if (info > 1) {
+                            int newDim = info - 1;
+                            ret = A.Storage.copyUpperTriangle(newDim); 
+                             Lapack.spotrf ('U',newDim,ret.GetArrayForRead(), newDim, ref info);
+                            if (info != 0) 
+                                throw new ILArgumentException("chol: the original matrix given was not pos. definit. An attempt to decompose the submatrix of order " + (newDim + 1).ToString() + " failed."); 
+                            return new ILRetArray<float>(ret); 
+                        } else {
+                            return empty<float>(ILSize.Empty00); 
+                        } 
+                    } else {
+                        throw new ILArgumentException("chol: the matrix given is not positive definite!"); 
+                    }
+                }
+                return new ILRetArray<float>(ret);
+            }
+        }
+        /// <summary>Cholesky factorization</summary>
+        /// <param name="A">Input array A. A must be a symmetric/hermitian matrix. 
+        /// Therefore the upper triangular part of A must be the transpose (complex conjugate for complex input) of the lower triangular part. No check 
+        /// is made for that! <br/> 
+        /// The elements of A will not be altered.</param>
+        /// <param name="throwException">Throw an ILArgumentException if A 
+        /// is found not to be positive definite.</param>
+        /// <returns>Cholesky factorization</returns>
+        /// <remarks><para>If <paramref name="throwException"/> is true and 
+        /// A is found not to be positive definite, an ILArgumentException 
+        /// will be thrown and the operation will be canceled.</para>
+        /// <para>If <paramref name="throwException"/> is false, check the
+        /// return value's dimension to determine the success of the 
+        /// operation (unless you are sure, A was positive definite). 
+        /// If A was found not to be positive definite the matrix returned 
+        /// will be of dimension [k x k] and the result of the cholesky 
+        /// factorization of A[0:k-1;0:k-1]. Here k is the first leading 
+        /// minor of A at which A was found to be not positive definite.</para>
+        /// The factorization is carried out by use of the LAPACK functions 
+        /// DPOTRF, ZPOTRF, SPOTRF or CPOTRF respectively. </remarks>
+        public static ILRetArray<fcomplex> chol(ILInArray<fcomplex> A, bool throwException = true) {
+            using (ILScope.Enter(A)) {
+                if (!A.IsMatrix)
+                    throw new ILArgumentSizeException("chol is defined for matrices only!");
+                int n = A.Size[0], info = 0; 
+                if (A.Size[1] != n) 
+                    throw new ILArgumentException("chol: input matrix must be square!");
+                ILDenseStorage<fcomplex> ret = A.Storage.copyUpperTriangle(n);
+                Lapack.cpotrf ('U', n, ret.GetArrayForRead(), n, ref info); 
+                if (info < 0 ) {
+                    throw new ILArgumentException("chol: illegal parameter error.");
+                } else if (info > 0) {
+                    // not pos.definite 
+                    if (! throwException) {
+                        if (info > 1) {
+                            int newDim = info - 1;
+                            ret = A.Storage.copyUpperTriangle(newDim); 
+                             Lapack.cpotrf ('U',newDim,ret.GetArrayForRead(), newDim, ref info);
+                            if (info != 0) 
+                                throw new ILArgumentException("chol: the original matrix given was not pos. definit. An attempt to decompose the submatrix of order " + (newDim + 1).ToString() + " failed."); 
+                            return new ILRetArray<fcomplex>(ret); 
+                        } else {
+                            return empty<fcomplex>(ILSize.Empty00); 
+                        } 
+                    } else {
+                        throw new ILArgumentException("chol: the matrix given is not positive definite!"); 
+                    }
+                }
+                return new ILRetArray<fcomplex>(ret);
+            }
+        }
+        /// <summary>Cholesky factorization</summary>
+        /// <param name="A">Input array A. A must be a symmetric/hermitian matrix. 
+        /// Therefore the upper triangular part of A must be the transpose (complex conjugate for complex input) of the lower triangular part. No check 
+        /// is made for that! <br/> 
+        /// The elements of A will not be altered.</param>
+        /// <param name="throwException">Throw an ILArgumentException if A 
+        /// is found not to be positive definite.</param>
+        /// <returns>Cholesky factorization</returns>
+        /// <remarks><para>If <paramref name="throwException"/> is true and 
+        /// A is found not to be positive definite, an ILArgumentException 
+        /// will be thrown and the operation will be canceled.</para>
+        /// <para>If <paramref name="throwException"/> is false, check the
+        /// return value's dimension to determine the success of the 
+        /// operation (unless you are sure, A was positive definite). 
+        /// If A was found not to be positive definite the matrix returned 
+        /// will be of dimension [k x k] and the result of the cholesky 
+        /// factorization of A[0:k-1;0:k-1]. Here k is the first leading 
+        /// minor of A at which A was found to be not positive definite.</para>
+        /// The factorization is carried out by use of the LAPACK functions 
+        /// DPOTRF, ZPOTRF, SPOTRF or CPOTRF respectively. </remarks>
+        public static ILRetArray<complex> chol(ILInArray<complex> A, bool throwException = true) {
+            using (ILScope.Enter(A)) {
+                if (!A.IsMatrix)
+                    throw new ILArgumentSizeException("chol is defined for matrices only!");
+                int n = A.Size[0], info = 0; 
+                if (A.Size[1] != n) 
+                    throw new ILArgumentException("chol: input matrix must be square!");
+                ILDenseStorage<complex> ret = A.Storage.copyUpperTriangle(n);
+                Lapack.zpotrf ('U', n, ret.GetArrayForRead(), n, ref info); 
+                if (info < 0 ) {
+                    throw new ILArgumentException("chol: illegal parameter error.");
+                } else if (info > 0) {
+                    // not pos.definite 
+                    if (! throwException) {
+                        if (info > 1) {
+                            int newDim = info - 1;
+                            ret = A.Storage.copyUpperTriangle(newDim); 
+                             Lapack.zpotrf ('U',newDim,ret.GetArrayForRead(), newDim, ref info);
+                            if (info != 0) 
+                                throw new ILArgumentException("chol: the original matrix given was not pos. definit. An attempt to decompose the submatrix of order " + (newDim + 1).ToString() + " failed."); 
+                            return new ILRetArray<complex>(ret); 
+                        } else {
+                            return empty<complex>(ILSize.Empty00); 
+                        } 
+                    } else {
+                        throw new ILArgumentException("chol: the matrix given is not positive definite!"); 
+                    }
+                }
+                return new ILRetArray<complex>(ret);
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/conj.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/conj.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/conj.cs	(revision 9102)
@@ -0,0 +1,232 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics;
+using ILNumerics.Exceptions; 
+using ILNumerics.Storage; 
+using ILNumerics.Misc;
+
+
+namespace ILNumerics {
+    public partial class ILMath {
+
+        #region convenience functions (real arguments)
+        /// <summary>
+        /// Complex conjugate of A
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns>The array itself</returns>
+        /// <remarks>This overload is provided for convenience only. It eases the implementation of complex functions, where complex conjugate transposes are needed.</remarks>
+        public static ILRetArray<double> conj (ILInArray<double> A) { 
+            using (ILScope.Enter(A))
+            return A.C; 
+        }
+        /// <summary>
+        /// Complex conjugate of A
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns>The array itself</returns>
+        /// <remarks>This overload is provided for convenience only. It eases the implementation of complex functions, where complex conjugate transposes are needed.</remarks>
+        public static ILRetArray<float> conj (ILInArray<float> A) { 
+            using (ILScope.Enter(A))
+            return A.C; 
+        }
+        #endregion convenience functions (real arguments)
+
+        /// <summary>Complex conjugate of array A</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Complex conjugate of array A</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static ILRetArray<complex> conj(ILInArray<complex> A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new ILRetArray<complex>(A.Size);
+                ILSize inDim = A.Size;
+                complex[] arrA = A.GetArrayForRead();
+                complex[] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<complex>(outLen);
+                    inplace = false;
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<complex> retStorage = new ILDenseStorage<complex>(retArr, inDim);
+
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+
+                    complex* cp = ((complex*)range.Item4 + range.Item1);
+
+                    complex* cLast = cp + range.Item2;
+                    if (range.Item5) {
+                        // inplace
+                        while (cp < cLast) {
+                            (*cp).imag = (*cp).imag * -1.0;
+                            cp++;
+                        }
+                    } else {
+                        complex* ap = ((complex*)range.Item3 + range.Item1);
+                        while (cp < cLast) {
+                            (*cp).real = (*ap).real; (*cp).imag = (*ap).imag * -1.0;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                //retStorage.PendingEvents = new System.Threading.CountdownEvent(workItemCount); 
+                fixed (complex* arrAP = arrA)
+                fixed (complex* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new ILRetArray<complex>(retStorage);
+            }
+        }
+
+        /// <summary>Complex conjugate of array A</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Complex conjugate of array A</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<fcomplex>  conj (ILInArray< fcomplex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<fcomplex>(A.Size); 
+                ILSize inDim = A.Size;
+                fcomplex[] arrA = A.GetArrayForRead(); 
+                fcomplex [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<fcomplex>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<fcomplex> retStorage = new ILDenseStorage<fcomplex>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    fcomplex* cp = ((fcomplex*)range.Item4 + range.Item1);
+                   
+                    fcomplex* cLast = cp + range.Item2;
+                    if (range.Item5) { 
+                        // inplace
+                        while (cp < cLast) {
+                            (*cp).imag = (*cp).imag * -1.0f;
+                            cp++; 
+                        }
+                    } else {
+                        fcomplex* ap = ((fcomplex*)range.Item3 + range.Item1);
+                        while (cp < cLast) {
+                            (*cp).real = (*ap).real; (*cp).imag = (*ap).imag * -1.0f;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                //retStorage.PendingEvents = new System.Threading.CountdownEvent(workItemCount); 
+                fixed ( fcomplex* arrAP = arrA)
+                fixed ( fcomplex* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<fcomplex>(retStorage);
+            }
+        }
+  
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/convert.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/convert.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/convert.cs	(revision 9102)
@@ -0,0 +1,1563 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions;
+using System.Runtime.InteropServices; 
+using System.Numerics;
+
+
+namespace ILNumerics  {
+    public partial class ILMath {
+        /// <summary>
+        /// Convert a numeric array to another numeric type
+        /// </summary>
+        /// <param name="X">Input array</param>
+        /// <typeparam name="inT">Type of array to convert</typeparam>
+        /// <typeparam name="outT">Type of array to return</typeparam>
+        /// <returns>Converted array</returns>
+        /// <remarks> The newly created array will be converted to the required type. 
+        /// <para>The array returned will always use new memory! Even if the type requested 
+        /// matches the incoming type.</para></remarks>
+        public static unsafe ILRetArray<outT> convert<inT, outT>(ILInArray<inT> X) {
+            using (ILScope.Enter(X)) {
+                outT[] retArrGen = ILMemoryPool.Pool.New<outT>(X.Size.NumberOfElements); 
+                inT[] inArrGen = X.GetArrayForRead(); 
+                if (inArrGen is double[]) {
+    #region input double
+                    double[] inArr = (double[])(object)inArrGen;  
+                    if (false) {
+
+                    } else if (retArrGen is  double []) {
+						 double [] dummyArray = ( double [])(object)retArrGen; 
+                        fixed ( double * pretArr = dummyArray)
+                        fixed (double * pinArr = inArr) {
+                            double * pInWalk = pinArr; 
+                            double * pInEnd = pinArr + X.S.NumberOfElements;
+                             double * pRetWalk = pretArr; 
+                            while (pInWalk < pInEnd) {
+                                *(pRetWalk++) = ( double ) (*(pInWalk++)); 
+                            }
+                        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+                    } else if (retArrGen is  Int64 []) {
+						 Int64 [] dummyArray = ( Int64 [])(object)retArrGen; 
+                        fixed ( Int64 * pretArr = dummyArray)
+                        fixed (double * pinArr = inArr) {
+                            double * pInWalk = pinArr; 
+                            double * pInEnd = pinArr + X.S.NumberOfElements;
+                            Int64 * pRetWalk = pretArr; 
+                            while (pInWalk < pInEnd) {
+                                *(pRetWalk++) = ( Int64 ) (*(pInWalk++)); 
+                            }
+                        }
+                    } else if (retArrGen is  Int32 []) {
+						 Int32 [] dummyArray = ( Int32 [])(object)retArrGen; 
+                        fixed ( Int32 * pretArr = dummyArray)
+                        fixed (double * pinArr = inArr) {
+                            double * pInWalk = pinArr; 
+                            double * pInEnd = pinArr + X.S.NumberOfElements;
+                            Int32 * pRetWalk = pretArr; 
+                            while (pInWalk < pInEnd) {
+                                *(pRetWalk++) = ( Int32 ) (*(pInWalk++)); 
+                            }
+                        }
+                    } else if (retArrGen is  byte []) {
+						 byte [] dummyArray = ( byte [])(object)retArrGen; 
+                        fixed ( byte * pretArr = dummyArray)
+                        fixed (double * pinArr = inArr) {
+                            double * pInWalk = pinArr; 
+                            double * pInEnd = pinArr + X.S.NumberOfElements;
+                            byte * pRetWalk = pretArr; 
+                            while (pInWalk < pInEnd) {
+                                *(pRetWalk++) = ( byte ) (*(pInWalk++)); 
+                            }
+                        }
+                    } else if (retArrGen is  fcomplex []) {
+						 fcomplex [] dummyArray = ( fcomplex [])(object)retArrGen; 
+                        fixed ( fcomplex * pretArr = dummyArray)
+                        fixed (double * pinArr = inArr) {
+                            double * pInWalk = pinArr; 
+                            double * pInEnd = pinArr + X.S.NumberOfElements;
+                            fcomplex * pRetWalk = pretArr; 
+                            while (pInWalk < pInEnd) {
+                                *(pRetWalk++) = ( fcomplex ) (*(pInWalk++)); 
+                            }
+                        }
+                    } else if (retArrGen is  complex []) {
+						 complex [] dummyArray = ( complex [])(object)retArrGen; 
+                        fixed ( complex * pretArr = dummyArray)
+                        fixed (double * pinArr = inArr) {
+                            double * pInWalk = pinArr; 
+                            double * pInEnd = pinArr + X.S.NumberOfElements;
+                            complex * pRetWalk = pretArr; 
+                            while (pInWalk < pInEnd) {
+                                *(pRetWalk++) = ( complex ) (*(pInWalk++)); 
+                            }
+                        }
+                    } else if (retArrGen is  float []) {
+						 float [] dummyArray = ( float [])(object)retArrGen; 
+                        fixed ( float * pretArr = dummyArray)
+                        fixed (double * pinArr = inArr) {
+                            double * pInWalk = pinArr; 
+                            double * pInEnd = pinArr + X.S.NumberOfElements;
+                            float * pRetWalk = pretArr; 
+                            while (pInWalk < pInEnd) {
+                                *(pRetWalk++) = ( float ) (*(pInWalk++)); 
+                            }
+                        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+                   } else 
+                        throw new ILArgumentException("unsupported target type: " + typeof(outT).Name);
+    #endregion
+                } else if (inArrGen is float[]) {
+    #region input float
+                    float[] inArr = (float[])(object)inArrGen;  
+                    if (false) {
+
+                    } else if (retArrGen is  double []) {
+						 double [] dummyArray = ( double [])(object)retArrGen; 
+                        fixed ( double * pretArr = dummyArray)
+                        fixed (float * pinArr = inArr) {
+                            float * pInWalk = pinArr; 
+                            float * pInEnd = pinArr + X.S.NumberOfElements;
+                             double * pRetWalk = pretArr; 
+                            while (pInWalk < pInEnd) {
+                                *(pRetWalk++) = ( double ) (*(pInWalk++)); 
+                            }
+                        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+                    } else if (retArrGen is  Int64 []) {
+						 Int64 [] dummyArray = ( Int64 [])(object)retArrGen; 
+                        fixed ( Int64 * pretArr = dummyArray)
+                        fixed (float * pinArr = inArr) {
+                            float * pInWalk = pinArr; 
+                            float * pInEnd = pinArr + X.S.NumberOfElements;
+                            Int64 * pRetWalk = pretArr; 
+                            while (pInWalk < pInEnd) {
+                                *(pRetWalk++) = ( Int64 ) (*(pInWalk++)); 
+                            }
+                        }
+                    } else if (retArrGen is  Int32 []) {
+						 Int32 [] dummyArray = ( Int32 [])(object)retArrGen; 
+                        fixed ( Int32 * pretArr = dummyArray)
+                        fixed (float * pinArr = inArr) {
+                            float * pInWalk = pinArr; 
+                            float * pInEnd = pinArr + X.S.NumberOfElements;
+                            Int32 * pRetWalk = pretArr; 
+                            while (pInWalk < pInEnd) {
+                                *(pRetWalk++) = ( Int32 ) (*(pInWalk++)); 
+                            }
+                        }
+                    } else if (retArrGen is  byte []) {
+						 byte [] dummyArray = ( byte [])(object)retArrGen; 
+                        fixed ( byte * pretArr = dummyArray)
+                        fixed (float * pinArr = inArr) {
+                            float * pInWalk = pinArr; 
+                            float * pInEnd = pinArr + X.S.NumberOfElements;
+                            byte * pRetWalk = pretArr; 
+                            while (pInWalk < pInEnd) {
+                                *(pRetWalk++) = ( byte ) (*(pInWalk++)); 
+                            }
+                        }
+                    } else if (retArrGen is  fcomplex []) {
+						 fcomplex [] dummyArray = ( fcomplex [])(object)retArrGen; 
+                        fixed ( fcomplex * pretArr = dummyArray)
+                        fixed (float * pinArr = inArr) {
+                            float * pInWalk = pinArr; 
+                            float * pInEnd = pinArr + X.S.NumberOfElements;
+                            fcomplex * pRetWalk = pretArr; 
+                            while (pInWalk < pInEnd) {
+                                *(pRetWalk++) = ( fcomplex ) (*(pInWalk++)); 
+                            }
+                        }
+                    } else if (retArrGen is  complex []) {
+						 complex [] dummyArray = ( complex [])(object)retArrGen; 
+                        fixed ( complex * pretArr = dummyArray)
+                        fixed (float * pinArr = inArr) {
+                            float * pInWalk = pinArr; 
+                            float * pInEnd = pinArr + X.S.NumberOfElements;
+                            complex * pRetWalk = pretArr; 
+                            while (pInWalk < pInEnd) {
+                                *(pRetWalk++) = ( complex ) (*(pInWalk++)); 
+                            }
+                        }
+                    } else if (retArrGen is  float []) {
+						 float [] dummyArray = ( float [])(object)retArrGen; 
+                        fixed ( float * pretArr = dummyArray)
+                        fixed (float * pinArr = inArr) {
+                            float * pInWalk = pinArr; 
+                            float * pInEnd = pinArr + X.S.NumberOfElements;
+                            float * pRetWalk = pretArr; 
+                            while (pInWalk < pInEnd) {
+                                *(pRetWalk++) = ( float ) (*(pInWalk++)); 
+                            }
+                        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+                   } else 
+                        throw new ILArgumentException("unsupported target type: " + typeof(outT).Name);
+    #endregion
+                } else if (inArrGen is complex[]) {
+    #region input complex
+                    complex[] inArr = (complex[])(object)inArrGen;  
+                    if (false) {
+
+                    } else if (retArrGen is  double []) {
+						 double [] dummyArray = ( double [])(object)retArrGen;
+                        fixed ( double * pretArr = dummyArray)
+                        fixed (complex * pinArr = inArr) {
+                            complex * pInWalk = pinArr; 
+                            complex * pInEnd = pinArr + X.S.NumberOfElements;
+                             double * pRetWalk = pretArr; 
+                            while (pInWalk < pInEnd) {
+                                *(pRetWalk++) = ( double ) (*(pInWalk++)); 
+                            }
+                        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+                    } else if (retArrGen is  Int64 []) {
+						 Int64 [] dummyArray = ( Int64 [])(object)retArrGen;
+                        fixed ( Int64 * pretArr = dummyArray)
+                        fixed (complex * pinArr = inArr) {
+                            complex * pInWalk = pinArr; 
+                            complex * pInEnd = pinArr + X.S.NumberOfElements;
+                            Int64 * pRetWalk = pretArr; 
+                            while (pInWalk < pInEnd) {
+                                *(pRetWalk++) = ( Int64 ) (*(pInWalk++)); 
+                            }
+                        }
+                    } else if (retArrGen is  Int32 []) {
+						 Int32 [] dummyArray = ( Int32 [])(object)retArrGen;
+                        fixed ( Int32 * pretArr = dummyArray)
+                        fixed (complex * pinArr = inArr) {
+                            complex * pInWalk = pinArr; 
+                            complex * pInEnd = pinArr + X.S.NumberOfElements;
+                            Int32 * pRetWalk = pretArr; 
+                            while (pInWalk < pInEnd) {
+                                *(pRetWalk++) = ( Int32 ) (*(pInWalk++)); 
+                            }
+                        }
+                    } else if (retArrGen is  byte []) {
+						 byte [] dummyArray = ( byte [])(object)retArrGen;
+                        fixed ( byte * pretArr = dummyArray)
+                        fixed (complex * pinArr = inArr) {
+                            complex * pInWalk = pinArr; 
+                            complex * pInEnd = pinArr + X.S.NumberOfElements;
+                            byte * pRetWalk = pretArr; 
+                            while (pInWalk < pInEnd) {
+                                *(pRetWalk++) = ( byte ) (*(pInWalk++)); 
+                            }
+                        }
+                    } else if (retArrGen is  fcomplex []) {
+						 fcomplex [] dummyArray = ( fcomplex [])(object)retArrGen;
+                        fixed ( fcomplex * pretArr = dummyArray)
+                        fixed (complex * pinArr = inArr) {
+                            complex * pInWalk = pinArr; 
+                            complex * pInEnd = pinArr + X.S.NumberOfElements;
+                            fcomplex * pRetWalk = pretArr; 
+                            while (pInWalk < pInEnd) {
+                                *(pRetWalk++) = ( fcomplex ) (*(pInWalk++)); 
+                            }
+                        }
+                    } else if (retArrGen is  complex []) {
+						 complex [] dummyArray = ( complex [])(object)retArrGen;
+                        fixed ( complex * pretArr = dummyArray)
+                        fixed (complex * pinArr = inArr) {
+                            complex * pInWalk = pinArr; 
+                            complex * pInEnd = pinArr + X.S.NumberOfElements;
+                            complex * pRetWalk = pretArr; 
+                            while (pInWalk < pInEnd) {
+                                *(pRetWalk++) = ( complex ) (*(pInWalk++)); 
+                            }
+                        }
+                    } else if (retArrGen is  float []) {
+						 float [] dummyArray = ( float [])(object)retArrGen;
+                        fixed ( float * pretArr = dummyArray)
+                        fixed (complex * pinArr = inArr) {
+                            complex * pInWalk = pinArr; 
+                            complex * pInEnd = pinArr + X.S.NumberOfElements;
+                            float * pRetWalk = pretArr; 
+                            while (pInWalk < pInEnd) {
+                                *(pRetWalk++) = ( float ) (*(pInWalk++)); 
+                            }
+                        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+                    } else if (retArrGen is Complex[]) {
+                        GCHandle retHandle = GCHandle.Alloc(retArrGen,GCHandleType.Pinned); 
+                        GCHandle inHandle = GCHandle.Alloc(inArrGen,GCHandleType.Pinned);
+                        complex* retP = (complex*)retHandle.AddrOfPinnedObject();
+                        complex* inP = (complex*)inHandle.AddrOfPinnedObject();
+                        complex2ComplexHelper(inP, retP, X.S.NumberOfElements);
+                        retHandle.Free(); 
+                        inHandle.Free(); 
+                    } else 
+                        throw new ILArgumentException("unsupported target type: " + typeof(outT).Name);
+    #endregion
+                } else if (inArrGen is fcomplex[]) {
+    #region input fcomplex
+                    fcomplex[] inArr = (fcomplex[])(object)inArrGen;  
+                    if (false) {
+
+                    } else if (retArrGen is  double []) {
+						 double [] dummyArray = ( double [])(object)retArrGen;
+                        fixed ( double * pretArr = dummyArray)
+                        fixed (fcomplex * pinArr = inArr) {
+                            fcomplex * pInWalk = pinArr; 
+                            fcomplex * pInEnd = pinArr + X.S.NumberOfElements;
+                             double * pRetWalk = pretArr; 
+                            while (pInWalk < pInEnd) {
+                                *(pRetWalk++) = ( double ) (*(pInWalk++)); 
+                            }
+                        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+                    } else if (retArrGen is  Int64 []) {
+						 Int64 [] dummyArray = ( Int64 [])(object)retArrGen;
+                        fixed ( Int64 * pretArr = dummyArray)
+                        fixed (fcomplex * pinArr = inArr) {
+                            fcomplex * pInWalk = pinArr; 
+                            fcomplex * pInEnd = pinArr + X.S.NumberOfElements;
+                            Int64 * pRetWalk = pretArr; 
+                            while (pInWalk < pInEnd) {
+                                *(pRetWalk++) = ( Int64 ) (*(pInWalk++)); 
+                            }
+                        }
+                    } else if (retArrGen is  Int32 []) {
+						 Int32 [] dummyArray = ( Int32 [])(object)retArrGen;
+                        fixed ( Int32 * pretArr = dummyArray)
+                        fixed (fcomplex * pinArr = inArr) {
+                            fcomplex * pInWalk = pinArr; 
+                            fcomplex * pInEnd = pinArr + X.S.NumberOfElements;
+                            Int32 * pRetWalk = pretArr; 
+                            while (pInWalk < pInEnd) {
+                                *(pRetWalk++) = ( Int32 ) (*(pInWalk++)); 
+                            }
+                        }
+                    } else if (retArrGen is  byte []) {
+						 byte [] dummyArray = ( byte [])(object)retArrGen;
+                        fixed ( byte * pretArr = dummyArray)
+                        fixed (fcomplex * pinArr = inArr) {
+                            fcomplex * pInWalk = pinArr; 
+                            fcomplex * pInEnd = pinArr + X.S.NumberOfElements;
+                            byte * pRetWalk = pretArr; 
+                            while (pInWalk < pInEnd) {
+                                *(pRetWalk++) = ( byte ) (*(pInWalk++)); 
+                            }
+                        }
+                    } else if (retArrGen is  fcomplex []) {
+						 fcomplex [] dummyArray = ( fcomplex [])(object)retArrGen;
+                        fixed ( fcomplex * pretArr = dummyArray)
+                        fixed (fcomplex * pinArr = inArr) {
+                            fcomplex * pInWalk = pinArr; 
+                            fcomplex * pInEnd = pinArr + X.S.NumberOfElements;
+                            fcomplex * pRetWalk = pretArr; 
+                            while (pInWalk < pInEnd) {
+                                *(pRetWalk++) = ( fcomplex ) (*(pInWalk++)); 
+                            }
+                        }
+                    } else if (retArrGen is  complex []) {
+						 complex [] dummyArray = ( complex [])(object)retArrGen;
+                        fixed ( complex * pretArr = dummyArray)
+                        fixed (fcomplex * pinArr = inArr) {
+                            fcomplex * pInWalk = pinArr; 
+                            fcomplex * pInEnd = pinArr + X.S.NumberOfElements;
+                            complex * pRetWalk = pretArr; 
+                            while (pInWalk < pInEnd) {
+                                *(pRetWalk++) = ( complex ) (*(pInWalk++)); 
+                            }
+                        }
+                    } else if (retArrGen is  float []) {
+						 float [] dummyArray = ( float [])(object)retArrGen;
+                        fixed ( float * pretArr = dummyArray)
+                        fixed (fcomplex * pinArr = inArr) {
+                            fcomplex * pInWalk = pinArr; 
+                            fcomplex * pInEnd = pinArr + X.S.NumberOfElements;
+                            float * pRetWalk = pretArr; 
+                            while (pInWalk < pInEnd) {
+                                *(pRetWalk++) = ( float ) (*(pInWalk++)); 
+                            }
+                        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+                   } else 
+                        throw new ILArgumentException("unsupported target type: " + typeof(outT).Name);
+    #endregion
+                } else if (inArrGen is byte[]) {
+    #region input byte
+                    byte[] inArr = (byte[])(object)inArrGen;  
+                    if (false) {
+
+                    } else if (retArrGen is  double []) {
+						 double [] dummyArray = ( double [])(object)retArrGen;
+                        fixed ( double * pretArr = dummyArray)
+                        fixed (byte * pinArr = inArr) {
+                            byte * pInWalk = pinArr; 
+                            byte * pInEnd = pinArr + X.S.NumberOfElements;
+                             double * pRetWalk = pretArr; 
+                            while (pInWalk < pInEnd) {
+                                *(pRetWalk++) = ( double ) (*(pInWalk++)); 
+                            }
+                        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+                    } else if (retArrGen is  Int64 []) {
+						 Int64 [] dummyArray = ( Int64 [])(object)retArrGen;
+                        fixed ( Int64 * pretArr = dummyArray)
+                        fixed (byte * pinArr = inArr) {
+                            byte * pInWalk = pinArr; 
+                            byte * pInEnd = pinArr + X.S.NumberOfElements;
+                            Int64 * pRetWalk = pretArr; 
+                            while (pInWalk < pInEnd) {
+                                *(pRetWalk++) = ( Int64 ) (*(pInWalk++)); 
+                            }
+                        }
+                    } else if (retArrGen is  Int32 []) {
+						 Int32 [] dummyArray = ( Int32 [])(object)retArrGen;
+                        fixed ( Int32 * pretArr = dummyArray)
+                        fixed (byte * pinArr = inArr) {
+                            byte * pInWalk = pinArr; 
+                            byte * pInEnd = pinArr + X.S.NumberOfElements;
+                            Int32 * pRetWalk = pretArr; 
+                            while (pInWalk < pInEnd) {
+                                *(pRetWalk++) = ( Int32 ) (*(pInWalk++)); 
+                            }
+                        }
+                    } else if (retArrGen is  byte []) {
+						 byte [] dummyArray = ( byte [])(object)retArrGen;
+                        fixed ( byte * pretArr = dummyArray)
+                        fixed (byte * pinArr = inArr) {
+                            byte * pInWalk = pinArr; 
+                            byte * pInEnd = pinArr + X.S.NumberOfElements;
+                            byte * pRetWalk = pretArr; 
+                            while (pInWalk < pInEnd) {
+                                *(pRetWalk++) = ( byte ) (*(pInWalk++)); 
+                            }
+                        }
+                    } else if (retArrGen is  fcomplex []) {
+						 fcomplex [] dummyArray = ( fcomplex [])(object)retArrGen;
+                        fixed ( fcomplex * pretArr = dummyArray)
+                        fixed (byte * pinArr = inArr) {
+                            byte * pInWalk = pinArr; 
+                            byte * pInEnd = pinArr + X.S.NumberOfElements;
+                            fcomplex * pRetWalk = pretArr; 
+                            while (pInWalk < pInEnd) {
+                                *(pRetWalk++) = ( fcomplex ) (*(pInWalk++)); 
+                            }
+                        }
+                    } else if (retArrGen is  complex []) {
+						 complex [] dummyArray = ( complex [])(object)retArrGen;
+                        fixed ( complex * pretArr = dummyArray)
+                        fixed (byte * pinArr = inArr) {
+                            byte * pInWalk = pinArr; 
+                            byte * pInEnd = pinArr + X.S.NumberOfElements;
+                            complex * pRetWalk = pretArr; 
+                            while (pInWalk < pInEnd) {
+                                *(pRetWalk++) = ( complex ) (*(pInWalk++)); 
+                            }
+                        }
+                    } else if (retArrGen is  float []) {
+						 float [] dummyArray = ( float [])(object)retArrGen;
+                        fixed ( float * pretArr = dummyArray)
+                        fixed (byte * pinArr = inArr) {
+                            byte * pInWalk = pinArr; 
+                            byte * pInEnd = pinArr + X.S.NumberOfElements;
+                            float * pRetWalk = pretArr; 
+                            while (pInWalk < pInEnd) {
+                                *(pRetWalk++) = ( float ) (*(pInWalk++)); 
+                            }
+                        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+                   } else 
+                        throw new ILArgumentException("unsupported target type: " + typeof(outT).Name);
+    #endregion
+                } else if (inArrGen is Int32[]) {
+    #region input Int32
+                    Int32[] inArr = (Int32[])(object)inArrGen;  
+                    if (false) {
+
+                    } else if (retArrGen is  double []) {
+						 double [] dummyArray = ( double [])(object)retArrGen;
+                        fixed ( double * pretArr = dummyArray)
+                        fixed (Int32 * pinArr = inArr) {
+                            Int32 * pInWalk = pinArr; 
+                            Int32 * pInEnd = pinArr + X.S.NumberOfElements;
+                             double * pRetWalk = pretArr; 
+                            while (pInWalk < pInEnd) {
+                                *(pRetWalk++) = ( double ) (*(pInWalk++)); 
+                            }
+                        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+                    } else if (retArrGen is  Int64 []) {
+						 Int64 [] dummyArray = ( Int64 [])(object)retArrGen;
+                        fixed ( Int64 * pretArr = dummyArray)
+                        fixed (Int32 * pinArr = inArr) {
+                            Int32 * pInWalk = pinArr; 
+                            Int32 * pInEnd = pinArr + X.S.NumberOfElements;
+                            Int64 * pRetWalk = pretArr; 
+                            while (pInWalk < pInEnd) {
+                                *(pRetWalk++) = ( Int64 ) (*(pInWalk++)); 
+                            }
+                        }
+                    } else if (retArrGen is  Int32 []) {
+						 Int32 [] dummyArray = ( Int32 [])(object)retArrGen;
+                        fixed ( Int32 * pretArr = dummyArray)
+                        fixed (Int32 * pinArr = inArr) {
+                            Int32 * pInWalk = pinArr; 
+                            Int32 * pInEnd = pinArr + X.S.NumberOfElements;
+                            Int32 * pRetWalk = pretArr; 
+                            while (pInWalk < pInEnd) {
+                                *(pRetWalk++) = ( Int32 ) (*(pInWalk++)); 
+                            }
+                        }
+                    } else if (retArrGen is  byte []) {
+						 byte [] dummyArray = ( byte [])(object)retArrGen;
+                        fixed ( byte * pretArr = dummyArray)
+                        fixed (Int32 * pinArr = inArr) {
+                            Int32 * pInWalk = pinArr; 
+                            Int32 * pInEnd = pinArr + X.S.NumberOfElements;
+                            byte * pRetWalk = pretArr; 
+                            while (pInWalk < pInEnd) {
+                                *(pRetWalk++) = ( byte ) (*(pInWalk++)); 
+                            }
+                        }
+                    } else if (retArrGen is  fcomplex []) {
+						 fcomplex [] dummyArray = ( fcomplex [])(object)retArrGen;
+                        fixed ( fcomplex * pretArr = dummyArray)
+                        fixed (Int32 * pinArr = inArr) {
+                            Int32 * pInWalk = pinArr; 
+                            Int32 * pInEnd = pinArr + X.S.NumberOfElements;
+                            fcomplex * pRetWalk = pretArr; 
+                            while (pInWalk < pInEnd) {
+                                *(pRetWalk++) = ( fcomplex ) (*(pInWalk++)); 
+                            }
+                        }
+                    } else if (retArrGen is  complex []) {
+						 complex [] dummyArray = ( complex [])(object)retArrGen;
+                        fixed ( complex * pretArr = dummyArray)
+                        fixed (Int32 * pinArr = inArr) {
+                            Int32 * pInWalk = pinArr; 
+                            Int32 * pInEnd = pinArr + X.S.NumberOfElements;
+                            complex * pRetWalk = pretArr; 
+                            while (pInWalk < pInEnd) {
+                                *(pRetWalk++) = ( complex ) (*(pInWalk++)); 
+                            }
+                        }
+                    } else if (retArrGen is  float []) {
+						 float [] dummyArray = ( float [])(object)retArrGen;
+                        fixed ( float * pretArr = dummyArray)
+                        fixed (Int32 * pinArr = inArr) {
+                            Int32 * pInWalk = pinArr; 
+                            Int32 * pInEnd = pinArr + X.S.NumberOfElements;
+                            float * pRetWalk = pretArr; 
+                            while (pInWalk < pInEnd) {
+                                *(pRetWalk++) = ( float ) (*(pInWalk++)); 
+                            }
+                        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+                   } else 
+                        throw new ILArgumentException("unsupported target type: " + typeof(outT).Name);
+    #endregion
+                } else if (inArrGen is Int64[]) {
+    #region input Int64
+                    Int64[] inArr = (Int64[])(object)inArrGen;  
+                    if (false) {
+
+                    } else if (retArrGen is  double []) {
+						 double [] dummyArray = ( double [])(object)retArrGen;
+                        fixed ( double * pretArr = dummyArray)
+                        fixed (Int64 * pinArr = inArr) {
+                            Int64 * pInWalk = pinArr; 
+                            Int64 * pInEnd = pinArr + X.S.NumberOfElements;
+                             double * pRetWalk = pretArr; 
+                            while (pInWalk < pInEnd) {
+                                *(pRetWalk++) = ( double ) (*(pInWalk++)); 
+                            }
+                        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+                    } else if (retArrGen is  Int64 []) {
+						 Int64 [] dummyArray = ( Int64 [])(object)retArrGen;
+                        fixed ( Int64 * pretArr = dummyArray)
+                        fixed (Int64 * pinArr = inArr) {
+                            Int64 * pInWalk = pinArr; 
+                            Int64 * pInEnd = pinArr + X.S.NumberOfElements;
+                            Int64 * pRetWalk = pretArr; 
+                            while (pInWalk < pInEnd) {
+                                *(pRetWalk++) = ( Int64 ) (*(pInWalk++)); 
+                            }
+                        }
+                    } else if (retArrGen is  Int32 []) {
+						 Int32 [] dummyArray = ( Int32 [])(object)retArrGen;
+                        fixed ( Int32 * pretArr = dummyArray)
+                        fixed (Int64 * pinArr = inArr) {
+                            Int64 * pInWalk = pinArr; 
+                            Int64 * pInEnd = pinArr + X.S.NumberOfElements;
+                            Int32 * pRetWalk = pretArr; 
+                            while (pInWalk < pInEnd) {
+                                *(pRetWalk++) = ( Int32 ) (*(pInWalk++)); 
+                            }
+                        }
+                    } else if (retArrGen is  byte []) {
+						 byte [] dummyArray = ( byte [])(object)retArrGen;
+                        fixed ( byte * pretArr = dummyArray)
+                        fixed (Int64 * pinArr = inArr) {
+                            Int64 * pInWalk = pinArr; 
+                            Int64 * pInEnd = pinArr + X.S.NumberOfElements;
+                            byte * pRetWalk = pretArr; 
+                            while (pInWalk < pInEnd) {
+                                *(pRetWalk++) = ( byte ) (*(pInWalk++)); 
+                            }
+                        }
+                    } else if (retArrGen is  fcomplex []) {
+						 fcomplex [] dummyArray = ( fcomplex [])(object)retArrGen;
+                        fixed ( fcomplex * pretArr = dummyArray)
+                        fixed (Int64 * pinArr = inArr) {
+                            Int64 * pInWalk = pinArr; 
+                            Int64 * pInEnd = pinArr + X.S.NumberOfElements;
+                            fcomplex * pRetWalk = pretArr; 
+                            while (pInWalk < pInEnd) {
+                                *(pRetWalk++) = ( fcomplex ) (*(pInWalk++)); 
+                            }
+                        }
+                    } else if (retArrGen is  complex []) {
+						 complex [] dummyArray = ( complex [])(object)retArrGen;
+                        fixed ( complex * pretArr = dummyArray)
+                        fixed (Int64 * pinArr = inArr) {
+                            Int64 * pInWalk = pinArr; 
+                            Int64 * pInEnd = pinArr + X.S.NumberOfElements;
+                            complex * pRetWalk = pretArr; 
+                            while (pInWalk < pInEnd) {
+                                *(pRetWalk++) = ( complex ) (*(pInWalk++)); 
+                            }
+                        }
+                    } else if (retArrGen is  float []) {
+						 float [] dummyArray = ( float [])(object)retArrGen;
+                        fixed ( float * pretArr = dummyArray)
+                        fixed (Int64 * pinArr = inArr) {
+                            Int64 * pInWalk = pinArr; 
+                            Int64 * pInEnd = pinArr + X.S.NumberOfElements;
+                            float * pRetWalk = pretArr; 
+                            while (pInWalk < pInEnd) {
+                                *(pRetWalk++) = ( float ) (*(pInWalk++)); 
+                            }
+                        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+                   } else 
+                        throw new ILArgumentException("unsupported target type: " + typeof(outT).Name);
+    #endregion
+                } else if (inArrGen is Complex[] && retArrGen is complex[]) {
+                    GCHandle retHandle = GCHandle.Alloc(retArrGen, GCHandleType.Pinned);
+                    GCHandle inHandle = GCHandle.Alloc(inArrGen, GCHandleType.Pinned);
+                    complex* retP = (complex*)retHandle.AddrOfPinnedObject();
+                    complex* inP = (complex*)inHandle.AddrOfPinnedObject();
+                    complex2ComplexHelper(inP, retP, X.S.NumberOfElements);
+                    retHandle.Free();
+                    inHandle.Free();
+                } else
+                    throw new ILArgumentException(String.Format("conversion from {0} to {1} is currently not supported.", typeof(inT).Name, typeof(outT).Name)); 
+                return new ILRetArray<outT>(retArrGen,X.Size); 
+            }
+        }
+
+        unsafe internal static void complex2ComplexHelper(complex* inArr, complex* outArr, int len) {
+            while (len > 8) {
+                outArr[0] = inArr[0];
+                outArr[1] = inArr[1];
+                outArr[2] = inArr[2];
+                outArr[3] = inArr[3];
+                outArr[4] = inArr[4];
+                outArr[5] = inArr[5];
+                outArr[6] = inArr[6];
+                outArr[7] = inArr[7];
+                inArr += 8; outArr += 8; len -= 8;
+            }
+            while (len-- > 0) *outArr++ = *inArr++;
+        }
+       
+
+        /// <summary>
+        /// Convert numeric array to double array
+        /// </summary>
+        /// <param name="X">Input array</param>
+        /// <returns>double array</returns>
+        /// <remarks><para>The function converts elements of X to double using standard explicit system conversions. 
+        /// The new array uses new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetArray<double> todouble(ILInArray< double > X) {
+             return convert< double ,double>(X); 
+        }
+        /// <summary>
+        /// Convert numeric array to float array
+        /// </summary>
+        /// <param name="X">Input array</param>
+        /// <returns>float array</returns>
+        /// <remarks><para>The new array converts elements of X to float using standard explicit system conversions. 
+        /// The new array uses new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetArray<float> tosingle(ILInArray< double > X) {
+             return convert< double ,float>(X); 
+        }
+        /// <summary>
+        /// Convert numeric array to complex array
+        /// </summary>
+        /// <param name="X">Input array </param>
+        /// <returns>complex array</returns>
+        /// <remarks><para>Real input arrays will be converted to the real part of the complex array returned.</para>
+        /// <para>The function converts elements of X to complex using standard explicit system conversions. 
+        /// The new array uses new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetArray<complex> tocomplex(ILInArray< double > X) {
+             return convert< double ,complex>(X); 
+        }
+        /// <summary>
+        /// Convert numeric array to fcomplex array
+        /// </summary>
+        /// <param name="X">Input array </param>
+        /// <returns>fcomplex array</returns>
+        /// <remarks>
+        /// <para>Real input arrays are converted to the real part of the complex array returned.</para>
+        /// <para>The function converts elements of X to fcomplex using standard explicit system conversions. 
+        /// The new array uses new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetArray<fcomplex> tofcomplex(ILInArray< double > X) {
+             return convert< double ,fcomplex>(X); 
+        }
+        /// <summary>
+        /// Convert numeric array to byte array
+        /// </summary>
+        /// <param name="X">Input array </param>
+        /// <returns>byte array</returns>
+        /// <remarks><para>The function converts elements of X to byte using standard explicit system conversions. 
+        /// The new array uses new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetArray<byte> tobyte(ILInArray< double > X) {
+             return convert< double ,byte>(X); 
+        }
+        /// <summary>
+        /// Convert numeric array to logical array
+        /// </summary>
+        /// <param name="X">Input array </param>
+        /// <returns>Logical array</returns>
+        /// <remarks><para>The function converts elements of X to byte using standard explicit system conversions. Non-zero
+        /// elements are converted to true, zero-elements are converted to false. 
+        /// The new array will always use new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetLogical tological(ILInArray< double > X) {
+             return new ILRetLogical (convert< double ,byte>(X).Storage as ILDenseStorage<byte>); 
+        }
+        /// <summary>
+        /// Convert numeric array to Int32 array
+        /// </summary>
+        /// <param name="X">Input array </param>
+        /// <returns>Int32 array</returns>
+        /// <remarks><para>The function converts elements of X to Int32 using standard explicit system conversions.  
+        /// The new array will always use new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetArray<Int32> toint32(ILInArray< double > X) {
+             return convert< double ,Int32>(X); 
+        }
+        /// <summary>
+        /// Convert numeric array to Int64 array
+        /// </summary>
+        /// <param name="X">Input array </param>
+        /// <returns>Int64 array</returns>
+        /// <remarks><para>The function converts elements of X to Int64 using standard explicit system conversions.  
+        /// The new array will always use new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetArray<Int64> toint64(ILInArray< double > X) {
+             return convert< double ,Int64>(X); 
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// Convert numeric array to double array
+        /// </summary>
+        /// <param name="X">Input array</param>
+        /// <returns>double array</returns>
+        /// <remarks><para>The function converts elements of X to double using standard explicit system conversions. 
+        /// The new array uses new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetArray<double> todouble(ILInArray< Int64 > X) {
+             return convert< Int64 ,double>(X); 
+        }
+        /// <summary>
+        /// Convert numeric array to float array
+        /// </summary>
+        /// <param name="X">Input array</param>
+        /// <returns>float array</returns>
+        /// <remarks><para>The new array converts elements of X to float using standard explicit system conversions. 
+        /// The new array uses new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetArray<float> tosingle(ILInArray< Int64 > X) {
+             return convert< Int64 ,float>(X); 
+        }
+        /// <summary>
+        /// Convert numeric array to complex array
+        /// </summary>
+        /// <param name="X">Input array </param>
+        /// <returns>complex array</returns>
+        /// <remarks><para>Real input arrays will be converted to the real part of the complex array returned.</para>
+        /// <para>The function converts elements of X to complex using standard explicit system conversions. 
+        /// The new array uses new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetArray<complex> tocomplex(ILInArray< Int64 > X) {
+             return convert< Int64 ,complex>(X); 
+        }
+        /// <summary>
+        /// Convert numeric array to fcomplex array
+        /// </summary>
+        /// <param name="X">Input array </param>
+        /// <returns>fcomplex array</returns>
+        /// <remarks>
+        /// <para>Real input arrays are converted to the real part of the complex array returned.</para>
+        /// <para>The function converts elements of X to fcomplex using standard explicit system conversions. 
+        /// The new array uses new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetArray<fcomplex> tofcomplex(ILInArray< Int64 > X) {
+             return convert< Int64 ,fcomplex>(X); 
+        }
+        /// <summary>
+        /// Convert numeric array to byte array
+        /// </summary>
+        /// <param name="X">Input array </param>
+        /// <returns>byte array</returns>
+        /// <remarks><para>The function converts elements of X to byte using standard explicit system conversions. 
+        /// The new array uses new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetArray<byte> tobyte(ILInArray< Int64 > X) {
+             return convert< Int64 ,byte>(X); 
+        }
+        /// <summary>
+        /// Convert numeric array to logical array
+        /// </summary>
+        /// <param name="X">Input array </param>
+        /// <returns>Logical array</returns>
+        /// <remarks><para>The function converts elements of X to byte using standard explicit system conversions. Non-zero
+        /// elements are converted to true, zero-elements are converted to false. 
+        /// The new array will always use new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetLogical tological(ILInArray< Int64 > X) {
+             return new ILRetLogical (convert< Int64 ,byte>(X).Storage as ILDenseStorage<byte>); 
+        }
+        /// <summary>
+        /// Convert numeric array to Int32 array
+        /// </summary>
+        /// <param name="X">Input array </param>
+        /// <returns>Int32 array</returns>
+        /// <remarks><para>The function converts elements of X to Int32 using standard explicit system conversions.  
+        /// The new array will always use new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetArray<Int32> toint32(ILInArray< Int64 > X) {
+             return convert< Int64 ,Int32>(X); 
+        }
+        /// <summary>
+        /// Convert numeric array to Int64 array
+        /// </summary>
+        /// <param name="X">Input array </param>
+        /// <returns>Int64 array</returns>
+        /// <remarks><para>The function converts elements of X to Int64 using standard explicit system conversions.  
+        /// The new array will always use new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetArray<Int64> toint64(ILInArray< Int64 > X) {
+             return convert< Int64 ,Int64>(X); 
+        }
+        /// <summary>
+        /// Convert numeric array to double array
+        /// </summary>
+        /// <param name="X">Input array</param>
+        /// <returns>double array</returns>
+        /// <remarks><para>The function converts elements of X to double using standard explicit system conversions. 
+        /// The new array uses new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetArray<double> todouble(ILInArray< Int32 > X) {
+             return convert< Int32 ,double>(X); 
+        }
+        /// <summary>
+        /// Convert numeric array to float array
+        /// </summary>
+        /// <param name="X">Input array</param>
+        /// <returns>float array</returns>
+        /// <remarks><para>The new array converts elements of X to float using standard explicit system conversions. 
+        /// The new array uses new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetArray<float> tosingle(ILInArray< Int32 > X) {
+             return convert< Int32 ,float>(X); 
+        }
+        /// <summary>
+        /// Convert numeric array to complex array
+        /// </summary>
+        /// <param name="X">Input array </param>
+        /// <returns>complex array</returns>
+        /// <remarks><para>Real input arrays will be converted to the real part of the complex array returned.</para>
+        /// <para>The function converts elements of X to complex using standard explicit system conversions. 
+        /// The new array uses new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetArray<complex> tocomplex(ILInArray< Int32 > X) {
+             return convert< Int32 ,complex>(X); 
+        }
+        /// <summary>
+        /// Convert numeric array to fcomplex array
+        /// </summary>
+        /// <param name="X">Input array </param>
+        /// <returns>fcomplex array</returns>
+        /// <remarks>
+        /// <para>Real input arrays are converted to the real part of the complex array returned.</para>
+        /// <para>The function converts elements of X to fcomplex using standard explicit system conversions. 
+        /// The new array uses new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetArray<fcomplex> tofcomplex(ILInArray< Int32 > X) {
+             return convert< Int32 ,fcomplex>(X); 
+        }
+        /// <summary>
+        /// Convert numeric array to byte array
+        /// </summary>
+        /// <param name="X">Input array </param>
+        /// <returns>byte array</returns>
+        /// <remarks><para>The function converts elements of X to byte using standard explicit system conversions. 
+        /// The new array uses new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetArray<byte> tobyte(ILInArray< Int32 > X) {
+             return convert< Int32 ,byte>(X); 
+        }
+        /// <summary>
+        /// Convert numeric array to logical array
+        /// </summary>
+        /// <param name="X">Input array </param>
+        /// <returns>Logical array</returns>
+        /// <remarks><para>The function converts elements of X to byte using standard explicit system conversions. Non-zero
+        /// elements are converted to true, zero-elements are converted to false. 
+        /// The new array will always use new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetLogical tological(ILInArray< Int32 > X) {
+             return new ILRetLogical (convert< Int32 ,byte>(X).Storage as ILDenseStorage<byte>); 
+        }
+        /// <summary>
+        /// Convert numeric array to Int32 array
+        /// </summary>
+        /// <param name="X">Input array </param>
+        /// <returns>Int32 array</returns>
+        /// <remarks><para>The function converts elements of X to Int32 using standard explicit system conversions.  
+        /// The new array will always use new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetArray<Int32> toint32(ILInArray< Int32 > X) {
+             return convert< Int32 ,Int32>(X); 
+        }
+        /// <summary>
+        /// Convert numeric array to Int64 array
+        /// </summary>
+        /// <param name="X">Input array </param>
+        /// <returns>Int64 array</returns>
+        /// <remarks><para>The function converts elements of X to Int64 using standard explicit system conversions.  
+        /// The new array will always use new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetArray<Int64> toint64(ILInArray< Int32 > X) {
+             return convert< Int32 ,Int64>(X); 
+        }
+        /// <summary>
+        /// Convert numeric array to double array
+        /// </summary>
+        /// <param name="X">Input array</param>
+        /// <returns>double array</returns>
+        /// <remarks><para>The function converts elements of X to double using standard explicit system conversions. 
+        /// The new array uses new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetArray<double> todouble(ILInArray< byte > X) {
+             return convert< byte ,double>(X); 
+        }
+        /// <summary>
+        /// Convert numeric array to float array
+        /// </summary>
+        /// <param name="X">Input array</param>
+        /// <returns>float array</returns>
+        /// <remarks><para>The new array converts elements of X to float using standard explicit system conversions. 
+        /// The new array uses new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetArray<float> tosingle(ILInArray< byte > X) {
+             return convert< byte ,float>(X); 
+        }
+        /// <summary>
+        /// Convert numeric array to complex array
+        /// </summary>
+        /// <param name="X">Input array </param>
+        /// <returns>complex array</returns>
+        /// <remarks><para>Real input arrays will be converted to the real part of the complex array returned.</para>
+        /// <para>The function converts elements of X to complex using standard explicit system conversions. 
+        /// The new array uses new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetArray<complex> tocomplex(ILInArray< byte > X) {
+             return convert< byte ,complex>(X); 
+        }
+        /// <summary>
+        /// Convert numeric array to fcomplex array
+        /// </summary>
+        /// <param name="X">Input array </param>
+        /// <returns>fcomplex array</returns>
+        /// <remarks>
+        /// <para>Real input arrays are converted to the real part of the complex array returned.</para>
+        /// <para>The function converts elements of X to fcomplex using standard explicit system conversions. 
+        /// The new array uses new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetArray<fcomplex> tofcomplex(ILInArray< byte > X) {
+             return convert< byte ,fcomplex>(X); 
+        }
+        /// <summary>
+        /// Convert numeric array to byte array
+        /// </summary>
+        /// <param name="X">Input array </param>
+        /// <returns>byte array</returns>
+        /// <remarks><para>The function converts elements of X to byte using standard explicit system conversions. 
+        /// The new array uses new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetArray<byte> tobyte(ILInArray< byte > X) {
+             return convert< byte ,byte>(X); 
+        }
+        /// <summary>
+        /// Convert numeric array to logical array
+        /// </summary>
+        /// <param name="X">Input array </param>
+        /// <returns>Logical array</returns>
+        /// <remarks><para>The function converts elements of X to byte using standard explicit system conversions. Non-zero
+        /// elements are converted to true, zero-elements are converted to false. 
+        /// The new array will always use new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetLogical tological(ILInArray< byte > X) {
+             return new ILRetLogical (convert< byte ,byte>(X).Storage as ILDenseStorage<byte>); 
+        }
+        /// <summary>
+        /// Convert numeric array to Int32 array
+        /// </summary>
+        /// <param name="X">Input array </param>
+        /// <returns>Int32 array</returns>
+        /// <remarks><para>The function converts elements of X to Int32 using standard explicit system conversions.  
+        /// The new array will always use new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetArray<Int32> toint32(ILInArray< byte > X) {
+             return convert< byte ,Int32>(X); 
+        }
+        /// <summary>
+        /// Convert numeric array to Int64 array
+        /// </summary>
+        /// <param name="X">Input array </param>
+        /// <returns>Int64 array</returns>
+        /// <remarks><para>The function converts elements of X to Int64 using standard explicit system conversions.  
+        /// The new array will always use new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetArray<Int64> toint64(ILInArray< byte > X) {
+             return convert< byte ,Int64>(X); 
+        }
+        /// <summary>
+        /// Convert numeric array to double array
+        /// </summary>
+        /// <param name="X">Input array</param>
+        /// <returns>double array</returns>
+        /// <remarks><para>The function converts elements of X to double using standard explicit system conversions. 
+        /// The new array uses new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetArray<double> todouble(ILInArray< fcomplex > X) {
+             return convert< fcomplex ,double>(X); 
+        }
+        /// <summary>
+        /// Convert numeric array to float array
+        /// </summary>
+        /// <param name="X">Input array</param>
+        /// <returns>float array</returns>
+        /// <remarks><para>The new array converts elements of X to float using standard explicit system conversions. 
+        /// The new array uses new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetArray<float> tosingle(ILInArray< fcomplex > X) {
+             return convert< fcomplex ,float>(X); 
+        }
+        /// <summary>
+        /// Convert numeric array to complex array
+        /// </summary>
+        /// <param name="X">Input array </param>
+        /// <returns>complex array</returns>
+        /// <remarks><para>Real input arrays will be converted to the real part of the complex array returned.</para>
+        /// <para>The function converts elements of X to complex using standard explicit system conversions. 
+        /// The new array uses new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetArray<complex> tocomplex(ILInArray< fcomplex > X) {
+             return convert< fcomplex ,complex>(X); 
+        }
+        /// <summary>
+        /// Convert numeric array to fcomplex array
+        /// </summary>
+        /// <param name="X">Input array </param>
+        /// <returns>fcomplex array</returns>
+        /// <remarks>
+        /// <para>Real input arrays are converted to the real part of the complex array returned.</para>
+        /// <para>The function converts elements of X to fcomplex using standard explicit system conversions. 
+        /// The new array uses new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetArray<fcomplex> tofcomplex(ILInArray< fcomplex > X) {
+             return convert< fcomplex ,fcomplex>(X); 
+        }
+        /// <summary>
+        /// Convert numeric array to byte array
+        /// </summary>
+        /// <param name="X">Input array </param>
+        /// <returns>byte array</returns>
+        /// <remarks><para>The function converts elements of X to byte using standard explicit system conversions. 
+        /// The new array uses new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetArray<byte> tobyte(ILInArray< fcomplex > X) {
+             return convert< fcomplex ,byte>(X); 
+        }
+        /// <summary>
+        /// Convert numeric array to logical array
+        /// </summary>
+        /// <param name="X">Input array </param>
+        /// <returns>Logical array</returns>
+        /// <remarks><para>The function converts elements of X to byte using standard explicit system conversions. Non-zero
+        /// elements are converted to true, zero-elements are converted to false. 
+        /// The new array will always use new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetLogical tological(ILInArray< fcomplex > X) {
+             return new ILRetLogical (convert< fcomplex ,byte>(X).Storage as ILDenseStorage<byte>); 
+        }
+        /// <summary>
+        /// Convert numeric array to Int32 array
+        /// </summary>
+        /// <param name="X">Input array </param>
+        /// <returns>Int32 array</returns>
+        /// <remarks><para>The function converts elements of X to Int32 using standard explicit system conversions.  
+        /// The new array will always use new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetArray<Int32> toint32(ILInArray< fcomplex > X) {
+             return convert< fcomplex ,Int32>(X); 
+        }
+        /// <summary>
+        /// Convert numeric array to Int64 array
+        /// </summary>
+        /// <param name="X">Input array </param>
+        /// <returns>Int64 array</returns>
+        /// <remarks><para>The function converts elements of X to Int64 using standard explicit system conversions.  
+        /// The new array will always use new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetArray<Int64> toint64(ILInArray< fcomplex > X) {
+             return convert< fcomplex ,Int64>(X); 
+        }
+        /// <summary>
+        /// Convert numeric array to double array
+        /// </summary>
+        /// <param name="X">Input array</param>
+        /// <returns>double array</returns>
+        /// <remarks><para>The function converts elements of X to double using standard explicit system conversions. 
+        /// The new array uses new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetArray<double> todouble(ILInArray< complex > X) {
+             return convert< complex ,double>(X); 
+        }
+        /// <summary>
+        /// Convert numeric array to float array
+        /// </summary>
+        /// <param name="X">Input array</param>
+        /// <returns>float array</returns>
+        /// <remarks><para>The new array converts elements of X to float using standard explicit system conversions. 
+        /// The new array uses new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetArray<float> tosingle(ILInArray< complex > X) {
+             return convert< complex ,float>(X); 
+        }
+        /// <summary>
+        /// Convert numeric array to complex array
+        /// </summary>
+        /// <param name="X">Input array </param>
+        /// <returns>complex array</returns>
+        /// <remarks><para>Real input arrays will be converted to the real part of the complex array returned.</para>
+        /// <para>The function converts elements of X to complex using standard explicit system conversions. 
+        /// The new array uses new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetArray<complex> tocomplex(ILInArray< complex > X) {
+             return convert< complex ,complex>(X); 
+        }
+        /// <summary>
+        /// Convert numeric array to fcomplex array
+        /// </summary>
+        /// <param name="X">Input array </param>
+        /// <returns>fcomplex array</returns>
+        /// <remarks>
+        /// <para>Real input arrays are converted to the real part of the complex array returned.</para>
+        /// <para>The function converts elements of X to fcomplex using standard explicit system conversions. 
+        /// The new array uses new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetArray<fcomplex> tofcomplex(ILInArray< complex > X) {
+             return convert< complex ,fcomplex>(X); 
+        }
+        /// <summary>
+        /// Convert numeric array to byte array
+        /// </summary>
+        /// <param name="X">Input array </param>
+        /// <returns>byte array</returns>
+        /// <remarks><para>The function converts elements of X to byte using standard explicit system conversions. 
+        /// The new array uses new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetArray<byte> tobyte(ILInArray< complex > X) {
+             return convert< complex ,byte>(X); 
+        }
+        /// <summary>
+        /// Convert numeric array to logical array
+        /// </summary>
+        /// <param name="X">Input array </param>
+        /// <returns>Logical array</returns>
+        /// <remarks><para>The function converts elements of X to byte using standard explicit system conversions. Non-zero
+        /// elements are converted to true, zero-elements are converted to false. 
+        /// The new array will always use new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetLogical tological(ILInArray< complex > X) {
+             return new ILRetLogical (convert< complex ,byte>(X).Storage as ILDenseStorage<byte>); 
+        }
+        /// <summary>
+        /// Convert numeric array to Int32 array
+        /// </summary>
+        /// <param name="X">Input array </param>
+        /// <returns>Int32 array</returns>
+        /// <remarks><para>The function converts elements of X to Int32 using standard explicit system conversions.  
+        /// The new array will always use new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetArray<Int32> toint32(ILInArray< complex > X) {
+             return convert< complex ,Int32>(X); 
+        }
+        /// <summary>
+        /// Convert numeric array to Int64 array
+        /// </summary>
+        /// <param name="X">Input array </param>
+        /// <returns>Int64 array</returns>
+        /// <remarks><para>The function converts elements of X to Int64 using standard explicit system conversions.  
+        /// The new array will always use new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetArray<Int64> toint64(ILInArray< complex > X) {
+             return convert< complex ,Int64>(X); 
+        }
+        /// <summary>
+        /// Convert numeric array to double array
+        /// </summary>
+        /// <param name="X">Input array</param>
+        /// <returns>double array</returns>
+        /// <remarks><para>The function converts elements of X to double using standard explicit system conversions. 
+        /// The new array uses new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetArray<double> todouble(ILInArray< float > X) {
+             return convert< float ,double>(X); 
+        }
+        /// <summary>
+        /// Convert numeric array to float array
+        /// </summary>
+        /// <param name="X">Input array</param>
+        /// <returns>float array</returns>
+        /// <remarks><para>The new array converts elements of X to float using standard explicit system conversions. 
+        /// The new array uses new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetArray<float> tosingle(ILInArray< float > X) {
+             return convert< float ,float>(X); 
+        }
+        /// <summary>
+        /// Convert numeric array to complex array
+        /// </summary>
+        /// <param name="X">Input array </param>
+        /// <returns>complex array</returns>
+        /// <remarks><para>Real input arrays will be converted to the real part of the complex array returned.</para>
+        /// <para>The function converts elements of X to complex using standard explicit system conversions. 
+        /// The new array uses new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetArray<complex> tocomplex(ILInArray< float > X) {
+             return convert< float ,complex>(X); 
+        }
+        /// <summary>
+        /// Convert numeric array to fcomplex array
+        /// </summary>
+        /// <param name="X">Input array </param>
+        /// <returns>fcomplex array</returns>
+        /// <remarks>
+        /// <para>Real input arrays are converted to the real part of the complex array returned.</para>
+        /// <para>The function converts elements of X to fcomplex using standard explicit system conversions. 
+        /// The new array uses new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetArray<fcomplex> tofcomplex(ILInArray< float > X) {
+             return convert< float ,fcomplex>(X); 
+        }
+        /// <summary>
+        /// Convert numeric array to byte array
+        /// </summary>
+        /// <param name="X">Input array </param>
+        /// <returns>byte array</returns>
+        /// <remarks><para>The function converts elements of X to byte using standard explicit system conversions. 
+        /// The new array uses new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetArray<byte> tobyte(ILInArray< float > X) {
+             return convert< float ,byte>(X); 
+        }
+        /// <summary>
+        /// Convert numeric array to logical array
+        /// </summary>
+        /// <param name="X">Input array </param>
+        /// <returns>Logical array</returns>
+        /// <remarks><para>The function converts elements of X to byte using standard explicit system conversions. Non-zero
+        /// elements are converted to true, zero-elements are converted to false. 
+        /// The new array will always use new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetLogical tological(ILInArray< float > X) {
+             return new ILRetLogical (convert< float ,byte>(X).Storage as ILDenseStorage<byte>); 
+        }
+        /// <summary>
+        /// Convert numeric array to Int32 array
+        /// </summary>
+        /// <param name="X">Input array </param>
+        /// <returns>Int32 array</returns>
+        /// <remarks><para>The function converts elements of X to Int32 using standard explicit system conversions.  
+        /// The new array will always use new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetArray<Int32> toint32(ILInArray< float > X) {
+             return convert< float ,Int32>(X); 
+        }
+        /// <summary>
+        /// Convert numeric array to Int64 array
+        /// </summary>
+        /// <param name="X">Input array </param>
+        /// <returns>Int64 array</returns>
+        /// <remarks><para>The function converts elements of X to Int64 using standard explicit system conversions.  
+        /// The new array will always use new memory, even if the incoming type is the same as the output type.</para></remarks>
+        public static ILRetArray<Int64> toint64(ILInArray< float > X) {
+             return convert< float ,Int64>(X); 
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+
+
+        /// <summary>
+        /// convert arbitrary numeric array to double array
+        /// </summary>
+        /// <param name="X">numeric array, one of supported numeric type</param>
+        /// <returns>double array</returns>
+        /// <remarks>This function enables to convert arbitrary numeric (dense) arrays to a known output array type 
+        /// - without knowing the concrete numeric type of the source. Supported element types include: double, 
+        /// float, complex, fcomplex, byte, logical, Int32, Int64.
+        /// <para>This function will always create new memory for the new array, even if both 
+        /// arrays have the same element type.</para>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if elements of X are 
+        /// not of any supported numeric type</exception>
+        public static ILRetArray< double>  todouble(ILBaseArray X) {
+            using (ILScope.Enter(X)) {
+                if (X is ILDenseArray<double>)
+                    return convert<double, double>((X as ILDenseArray<double>).C);
+                else if (X is ILDenseArray<float>)
+                    return convert<float, double>((X as ILDenseArray<float>).C);
+                else if (X is ILDenseArray<complex>)
+                    return convert<complex, double>((X as ILDenseArray<complex>).C);
+                else if (X is ILDenseArray<fcomplex>)
+                    return convert<fcomplex, double>((X as ILDenseArray<fcomplex>).C);
+                else if (X is ILDenseArray<byte>)
+                    return convert<byte, double>((X as ILDenseArray<byte>).C);
+                else if (X is ILDenseArray<Int32>)
+                    return convert<Int32, double>((X as ILDenseArray<Int32>).C);
+                else if (X is ILDenseArray<Int64>)
+                    return convert<Int64, double>((X as ILDenseArray<Int64>).C);
+                else
+                    throw new ILArgumentException("input type not supported: " + X.GetType().Name);
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+
+        /// <summary>convert arbitrary numeric array to Int64 array</summary>
+        /// <param name="X">numeric array, one of supported numeric type</param>
+        /// <returns>Int64 array</returns>
+        /// <remarks>This function enables to convert arbitrary numeric (dense) arrays to a known output array type 
+        /// - without knowing the concrete numeric type of the source. Supported element types include: double, 
+        /// float, complex, fcomplex, byte, logical, Int32, Int64.
+        /// <para>This function will always create new memory for the new array, even if both 
+        /// arrays have the same element type.</para>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if elements of X are 
+        /// not of any supported numeric type</exception>
+        public static ILRetArray< Int64>  toint64(ILBaseArray X) {
+            using (ILScope.Enter(X)) {
+                if (X is ILDenseArray<double>)
+                    return convert<double, Int64>((X as ILDenseArray<double>).C);
+                else if (X is ILDenseArray<float>)
+                    return convert<float, Int64>((X as ILDenseArray<float>).C);
+                else if (X is ILDenseArray<complex>)
+                    return convert<complex, Int64>((X as ILDenseArray<complex>).C);
+                else if (X is ILDenseArray<fcomplex>)
+                    return convert<fcomplex, Int64>((X as ILDenseArray<fcomplex>).C);
+                else if (X is ILDenseArray<byte>)
+                    return convert<byte, Int64>((X as ILDenseArray<byte>).C);
+                else if (X is ILDenseArray<Int32>)
+                    return convert<Int32, Int64>((X as ILDenseArray<Int32>).C);
+                else if (X is ILDenseArray<Int64>)
+                    return convert<Int64, Int64>((X as ILDenseArray<Int64>).C);
+                else
+                    throw new ILArgumentException("input type not supported: " + X.GetType().Name);
+            }
+        }
+
+        /// <summary>convert arbitrary numeric array to Int32 array</summary>
+        /// <param name="X">numeric array, one of supported numeric type</param>
+        /// <returns>Int32 array</returns>
+        /// <remarks>This function enables to convert arbitrary numeric (dense) arrays to a known output array type 
+        /// - without knowing the concrete numeric type of the source. Supported element types include: double, 
+        /// float, complex, fcomplex, byte, logical, Int32, Int64.
+        /// <para>This function will always create new memory for the new array, even if both 
+        /// arrays have the same element type.</para>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if elements of X are 
+        /// not of any supported numeric type</exception>
+        public static ILRetArray< Int32>  toint32(ILBaseArray X) {
+            using (ILScope.Enter(X)) {
+                if (X is ILDenseArray<double>)
+                    return convert<double, Int32>((X as ILDenseArray<double>).C);
+                else if (X is ILDenseArray<float>)
+                    return convert<float, Int32>((X as ILDenseArray<float>).C);
+                else if (X is ILDenseArray<complex>)
+                    return convert<complex, Int32>((X as ILDenseArray<complex>).C);
+                else if (X is ILDenseArray<fcomplex>)
+                    return convert<fcomplex, Int32>((X as ILDenseArray<fcomplex>).C);
+                else if (X is ILDenseArray<byte>)
+                    return convert<byte, Int32>((X as ILDenseArray<byte>).C);
+                else if (X is ILDenseArray<Int32>)
+                    return convert<Int32, Int32>((X as ILDenseArray<Int32>).C);
+                else if (X is ILDenseArray<Int64>)
+                    return convert<Int64, Int32>((X as ILDenseArray<Int64>).C);
+                else
+                    throw new ILArgumentException("input type not supported: " + X.GetType().Name);
+            }
+        }
+
+        /// <summary>convert arbitrary numeric array to byte array</summary>
+        /// <param name="X">numeric array, one of supported numeric type</param>
+        /// <returns>byte array</returns>
+        /// <remarks>This function enables to convert arbitrary numeric (dense) arrays to a known output array type 
+        /// - without knowing the concrete numeric type of the source. Supported element types include: double, 
+        /// float, complex, fcomplex, byte, logical, Int32, Int64.
+        /// <para>This function will always create new memory for the new array, even if both 
+        /// arrays have the same element type.</para>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if elements of X are 
+        /// not of any supported numeric type</exception>
+        public static ILRetArray< byte>  tobyte(ILBaseArray X) {
+            using (ILScope.Enter(X)) {
+                if (X is ILDenseArray<double>)
+                    return convert<double, byte>((X as ILDenseArray<double>).C);
+                else if (X is ILDenseArray<float>)
+                    return convert<float, byte>((X as ILDenseArray<float>).C);
+                else if (X is ILDenseArray<complex>)
+                    return convert<complex, byte>((X as ILDenseArray<complex>).C);
+                else if (X is ILDenseArray<fcomplex>)
+                    return convert<fcomplex, byte>((X as ILDenseArray<fcomplex>).C);
+                else if (X is ILDenseArray<byte>)
+                    return convert<byte, byte>((X as ILDenseArray<byte>).C);
+                else if (X is ILDenseArray<Int32>)
+                    return convert<Int32, byte>((X as ILDenseArray<Int32>).C);
+                else if (X is ILDenseArray<Int64>)
+                    return convert<Int64, byte>((X as ILDenseArray<Int64>).C);
+                else
+                    throw new ILArgumentException("input type not supported: " + X.GetType().Name);
+            }
+        }
+
+        /// <summary>convert arbitrary numeric array to fcomplex array</summary>
+        /// <param name="X">numeric array, one of supported numeric type</param>
+        /// <returns>fcomplex array</returns>
+        /// <remarks>This function enables to convert arbitrary numeric (dense) arrays to a known output array type 
+        /// - without knowing the concrete numeric type of the source. Supported element types include: double, 
+        /// float, complex, fcomplex, byte, logical, Int32, Int64.
+        /// <para>This function will always create new memory for the new array, even if both 
+        /// arrays have the same element type.</para>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if elements of X are 
+        /// not of any supported numeric type</exception>
+        public static ILRetArray< fcomplex>  tofcomplex(ILBaseArray X) {
+            using (ILScope.Enter(X)) {
+                if (X is ILDenseArray<double>)
+                    return convert<double, fcomplex>((X as ILDenseArray<double>).C);
+                else if (X is ILDenseArray<float>)
+                    return convert<float, fcomplex>((X as ILDenseArray<float>).C);
+                else if (X is ILDenseArray<complex>)
+                    return convert<complex, fcomplex>((X as ILDenseArray<complex>).C);
+                else if (X is ILDenseArray<fcomplex>)
+                    return convert<fcomplex, fcomplex>((X as ILDenseArray<fcomplex>).C);
+                else if (X is ILDenseArray<byte>)
+                    return convert<byte, fcomplex>((X as ILDenseArray<byte>).C);
+                else if (X is ILDenseArray<Int32>)
+                    return convert<Int32, fcomplex>((X as ILDenseArray<Int32>).C);
+                else if (X is ILDenseArray<Int64>)
+                    return convert<Int64, fcomplex>((X as ILDenseArray<Int64>).C);
+                else
+                    throw new ILArgumentException("input type not supported: " + X.GetType().Name);
+            }
+        }
+
+        /// <summary>convert arbitrary numeric array to complex array</summary>
+        /// <param name="X">numeric array, one of supported numeric type</param>
+        /// <returns>complex array</returns>
+        /// <remarks>This function enables to convert arbitrary numeric (dense) arrays to a known output array type 
+        /// - without knowing the concrete numeric type of the source. Supported element types include: double, 
+        /// float, complex, fcomplex, byte, logical, Int32, Int64.
+        /// <para>This function will always create new memory for the new array, even if both 
+        /// arrays have the same element type.</para>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if elements of X are 
+        /// not of any supported numeric type</exception>
+        public static ILRetArray< complex>  tocomplex(ILBaseArray X) {
+            using (ILScope.Enter(X)) {
+                if (X is ILDenseArray<double>)
+                    return convert<double, complex>((X as ILDenseArray<double>).C);
+                else if (X is ILDenseArray<float>)
+                    return convert<float, complex>((X as ILDenseArray<float>).C);
+                else if (X is ILDenseArray<complex>)
+                    return convert<complex, complex>((X as ILDenseArray<complex>).C);
+                else if (X is ILDenseArray<fcomplex>)
+                    return convert<fcomplex, complex>((X as ILDenseArray<fcomplex>).C);
+                else if (X is ILDenseArray<byte>)
+                    return convert<byte, complex>((X as ILDenseArray<byte>).C);
+                else if (X is ILDenseArray<Int32>)
+                    return convert<Int32, complex>((X as ILDenseArray<Int32>).C);
+                else if (X is ILDenseArray<Int64>)
+                    return convert<Int64, complex>((X as ILDenseArray<Int64>).C);
+                else
+                    throw new ILArgumentException("input type not supported: " + X.GetType().Name);
+            }
+        }
+
+        /// <summary>convert arbitrary numeric array to float array</summary>
+        /// <param name="X">numeric array, one of supported numeric type</param>
+        /// <returns>float array</returns>
+        /// <remarks>This function enables to convert arbitrary numeric (dense) arrays to a known output array type 
+        /// - without knowing the concrete numeric type of the source. Supported element types include: double, 
+        /// float, complex, fcomplex, byte, logical, Int32, Int64.
+        /// <para>This function will always create new memory for the new array, even if both 
+        /// arrays have the same element type.</para>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if elements of X are 
+        /// not of any supported numeric type</exception>
+        public static ILRetArray< float>  tosingle(ILBaseArray X) {
+            using (ILScope.Enter(X)) {
+                if (X is ILDenseArray<double>)
+                    return convert<double, float>((X as ILDenseArray<double>).C);
+                else if (X is ILDenseArray<float>)
+                    return convert<float, float>((X as ILDenseArray<float>).C);
+                else if (X is ILDenseArray<complex>)
+                    return convert<complex, float>((X as ILDenseArray<complex>).C);
+                else if (X is ILDenseArray<fcomplex>)
+                    return convert<fcomplex, float>((X as ILDenseArray<fcomplex>).C);
+                else if (X is ILDenseArray<byte>)
+                    return convert<byte, float>((X as ILDenseArray<byte>).C);
+                else if (X is ILDenseArray<Int32>)
+                    return convert<Int32, float>((X as ILDenseArray<Int32>).C);
+                else if (X is ILDenseArray<Int64>)
+                    return convert<Int64, float>((X as ILDenseArray<Int64>).C);
+                else
+                    throw new ILArgumentException("input type not supported: " + X.GetType().Name);
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/cos.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/cos.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/cos.cs	(revision 9102)
@@ -0,0 +1,559 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics;
+using ILNumerics.Exceptions; 
+using ILNumerics.Storage; 
+using ILNumerics.Misc; 
+
+
+
+namespace ILNumerics {
+    
+    public partial class ILMath {
+ 
+
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>Cosine of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Cosine of array elements</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<complex>  cos (ILInArray< complex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<complex>(A.Size); 
+                ILSize inDim = A.Size;
+                complex[] arrA = A.GetArrayForRead(); 
+                complex [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<complex>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<complex> retStorage = new ILDenseStorage<complex>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    complex* cp = ((complex*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  complex.Cos(cp[0]  )  /*dummy*/;
+                            cp[1] =  complex.Cos(cp[1]  )  /*dummy*/;
+                            cp[2] =  complex.Cos(cp[2]  )  /*dummy*/;
+                            cp[3] =  complex.Cos(cp[3]  )  /*dummy*/;
+                            cp[4] =  complex.Cos(cp[4]  )  /*dummy*/;
+                            cp[5] =  complex.Cos(cp[5]  )  /*dummy*/;
+                            cp[6] =  complex.Cos(cp[6]  )  /*dummy*/;
+                            cp[7] =  complex.Cos(cp[7]  )  /*dummy*/;
+                            cp[8] =  complex.Cos(cp[8]  )  /*dummy*/;
+                            cp[9] =  complex.Cos(cp[9]  )  /*dummy*/;
+                            cp[10] =  complex.Cos(cp[10]  )  /*dummy*/;
+                            cp[11] =  complex.Cos(cp[11]  )  /*dummy*/;
+                            cp[12] =  complex.Cos(cp[12]  )  /*dummy*/;
+                            cp[13] =  complex.Cos(cp[13]  )  /*dummy*/;
+                            cp[14] =  complex.Cos(cp[14]  )  /*dummy*/;
+                            cp[15] =  complex.Cos(cp[15]  )  /*dummy*/;
+                            cp[16] =  complex.Cos(cp[16]  )  /*dummy*/;
+                            cp[17] =  complex.Cos(cp[17]  )  /*dummy*/;
+                            cp[18] =  complex.Cos(cp[18]  )  /*dummy*/;
+                            cp[19] =  complex.Cos(cp[19]  )  /*dummy*/;
+                            cp[20] =  complex.Cos(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.Cos(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        complex* ap = ((complex*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  complex.Cos(ap[0]  )  /*dummy*/;
+                            cp[1] =  complex.Cos(ap[1]  )  /*dummy*/;
+                            cp[2] =  complex.Cos(ap[2]  )  /*dummy*/;
+                            cp[3] =  complex.Cos(ap[3]  )  /*dummy*/;
+                            cp[4] =  complex.Cos(ap[4]  )  /*dummy*/;
+                            cp[5] =  complex.Cos(ap[5]  )  /*dummy*/;
+                            cp[6] =  complex.Cos(ap[6]  )  /*dummy*/;
+                            cp[7] =  complex.Cos(ap[7]  )  /*dummy*/;
+                            cp[8] =  complex.Cos(ap[8]  )  /*dummy*/;
+                            cp[9] =  complex.Cos(ap[9]  )  /*dummy*/;
+                            cp[10] =  complex.Cos(ap[10]  )  /*dummy*/;
+                            cp[11] =  complex.Cos(ap[11]  )  /*dummy*/;
+                            cp[12] =  complex.Cos(ap[12]  )  /*dummy*/;
+                            cp[13] =  complex.Cos(ap[13]  )  /*dummy*/;
+                            cp[14] =  complex.Cos(ap[14]  )  /*dummy*/;
+                            cp[15] =  complex.Cos(ap[15]  )  /*dummy*/;
+                            cp[16] =  complex.Cos(ap[16]  )  /*dummy*/;
+                            cp[17] =  complex.Cos(ap[17]  )  /*dummy*/;
+                            cp[18] =  complex.Cos(ap[18]  )  /*dummy*/;
+                            cp[19] =  complex.Cos(ap[19]  )  /*dummy*/;
+                            cp[20] =  complex.Cos(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.Cos(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( complex* arrAP = arrA)
+                fixed ( complex* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<complex>(retStorage);
+            }
+        }
+        /// <summary>Cosine of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Cosine of array elements</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<fcomplex>  cos (ILInArray< fcomplex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<fcomplex>(A.Size); 
+                ILSize inDim = A.Size;
+                fcomplex[] arrA = A.GetArrayForRead(); 
+                fcomplex [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<fcomplex>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<fcomplex> retStorage = new ILDenseStorage<fcomplex>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    fcomplex* cp = ((fcomplex*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  fcomplex.Cos(cp[0]  )  /*dummy*/;
+                            cp[1] =  fcomplex.Cos(cp[1]  )  /*dummy*/;
+                            cp[2] =  fcomplex.Cos(cp[2]  )  /*dummy*/;
+                            cp[3] =  fcomplex.Cos(cp[3]  )  /*dummy*/;
+                            cp[4] =  fcomplex.Cos(cp[4]  )  /*dummy*/;
+                            cp[5] =  fcomplex.Cos(cp[5]  )  /*dummy*/;
+                            cp[6] =  fcomplex.Cos(cp[6]  )  /*dummy*/;
+                            cp[7] =  fcomplex.Cos(cp[7]  )  /*dummy*/;
+                            cp[8] =  fcomplex.Cos(cp[8]  )  /*dummy*/;
+                            cp[9] =  fcomplex.Cos(cp[9]  )  /*dummy*/;
+                            cp[10] =  fcomplex.Cos(cp[10]  )  /*dummy*/;
+                            cp[11] =  fcomplex.Cos(cp[11]  )  /*dummy*/;
+                            cp[12] =  fcomplex.Cos(cp[12]  )  /*dummy*/;
+                            cp[13] =  fcomplex.Cos(cp[13]  )  /*dummy*/;
+                            cp[14] =  fcomplex.Cos(cp[14]  )  /*dummy*/;
+                            cp[15] =  fcomplex.Cos(cp[15]  )  /*dummy*/;
+                            cp[16] =  fcomplex.Cos(cp[16]  )  /*dummy*/;
+                            cp[17] =  fcomplex.Cos(cp[17]  )  /*dummy*/;
+                            cp[18] =  fcomplex.Cos(cp[18]  )  /*dummy*/;
+                            cp[19] =  fcomplex.Cos(cp[19]  )  /*dummy*/;
+                            cp[20] =  fcomplex.Cos(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.Cos(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        fcomplex* ap = ((fcomplex*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  fcomplex.Cos(ap[0]  )  /*dummy*/;
+                            cp[1] =  fcomplex.Cos(ap[1]  )  /*dummy*/;
+                            cp[2] =  fcomplex.Cos(ap[2]  )  /*dummy*/;
+                            cp[3] =  fcomplex.Cos(ap[3]  )  /*dummy*/;
+                            cp[4] =  fcomplex.Cos(ap[4]  )  /*dummy*/;
+                            cp[5] =  fcomplex.Cos(ap[5]  )  /*dummy*/;
+                            cp[6] =  fcomplex.Cos(ap[6]  )  /*dummy*/;
+                            cp[7] =  fcomplex.Cos(ap[7]  )  /*dummy*/;
+                            cp[8] =  fcomplex.Cos(ap[8]  )  /*dummy*/;
+                            cp[9] =  fcomplex.Cos(ap[9]  )  /*dummy*/;
+                            cp[10] =  fcomplex.Cos(ap[10]  )  /*dummy*/;
+                            cp[11] =  fcomplex.Cos(ap[11]  )  /*dummy*/;
+                            cp[12] =  fcomplex.Cos(ap[12]  )  /*dummy*/;
+                            cp[13] =  fcomplex.Cos(ap[13]  )  /*dummy*/;
+                            cp[14] =  fcomplex.Cos(ap[14]  )  /*dummy*/;
+                            cp[15] =  fcomplex.Cos(ap[15]  )  /*dummy*/;
+                            cp[16] =  fcomplex.Cos(ap[16]  )  /*dummy*/;
+                            cp[17] =  fcomplex.Cos(ap[17]  )  /*dummy*/;
+                            cp[18] =  fcomplex.Cos(ap[18]  )  /*dummy*/;
+                            cp[19] =  fcomplex.Cos(ap[19]  )  /*dummy*/;
+                            cp[20] =  fcomplex.Cos(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.Cos(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( fcomplex* arrAP = arrA)
+                fixed ( fcomplex* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<fcomplex>(retStorage);
+            }
+        }
+        /// <summary>Cosine of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Cosine of array elements</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<float>  cos (ILInArray< float > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<float>(A.Size); 
+                ILSize inDim = A.Size;
+                float[] arrA = A.GetArrayForRead(); 
+                float [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<float>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<float> retStorage = new ILDenseStorage<float>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    float* cp = ((float*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  (float)Math.Cos(cp[0]  )  /*dummy*/;
+                            cp[1] =  (float)Math.Cos(cp[1]  )  /*dummy*/;
+                            cp[2] =  (float)Math.Cos(cp[2]  )  /*dummy*/;
+                            cp[3] =  (float)Math.Cos(cp[3]  )  /*dummy*/;
+                            cp[4] =  (float)Math.Cos(cp[4]  )  /*dummy*/;
+                            cp[5] =  (float)Math.Cos(cp[5]  )  /*dummy*/;
+                            cp[6] =  (float)Math.Cos(cp[6]  )  /*dummy*/;
+                            cp[7] =  (float)Math.Cos(cp[7]  )  /*dummy*/;
+                            cp[8] =  (float)Math.Cos(cp[8]  )  /*dummy*/;
+                            cp[9] =  (float)Math.Cos(cp[9]  )  /*dummy*/;
+                            cp[10] =  (float)Math.Cos(cp[10]  )  /*dummy*/;
+                            cp[11] =  (float)Math.Cos(cp[11]  )  /*dummy*/;
+                            cp[12] =  (float)Math.Cos(cp[12]  )  /*dummy*/;
+                            cp[13] =  (float)Math.Cos(cp[13]  )  /*dummy*/;
+                            cp[14] =  (float)Math.Cos(cp[14]  )  /*dummy*/;
+                            cp[15] =  (float)Math.Cos(cp[15]  )  /*dummy*/;
+                            cp[16] =  (float)Math.Cos(cp[16]  )  /*dummy*/;
+                            cp[17] =  (float)Math.Cos(cp[17]  )  /*dummy*/;
+                            cp[18] =  (float)Math.Cos(cp[18]  )  /*dummy*/;
+                            cp[19] =  (float)Math.Cos(cp[19]  )  /*dummy*/;
+                            cp[20] =  (float)Math.Cos(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  (float)Math.Cos(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        float* ap = ((float*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  (float)Math.Cos(ap[0]  )  /*dummy*/;
+                            cp[1] =  (float)Math.Cos(ap[1]  )  /*dummy*/;
+                            cp[2] =  (float)Math.Cos(ap[2]  )  /*dummy*/;
+                            cp[3] =  (float)Math.Cos(ap[3]  )  /*dummy*/;
+                            cp[4] =  (float)Math.Cos(ap[4]  )  /*dummy*/;
+                            cp[5] =  (float)Math.Cos(ap[5]  )  /*dummy*/;
+                            cp[6] =  (float)Math.Cos(ap[6]  )  /*dummy*/;
+                            cp[7] =  (float)Math.Cos(ap[7]  )  /*dummy*/;
+                            cp[8] =  (float)Math.Cos(ap[8]  )  /*dummy*/;
+                            cp[9] =  (float)Math.Cos(ap[9]  )  /*dummy*/;
+                            cp[10] =  (float)Math.Cos(ap[10]  )  /*dummy*/;
+                            cp[11] =  (float)Math.Cos(ap[11]  )  /*dummy*/;
+                            cp[12] =  (float)Math.Cos(ap[12]  )  /*dummy*/;
+                            cp[13] =  (float)Math.Cos(ap[13]  )  /*dummy*/;
+                            cp[14] =  (float)Math.Cos(ap[14]  )  /*dummy*/;
+                            cp[15] =  (float)Math.Cos(ap[15]  )  /*dummy*/;
+                            cp[16] =  (float)Math.Cos(ap[16]  )  /*dummy*/;
+                            cp[17] =  (float)Math.Cos(ap[17]  )  /*dummy*/;
+                            cp[18] =  (float)Math.Cos(ap[18]  )  /*dummy*/;
+                            cp[19] =  (float)Math.Cos(ap[19]  )  /*dummy*/;
+                            cp[20] =  (float)Math.Cos(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  (float)Math.Cos(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( float* arrAP = arrA)
+                fixed ( float* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<float>(retStorage);
+            }
+        }
+        /// <summary>Cosine of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Cosine of array elements</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<double>  cos (ILInArray< double > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<double>(A.Size); 
+                ILSize inDim = A.Size;
+                double[] arrA = A.GetArrayForRead(); 
+                double [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<double>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<double> retStorage = new ILDenseStorage<double>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    double* cp = ((double*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  Math.Cos(cp[0]  )  /*dummy*/;
+                            cp[1] =  Math.Cos(cp[1]  )  /*dummy*/;
+                            cp[2] =  Math.Cos(cp[2]  )  /*dummy*/;
+                            cp[3] =  Math.Cos(cp[3]  )  /*dummy*/;
+                            cp[4] =  Math.Cos(cp[4]  )  /*dummy*/;
+                            cp[5] =  Math.Cos(cp[5]  )  /*dummy*/;
+                            cp[6] =  Math.Cos(cp[6]  )  /*dummy*/;
+                            cp[7] =  Math.Cos(cp[7]  )  /*dummy*/;
+                            cp[8] =  Math.Cos(cp[8]  )  /*dummy*/;
+                            cp[9] =  Math.Cos(cp[9]  )  /*dummy*/;
+                            cp[10] =  Math.Cos(cp[10]  )  /*dummy*/;
+                            cp[11] =  Math.Cos(cp[11]  )  /*dummy*/;
+                            cp[12] =  Math.Cos(cp[12]  )  /*dummy*/;
+                            cp[13] =  Math.Cos(cp[13]  )  /*dummy*/;
+                            cp[14] =  Math.Cos(cp[14]  )  /*dummy*/;
+                            cp[15] =  Math.Cos(cp[15]  )  /*dummy*/;
+                            cp[16] =  Math.Cos(cp[16]  )  /*dummy*/;
+                            cp[17] =  Math.Cos(cp[17]  )  /*dummy*/;
+                            cp[18] =  Math.Cos(cp[18]  )  /*dummy*/;
+                            cp[19] =  Math.Cos(cp[19]  )  /*dummy*/;
+                            cp[20] =  Math.Cos(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Math.Cos(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        double* ap = ((double*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  Math.Cos(ap[0]  )  /*dummy*/;
+                            cp[1] =  Math.Cos(ap[1]  )  /*dummy*/;
+                            cp[2] =  Math.Cos(ap[2]  )  /*dummy*/;
+                            cp[3] =  Math.Cos(ap[3]  )  /*dummy*/;
+                            cp[4] =  Math.Cos(ap[4]  )  /*dummy*/;
+                            cp[5] =  Math.Cos(ap[5]  )  /*dummy*/;
+                            cp[6] =  Math.Cos(ap[6]  )  /*dummy*/;
+                            cp[7] =  Math.Cos(ap[7]  )  /*dummy*/;
+                            cp[8] =  Math.Cos(ap[8]  )  /*dummy*/;
+                            cp[9] =  Math.Cos(ap[9]  )  /*dummy*/;
+                            cp[10] =  Math.Cos(ap[10]  )  /*dummy*/;
+                            cp[11] =  Math.Cos(ap[11]  )  /*dummy*/;
+                            cp[12] =  Math.Cos(ap[12]  )  /*dummy*/;
+                            cp[13] =  Math.Cos(ap[13]  )  /*dummy*/;
+                            cp[14] =  Math.Cos(ap[14]  )  /*dummy*/;
+                            cp[15] =  Math.Cos(ap[15]  )  /*dummy*/;
+                            cp[16] =  Math.Cos(ap[16]  )  /*dummy*/;
+                            cp[17] =  Math.Cos(ap[17]  )  /*dummy*/;
+                            cp[18] =  Math.Cos(ap[18]  )  /*dummy*/;
+                            cp[19] =  Math.Cos(ap[19]  )  /*dummy*/;
+                            cp[20] =  Math.Cos(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Math.Cos(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( double* arrAP = arrA)
+                fixed ( double* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<double>(retStorage);
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+   
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/cosh.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/cosh.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/cosh.cs	(revision 9102)
@@ -0,0 +1,559 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics;
+using ILNumerics.Exceptions; 
+using ILNumerics.Storage; 
+using ILNumerics.Misc; 
+
+
+
+namespace ILNumerics {
+    
+    public partial class ILMath {
+ 
+
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>Hyperbolic cosine of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Hyperbolic cosine of array elements</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<complex>  cosh (ILInArray< complex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<complex>(A.Size); 
+                ILSize inDim = A.Size;
+                complex[] arrA = A.GetArrayForRead(); 
+                complex [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<complex>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<complex> retStorage = new ILDenseStorage<complex>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    complex* cp = ((complex*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  complex.Cosh(cp[0]  )  /*dummy*/;
+                            cp[1] =  complex.Cosh(cp[1]  )  /*dummy*/;
+                            cp[2] =  complex.Cosh(cp[2]  )  /*dummy*/;
+                            cp[3] =  complex.Cosh(cp[3]  )  /*dummy*/;
+                            cp[4] =  complex.Cosh(cp[4]  )  /*dummy*/;
+                            cp[5] =  complex.Cosh(cp[5]  )  /*dummy*/;
+                            cp[6] =  complex.Cosh(cp[6]  )  /*dummy*/;
+                            cp[7] =  complex.Cosh(cp[7]  )  /*dummy*/;
+                            cp[8] =  complex.Cosh(cp[8]  )  /*dummy*/;
+                            cp[9] =  complex.Cosh(cp[9]  )  /*dummy*/;
+                            cp[10] =  complex.Cosh(cp[10]  )  /*dummy*/;
+                            cp[11] =  complex.Cosh(cp[11]  )  /*dummy*/;
+                            cp[12] =  complex.Cosh(cp[12]  )  /*dummy*/;
+                            cp[13] =  complex.Cosh(cp[13]  )  /*dummy*/;
+                            cp[14] =  complex.Cosh(cp[14]  )  /*dummy*/;
+                            cp[15] =  complex.Cosh(cp[15]  )  /*dummy*/;
+                            cp[16] =  complex.Cosh(cp[16]  )  /*dummy*/;
+                            cp[17] =  complex.Cosh(cp[17]  )  /*dummy*/;
+                            cp[18] =  complex.Cosh(cp[18]  )  /*dummy*/;
+                            cp[19] =  complex.Cosh(cp[19]  )  /*dummy*/;
+                            cp[20] =  complex.Cosh(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.Cosh(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        complex* ap = ((complex*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  complex.Cosh(ap[0]  )  /*dummy*/;
+                            cp[1] =  complex.Cosh(ap[1]  )  /*dummy*/;
+                            cp[2] =  complex.Cosh(ap[2]  )  /*dummy*/;
+                            cp[3] =  complex.Cosh(ap[3]  )  /*dummy*/;
+                            cp[4] =  complex.Cosh(ap[4]  )  /*dummy*/;
+                            cp[5] =  complex.Cosh(ap[5]  )  /*dummy*/;
+                            cp[6] =  complex.Cosh(ap[6]  )  /*dummy*/;
+                            cp[7] =  complex.Cosh(ap[7]  )  /*dummy*/;
+                            cp[8] =  complex.Cosh(ap[8]  )  /*dummy*/;
+                            cp[9] =  complex.Cosh(ap[9]  )  /*dummy*/;
+                            cp[10] =  complex.Cosh(ap[10]  )  /*dummy*/;
+                            cp[11] =  complex.Cosh(ap[11]  )  /*dummy*/;
+                            cp[12] =  complex.Cosh(ap[12]  )  /*dummy*/;
+                            cp[13] =  complex.Cosh(ap[13]  )  /*dummy*/;
+                            cp[14] =  complex.Cosh(ap[14]  )  /*dummy*/;
+                            cp[15] =  complex.Cosh(ap[15]  )  /*dummy*/;
+                            cp[16] =  complex.Cosh(ap[16]  )  /*dummy*/;
+                            cp[17] =  complex.Cosh(ap[17]  )  /*dummy*/;
+                            cp[18] =  complex.Cosh(ap[18]  )  /*dummy*/;
+                            cp[19] =  complex.Cosh(ap[19]  )  /*dummy*/;
+                            cp[20] =  complex.Cosh(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.Cosh(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( complex* arrAP = arrA)
+                fixed ( complex* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<complex>(retStorage);
+            }
+        }
+        /// <summary>Hyperbolic cosine of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Hyperbolic cosine of array elements</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<fcomplex>  cosh (ILInArray< fcomplex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<fcomplex>(A.Size); 
+                ILSize inDim = A.Size;
+                fcomplex[] arrA = A.GetArrayForRead(); 
+                fcomplex [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<fcomplex>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<fcomplex> retStorage = new ILDenseStorage<fcomplex>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    fcomplex* cp = ((fcomplex*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  fcomplex.Cosh(cp[0]  )  /*dummy*/;
+                            cp[1] =  fcomplex.Cosh(cp[1]  )  /*dummy*/;
+                            cp[2] =  fcomplex.Cosh(cp[2]  )  /*dummy*/;
+                            cp[3] =  fcomplex.Cosh(cp[3]  )  /*dummy*/;
+                            cp[4] =  fcomplex.Cosh(cp[4]  )  /*dummy*/;
+                            cp[5] =  fcomplex.Cosh(cp[5]  )  /*dummy*/;
+                            cp[6] =  fcomplex.Cosh(cp[6]  )  /*dummy*/;
+                            cp[7] =  fcomplex.Cosh(cp[7]  )  /*dummy*/;
+                            cp[8] =  fcomplex.Cosh(cp[8]  )  /*dummy*/;
+                            cp[9] =  fcomplex.Cosh(cp[9]  )  /*dummy*/;
+                            cp[10] =  fcomplex.Cosh(cp[10]  )  /*dummy*/;
+                            cp[11] =  fcomplex.Cosh(cp[11]  )  /*dummy*/;
+                            cp[12] =  fcomplex.Cosh(cp[12]  )  /*dummy*/;
+                            cp[13] =  fcomplex.Cosh(cp[13]  )  /*dummy*/;
+                            cp[14] =  fcomplex.Cosh(cp[14]  )  /*dummy*/;
+                            cp[15] =  fcomplex.Cosh(cp[15]  )  /*dummy*/;
+                            cp[16] =  fcomplex.Cosh(cp[16]  )  /*dummy*/;
+                            cp[17] =  fcomplex.Cosh(cp[17]  )  /*dummy*/;
+                            cp[18] =  fcomplex.Cosh(cp[18]  )  /*dummy*/;
+                            cp[19] =  fcomplex.Cosh(cp[19]  )  /*dummy*/;
+                            cp[20] =  fcomplex.Cosh(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.Cosh(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        fcomplex* ap = ((fcomplex*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  fcomplex.Cosh(ap[0]  )  /*dummy*/;
+                            cp[1] =  fcomplex.Cosh(ap[1]  )  /*dummy*/;
+                            cp[2] =  fcomplex.Cosh(ap[2]  )  /*dummy*/;
+                            cp[3] =  fcomplex.Cosh(ap[3]  )  /*dummy*/;
+                            cp[4] =  fcomplex.Cosh(ap[4]  )  /*dummy*/;
+                            cp[5] =  fcomplex.Cosh(ap[5]  )  /*dummy*/;
+                            cp[6] =  fcomplex.Cosh(ap[6]  )  /*dummy*/;
+                            cp[7] =  fcomplex.Cosh(ap[7]  )  /*dummy*/;
+                            cp[8] =  fcomplex.Cosh(ap[8]  )  /*dummy*/;
+                            cp[9] =  fcomplex.Cosh(ap[9]  )  /*dummy*/;
+                            cp[10] =  fcomplex.Cosh(ap[10]  )  /*dummy*/;
+                            cp[11] =  fcomplex.Cosh(ap[11]  )  /*dummy*/;
+                            cp[12] =  fcomplex.Cosh(ap[12]  )  /*dummy*/;
+                            cp[13] =  fcomplex.Cosh(ap[13]  )  /*dummy*/;
+                            cp[14] =  fcomplex.Cosh(ap[14]  )  /*dummy*/;
+                            cp[15] =  fcomplex.Cosh(ap[15]  )  /*dummy*/;
+                            cp[16] =  fcomplex.Cosh(ap[16]  )  /*dummy*/;
+                            cp[17] =  fcomplex.Cosh(ap[17]  )  /*dummy*/;
+                            cp[18] =  fcomplex.Cosh(ap[18]  )  /*dummy*/;
+                            cp[19] =  fcomplex.Cosh(ap[19]  )  /*dummy*/;
+                            cp[20] =  fcomplex.Cosh(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.Cosh(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( fcomplex* arrAP = arrA)
+                fixed ( fcomplex* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<fcomplex>(retStorage);
+            }
+        }
+        /// <summary>Hyperbolic cosine of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Hyperbolic cosine of array elements</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<float>  cosh (ILInArray< float > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<float>(A.Size); 
+                ILSize inDim = A.Size;
+                float[] arrA = A.GetArrayForRead(); 
+                float [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<float>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<float> retStorage = new ILDenseStorage<float>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    float* cp = ((float*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  (float)Math.Cosh(cp[0]  )  /*dummy*/;
+                            cp[1] =  (float)Math.Cosh(cp[1]  )  /*dummy*/;
+                            cp[2] =  (float)Math.Cosh(cp[2]  )  /*dummy*/;
+                            cp[3] =  (float)Math.Cosh(cp[3]  )  /*dummy*/;
+                            cp[4] =  (float)Math.Cosh(cp[4]  )  /*dummy*/;
+                            cp[5] =  (float)Math.Cosh(cp[5]  )  /*dummy*/;
+                            cp[6] =  (float)Math.Cosh(cp[6]  )  /*dummy*/;
+                            cp[7] =  (float)Math.Cosh(cp[7]  )  /*dummy*/;
+                            cp[8] =  (float)Math.Cosh(cp[8]  )  /*dummy*/;
+                            cp[9] =  (float)Math.Cosh(cp[9]  )  /*dummy*/;
+                            cp[10] =  (float)Math.Cosh(cp[10]  )  /*dummy*/;
+                            cp[11] =  (float)Math.Cosh(cp[11]  )  /*dummy*/;
+                            cp[12] =  (float)Math.Cosh(cp[12]  )  /*dummy*/;
+                            cp[13] =  (float)Math.Cosh(cp[13]  )  /*dummy*/;
+                            cp[14] =  (float)Math.Cosh(cp[14]  )  /*dummy*/;
+                            cp[15] =  (float)Math.Cosh(cp[15]  )  /*dummy*/;
+                            cp[16] =  (float)Math.Cosh(cp[16]  )  /*dummy*/;
+                            cp[17] =  (float)Math.Cosh(cp[17]  )  /*dummy*/;
+                            cp[18] =  (float)Math.Cosh(cp[18]  )  /*dummy*/;
+                            cp[19] =  (float)Math.Cosh(cp[19]  )  /*dummy*/;
+                            cp[20] =  (float)Math.Cosh(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  (float)Math.Cosh(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        float* ap = ((float*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  (float)Math.Cosh(ap[0]  )  /*dummy*/;
+                            cp[1] =  (float)Math.Cosh(ap[1]  )  /*dummy*/;
+                            cp[2] =  (float)Math.Cosh(ap[2]  )  /*dummy*/;
+                            cp[3] =  (float)Math.Cosh(ap[3]  )  /*dummy*/;
+                            cp[4] =  (float)Math.Cosh(ap[4]  )  /*dummy*/;
+                            cp[5] =  (float)Math.Cosh(ap[5]  )  /*dummy*/;
+                            cp[6] =  (float)Math.Cosh(ap[6]  )  /*dummy*/;
+                            cp[7] =  (float)Math.Cosh(ap[7]  )  /*dummy*/;
+                            cp[8] =  (float)Math.Cosh(ap[8]  )  /*dummy*/;
+                            cp[9] =  (float)Math.Cosh(ap[9]  )  /*dummy*/;
+                            cp[10] =  (float)Math.Cosh(ap[10]  )  /*dummy*/;
+                            cp[11] =  (float)Math.Cosh(ap[11]  )  /*dummy*/;
+                            cp[12] =  (float)Math.Cosh(ap[12]  )  /*dummy*/;
+                            cp[13] =  (float)Math.Cosh(ap[13]  )  /*dummy*/;
+                            cp[14] =  (float)Math.Cosh(ap[14]  )  /*dummy*/;
+                            cp[15] =  (float)Math.Cosh(ap[15]  )  /*dummy*/;
+                            cp[16] =  (float)Math.Cosh(ap[16]  )  /*dummy*/;
+                            cp[17] =  (float)Math.Cosh(ap[17]  )  /*dummy*/;
+                            cp[18] =  (float)Math.Cosh(ap[18]  )  /*dummy*/;
+                            cp[19] =  (float)Math.Cosh(ap[19]  )  /*dummy*/;
+                            cp[20] =  (float)Math.Cosh(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  (float)Math.Cosh(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( float* arrAP = arrA)
+                fixed ( float* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<float>(retStorage);
+            }
+        }
+        /// <summary>Hyperbolic cosine of array elements </summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Hyperbolic cosine of array elements</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<double>  cosh (ILInArray< double > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<double>(A.Size); 
+                ILSize inDim = A.Size;
+                double[] arrA = A.GetArrayForRead(); 
+                double [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<double>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<double> retStorage = new ILDenseStorage<double>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    double* cp = ((double*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  Math.Cosh(cp[0]  )  /*dummy*/;
+                            cp[1] =  Math.Cosh(cp[1]  )  /*dummy*/;
+                            cp[2] =  Math.Cosh(cp[2]  )  /*dummy*/;
+                            cp[3] =  Math.Cosh(cp[3]  )  /*dummy*/;
+                            cp[4] =  Math.Cosh(cp[4]  )  /*dummy*/;
+                            cp[5] =  Math.Cosh(cp[5]  )  /*dummy*/;
+                            cp[6] =  Math.Cosh(cp[6]  )  /*dummy*/;
+                            cp[7] =  Math.Cosh(cp[7]  )  /*dummy*/;
+                            cp[8] =  Math.Cosh(cp[8]  )  /*dummy*/;
+                            cp[9] =  Math.Cosh(cp[9]  )  /*dummy*/;
+                            cp[10] =  Math.Cosh(cp[10]  )  /*dummy*/;
+                            cp[11] =  Math.Cosh(cp[11]  )  /*dummy*/;
+                            cp[12] =  Math.Cosh(cp[12]  )  /*dummy*/;
+                            cp[13] =  Math.Cosh(cp[13]  )  /*dummy*/;
+                            cp[14] =  Math.Cosh(cp[14]  )  /*dummy*/;
+                            cp[15] =  Math.Cosh(cp[15]  )  /*dummy*/;
+                            cp[16] =  Math.Cosh(cp[16]  )  /*dummy*/;
+                            cp[17] =  Math.Cosh(cp[17]  )  /*dummy*/;
+                            cp[18] =  Math.Cosh(cp[18]  )  /*dummy*/;
+                            cp[19] =  Math.Cosh(cp[19]  )  /*dummy*/;
+                            cp[20] =  Math.Cosh(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Math.Cosh(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        double* ap = ((double*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  Math.Cosh(ap[0]  )  /*dummy*/;
+                            cp[1] =  Math.Cosh(ap[1]  )  /*dummy*/;
+                            cp[2] =  Math.Cosh(ap[2]  )  /*dummy*/;
+                            cp[3] =  Math.Cosh(ap[3]  )  /*dummy*/;
+                            cp[4] =  Math.Cosh(ap[4]  )  /*dummy*/;
+                            cp[5] =  Math.Cosh(ap[5]  )  /*dummy*/;
+                            cp[6] =  Math.Cosh(ap[6]  )  /*dummy*/;
+                            cp[7] =  Math.Cosh(ap[7]  )  /*dummy*/;
+                            cp[8] =  Math.Cosh(ap[8]  )  /*dummy*/;
+                            cp[9] =  Math.Cosh(ap[9]  )  /*dummy*/;
+                            cp[10] =  Math.Cosh(ap[10]  )  /*dummy*/;
+                            cp[11] =  Math.Cosh(ap[11]  )  /*dummy*/;
+                            cp[12] =  Math.Cosh(ap[12]  )  /*dummy*/;
+                            cp[13] =  Math.Cosh(ap[13]  )  /*dummy*/;
+                            cp[14] =  Math.Cosh(ap[14]  )  /*dummy*/;
+                            cp[15] =  Math.Cosh(ap[15]  )  /*dummy*/;
+                            cp[16] =  Math.Cosh(ap[16]  )  /*dummy*/;
+                            cp[17] =  Math.Cosh(ap[17]  )  /*dummy*/;
+                            cp[18] =  Math.Cosh(ap[18]  )  /*dummy*/;
+                            cp[19] =  Math.Cosh(ap[19]  )  /*dummy*/;
+                            cp[20] =  Math.Cosh(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Math.Cosh(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( double* arrAP = arrA)
+                fixed ( double* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<double>(retStorage);
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+   
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/counter.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/counter.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/counter.cs	(revision 9102)
@@ -0,0 +1,277 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.InteropServices; 
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Native;
+using ILNumerics.Exceptions;
+
+namespace ILNumerics {
+
+    public partial class ILMath {
+
+        #region counter
+        /// <summary>
+        /// Create n-dimensional array with elements counting from 1, double precision
+        /// </summary>
+        /// <param name="dimensions">Variable number of numeric scalar arrays with dimension specification</param>
+        /// <returns>Double array with elements counting from 1 to dimensions.NumberOfElements</returns>
+        /// <remarks>This function may be used for the convenient creation of arrays for testing purposes.</remarks>
+        public static ILRetArray<double> counter(params ILBaseArray[] dimensions) {
+            return counter<double>(1.0, 1.0, dimensions);
+        }
+        /// <summary>
+        /// Create n-dimensional array with elements counting from 1, double precision
+        /// </summary>
+        /// <param name="dimensions">Variable number of numeric scalar arrays with dimension specification</param>
+        /// <returns>Double array with elements counting from 1 ... dimensions.NumberOfElements</returns>
+        /// <remarks>This function may be used for the convenient creation of arrays for testing purposes.</remarks>
+        public static ILRetArray<double> counter(params int[] dimensions) {
+            return counter<double>(1.0, 1.0, new ILSize(dimensions));
+        }
+        /// <summary>
+        /// Create n-dimensional array with elements counting from 1, double precision
+        /// </summary>
+        /// <param name="dimensions">Variable number of numeric scalar arrays with dimension specification</param>
+        /// <param name="start">Starting number</param>
+        /// <param name="inc">Incrementing step</param>
+        /// <returns>Double array with elements counting from start to start + (dimensions.NumberOfElements * inc)</returns>
+        /// <remarks>This function may be used for the convenient creation of arrays for testing purposes.</remarks>
+        public static ILRetArray<double> counter(double start, double inc, params ILBaseArray[] dimensions) {
+            return counter<double>(start, inc, dimensions);
+        }
+        /// <summary>
+        /// Create n-dimensional array with elements counting from 1, double precision
+        /// </summary>
+        /// <param name="dimensions">Variable number of numeric scalar arrays with dimension specification</param>
+        /// <param name="start">Starting number</param>
+        /// <param name="inc">Incrementing step</param>
+        /// <returns>Double array with elements counting from start to start + (dimensions.NumberOfElements * inc)</returns>
+        /// <remarks>This function may be used for the convenient creation of arrays for testing purposes.</remarks>
+        public static ILRetArray<double> counter(double start, double inc, ILSize dimensions) {
+            return counter<double>(start, inc, dimensions);
+        }
+        /// <summary>
+        /// Create n-dimensional array with elements counting from 1, double precision
+        /// </summary>
+        /// <param name="dimensions">Variable number of numeric scalar arrays with dimension specification</param>
+        /// <returns>Double array with elements counting from 1 ... dimensions.NumberOfElements</returns>
+        /// <remarks>This function may be used for the convenient creation of arrays for testing purposes.</remarks>
+        public static ILRetArray<double> counter(ILSize dimensions) {
+            return counter<double>(1.0, 1.0, dimensions);
+        }
+        /// <summary>
+        /// Create n-dimensional array with counting elements 
+        /// </summary>
+        /// <param name="start">Initial value</param>
+        /// <param name="increment">Increment for each element</param>
+        /// <param name="dimensions">Variable number of numeric, scalar arrays with dimension specification</param>
+        /// <returns>Array with elements counting from <paramref name="start"/> along the first dimension with steps of <paramref name="increment"/>.</returns>
+        /// <remarks>
+        /// <example><code>
+        /// // This will create elements counting from 1...24: 
+        /// <![CDATA[ILArray<double>]]> A = ILMath.counter(4,3,2); 
+        /// // This will create elements counting from 1...48 with intervals of 2.0: 
+        /// <![CDATA[ILArray<double>]]> A = ILMath.counter(1.0,2.0,4,3,2); 
+        /// // This will create an array with all elements having contant value of -4f:
+        /// // (note: start, increment and dimension specifier do not need to be of the same type)
+        /// <![CDATA[ILArray<float> A = ILMath.counter<float>(4.0,0,4,3,2);]]> 
+        /// </code></example>  </remarks>
+        public static ILRetArray<T> counter<T>(ILBaseArray start, ILBaseArray increment, params ILBaseArray[] dimensions) {
+            using (ILScope.Enter(dimensions))
+                return counter<T>(start, increment, new ILSize(dimensions));
+        }
+        /// <summary>
+        /// Create n-dimensional array with counting elements 
+        /// </summary>
+        /// <param name="start">Initial value</param>
+        /// <param name="increment">Increment for each element</param>
+        /// <param name="dimensions">Variable int array with dimension specification</param>
+        /// <returns>Array with elements counting from <paramref name="start"/> to dimensions.NumberOfElements - <paramref name="start"/>.</returns>
+        /// <remarks>
+        /// <example><code>
+        /// // This will create elements counting from 1...24: 
+        /// <![CDATA[ILArray<double>]]> A = ILMath.counter(4,3,2); 
+        /// // This will create elements counting from 1...48 with intervals of 2.0: 
+        /// <![CDATA[ILArray<double>]]> A = ILMath.counter(1.0,2.0,4,3,2); 
+        /// // This will create an array with all elements having contant value of -4f:
+        /// // (note: start, increment and dimension specifier do not need to be of the same type)
+        /// <![CDATA[ILArray<float> A = ILMath.counter<float>(4.0,0,4,3,2);]]> 
+        /// </code></example>  </remarks>
+        public static ILRetArray<T> counter<T>(ILBaseArray start, ILBaseArray increment, ILSize dimensions) {
+            using (ILScope.Enter(start, increment)) {
+                if (object.Equals(start, null) || !start.IsNumeric || !start.IsScalar) throw new ILArgumentException("start must be a numeric scalar");
+                if (object.Equals(increment, null) || !increment.IsNumeric || !increment.IsScalar) throw new ILArgumentException("increment must be a numeric scalar");
+                double dStart = todouble(start).GetValue(0);
+                double dInc = todouble(increment).GetValue(0);
+
+                T[] retArr = ILMemoryPool.Pool.New<T>(dimensions.NumberOfElements);
+                if (false) {
+
+                    
+                } else if (retArr is  double[]) {
+                    
+                    double val = ( double)dStart;
+                    unsafe {
+                        fixed ( double* pRetArr = (retArr as  double[])) {
+                            
+                            double* pRetArray = pRetArr;
+                            
+                            double* pEnd = pRetArr + dimensions.NumberOfElements;
+                            while (pRetArray < pEnd) {
+                                *pRetArray++ = val;
+                                val = ( double)(val + dInc);
+                            }
+                        }
+                    }
+
+#region HYCALPER AUTO GENERATED CODE
+
+                   
+                } else if (retArr is  byte[]) {
+                   
+                    byte val = ( byte)dStart;
+                    unsafe {
+                        fixed ( byte* pRetArr = (retArr as  byte[])) {
+                           
+                            byte* pRetArray = pRetArr;
+                           
+                            byte* pEnd = pRetArr + dimensions.NumberOfElements;
+                            while (pRetArray < pEnd) {
+                                *pRetArray++ = val;
+                                val = ( byte)(val + dInc);
+                            }
+                        }
+                    }
+                   
+                } else if (retArr is  Int64[]) {
+                   
+                    Int64 val = ( Int64)dStart;
+                    unsafe {
+                        fixed ( Int64* pRetArr = (retArr as  Int64[])) {
+                           
+                            Int64* pRetArray = pRetArr;
+                           
+                            Int64* pEnd = pRetArr + dimensions.NumberOfElements;
+                            while (pRetArray < pEnd) {
+                                *pRetArray++ = val;
+                                val = ( Int64)(val + dInc);
+                            }
+                        }
+                    }
+                   
+                } else if (retArr is  complex[]) {
+                   
+                    complex val = ( complex)dStart;
+                    unsafe {
+                        fixed ( complex* pRetArr = (retArr as  complex[])) {
+                           
+                            complex* pRetArray = pRetArr;
+                           
+                            complex* pEnd = pRetArr + dimensions.NumberOfElements;
+                            while (pRetArray < pEnd) {
+                                *pRetArray++ = val;
+                                val = ( complex)(val + dInc);
+                            }
+                        }
+                    }
+                   
+                } else if (retArr is  fcomplex[]) {
+                   
+                    fcomplex val = ( fcomplex)dStart;
+                    unsafe {
+                        fixed ( fcomplex* pRetArr = (retArr as  fcomplex[])) {
+                           
+                            fcomplex* pRetArray = pRetArr;
+                           
+                            fcomplex* pEnd = pRetArr + dimensions.NumberOfElements;
+                            while (pRetArray < pEnd) {
+                                *pRetArray++ = val;
+                                val = ( fcomplex)(val + dInc);
+                            }
+                        }
+                    }
+                   
+                } else if (retArr is  Int32[]) {
+                   
+                    Int32 val = ( Int32)dStart;
+                    unsafe {
+                        fixed ( Int32* pRetArr = (retArr as  Int32[])) {
+                           
+                            Int32* pRetArray = pRetArr;
+                           
+                            Int32* pEnd = pRetArr + dimensions.NumberOfElements;
+                            while (pRetArray < pEnd) {
+                                *pRetArray++ = val;
+                                val = ( Int32)(val + dInc);
+                            }
+                        }
+                    }
+                   
+                } else if (retArr is  float[]) {
+                   
+                    float val = ( float)dStart;
+                    unsafe {
+                        fixed ( float* pRetArr = (retArr as  float[])) {
+                           
+                            float* pRetArray = pRetArr;
+                           
+                            float* pEnd = pRetArr + dimensions.NumberOfElements;
+                            while (pRetArray < pEnd) {
+                                *pRetArray++ = val;
+                                val = ( float)(val + dInc);
+                            }
+                        }
+                    }
+
+#endregion HYCALPER AUTO GENERATED CODE
+               } else {
+                    throw new ILArgumentException(String.Format("counter is not supported for arrays of inner type '{0}'", typeof(T).Name));
+                }
+                return new ILRetArray<T>(retArr, dimensions);
+            }
+        }
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/cov.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/cov.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/cov.cs	(revision 9102)
@@ -0,0 +1,142 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics;
+using ILNumerics.Exceptions;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+
+
+
+namespace ILNumerics {
+
+    public partial class ILMath {
+
+
+        
+        /// <summary>
+        /// Covariance matrix of A
+        /// </summary>
+        /// <param name="A">Input vector or data matrix, samples in columns, variables in rows</param>
+        /// <param name="unbiased">[Optional] If true, calculate the best unbiased variance estimate if the observations are from a normal distribution. This normalizes by n-1 if n>1 (n = number of samples). If n == 1 normalization is always 1. If false always normalize by n.</param>
+        /// <returns>Variance of vector A/Covariance matrix of A</returns>
+        /// <remarks><para>If A is a vector <c>cov(A)</c> returns the variance of A</para>
+        /// <para>If A is a m x n matrix, where each of the n columns is an m-dimensional observation, <c>cov(A)</c> is the n x n covariance matrix.</para>
+        /// <para>The mean is removed from each column before calculating the result.</para>
+        /// </remarks>
+        public static ILRetArray<double> cov(ILInArray<double> A, bool unbiased = true) {
+            using (ILScope.Enter(A)) {
+                if (isnull(A)) {
+                    throw new ILArgumentException("Parameter A must not be null");
+                }
+                if (!A.IsMatrix)
+                    throw new ILArgumentException("Input array A must be a matrix (2d)");
+                if (A.IsEmpty) {
+                    if (A.S[0] == 0 && A.S[1] == 0)
+                        return array<double>(double.NaN, 1, 1);
+                    return array<double>(double.NaN, A.S[0], A.S[0]);  
+                }
+
+                if (A.IsVector)
+                {
+                    // A vector, return variance
+                    int normFactor = unbiased ? (A.Size.NumberOfElements > 1 ? A.Size.NumberOfElements - 1 : 1) : A.Size.NumberOfElements;
+                    ILArray<double> AnoMean = A - mean(A);
+                    return sum(multiplyElem(AnoMean, AnoMean)) / (double )normFactor;
+                    // return zeros<double>(A.D[0], A.D[0]);
+                }
+                else
+                {
+                    int normFactor = unbiased ? (A.S[1] > 1 ? A.S[1] - 1 : 1) : A.S[1];
+                    ILArray<double> AnoMean = A - mean(A, 1);
+                    return multiply(AnoMean, AnoMean.T) / (double )normFactor;
+                }
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+        
+        /// <summary>
+        /// Covariance matrix of A
+        /// </summary>
+        /// <param name="A">Input vector or data matrix, samples in columns, variables in rows</param>
+        /// <param name="unbiased">[Optional] If true, calculate the best unbiased variance estimate if the observations are from a normal distribution. This normalizes by n-1 if n>1 (n = number of samples). If n == 1 normalization is always 1. If false always normalize by n.</param>
+        /// <returns>Variance of vector A/Covariance matrix of A</returns>
+        /// <remarks><para>If A is a vector <c>cov(A)</c> returns the variance of A</para>
+        /// <para>If A is a m x n matrix, where each of the n columns is an m-dimensional observation, <c>cov(A)</c> is the n x n covariance matrix.</para>
+        /// <para>The mean is removed from each column before calculating the result.</para>
+        /// </remarks>
+        public static ILRetArray<float> cov(ILInArray<float> A, bool unbiased = true) {
+            using (ILScope.Enter(A)) {
+                if (isnull(A)) {
+                    throw new ILArgumentException("Parameter A must not be null");
+                }
+                if (!A.IsMatrix)
+                    throw new ILArgumentException("Input array A must be a matrix (2d)");
+                if (A.IsEmpty) {
+                    if (A.S[0] == 0 && A.S[1] == 0)
+                        return array<float>(float.NaN, 1, 1);
+                    return array<float>(float.NaN, A.S[0], A.S[0]);  
+                }
+
+                if (A.IsVector)
+                {
+                    // A vector, return variance
+                    int normFactor = unbiased ? (A.Size.NumberOfElements > 1 ? A.Size.NumberOfElements - 1 : 1) : A.Size.NumberOfElements;
+                    ILArray<float> AnoMean = A - mean(A);
+                    return sum(multiplyElem(AnoMean, AnoMean)) / (float )normFactor;
+                    // return zeros<float>(A.D[0], A.D[0]);
+                }
+                else
+                {
+                    int normFactor = unbiased ? (A.S[1] > 1 ? A.S[1] - 1 : 1) : A.S[1];
+                    ILArray<float> AnoMean = A - mean(A, 1);
+                    return multiply(AnoMean, AnoMean.T) / (float )normFactor;
+                }
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/cross.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/cross.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/cross.cs	(revision 9102)
@@ -0,0 +1,124 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.InteropServices; 
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Native;
+using ILNumerics.Exceptions;
+
+
+namespace ILNumerics {
+
+    public partial class ILMath {
+
+
+        /// <summary>
+        /// Cross products of columns of two arrays 
+        /// </summary>
+        /// <param name="A">First array with vectors in columns</param>
+        /// <param name="B">Second array with vectors in columns</param>
+        /// <returns>Array with cross products of vectors from A and B</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arguments is not the same.</exception>
+        public static ILRetArray<double> cross(ILInArray<double> A, 
+                                                            ILInArray<double> B,
+                                                            bool normalize = false) {
+            using (ILScope.Enter(A, B)) {
+                if (!A.Size.IsSameSize(B.Size))
+                    throw new ILArgumentException("input arrays must have the same size!");
+                ILArray<double> ret = array<double>(A.Size);
+                using (ILScope.Enter()) {
+                    ILArray<double> Ax = A[0, full];
+                    ILArray<double> Ay = A[1, full];
+                    ILArray<double> Az = A[2, full];
+                    ILArray<double> Bx = B[0, full];
+                    ILArray<double> By = B[1, full];
+                    ILArray<double> Bz = B[2, full];
+                    ret[0, full] = Ay * Bz - Az * By;
+                    ret[1, full] = Az * Bx - Ax * Bz;
+                    ret[2, full] = Ax * By - Ay * Bx;
+                }
+                if (!normalize)
+                    return ret; 
+                else 
+                    return ret / sqrt(sum(ret * ret,0)); 
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// Cross products of columns of two arrays 
+        /// </summary>
+        /// <param name="A">First array with vectors in columns</param>
+        /// <param name="B">Second array with vectors in columns</param>
+        /// <returns>Array with cross products of vectors from A and B</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arguments is not the same.</exception>
+        public static ILRetArray<float> cross(ILInArray<float> A, 
+                                                            ILInArray<float> B,
+                                                            bool normalize = false) {
+            using (ILScope.Enter(A, B)) {
+                if (!A.Size.IsSameSize(B.Size))
+                    throw new ILArgumentException("input arrays must have the same size!");
+                ILArray<float> ret = array<float>(A.Size);
+                using (ILScope.Enter()) {
+                    ILArray<float> Ax = A[0, full];
+                    ILArray<float> Ay = A[1, full];
+                    ILArray<float> Az = A[2, full];
+                    ILArray<float> Bx = B[0, full];
+                    ILArray<float> By = B[1, full];
+                    ILArray<float> Bz = B[2, full];
+                    ret[0, full] = Ay * Bz - Az * By;
+                    ret[1, full] = Az * Bx - Ax * Bz;
+                    ret[2, full] = Ax * By - Ay * Bx;
+                }
+                if (!normalize)
+                    return ret; 
+                else 
+                    return ret / sqrt(sum(ret * ret,0)); 
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/det.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/det.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/det.cs	(revision 9102)
@@ -0,0 +1,268 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions; 
+
+
+
+namespace ILNumerics {
+
+    public partial class ILMath {
+
+
+        /// <summary>
+        /// Determinant of square matrix
+        /// </summary>
+        /// <param name="A">Input matrix (square)</param>
+        /// <returns>Determinant of A</returns>
+        /// <remarks><para>The determinant is computed by decomposing A into upper and lower triangular part (using the LAPACK function ?getrf).<br />
+        /// Due to the properties of determinants, det(a) is the same as det(L) * det(U),where det(L) can easily be extracted from the permutation indices returned from LU decomposition. det(U) - with U being an upper triangular matrix - equals the product of the diagonal elements.</para>
+        /// <para>For scalar A, a plain copy of A is returned.</para></remarks>
+        /// <example>Creating a nonsingular 4x4 (double) matrix and it's determinant
+        /// <code>ILArray&lt;double&gt; A = ILMath.counter(1.0,1.0,4,4);
+        ///A[1] = 0.0;  // make A nonsingular
+        ///A[14] = 0.0; //(same as: A[2,3] = 0.0;) 
+        /// // A is now:
+        /// //&lt;Double&gt; [4,4]
+        /// //(:,:) 1e+001 * 
+        /// // 0,10000   0,50000   0,90000   1,30000 
+        /// // 0,00000   0,60000   1,00000   1,40000 
+        /// // 0,30000   0,70000   1,10000   0,00000 
+        /// // 0,40000   0,80000   1,20000   1,60000 
+        /// 
+        ///ILMath.det(A) gives:
+        /// //&lt;Double&gt; -360
+        ///</code></example>
+        ///<exception cref="ILNumerics.Exceptions.ILArgumentException">if A is empty or not a square matrix</exception>
+        public static ILRetArray< double > det(ILInArray< double > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsScalar) 
+                    return A.C; 
+                if (A.IsEmpty) 
+                    throw new ILArgumentException("det: A must be a matrix"); 
+                int m = A.Size[0]; 
+                if (m != A.Size[1]) {
+                    throw new ILArgumentException("det: matrix A must be square"); 
+                }
+
+                ILArray< double > L = A.C; 
+                 double [] lArr = L.GetArrayForWrite(); 
+                int [] pivInd = new int[m]; 
+                int info = 0; 
+                /*!HC:lapack_*getrf*/ Lapack.dgetrf (m, m, lArr, m, pivInd ,ref info); 
+                if (info < 0 ) {
+                    throw new ILArgumentException("det: illegal parameter error");
+                }
+                // determine pivoting: number of exchanges 
+                 double retA =  1.0 ; 
+                for (int i = 0; i < m;) {
+                    retA *= lArr[i * m + i]; 
+                    if (pivInd[i] != ++i) retA *=  -1.0 ; 
+                }
+                return retA;
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// Determinant of square matrix
+        /// </summary>
+        /// <param name="A">Input matrix (square)</param>
+        /// <returns>Determinant of A</returns>
+        /// <remarks><para>The determinant is computed by decomposing A into upper and lower triangular part (using the LAPACK function ?getrf).<br />
+        /// Due to the properties of determinants, det(a) is the same as det(L) * det(U),where det(L) can easily be extracted from the permutation indices returned from LU decomposition. det(U) - with U being an upper triangular matrix - equals the product of the diagonal elements.</para>
+        /// <para>For scalar A, a plain copy of A is returned.</para></remarks>
+        /// <example>Creating a nonsingular 4x4 (double) matrix and it's determinant
+        /// <code>ILArray&lt;double&gt; A = ILMath.counter(1.0,1.0,4,4);
+        ///A[1] = 0.0;  // make A nonsingular
+        ///A[14] = 0.0; //(same as: A[2,3] = 0.0;) 
+        /// // A is now:
+        /// //&lt;Double&gt; [4,4]
+        /// //(:,:) 1e+001 * 
+        /// // 0,10000   0,50000   0,90000   1,30000 
+        /// // 0,00000   0,60000   1,00000   1,40000 
+        /// // 0,30000   0,70000   1,10000   0,00000 
+        /// // 0,40000   0,80000   1,20000   1,60000 
+        /// 
+        ///ILMath.det(A) gives:
+        /// //&lt;Double&gt; -360
+        ///</code></example>
+        ///<exception cref="ILNumerics.Exceptions.ILArgumentException">if A is empty or not a square matrix</exception>
+        public static ILRetArray< float > det(ILInArray< float > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsScalar) 
+                    return A.C; 
+                if (A.IsEmpty) 
+                    throw new ILArgumentException("det: A must be a matrix"); 
+                int m = A.Size[0]; 
+                if (m != A.Size[1]) {
+                    throw new ILArgumentException("det: matrix A must be square"); 
+                }
+
+                ILArray< float > L = A.C; 
+                float [] lArr = L.GetArrayForWrite(); 
+                int [] pivInd = new int[m]; 
+                int info = 0; 
+                Lapack.sgetrf (m, m, lArr, m, pivInd ,ref info); 
+                if (info < 0 ) {
+                    throw new ILArgumentException("det: illegal parameter error");
+                }
+                // determine pivoting: number of exchanges 
+                float retA =  1.0f ; 
+                for (int i = 0; i < m;) {
+                    retA *= lArr[i * m + i]; 
+                    if (pivInd[i] != ++i) retA *=  -1.0f ; 
+                }
+                return retA;
+            }
+        }
+        /// <summary>
+        /// Determinant of square matrix
+        /// </summary>
+        /// <param name="A">Input matrix (square)</param>
+        /// <returns>Determinant of A</returns>
+        /// <remarks><para>The determinant is computed by decomposing A into upper and lower triangular part (using the LAPACK function ?getrf).<br />
+        /// Due to the properties of determinants, det(a) is the same as det(L) * det(U),where det(L) can easily be extracted from the permutation indices returned from LU decomposition. det(U) - with U being an upper triangular matrix - equals the product of the diagonal elements.</para>
+        /// <para>For scalar A, a plain copy of A is returned.</para></remarks>
+        /// <example>Creating a nonsingular 4x4 (double) matrix and it's determinant
+        /// <code>ILArray&lt;double&gt; A = ILMath.counter(1.0,1.0,4,4);
+        ///A[1] = 0.0;  // make A nonsingular
+        ///A[14] = 0.0; //(same as: A[2,3] = 0.0;) 
+        /// // A is now:
+        /// //&lt;Double&gt; [4,4]
+        /// //(:,:) 1e+001 * 
+        /// // 0,10000   0,50000   0,90000   1,30000 
+        /// // 0,00000   0,60000   1,00000   1,40000 
+        /// // 0,30000   0,70000   1,10000   0,00000 
+        /// // 0,40000   0,80000   1,20000   1,60000 
+        /// 
+        ///ILMath.det(A) gives:
+        /// //&lt;Double&gt; -360
+        ///</code></example>
+        ///<exception cref="ILNumerics.Exceptions.ILArgumentException">if A is empty or not a square matrix</exception>
+        public static ILRetArray< fcomplex > det(ILInArray< fcomplex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsScalar) 
+                    return A.C; 
+                if (A.IsEmpty) 
+                    throw new ILArgumentException("det: A must be a matrix"); 
+                int m = A.Size[0]; 
+                if (m != A.Size[1]) {
+                    throw new ILArgumentException("det: matrix A must be square"); 
+                }
+
+                ILArray< fcomplex > L = A.C; 
+                fcomplex [] lArr = L.GetArrayForWrite(); 
+                int [] pivInd = new int[m]; 
+                int info = 0; 
+                Lapack.cgetrf (m, m, lArr, m, pivInd ,ref info); 
+                if (info < 0 ) {
+                    throw new ILArgumentException("det: illegal parameter error");
+                }
+                // determine pivoting: number of exchanges 
+                fcomplex retA =  new fcomplex(1.0f,0.0f) ; 
+                for (int i = 0; i < m;) {
+                    retA *= lArr[i * m + i]; 
+                    if (pivInd[i] != ++i) retA *=  -1.0f ; 
+                }
+                return retA;
+            }
+        }
+        /// <summary>
+        /// Determinant of square matrix
+        /// </summary>
+        /// <param name="A">Input matrix (square)</param>
+        /// <returns>Determinant of A</returns>
+        /// <remarks><para>The determinant is computed by decomposing A into upper and lower triangular part (using the LAPACK function ?getrf).<br />
+        /// Due to the properties of determinants, det(a) is the same as det(L) * det(U),where det(L) can easily be extracted from the permutation indices returned from LU decomposition. det(U) - with U being an upper triangular matrix - equals the product of the diagonal elements.</para>
+        /// <para>For scalar A, a plain copy of A is returned.</para></remarks>
+        /// <example>Creating a nonsingular 4x4 (double) matrix and it's determinant
+        /// <code>ILArray&lt;double&gt; A = ILMath.counter(1.0,1.0,4,4);
+        ///A[1] = 0.0;  // make A nonsingular
+        ///A[14] = 0.0; //(same as: A[2,3] = 0.0;) 
+        /// // A is now:
+        /// //&lt;Double&gt; [4,4]
+        /// //(:,:) 1e+001 * 
+        /// // 0,10000   0,50000   0,90000   1,30000 
+        /// // 0,00000   0,60000   1,00000   1,40000 
+        /// // 0,30000   0,70000   1,10000   0,00000 
+        /// // 0,40000   0,80000   1,20000   1,60000 
+        /// 
+        ///ILMath.det(A) gives:
+        /// //&lt;Double&gt; -360
+        ///</code></example>
+        ///<exception cref="ILNumerics.Exceptions.ILArgumentException">if A is empty or not a square matrix</exception>
+        public static ILRetArray< complex > det(ILInArray< complex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsScalar) 
+                    return A.C; 
+                if (A.IsEmpty) 
+                    throw new ILArgumentException("det: A must be a matrix"); 
+                int m = A.Size[0]; 
+                if (m != A.Size[1]) {
+                    throw new ILArgumentException("det: matrix A must be square"); 
+                }
+
+                ILArray< complex > L = A.C; 
+                complex [] lArr = L.GetArrayForWrite(); 
+                int [] pivInd = new int[m]; 
+                int info = 0; 
+                Lapack.zgetrf (m, m, lArr, m, pivInd ,ref info); 
+                if (info < 0 ) {
+                    throw new ILArgumentException("det: illegal parameter error");
+                }
+                // determine pivoting: number of exchanges 
+                complex retA =  new complex(1.0,0.0) ; 
+                for (int i = 0; i < m;) {
+                    retA *= lArr[i * m + i]; 
+                    if (pivInd[i] != ++i) retA *=  -1.0 ; 
+                }
+                return retA;
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+   }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/diag.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/diag.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/diag.cs	(revision 9102)
@@ -0,0 +1,222 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions;
+
+
+
+
+namespace ILNumerics  {
+    public partial class ILMath {
+
+
+        /// <summary>
+        /// Diagonal matrix or diagonal of matrix
+        /// </summary>
+        /// <param name="X">Input matrix or vector. If X is matrix, diag(X) returns the 
+        /// elements on the diagPosition's diagonal as column vector. If X is vector, a square matrix of size 
+        /// [length(X) + abs(diagPosition), length(X) + abs(diagPosition)] will be created, having 
+        /// the elements of X on the diagPosition's diagonal.</param>
+        /// <param name="diagPosition">[Optional] Index of diagonal to extract/create. Here 0 means the 
+        /// main diagonal, diagPosition > 0 is above the main diagonal, diagPosition smaller 0 means 
+        /// below the main diagonal.</param>
+        /// <returns>Depending on X a matrix or a vector with the elements on a diagonal.</returns>
+        /// <remarks>The type of the ILArray returned will be the same as the type of X.</remarks>
+        public static ILRetArray<double> diag(ILInArray<double> X, int diagPosition = 0) {
+            return diag<double>(X, diagPosition); 
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// Diagonal matrix or diagonal of matrix
+        /// </summary>
+        /// <param name="X">Input matrix or vector. If X is matrix, diag(X) returns the 
+        /// elements on the diagPosition's diagonal as column vector. If X is vector, a square matrix of size 
+        /// [length(X) + abs(diagPosition), length(X) + abs(diagPosition)] will be created, having 
+        /// the elements of X on the diagPosition's diagonal.</param>
+        /// <param name="diagPosition">[Optional] Index of diagonal to extract/create. Here 0 means the 
+        /// main diagonal, diagPosition > 0 is above the main diagonal, diagPosition smaller 0 means 
+        /// below the main diagonal.</param>
+        /// <returns>Depending on X a matrix or a vector with the elements on a diagonal.</returns>
+        /// <remarks>The type of the ILArray returned will be the same as the type of X.</remarks>
+        public static ILRetArray<fcomplex> diag(ILInArray<fcomplex> X, int diagPosition = 0) {
+            return diag<fcomplex>(X, diagPosition); 
+        }
+        /// <summary>
+        /// Diagonal matrix or diagonal of matrix
+        /// </summary>
+        /// <param name="X">Input matrix or vector. If X is matrix, diag(X) returns the 
+        /// elements on the diagPosition's diagonal as column vector. If X is vector, a square matrix of size 
+        /// [length(X) + abs(diagPosition), length(X) + abs(diagPosition)] will be created, having 
+        /// the elements of X on the diagPosition's diagonal.</param>
+        /// <param name="diagPosition">[Optional] Index of diagonal to extract/create. Here 0 means the 
+        /// main diagonal, diagPosition > 0 is above the main diagonal, diagPosition smaller 0 means 
+        /// below the main diagonal.</param>
+        /// <returns>Depending on X a matrix or a vector with the elements on a diagonal.</returns>
+        /// <remarks>The type of the ILArray returned will be the same as the type of X.</remarks>
+        public static ILRetArray<complex> diag(ILInArray<complex> X, int diagPosition = 0) {
+            return diag<complex>(X, diagPosition); 
+        }
+        /// <summary>
+        /// Diagonal matrix or diagonal of matrix
+        /// </summary>
+        /// <param name="X">Input matrix or vector. If X is matrix, diag(X) returns the 
+        /// elements on the diagPosition's diagonal as column vector. If X is vector, a square matrix of size 
+        /// [length(X) + abs(diagPosition), length(X) + abs(diagPosition)] will be created, having 
+        /// the elements of X on the diagPosition's diagonal.</param>
+        /// <param name="diagPosition">[Optional] Index of diagonal to extract/create. Here 0 means the 
+        /// main diagonal, diagPosition > 0 is above the main diagonal, diagPosition smaller 0 means 
+        /// below the main diagonal.</param>
+        /// <returns>Depending on X a matrix or a vector with the elements on a diagonal.</returns>
+        /// <remarks>The type of the ILArray returned will be the same as the type of X.</remarks>
+        public static ILRetArray<byte> diag(ILInArray<byte> X, int diagPosition = 0) {
+            return diag<byte>(X, diagPosition); 
+        }
+        /// <summary>
+        /// Diagonal matrix or diagonal of matrix
+        /// </summary>
+        /// <param name="X">Input matrix or vector. If X is matrix, diag(X) returns the 
+        /// elements on the diagPosition's diagonal as column vector. If X is vector, a square matrix of size 
+        /// [length(X) + abs(diagPosition), length(X) + abs(diagPosition)] will be created, having 
+        /// the elements of X on the diagPosition's diagonal.</param>
+        /// <param name="diagPosition">[Optional] Index of diagonal to extract/create. Here 0 means the 
+        /// main diagonal, diagPosition > 0 is above the main diagonal, diagPosition smaller 0 means 
+        /// below the main diagonal.</param>
+        /// <returns>Depending on X a matrix or a vector with the elements on a diagonal.</returns>
+        /// <remarks>The type of the ILArray returned will be the same as the type of X.</remarks>
+        public static ILRetArray<Int64> diag(ILInArray<Int64> X, int diagPosition = 0) {
+            return diag<Int64>(X, diagPosition); 
+        }
+        /// <summary>
+        /// Diagonal matrix or diagonal of matrix
+        /// </summary>
+        /// <param name="X">Input matrix or vector. If X is matrix, diag(X) returns the 
+        /// elements on the diagPosition's diagonal as column vector. If X is vector, a square matrix of size 
+        /// [length(X) + abs(diagPosition), length(X) + abs(diagPosition)] will be created, having 
+        /// the elements of X on the diagPosition's diagonal.</param>
+        /// <param name="diagPosition">[Optional] Index of diagonal to extract/create. Here 0 means the 
+        /// main diagonal, diagPosition > 0 is above the main diagonal, diagPosition smaller 0 means 
+        /// below the main diagonal.</param>
+        /// <returns>Depending on X a matrix or a vector with the elements on a diagonal.</returns>
+        /// <remarks>The type of the ILArray returned will be the same as the type of X.</remarks>
+        public static ILRetArray<Int32> diag(ILInArray<Int32> X, int diagPosition = 0) {
+            return diag<Int32>(X, diagPosition); 
+        }
+        /// <summary>
+        /// Diagonal matrix or diagonal of matrix
+        /// </summary>
+        /// <param name="X">Input matrix or vector. If X is matrix, diag(X) returns the 
+        /// elements on the diagPosition's diagonal as column vector. If X is vector, a square matrix of size 
+        /// [length(X) + abs(diagPosition), length(X) + abs(diagPosition)] will be created, having 
+        /// the elements of X on the diagPosition's diagonal.</param>
+        /// <param name="diagPosition">[Optional] Index of diagonal to extract/create. Here 0 means the 
+        /// main diagonal, diagPosition > 0 is above the main diagonal, diagPosition smaller 0 means 
+        /// below the main diagonal.</param>
+        /// <returns>Depending on X a matrix or a vector with the elements on a diagonal.</returns>
+        /// <remarks>The type of the ILArray returned will be the same as the type of X.</remarks>
+        public static ILRetArray<float> diag(ILInArray<float> X, int diagPosition = 0) {
+            return diag<float>(X, diagPosition); 
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// Diagonal matrix or diagonal of matrix
+        /// </summary>
+        /// <param name="X">Input matrix or vector. If X is matrix, diag(X) returns the 
+        /// elements on the diagPosition's diagonal as column vector. If X is vector, a square matrix of size 
+        /// [length(X) + abs(diagPosition), length(X) + abs(diagPosition)] will be created, having 
+        /// the elements of X on the diagPosition's diagonal.</param>
+        /// <param name="diagPosition">[Optional] Index of diagonal to extract/create. Here 0 means the 
+        /// main diagonal, diagPosition > 0 is above the main diagonal, diagPosition smaller 0 means 
+        /// below the main diagonal.</param>
+        /// <returns>Depending on 'X' a matrix or a vector with the elements on a diagonal.</returns>
+        /// <remarks>The type of the ILArray returned will be the same as the type of X.</remarks>
+        public static ILRetArray<T> diag<T>(ILInArray<T> X, int diagPosition = 0) {
+            using (ILScope.Enter(X)) {
+                if (Object.Equals(X, null) || X.Size.NumberOfDimensions > 2) {
+                    throw new ILArgumentException("diag: input array must be matrix, vector or scalar"); 
+                }
+                if (X.IsEmpty) 
+                    return empty<T>(X.Size); 
+                ILArray<T> ret = empty<T>(ILSize.Empty00);
+                if  (X.IsScalar) {
+                    ret.a = X.GetValue(0,0);
+                } else if (X.IsVector) {
+                    int retLen = X.Length + Math.Abs(diagPosition);
+                    ret.a = zeros<T> (new ILSize(retLen, retLen));
+                    T [] dIn = X.GetArrayForRead();
+                    if (diagPosition > 0) {
+                        for (int i = 0; i < X.S.NumberOfElements; i++) {
+                            ret.SetValue(dIn[i], i, i + diagPosition);
+                        }
+                    } else {
+                        for (int i = 0; i < X.S.NumberOfElements; i++) {
+                            ret.SetValue(dIn[i],i - diagPosition, i);
+                        }
+                    }
+                } else  { // X is matrix
+                    int retLen = Math.Min(X.Size[0], X.Size[1]) - Math.Abs(diagPosition);
+                    ret = zeros<T> (new ILSize(retLen, 1));
+                    T [] dRet = ret.GetArrayForWrite();
+                    if (diagPosition > 0) {
+                        if (diagPosition >= X.Size[1])
+                            return empty<T>(ILSize.Empty00);
+                        for (int i = 0; i < retLen; i++) {
+                            dRet[i] = X.GetValue(i, diagPosition + i);
+                        }
+                    } else {
+                        if (diagPosition <= -X.Size[0])
+                            return empty<T>(ILSize.Empty00);
+                        for (int i = 0; i < retLen; i++) {
+                            dRet[i] = X.GetValue(diagPosition + i, i);
+                        }
+                    }
+                }
+                return ret;
+            }
+        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/diff.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/diff.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/diff.cs	(revision 9102)
@@ -0,0 +1,999 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions;
+
+
+
+namespace ILNumerics  {
+    
+    public partial class ILMath {
+    
+
+        /// <summary>
+        /// Take n-th derivative
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <param name="N">[Optional] Degree of derivates. If not specified N=1 is assumed.</param>
+        /// <returns>Array with first derivative of A along dimension <c>dim</c> of first non singleton dimension</returns>
+        /// <remarks>N must be a number in range 1..L, where L is the length of A.Dimensions[dim]. 
+        /// Otherwise an empty array will be returned.
+        /// <para>If A is empty or scalar, or if N exceeds the length the specified dimension of A, 
+        /// an empty array will be returned.</para></remarks>
+        public static ILRetArray< double > diff(ILInArray< double > A, int N = 1, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (Object.Equals(A,null)) 
+                    throw new ILArgumentException ("diff: input array A must not be null"); 
+                if (dim < 0) {
+                    dim = A.Size.WorkingDimension();
+                }
+                if (dim >= A.Size.NumberOfDimensions) {
+                    int[] outDims = A.Size.ToIntArray(dim+1); 
+                    outDims[dim] = 0; 
+                    return empty< double >(new ILSize(outDims)); 
+                }
+                if (A.IsScalar) return empty< double >(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    int [] retDim = A.Size.ToIntArray(); 
+                    retDim[dim]--; 
+                    return empty<  double >(new ILSize(retDim)); 
+                }
+                if (N == 0) 
+                    return A.C; 
+                if (N < 1 || N > A.Size[dim]) {
+                    return empty<  double >(ILSize.Empty00); 
+                }
+                ILArray< double > ret = A.C; 
+                for (int n = 0; n < N; n++) {
+                    ret.a = diff(dim,ret);      
+                }
+                return ret;
+            }
+        }
+        /// <summary>
+        /// First derivative along specific dimension
+        /// </summary>
+        /// <param name="A">input array</param>
+        /// <param name="dim">dimensions to create derivative along</param>
+        /// <returns>array with first derivative of A along dimension <c>dim</c></returns>
+        private static ILRetArray< double > diff(int dim, ILInArray< double > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) return empty< double >(A.Size);
+                if (A.IsScalar) return empty< double >(ILSize.Empty00);
+                if (dim < 0)
+                    throw new ILArgumentException("diff: leading dimension out of range!");
+                if (dim >= A.Size.NumberOfDimensions) {
+                    int[] outDims = A.Size.ToIntArray(dim+1); 
+                    outDims[dim] = 0; 
+                    return empty< double >(new ILSize(outDims)); 
+                }
+                ILSize inDim = A.Size; 
+                int[] newDims = inDim.ToIntArray();
+                
+                if (inDim[dim] == 1) return empty< double >(ILSize.Empty00);
+                int newLength;
+                 double [] retArr;
+                // build ILSize
+                newLength = inDim.NumberOfElements / newDims[dim];
+                newDims[dim] --;
+                newLength = newLength * newDims[dim];
+                retArr = ILMemoryPool.Pool.New< double >(newLength);
+                ILSize newDimension = new ILSize(newDims); 
+                int leadDimLen = inDim[dim];
+                int nrHigherDims = inDim.NumberOfElements / leadDimLen;
+                int incOut = newDimension.SequentialIndexDistance(dim); 
+                 double firstVal, secVal; 
+                if (A.IsVector) 
+                    return A["1:end"] - A[vec(0,A.Length-2)];     
+                if (dim == 0) {
+    #region physical along 1st leading dimension
+                    unsafe {
+                        fixed ( double * pOutArr = retArr)
+                        fixed ( double * pInArr = A.GetArrayForRead()) {
+                             double * lastElement;
+                             double * tmpOut = pOutArr;
+                             double * tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                lastElement = tmpIn + leadDimLen;
+                                 
+                                firstVal = *tmpIn++;
+                                while (tmpIn < lastElement) {
+                                    secVal = *tmpIn++;
+                                    *(tmpOut++) = ( double )(secVal-firstVal);
+                                    firstVal = secVal; 
+                                }
+                            }
+                        }
+                    }
+    #endregion
+                } else {
+    #region physical along abitrary dimension
+                    // sum along abitrary dimension 
+                    unsafe {
+                        fixed ( double * pOutArr = retArr)
+                        fixed ( double * pInArr = A.GetArrayForRead()) {
+                             double * lastElementOut = newLength + pOutArr -1;
+                            int inLength = inDim.NumberOfElements -1; 
+                             double * lastElementIn = pInArr + inLength; 
+                            int inc = inDim.SequentialIndexDistance(dim); 
+                             double * tmpOut = pOutArr;
+                            int outLength = newLength - 1;
+                             double * leadEnd; 
+                             double * tmpIn = pInArr;
+                            for (int h = nrHigherDims; h--> 0; ) {
+                                leadEnd = tmpIn + leadDimLen * inc;
+                                firstVal = *tmpIn; 
+                                tmpIn += inc; 
+                                while (tmpIn < leadEnd) {
+                                    secVal = *tmpIn; 
+                                    *tmpOut = ( double )(secVal - firstVal);
+                                    tmpIn += inc;
+                                    tmpOut += incOut; 
+                                    firstVal = secVal; 
+                                }
+                                if (tmpOut > lastElementOut)
+                                    tmpOut -= outLength;
+                                if (tmpIn > lastElementIn)
+                                    tmpIn -= inLength; 
+                            }
+                        }
+                    }
+    #endregion
+                }
+                return new ILRetArray< double >(retArr, newDimension);
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// Take n-th derivative
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <param name="N">[Optional] Degree of derivates. If not specified N=1 is assumed.</param>
+        /// <returns>Array with first derivative of A along dimension <c>dim</c> of first non singleton dimension</returns>
+        /// <remarks>N must be a number in range 1..L, where L is the length of A.Dimensions[dim]. 
+        /// Otherwise an empty array will be returned.
+        /// <para>If A is empty or scalar, or if N exceeds the length the specified dimension of A, 
+        /// an empty array will be returned.</para></remarks>
+        public static ILRetArray< Int64 > diff(ILInArray< Int64 > A, int N = 1, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (Object.Equals(A,null)) 
+                    throw new ILArgumentException ("diff: input array A must not be null"); 
+                if (dim < 0) {
+                    dim = A.Size.WorkingDimension();
+                }
+                if (dim >= A.Size.NumberOfDimensions) {
+                    int[] outDims = A.Size.ToIntArray(dim+1); 
+                    outDims[dim] = 0; 
+                    return empty< Int64 >(new ILSize(outDims)); 
+                }
+                if (A.IsScalar) return empty< Int64 >(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    int [] retDim = A.Size.ToIntArray(); 
+                    retDim[dim]--; 
+                    return empty<  Int64 >(new ILSize(retDim)); 
+                }
+                if (N == 0) 
+                    return A.C; 
+                if (N < 1 || N > A.Size[dim]) {
+                    return empty<  Int64 >(ILSize.Empty00); 
+                }
+                ILArray< Int64 > ret = A.C; 
+                for (int n = 0; n < N; n++) {
+                    ret.a = diff(dim,ret);      
+                }
+                return ret;
+            }
+        }
+        /// <summary>
+        /// First derivative along specific dimension
+        /// </summary>
+        /// <param name="A">input array</param>
+        /// <param name="dim">dimensions to create derivative along</param>
+        /// <returns>array with first derivative of A along dimension <c>dim</c></returns>
+        private static ILRetArray< Int64 > diff(int dim, ILInArray< Int64 > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) return empty< Int64 >(A.Size);
+                if (A.IsScalar) return empty< Int64 >(ILSize.Empty00);
+                if (dim < 0)
+                    throw new ILArgumentException("diff: leading dimension out of range!");
+                if (dim >= A.Size.NumberOfDimensions) {
+                    int[] outDims = A.Size.ToIntArray(dim+1); 
+                    outDims[dim] = 0; 
+                    return empty< Int64 >(new ILSize(outDims)); 
+                }
+                ILSize inDim = A.Size; 
+                int[] newDims = inDim.ToIntArray();
+               
+                if (inDim[dim] == 1) return empty< Int64 >(ILSize.Empty00);
+                int newLength;
+                Int64 [] retArr;
+                // build ILSize
+                newLength = inDim.NumberOfElements / newDims[dim];
+                newDims[dim] --;
+                newLength = newLength * newDims[dim];
+                retArr = ILMemoryPool.Pool.New< Int64 >(newLength);
+                ILSize newDimension = new ILSize(newDims); 
+                int leadDimLen = inDim[dim];
+                int nrHigherDims = inDim.NumberOfElements / leadDimLen;
+                int incOut = newDimension.SequentialIndexDistance(dim); 
+                Int64 firstVal, secVal; 
+                if (A.IsVector) 
+                    return A["1:end"] - A[vec(0,A.Length-2)];     
+                if (dim == 0) {
+    #region physical along 1st leading dimension
+                    unsafe {
+                        fixed ( Int64 * pOutArr = retArr)
+                        fixed ( Int64 * pInArr = A.GetArrayForRead()) {
+                            Int64 * lastElement;
+                            Int64 * tmpOut = pOutArr;
+                            Int64 * tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                lastElement = tmpIn + leadDimLen;
+                                
+                                firstVal = *tmpIn++;
+                                while (tmpIn < lastElement) {
+                                    secVal = *tmpIn++;
+                                    *(tmpOut++) = ( Int64 )(secVal-firstVal);
+                                    firstVal = secVal; 
+                                }
+                            }
+                        }
+                    }
+    #endregion
+                } else {
+    #region physical along abitrary dimension
+                    // sum along abitrary dimension 
+                    unsafe {
+                        fixed ( Int64 * pOutArr = retArr)
+                        fixed ( Int64 * pInArr = A.GetArrayForRead()) {
+                            Int64 * lastElementOut = newLength + pOutArr -1;
+                            int inLength = inDim.NumberOfElements -1; 
+                            Int64 * lastElementIn = pInArr + inLength; 
+                            int inc = inDim.SequentialIndexDistance(dim); 
+                            Int64 * tmpOut = pOutArr;
+                            int outLength = newLength - 1;
+                            Int64 * leadEnd; 
+                            Int64 * tmpIn = pInArr;
+                            for (int h = nrHigherDims; h--> 0; ) {
+                                leadEnd = tmpIn + leadDimLen * inc;
+                                firstVal = *tmpIn; 
+                                tmpIn += inc; 
+                                while (tmpIn < leadEnd) {
+                                    secVal = *tmpIn; 
+                                    *tmpOut = ( Int64 )(secVal - firstVal);
+                                    tmpIn += inc;
+                                    tmpOut += incOut; 
+                                    firstVal = secVal; 
+                                }
+                                if (tmpOut > lastElementOut)
+                                    tmpOut -= outLength;
+                                if (tmpIn > lastElementIn)
+                                    tmpIn -= inLength; 
+                            }
+                        }
+                    }
+    #endregion
+                }
+                return new ILRetArray< Int64 >(retArr, newDimension);
+            }
+        }
+        /// <summary>
+        /// Take n-th derivative
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <param name="N">[Optional] Degree of derivates. If not specified N=1 is assumed.</param>
+        /// <returns>Array with first derivative of A along dimension <c>dim</c> of first non singleton dimension</returns>
+        /// <remarks>N must be a number in range 1..L, where L is the length of A.Dimensions[dim]. 
+        /// Otherwise an empty array will be returned.
+        /// <para>If A is empty or scalar, or if N exceeds the length the specified dimension of A, 
+        /// an empty array will be returned.</para></remarks>
+        public static ILRetArray< Int32 > diff(ILInArray< Int32 > A, int N = 1, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (Object.Equals(A,null)) 
+                    throw new ILArgumentException ("diff: input array A must not be null"); 
+                if (dim < 0) {
+                    dim = A.Size.WorkingDimension();
+                }
+                if (dim >= A.Size.NumberOfDimensions) {
+                    int[] outDims = A.Size.ToIntArray(dim+1); 
+                    outDims[dim] = 0; 
+                    return empty< Int32 >(new ILSize(outDims)); 
+                }
+                if (A.IsScalar) return empty< Int32 >(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    int [] retDim = A.Size.ToIntArray(); 
+                    retDim[dim]--; 
+                    return empty<  Int32 >(new ILSize(retDim)); 
+                }
+                if (N == 0) 
+                    return A.C; 
+                if (N < 1 || N > A.Size[dim]) {
+                    return empty<  Int32 >(ILSize.Empty00); 
+                }
+                ILArray< Int32 > ret = A.C; 
+                for (int n = 0; n < N; n++) {
+                    ret.a = diff(dim,ret);      
+                }
+                return ret;
+            }
+        }
+        /// <summary>
+        /// First derivative along specific dimension
+        /// </summary>
+        /// <param name="A">input array</param>
+        /// <param name="dim">dimensions to create derivative along</param>
+        /// <returns>array with first derivative of A along dimension <c>dim</c></returns>
+        private static ILRetArray< Int32 > diff(int dim, ILInArray< Int32 > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) return empty< Int32 >(A.Size);
+                if (A.IsScalar) return empty< Int32 >(ILSize.Empty00);
+                if (dim < 0)
+                    throw new ILArgumentException("diff: leading dimension out of range!");
+                if (dim >= A.Size.NumberOfDimensions) {
+                    int[] outDims = A.Size.ToIntArray(dim+1); 
+                    outDims[dim] = 0; 
+                    return empty< Int32 >(new ILSize(outDims)); 
+                }
+                ILSize inDim = A.Size; 
+                int[] newDims = inDim.ToIntArray();
+               
+                if (inDim[dim] == 1) return empty< Int32 >(ILSize.Empty00);
+                int newLength;
+                Int32 [] retArr;
+                // build ILSize
+                newLength = inDim.NumberOfElements / newDims[dim];
+                newDims[dim] --;
+                newLength = newLength * newDims[dim];
+                retArr = ILMemoryPool.Pool.New< Int32 >(newLength);
+                ILSize newDimension = new ILSize(newDims); 
+                int leadDimLen = inDim[dim];
+                int nrHigherDims = inDim.NumberOfElements / leadDimLen;
+                int incOut = newDimension.SequentialIndexDistance(dim); 
+                Int32 firstVal, secVal; 
+                if (A.IsVector) 
+                    return A["1:end"] - A[vec(0,A.Length-2)];     
+                if (dim == 0) {
+    #region physical along 1st leading dimension
+                    unsafe {
+                        fixed ( Int32 * pOutArr = retArr)
+                        fixed ( Int32 * pInArr = A.GetArrayForRead()) {
+                            Int32 * lastElement;
+                            Int32 * tmpOut = pOutArr;
+                            Int32 * tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                lastElement = tmpIn + leadDimLen;
+                                
+                                firstVal = *tmpIn++;
+                                while (tmpIn < lastElement) {
+                                    secVal = *tmpIn++;
+                                    *(tmpOut++) = ( Int32 )(secVal-firstVal);
+                                    firstVal = secVal; 
+                                }
+                            }
+                        }
+                    }
+    #endregion
+                } else {
+    #region physical along abitrary dimension
+                    // sum along abitrary dimension 
+                    unsafe {
+                        fixed ( Int32 * pOutArr = retArr)
+                        fixed ( Int32 * pInArr = A.GetArrayForRead()) {
+                            Int32 * lastElementOut = newLength + pOutArr -1;
+                            int inLength = inDim.NumberOfElements -1; 
+                            Int32 * lastElementIn = pInArr + inLength; 
+                            int inc = inDim.SequentialIndexDistance(dim); 
+                            Int32 * tmpOut = pOutArr;
+                            int outLength = newLength - 1;
+                            Int32 * leadEnd; 
+                            Int32 * tmpIn = pInArr;
+                            for (int h = nrHigherDims; h--> 0; ) {
+                                leadEnd = tmpIn + leadDimLen * inc;
+                                firstVal = *tmpIn; 
+                                tmpIn += inc; 
+                                while (tmpIn < leadEnd) {
+                                    secVal = *tmpIn; 
+                                    *tmpOut = ( Int32 )(secVal - firstVal);
+                                    tmpIn += inc;
+                                    tmpOut += incOut; 
+                                    firstVal = secVal; 
+                                }
+                                if (tmpOut > lastElementOut)
+                                    tmpOut -= outLength;
+                                if (tmpIn > lastElementIn)
+                                    tmpIn -= inLength; 
+                            }
+                        }
+                    }
+    #endregion
+                }
+                return new ILRetArray< Int32 >(retArr, newDimension);
+            }
+        }
+        /// <summary>
+        /// Take n-th derivative
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <param name="N">[Optional] Degree of derivates. If not specified N=1 is assumed.</param>
+        /// <returns>Array with first derivative of A along dimension <c>dim</c> of first non singleton dimension</returns>
+        /// <remarks>N must be a number in range 1..L, where L is the length of A.Dimensions[dim]. 
+        /// Otherwise an empty array will be returned.
+        /// <para>If A is empty or scalar, or if N exceeds the length the specified dimension of A, 
+        /// an empty array will be returned.</para></remarks>
+        public static ILRetArray< byte > diff(ILInArray< byte > A, int N = 1, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (Object.Equals(A,null)) 
+                    throw new ILArgumentException ("diff: input array A must not be null"); 
+                if (dim < 0) {
+                    dim = A.Size.WorkingDimension();
+                }
+                if (dim >= A.Size.NumberOfDimensions) {
+                    int[] outDims = A.Size.ToIntArray(dim+1); 
+                    outDims[dim] = 0; 
+                    return empty< byte >(new ILSize(outDims)); 
+                }
+                if (A.IsScalar) return empty< byte >(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    int [] retDim = A.Size.ToIntArray(); 
+                    retDim[dim]--; 
+                    return empty<  byte >(new ILSize(retDim)); 
+                }
+                if (N == 0) 
+                    return A.C; 
+                if (N < 1 || N > A.Size[dim]) {
+                    return empty<  byte >(ILSize.Empty00); 
+                }
+                ILArray< byte > ret = A.C; 
+                for (int n = 0; n < N; n++) {
+                    ret.a = diff(dim,ret);      
+                }
+                return ret;
+            }
+        }
+        /// <summary>
+        /// First derivative along specific dimension
+        /// </summary>
+        /// <param name="A">input array</param>
+        /// <param name="dim">dimensions to create derivative along</param>
+        /// <returns>array with first derivative of A along dimension <c>dim</c></returns>
+        private static ILRetArray< byte > diff(int dim, ILInArray< byte > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) return empty< byte >(A.Size);
+                if (A.IsScalar) return empty< byte >(ILSize.Empty00);
+                if (dim < 0)
+                    throw new ILArgumentException("diff: leading dimension out of range!");
+                if (dim >= A.Size.NumberOfDimensions) {
+                    int[] outDims = A.Size.ToIntArray(dim+1); 
+                    outDims[dim] = 0; 
+                    return empty< byte >(new ILSize(outDims)); 
+                }
+                ILSize inDim = A.Size; 
+                int[] newDims = inDim.ToIntArray();
+               
+                if (inDim[dim] == 1) return empty< byte >(ILSize.Empty00);
+                int newLength;
+                byte [] retArr;
+                // build ILSize
+                newLength = inDim.NumberOfElements / newDims[dim];
+                newDims[dim] --;
+                newLength = newLength * newDims[dim];
+                retArr = ILMemoryPool.Pool.New< byte >(newLength);
+                ILSize newDimension = new ILSize(newDims); 
+                int leadDimLen = inDim[dim];
+                int nrHigherDims = inDim.NumberOfElements / leadDimLen;
+                int incOut = newDimension.SequentialIndexDistance(dim); 
+                byte firstVal, secVal; 
+                if (A.IsVector) 
+                    return A["1:end"] - A[vec(0,A.Length-2)];     
+                if (dim == 0) {
+    #region physical along 1st leading dimension
+                    unsafe {
+                        fixed ( byte * pOutArr = retArr)
+                        fixed ( byte * pInArr = A.GetArrayForRead()) {
+                            byte * lastElement;
+                            byte * tmpOut = pOutArr;
+                            byte * tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                lastElement = tmpIn + leadDimLen;
+                                
+                                firstVal = *tmpIn++;
+                                while (tmpIn < lastElement) {
+                                    secVal = *tmpIn++;
+                                    *(tmpOut++) = ( byte )(secVal-firstVal);
+                                    firstVal = secVal; 
+                                }
+                            }
+                        }
+                    }
+    #endregion
+                } else {
+    #region physical along abitrary dimension
+                    // sum along abitrary dimension 
+                    unsafe {
+                        fixed ( byte * pOutArr = retArr)
+                        fixed ( byte * pInArr = A.GetArrayForRead()) {
+                            byte * lastElementOut = newLength + pOutArr -1;
+                            int inLength = inDim.NumberOfElements -1; 
+                            byte * lastElementIn = pInArr + inLength; 
+                            int inc = inDim.SequentialIndexDistance(dim); 
+                            byte * tmpOut = pOutArr;
+                            int outLength = newLength - 1;
+                            byte * leadEnd; 
+                            byte * tmpIn = pInArr;
+                            for (int h = nrHigherDims; h--> 0; ) {
+                                leadEnd = tmpIn + leadDimLen * inc;
+                                firstVal = *tmpIn; 
+                                tmpIn += inc; 
+                                while (tmpIn < leadEnd) {
+                                    secVal = *tmpIn; 
+                                    *tmpOut = ( byte )(secVal - firstVal);
+                                    tmpIn += inc;
+                                    tmpOut += incOut; 
+                                    firstVal = secVal; 
+                                }
+                                if (tmpOut > lastElementOut)
+                                    tmpOut -= outLength;
+                                if (tmpIn > lastElementIn)
+                                    tmpIn -= inLength; 
+                            }
+                        }
+                    }
+    #endregion
+                }
+                return new ILRetArray< byte >(retArr, newDimension);
+            }
+        }
+        /// <summary>
+        /// Take n-th derivative
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <param name="N">[Optional] Degree of derivates. If not specified N=1 is assumed.</param>
+        /// <returns>Array with first derivative of A along dimension <c>dim</c> of first non singleton dimension</returns>
+        /// <remarks>N must be a number in range 1..L, where L is the length of A.Dimensions[dim]. 
+        /// Otherwise an empty array will be returned.
+        /// <para>If A is empty or scalar, or if N exceeds the length the specified dimension of A, 
+        /// an empty array will be returned.</para></remarks>
+        public static ILRetArray< fcomplex > diff(ILInArray< fcomplex > A, int N = 1, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (Object.Equals(A,null)) 
+                    throw new ILArgumentException ("diff: input array A must not be null"); 
+                if (dim < 0) {
+                    dim = A.Size.WorkingDimension();
+                }
+                if (dim >= A.Size.NumberOfDimensions) {
+                    int[] outDims = A.Size.ToIntArray(dim+1); 
+                    outDims[dim] = 0; 
+                    return empty< fcomplex >(new ILSize(outDims)); 
+                }
+                if (A.IsScalar) return empty< fcomplex >(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    int [] retDim = A.Size.ToIntArray(); 
+                    retDim[dim]--; 
+                    return empty<  fcomplex >(new ILSize(retDim)); 
+                }
+                if (N == 0) 
+                    return A.C; 
+                if (N < 1 || N > A.Size[dim]) {
+                    return empty<  fcomplex >(ILSize.Empty00); 
+                }
+                ILArray< fcomplex > ret = A.C; 
+                for (int n = 0; n < N; n++) {
+                    ret.a = diff(dim,ret);      
+                }
+                return ret;
+            }
+        }
+        /// <summary>
+        /// First derivative along specific dimension
+        /// </summary>
+        /// <param name="A">input array</param>
+        /// <param name="dim">dimensions to create derivative along</param>
+        /// <returns>array with first derivative of A along dimension <c>dim</c></returns>
+        private static ILRetArray< fcomplex > diff(int dim, ILInArray< fcomplex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) return empty< fcomplex >(A.Size);
+                if (A.IsScalar) return empty< fcomplex >(ILSize.Empty00);
+                if (dim < 0)
+                    throw new ILArgumentException("diff: leading dimension out of range!");
+                if (dim >= A.Size.NumberOfDimensions) {
+                    int[] outDims = A.Size.ToIntArray(dim+1); 
+                    outDims[dim] = 0; 
+                    return empty< fcomplex >(new ILSize(outDims)); 
+                }
+                ILSize inDim = A.Size; 
+                int[] newDims = inDim.ToIntArray();
+               
+                if (inDim[dim] == 1) return empty< fcomplex >(ILSize.Empty00);
+                int newLength;
+                fcomplex [] retArr;
+                // build ILSize
+                newLength = inDim.NumberOfElements / newDims[dim];
+                newDims[dim] --;
+                newLength = newLength * newDims[dim];
+                retArr = ILMemoryPool.Pool.New< fcomplex >(newLength);
+                ILSize newDimension = new ILSize(newDims); 
+                int leadDimLen = inDim[dim];
+                int nrHigherDims = inDim.NumberOfElements / leadDimLen;
+                int incOut = newDimension.SequentialIndexDistance(dim); 
+                fcomplex firstVal, secVal; 
+                if (A.IsVector) 
+                    return A["1:end"] - A[vec(0,A.Length-2)];     
+                if (dim == 0) {
+    #region physical along 1st leading dimension
+                    unsafe {
+                        fixed ( fcomplex * pOutArr = retArr)
+                        fixed ( fcomplex * pInArr = A.GetArrayForRead()) {
+                            fcomplex * lastElement;
+                            fcomplex * tmpOut = pOutArr;
+                            fcomplex * tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                lastElement = tmpIn + leadDimLen;
+                                
+                                firstVal = *tmpIn++;
+                                while (tmpIn < lastElement) {
+                                    secVal = *tmpIn++;
+                                    *(tmpOut++) = ( fcomplex )(secVal-firstVal);
+                                    firstVal = secVal; 
+                                }
+                            }
+                        }
+                    }
+    #endregion
+                } else {
+    #region physical along abitrary dimension
+                    // sum along abitrary dimension 
+                    unsafe {
+                        fixed ( fcomplex * pOutArr = retArr)
+                        fixed ( fcomplex * pInArr = A.GetArrayForRead()) {
+                            fcomplex * lastElementOut = newLength + pOutArr -1;
+                            int inLength = inDim.NumberOfElements -1; 
+                            fcomplex * lastElementIn = pInArr + inLength; 
+                            int inc = inDim.SequentialIndexDistance(dim); 
+                            fcomplex * tmpOut = pOutArr;
+                            int outLength = newLength - 1;
+                            fcomplex * leadEnd; 
+                            fcomplex * tmpIn = pInArr;
+                            for (int h = nrHigherDims; h--> 0; ) {
+                                leadEnd = tmpIn + leadDimLen * inc;
+                                firstVal = *tmpIn; 
+                                tmpIn += inc; 
+                                while (tmpIn < leadEnd) {
+                                    secVal = *tmpIn; 
+                                    *tmpOut = ( fcomplex )(secVal - firstVal);
+                                    tmpIn += inc;
+                                    tmpOut += incOut; 
+                                    firstVal = secVal; 
+                                }
+                                if (tmpOut > lastElementOut)
+                                    tmpOut -= outLength;
+                                if (tmpIn > lastElementIn)
+                                    tmpIn -= inLength; 
+                            }
+                        }
+                    }
+    #endregion
+                }
+                return new ILRetArray< fcomplex >(retArr, newDimension);
+            }
+        }
+        /// <summary>
+        /// Take n-th derivative
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <param name="N">[Optional] Degree of derivates. If not specified N=1 is assumed.</param>
+        /// <returns>Array with first derivative of A along dimension <c>dim</c> of first non singleton dimension</returns>
+        /// <remarks>N must be a number in range 1..L, where L is the length of A.Dimensions[dim]. 
+        /// Otherwise an empty array will be returned.
+        /// <para>If A is empty or scalar, or if N exceeds the length the specified dimension of A, 
+        /// an empty array will be returned.</para></remarks>
+        public static ILRetArray< float > diff(ILInArray< float > A, int N = 1, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (Object.Equals(A,null)) 
+                    throw new ILArgumentException ("diff: input array A must not be null"); 
+                if (dim < 0) {
+                    dim = A.Size.WorkingDimension();
+                }
+                if (dim >= A.Size.NumberOfDimensions) {
+                    int[] outDims = A.Size.ToIntArray(dim+1); 
+                    outDims[dim] = 0; 
+                    return empty< float >(new ILSize(outDims)); 
+                }
+                if (A.IsScalar) return empty< float >(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    int [] retDim = A.Size.ToIntArray(); 
+                    retDim[dim]--; 
+                    return empty<  float >(new ILSize(retDim)); 
+                }
+                if (N == 0) 
+                    return A.C; 
+                if (N < 1 || N > A.Size[dim]) {
+                    return empty<  float >(ILSize.Empty00); 
+                }
+                ILArray< float > ret = A.C; 
+                for (int n = 0; n < N; n++) {
+                    ret.a = diff(dim,ret);      
+                }
+                return ret;
+            }
+        }
+        /// <summary>
+        /// First derivative along specific dimension
+        /// </summary>
+        /// <param name="A">input array</param>
+        /// <param name="dim">dimensions to create derivative along</param>
+        /// <returns>array with first derivative of A along dimension <c>dim</c></returns>
+        private static ILRetArray< float > diff(int dim, ILInArray< float > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) return empty< float >(A.Size);
+                if (A.IsScalar) return empty< float >(ILSize.Empty00);
+                if (dim < 0)
+                    throw new ILArgumentException("diff: leading dimension out of range!");
+                if (dim >= A.Size.NumberOfDimensions) {
+                    int[] outDims = A.Size.ToIntArray(dim+1); 
+                    outDims[dim] = 0; 
+                    return empty< float >(new ILSize(outDims)); 
+                }
+                ILSize inDim = A.Size; 
+                int[] newDims = inDim.ToIntArray();
+               
+                if (inDim[dim] == 1) return empty< float >(ILSize.Empty00);
+                int newLength;
+                float [] retArr;
+                // build ILSize
+                newLength = inDim.NumberOfElements / newDims[dim];
+                newDims[dim] --;
+                newLength = newLength * newDims[dim];
+                retArr = ILMemoryPool.Pool.New< float >(newLength);
+                ILSize newDimension = new ILSize(newDims); 
+                int leadDimLen = inDim[dim];
+                int nrHigherDims = inDim.NumberOfElements / leadDimLen;
+                int incOut = newDimension.SequentialIndexDistance(dim); 
+                float firstVal, secVal; 
+                if (A.IsVector) 
+                    return A["1:end"] - A[vec(0,A.Length-2)];     
+                if (dim == 0) {
+    #region physical along 1st leading dimension
+                    unsafe {
+                        fixed ( float * pOutArr = retArr)
+                        fixed ( float * pInArr = A.GetArrayForRead()) {
+                            float * lastElement;
+                            float * tmpOut = pOutArr;
+                            float * tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                lastElement = tmpIn + leadDimLen;
+                                
+                                firstVal = *tmpIn++;
+                                while (tmpIn < lastElement) {
+                                    secVal = *tmpIn++;
+                                    *(tmpOut++) = ( float )(secVal-firstVal);
+                                    firstVal = secVal; 
+                                }
+                            }
+                        }
+                    }
+    #endregion
+                } else {
+    #region physical along abitrary dimension
+                    // sum along abitrary dimension 
+                    unsafe {
+                        fixed ( float * pOutArr = retArr)
+                        fixed ( float * pInArr = A.GetArrayForRead()) {
+                            float * lastElementOut = newLength + pOutArr -1;
+                            int inLength = inDim.NumberOfElements -1; 
+                            float * lastElementIn = pInArr + inLength; 
+                            int inc = inDim.SequentialIndexDistance(dim); 
+                            float * tmpOut = pOutArr;
+                            int outLength = newLength - 1;
+                            float * leadEnd; 
+                            float * tmpIn = pInArr;
+                            for (int h = nrHigherDims; h--> 0; ) {
+                                leadEnd = tmpIn + leadDimLen * inc;
+                                firstVal = *tmpIn; 
+                                tmpIn += inc; 
+                                while (tmpIn < leadEnd) {
+                                    secVal = *tmpIn; 
+                                    *tmpOut = ( float )(secVal - firstVal);
+                                    tmpIn += inc;
+                                    tmpOut += incOut; 
+                                    firstVal = secVal; 
+                                }
+                                if (tmpOut > lastElementOut)
+                                    tmpOut -= outLength;
+                                if (tmpIn > lastElementIn)
+                                    tmpIn -= inLength; 
+                            }
+                        }
+                    }
+    #endregion
+                }
+                return new ILRetArray< float >(retArr, newDimension);
+            }
+        }
+        /// <summary>
+        /// Take n-th derivative
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <param name="N">[Optional] Degree of derivates. If not specified N=1 is assumed.</param>
+        /// <returns>Array with first derivative of A along dimension <c>dim</c> of first non singleton dimension</returns>
+        /// <remarks>N must be a number in range 1..L, where L is the length of A.Dimensions[dim]. 
+        /// Otherwise an empty array will be returned.
+        /// <para>If A is empty or scalar, or if N exceeds the length the specified dimension of A, 
+        /// an empty array will be returned.</para></remarks>
+        public static ILRetArray< complex > diff(ILInArray< complex > A, int N = 1, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (Object.Equals(A,null)) 
+                    throw new ILArgumentException ("diff: input array A must not be null"); 
+                if (dim < 0) {
+                    dim = A.Size.WorkingDimension();
+                }
+                if (dim >= A.Size.NumberOfDimensions) {
+                    int[] outDims = A.Size.ToIntArray(dim+1); 
+                    outDims[dim] = 0; 
+                    return empty< complex >(new ILSize(outDims)); 
+                }
+                if (A.IsScalar) return empty< complex >(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    int [] retDim = A.Size.ToIntArray(); 
+                    retDim[dim]--; 
+                    return empty<  complex >(new ILSize(retDim)); 
+                }
+                if (N == 0) 
+                    return A.C; 
+                if (N < 1 || N > A.Size[dim]) {
+                    return empty<  complex >(ILSize.Empty00); 
+                }
+                ILArray< complex > ret = A.C; 
+                for (int n = 0; n < N; n++) {
+                    ret.a = diff(dim,ret);      
+                }
+                return ret;
+            }
+        }
+        /// <summary>
+        /// First derivative along specific dimension
+        /// </summary>
+        /// <param name="A">input array</param>
+        /// <param name="dim">dimensions to create derivative along</param>
+        /// <returns>array with first derivative of A along dimension <c>dim</c></returns>
+        private static ILRetArray< complex > diff(int dim, ILInArray< complex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) return empty< complex >(A.Size);
+                if (A.IsScalar) return empty< complex >(ILSize.Empty00);
+                if (dim < 0)
+                    throw new ILArgumentException("diff: leading dimension out of range!");
+                if (dim >= A.Size.NumberOfDimensions) {
+                    int[] outDims = A.Size.ToIntArray(dim+1); 
+                    outDims[dim] = 0; 
+                    return empty< complex >(new ILSize(outDims)); 
+                }
+                ILSize inDim = A.Size; 
+                int[] newDims = inDim.ToIntArray();
+               
+                if (inDim[dim] == 1) return empty< complex >(ILSize.Empty00);
+                int newLength;
+                complex [] retArr;
+                // build ILSize
+                newLength = inDim.NumberOfElements / newDims[dim];
+                newDims[dim] --;
+                newLength = newLength * newDims[dim];
+                retArr = ILMemoryPool.Pool.New< complex >(newLength);
+                ILSize newDimension = new ILSize(newDims); 
+                int leadDimLen = inDim[dim];
+                int nrHigherDims = inDim.NumberOfElements / leadDimLen;
+                int incOut = newDimension.SequentialIndexDistance(dim); 
+                complex firstVal, secVal; 
+                if (A.IsVector) 
+                    return A["1:end"] - A[vec(0,A.Length-2)];     
+                if (dim == 0) {
+    #region physical along 1st leading dimension
+                    unsafe {
+                        fixed ( complex * pOutArr = retArr)
+                        fixed ( complex * pInArr = A.GetArrayForRead()) {
+                            complex * lastElement;
+                            complex * tmpOut = pOutArr;
+                            complex * tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                lastElement = tmpIn + leadDimLen;
+                                
+                                firstVal = *tmpIn++;
+                                while (tmpIn < lastElement) {
+                                    secVal = *tmpIn++;
+                                    *(tmpOut++) = ( complex )(secVal-firstVal);
+                                    firstVal = secVal; 
+                                }
+                            }
+                        }
+                    }
+    #endregion
+                } else {
+    #region physical along abitrary dimension
+                    // sum along abitrary dimension 
+                    unsafe {
+                        fixed ( complex * pOutArr = retArr)
+                        fixed ( complex * pInArr = A.GetArrayForRead()) {
+                            complex * lastElementOut = newLength + pOutArr -1;
+                            int inLength = inDim.NumberOfElements -1; 
+                            complex * lastElementIn = pInArr + inLength; 
+                            int inc = inDim.SequentialIndexDistance(dim); 
+                            complex * tmpOut = pOutArr;
+                            int outLength = newLength - 1;
+                            complex * leadEnd; 
+                            complex * tmpIn = pInArr;
+                            for (int h = nrHigherDims; h--> 0; ) {
+                                leadEnd = tmpIn + leadDimLen * inc;
+                                firstVal = *tmpIn; 
+                                tmpIn += inc; 
+                                while (tmpIn < leadEnd) {
+                                    secVal = *tmpIn; 
+                                    *tmpOut = ( complex )(secVal - firstVal);
+                                    tmpIn += inc;
+                                    tmpOut += incOut; 
+                                    firstVal = secVal; 
+                                }
+                                if (tmpOut > lastElementOut)
+                                    tmpOut -= outLength;
+                                if (tmpIn > lastElementIn)
+                                    tmpIn -= inLength; 
+                            }
+                        }
+                    }
+    #endregion
+                }
+                return new ILRetArray< complex >(retArr, newDimension);
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+  
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/dimensionWrapper.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/dimensionWrapper.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/dimensionWrapper.cs	(revision 9102)
@@ -0,0 +1,132 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics;
+using ILNumerics.Exceptions;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+
+namespace ILNumerics {
+
+    public partial class ILMath {
+
+        /// <summary>
+        /// Size of dimensions of A 
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Double array with the length of each dimension of A</returns>
+        /// <remarks>If A is null, an empty array will be returned. Otherwise the array returned will always be a row vector of length s. s &gt;= 2</remarks>
+        public static ILRetArray<double> size(ILBaseArray A) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals (A,null))
+                    return empty<double>(ILSize.Empty00); 
+                int numDim = A.Size.NumberOfDimensions;
+                double [] retArr = new double[numDim]; 
+                for (int i = 0; i < numDim; i++) {
+                    retArr[i] = A.Size[i];     
+                }
+                return new ILRetArray<double>(retArr,1,numDim); 
+            }
+        }
+        /// <summary>
+        /// Length of one specific dimension of A
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="dim">Number of dimension to query the length for</param>
+        /// <returns>Length of dimension 'dim'</returns>
+        public static int size(ILBaseArray A, int dim) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A,null) || dim < 0)
+                    throw new ILArgumentException("size: A must not be null");
+                return A.Size[dim];
+            }
+        }
+        /// <summary>
+        /// Create a size descriptor
+        /// </summary>
+        /// <param name="dimensions">Arbitrary number of dimension length</param>
+        /// <returns>Size descriptor</returns>
+        public static ILSize size(params int[] dimensions) {
+            return new ILSize(dimensions); 
+        }
+
+        /// <summary>
+        /// Longest dimension of A
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns>If A is null:0 - length of longest dimension of A</returns>
+        /// <remarks>This is an alias/abreviation for A.Dimensions.Longest</remarks>
+        public static int length(ILBaseArray A) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A,null)) return 0;
+                return A.Size.Longest;
+            }
+        }
+        
+        /// <summary>
+        /// Number of dimensions of A
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns>If A is null: 0 - else number of dimensions of A</returns>
+        /// <remarks>This is an alias/abreviation for A.Dimensions.NumberOfDimensions</remarks>
+        /// 
+        public static int ndims(ILBaseArray A) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A,null)) return 0;
+                return A.Size.NumberOfDimensions;  
+            }
+        }
+
+        /// <summary>
+        /// Number of elements of A
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Number of elements of A</returns>
+        /// <remarks>This is an alias/abreviation for A.Dimensions.NumberOfElements</remarks>
+        public static int numel(ILBaseArray A) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A,null)) return 0;
+                return A.Size.NumberOfElements;   
+            }
+        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/distL1.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/distL1.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/distL1.cs	(revision 9102)
@@ -0,0 +1,1328 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using ILNumerics;
+using ILNumerics.Misc;
+using ILNumerics.Storage;
+using ILNumerics.Native;
+using ILNumerics.Exceptions;
+
+
+
+namespace ILNumerics {
+
+    public partial class ILMath {
+
+
+
+        /// <summary>
+        /// pairwise L1 distance 
+        /// </summary>
+        /// <param name="A">input points (matrix)</param>
+        /// <param name="B">input point (vector)</param>
+        /// <returns>pairwise L1 distances between the data point provided in the input vector <paramref name="B"/> and the data points stored in the matrix <paramref name="A"/>.</returns>
+        /// <remarks>
+        /// <para>If <paramref name="B"/> is a colum vector, the distances between <paramref name="B"/> and the columns of <paramref name="A"/> are calculated. The number of rows of <paramref name="A"/> 
+        /// must match the length of vector <paramref name="B"/> than. Therefore, the length of the returned vector of distances matches the number of columns of <paramref name="A"/>: <code>A.S[1]</code>.</para>
+        /// <para>If <paramref name="B"/> is a row vector, the distances between <paramref name="B"/> and the rows of <paramref name="A"/> are calculated. The number of columns of <paramref name="A"/> 
+        /// must match the length of vector <paramref name="B"/> than. Therefore, the length of the returned vector of distances matches the number of rows of <paramref name="A"/>: <code>A.S[0]</code>.</para>
+        /// <para>This function is cummulative, the single data point may be provided in <paramref name="A"/> and the data point matrix may be provided in <paramref name="B"/> as well.</para>
+        /// </remarks>
+        public static unsafe ILRetArray<double> distL1(ILInArray<double> A, ILInArray<double> B) {
+            using (ILScope.Enter(A, B)) {
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<double>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<double>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<double>(A.S);
+                }
+                // early exit: make the function cummutative
+                if (A.IsVector && !B.IsVector) {
+                    return distL1(B, A); 
+                } 
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                
+                dim = -(dim - 1);  // 0 -> 1, 1 -> 0
+                #endregion
+
+                #region parameter preparation
+                ILSize outDims; 
+                if (dim == 0) {
+                    outDims = size(1,A.S[1]);    
+                } else if (dim == 1) {
+                    outDims = size(A.S[0], 1);
+                } else if (A.S.IsSameSize(B.S)) {
+                    outDims = A.S;
+                    dim = 0; 
+                } else 
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+
+                
+                double[] retArr = ILMemoryPool.Pool.New<double>(outDims.NumberOfElements);
+
+                
+                double[] arrA = A.GetArrayForRead();
+
+                
+                double[] arrB = B.GetArrayForRead();
+                int itLen = A.S[0]; 
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<double> retStorage = new ILDenseStorage<double>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, IntPtr, IntPtr, IntPtr>)data;
+
+                    
+                    double* ap;
+
+                    
+                    double* bp;
+
+                    
+                    double* cp;
+                    if (dim == 0) {
+                        ap = (double*)range.Item2;
+                        cp = (double*)range.Item4;
+                        for (int s = 0; s < range.Item1; s++) {
+                            bp = (double*)range.Item3;
+                            
+                            double sum = 0; 
+                            int l = itLen;
+                            while (l > 20) {
+                                sum +=  Math.Abs(ap[0] - bp[0])
+                                    +   Math.Abs(ap[1] - bp[1])
+                                    +   Math.Abs(ap[2] - bp[2])
+                                    +   Math.Abs(ap[3] - bp[3])
+                                    +   Math.Abs(ap[4] - bp[4])
+                                    +   Math.Abs(ap[5] - bp[5])
+                                    +   Math.Abs(ap[6] - bp[6])
+                                    +   Math.Abs(ap[7] - bp[7])
+                                    +   Math.Abs(ap[8] - bp[8])
+                                    +   Math.Abs(ap[9] - bp[9])
+                                    +   Math.Abs(ap[10] - bp[10])
+                                    +   Math.Abs(ap[11] - bp[11])
+                                    +   Math.Abs(ap[12] - bp[12])
+                                    +   Math.Abs(ap[13] - bp[13])
+                                    +   Math.Abs(ap[14] - bp[14])
+                                    +   Math.Abs(ap[15] - bp[15])
+                                    +   Math.Abs(ap[16] - bp[16])
+                                    +   Math.Abs(ap[17] - bp[17])
+                                    +   Math.Abs(ap[18] - bp[18])
+                                    +   Math.Abs(ap[19] - bp[19])
+                                    +   Math.Abs(ap[20] - bp[20]);
+                                ap += 21;
+                                bp += 21;
+                                l -= 21;
+                            }
+                            while (l-- > 0) {
+                                sum +=  Math.Abs(*ap - *bp);
+                                ap++;
+                                bp++;
+                            }
+                            *cp++ = sum; 
+                        }
+                    } else {
+                        // dim = 1
+                        ap = (double*)range.Item2;
+                        bp = (double*)range.Item3;
+                        cp = (double*)range.Item4;
+                        for (int s = 0; s < range.Item1; s++) { // TODO: further potential speedup: unroll in s direction!
+                            
+                            double val = *bp++;
+                            int l = itLen;
+                            while (l > 10) {
+                                cp[0] +=   Math.Abs(ap[0] - val);
+                                cp[1] +=   Math.Abs(ap[1] - val);
+                                cp[2] +=   Math.Abs(ap[2] - val);
+                                cp[3] +=   Math.Abs(ap[3] - val);
+                                cp[4] +=   Math.Abs(ap[4] - val);
+                                cp[5] +=   Math.Abs(ap[5] - val);
+                                cp[6] +=   Math.Abs(ap[6] - val);
+                                cp[7] +=   Math.Abs(ap[7] - val);
+                                cp[8] +=   Math.Abs(ap[8] - val);
+                                cp[9] +=   Math.Abs(ap[9] - val);
+                                cp[10] +=  Math.Abs(ap[10] - val);
+                                cp[11] +=  Math.Abs(ap[11] - val);
+                                cp[12] +=  Math.Abs(ap[12] - val);
+                                cp[13] +=  Math.Abs(ap[13] - val);
+                                cp[14] +=  Math.Abs(ap[14] - val);
+                                cp[15] +=  Math.Abs(ap[15] - val);
+                                cp[16] +=  Math.Abs(ap[16] - val);
+                                cp[17] +=  Math.Abs(ap[17] - val);
+                                cp[18] +=  Math.Abs(ap[18] - val);
+                                cp[19] +=  Math.Abs(ap[19] - val);
+                                cp[20] +=  Math.Abs(ap[20] - val);
+                                ap += 21;
+                                cp += 21;
+                                l -= 21;
+                            }
+                            while (l-- > 0) {
+                                *cp +=  Math.Abs(*ap - val);
+                                ap++;
+                                cp++;
+                            }
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outDims.NumberOfElements >= Settings.s_minParallelElement1Count
+                    && outDims[1] > 1) {
+                        if (outDims[1] > workItemCount) {
+                        workItemLength = outDims[1] / workItemCount;
+                    } else {
+                        workItemLength = outDims[1] / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outDims[1];
+                    workItemCount = 1;
+                }
+
+                //int[] partResults = new int[workItemCount]; 
+                fixed ( double* arrAP = arrA)
+                fixed ( double* arrBP = arrB)
+                fixed ( double* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, IntPtr, IntPtr, IntPtr> range = new Tuple<int, IntPtr, IntPtr, IntPtr>
+                               (workItemLength
+                               , (IntPtr)(arrAP + i * outDims[0] * workItemLength)
+                               , (IntPtr)(arrBP + i * dim * workItemLength)
+                               , (IntPtr)(retArrP + i * workItemLength)); 
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, IntPtr, IntPtr, IntPtr>
+                                (outDims[1] - i * workItemLength
+                                , (IntPtr)(arrAP + i * outDims[0] * workItemLength)
+                                , (IntPtr)(arrBP + i * dim * workItemLength)
+                                , (IntPtr)(retArrP + i * workItemLength)));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<double>(retStorage);
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// pairwise L1 distance 
+        /// </summary>
+        /// <param name="A">input points (matrix)</param>
+        /// <param name="B">input point (vector)</param>
+        /// <returns>pairwise L1 distances between the data point provided in the input vector <paramref name="B"/> and the data points stored in the matrix <paramref name="A"/>.</returns>
+        /// <remarks>
+        /// <para>If <paramref name="B"/> is a colum vector, the distances between <paramref name="B"/> and the columns of <paramref name="A"/> are calculated. The number of rows of <paramref name="A"/> 
+        /// must match the length of vector <paramref name="B"/> than. Therefore, the length of the returned vector of distances matches the number of columns of <paramref name="A"/>: <code>A.S[1]</code>.</para>
+        /// <para>If <paramref name="B"/> is a row vector, the distances between <paramref name="B"/> and the rows of <paramref name="A"/> are calculated. The number of columns of <paramref name="A"/> 
+        /// must match the length of vector <paramref name="B"/> than. Therefore, the length of the returned vector of distances matches the number of rows of <paramref name="A"/>: <code>A.S[0]</code>.</para>
+        /// <para>This function is cummulative, the single data point may be provided in <paramref name="A"/> and the data point matrix may be provided in <paramref name="B"/> as well.</para>
+        /// </remarks>
+        public static unsafe ILRetArray<Int64> distL1(ILInArray<Int64> A, ILInArray<Int64> B) {
+            using (ILScope.Enter(A, B)) {
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<Int64>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<Int64>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<Int64>(A.S);
+                }
+                // early exit: make the function cummutative
+                if (A.IsVector && !B.IsVector) {
+                    return distL1(B, A); 
+                } 
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                
+                dim = -(dim - 1);  // 0 -> 1, 1 -> 0
+                #endregion
+
+                #region parameter preparation
+                ILSize outDims; 
+                if (dim == 0) {
+                    outDims = size(1,A.S[1]);    
+                } else if (dim == 1) {
+                    outDims = size(A.S[0], 1);
+                } else if (A.S.IsSameSize(B.S)) {
+                    outDims = A.S;
+                    dim = 0; 
+                } else 
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+
+               
+                Int64[] retArr = ILMemoryPool.Pool.New<Int64>(outDims.NumberOfElements);
+
+               
+                Int64[] arrA = A.GetArrayForRead();
+
+               
+                Int64[] arrB = B.GetArrayForRead();
+                int itLen = A.S[0]; 
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<Int64> retStorage = new ILDenseStorage<Int64>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, IntPtr, IntPtr, IntPtr>)data;
+
+                   
+                    Int64* ap;
+
+                   
+                    Int64* bp;
+
+                   
+                    Int64* cp;
+                    if (dim == 0) {
+                        ap = (Int64*)range.Item2;
+                        cp = (Int64*)range.Item4;
+                        for (int s = 0; s < range.Item1; s++) {
+                            bp = (Int64*)range.Item3;
+                           
+                            Int64 sum = 0; 
+                            int l = itLen;
+                            while (l > 20) {
+                                sum +=  Math.Abs(ap[0] - bp[0])
+                                    +  Math.Abs(ap[1] - bp[1])
+                                    +  Math.Abs(ap[2] - bp[2])
+                                    +  Math.Abs(ap[3] - bp[3])
+                                    +  Math.Abs(ap[4] - bp[4])
+                                    +  Math.Abs(ap[5] - bp[5])
+                                    +  Math.Abs(ap[6] - bp[6])
+                                    +  Math.Abs(ap[7] - bp[7])
+                                    +  Math.Abs(ap[8] - bp[8])
+                                    +  Math.Abs(ap[9] - bp[9])
+                                    +  Math.Abs(ap[10] - bp[10])
+                                    +  Math.Abs(ap[11] - bp[11])
+                                    +  Math.Abs(ap[12] - bp[12])
+                                    +  Math.Abs(ap[13] - bp[13])
+                                    +  Math.Abs(ap[14] - bp[14])
+                                    +  Math.Abs(ap[15] - bp[15])
+                                    +  Math.Abs(ap[16] - bp[16])
+                                    +  Math.Abs(ap[17] - bp[17])
+                                    +  Math.Abs(ap[18] - bp[18])
+                                    +  Math.Abs(ap[19] - bp[19])
+                                    +  Math.Abs(ap[20] - bp[20]);
+                                ap += 21;
+                                bp += 21;
+                                l -= 21;
+                            }
+                            while (l-- > 0) {
+                                sum +=  Math.Abs(*ap - *bp);
+                                ap++;
+                                bp++;
+                            }
+                            *cp++ = sum; 
+                        }
+                    } else {
+                        // dim = 1
+                        ap = (Int64*)range.Item2;
+                        bp = (Int64*)range.Item3;
+                        cp = (Int64*)range.Item4;
+                        for (int s = 0; s < range.Item1; s++) { // TODO: further potential speedup: unroll in s direction!
+                           
+                            Int64 val = *bp++;
+                            int l = itLen;
+                            while (l > 10) {
+                                cp[0] +=  Math.Abs(ap[0] - val);
+                                cp[1] +=  Math.Abs(ap[1] - val);
+                                cp[2] +=  Math.Abs(ap[2] - val);
+                                cp[3] +=  Math.Abs(ap[3] - val);
+                                cp[4] +=  Math.Abs(ap[4] - val);
+                                cp[5] +=  Math.Abs(ap[5] - val);
+                                cp[6] +=  Math.Abs(ap[6] - val);
+                                cp[7] +=  Math.Abs(ap[7] - val);
+                                cp[8] +=  Math.Abs(ap[8] - val);
+                                cp[9] +=  Math.Abs(ap[9] - val);
+                                cp[10] +=  Math.Abs(ap[10] - val);
+                                cp[11] +=  Math.Abs(ap[11] - val);
+                                cp[12] +=  Math.Abs(ap[12] - val);
+                                cp[13] +=  Math.Abs(ap[13] - val);
+                                cp[14] +=  Math.Abs(ap[14] - val);
+                                cp[15] +=  Math.Abs(ap[15] - val);
+                                cp[16] +=  Math.Abs(ap[16] - val);
+                                cp[17] +=  Math.Abs(ap[17] - val);
+                                cp[18] +=  Math.Abs(ap[18] - val);
+                                cp[19] +=  Math.Abs(ap[19] - val);
+                                cp[20] +=  Math.Abs(ap[20] - val);
+                                ap += 21;
+                                cp += 21;
+                                l -= 21;
+                            }
+                            while (l-- > 0) {
+                                *cp +=  Math.Abs(*ap - val);
+                                ap++;
+                                cp++;
+                            }
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outDims.NumberOfElements >= Settings.s_minParallelElement1Count
+                    && outDims[1] > 1) {
+                        if (outDims[1] > workItemCount) {
+                        workItemLength = outDims[1] / workItemCount;
+                    } else {
+                        workItemLength = outDims[1] / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outDims[1];
+                    workItemCount = 1;
+                }
+
+                //int[] partResults = new int[workItemCount]; 
+                fixed ( Int64* arrAP = arrA)
+                fixed ( Int64* arrBP = arrB)
+                fixed ( Int64* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, IntPtr, IntPtr, IntPtr> range = new Tuple<int, IntPtr, IntPtr, IntPtr>
+                               (workItemLength
+                               , (IntPtr)(arrAP + i * outDims[0] * workItemLength)
+                               , (IntPtr)(arrBP + i * dim * workItemLength)
+                               , (IntPtr)(retArrP + i * workItemLength)); 
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, IntPtr, IntPtr, IntPtr>
+                                (outDims[1] - i * workItemLength
+                                , (IntPtr)(arrAP + i * outDims[0] * workItemLength)
+                                , (IntPtr)(arrBP + i * dim * workItemLength)
+                                , (IntPtr)(retArrP + i * workItemLength)));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<Int64>(retStorage);
+            }
+        }
+        /// <summary>
+        /// pairwise L1 distance 
+        /// </summary>
+        /// <param name="A">input points (matrix)</param>
+        /// <param name="B">input point (vector)</param>
+        /// <returns>pairwise L1 distances between the data point provided in the input vector <paramref name="B"/> and the data points stored in the matrix <paramref name="A"/>.</returns>
+        /// <remarks>
+        /// <para>If <paramref name="B"/> is a colum vector, the distances between <paramref name="B"/> and the columns of <paramref name="A"/> are calculated. The number of rows of <paramref name="A"/> 
+        /// must match the length of vector <paramref name="B"/> than. Therefore, the length of the returned vector of distances matches the number of columns of <paramref name="A"/>: <code>A.S[1]</code>.</para>
+        /// <para>If <paramref name="B"/> is a row vector, the distances between <paramref name="B"/> and the rows of <paramref name="A"/> are calculated. The number of columns of <paramref name="A"/> 
+        /// must match the length of vector <paramref name="B"/> than. Therefore, the length of the returned vector of distances matches the number of rows of <paramref name="A"/>: <code>A.S[0]</code>.</para>
+        /// <para>This function is cummulative, the single data point may be provided in <paramref name="A"/> and the data point matrix may be provided in <paramref name="B"/> as well.</para>
+        /// </remarks>
+        public static unsafe ILRetArray<Int32> distL1(ILInArray<Int32> A, ILInArray<Int32> B) {
+            using (ILScope.Enter(A, B)) {
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<Int32>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<Int32>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<Int32>(A.S);
+                }
+                // early exit: make the function cummutative
+                if (A.IsVector && !B.IsVector) {
+                    return distL1(B, A); 
+                } 
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                
+                dim = -(dim - 1);  // 0 -> 1, 1 -> 0
+                #endregion
+
+                #region parameter preparation
+                ILSize outDims; 
+                if (dim == 0) {
+                    outDims = size(1,A.S[1]);    
+                } else if (dim == 1) {
+                    outDims = size(A.S[0], 1);
+                } else if (A.S.IsSameSize(B.S)) {
+                    outDims = A.S;
+                    dim = 0; 
+                } else 
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+
+               
+                Int32[] retArr = ILMemoryPool.Pool.New<Int32>(outDims.NumberOfElements);
+
+               
+                Int32[] arrA = A.GetArrayForRead();
+
+               
+                Int32[] arrB = B.GetArrayForRead();
+                int itLen = A.S[0]; 
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<Int32> retStorage = new ILDenseStorage<Int32>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, IntPtr, IntPtr, IntPtr>)data;
+
+                   
+                    Int32* ap;
+
+                   
+                    Int32* bp;
+
+                   
+                    Int32* cp;
+                    if (dim == 0) {
+                        ap = (Int32*)range.Item2;
+                        cp = (Int32*)range.Item4;
+                        for (int s = 0; s < range.Item1; s++) {
+                            bp = (Int32*)range.Item3;
+                           
+                            Int32 sum = 0; 
+                            int l = itLen;
+                            while (l > 20) {
+                                sum +=  Math.Abs(ap[0] - bp[0])
+                                    +  Math.Abs(ap[1] - bp[1])
+                                    +  Math.Abs(ap[2] - bp[2])
+                                    +  Math.Abs(ap[3] - bp[3])
+                                    +  Math.Abs(ap[4] - bp[4])
+                                    +  Math.Abs(ap[5] - bp[5])
+                                    +  Math.Abs(ap[6] - bp[6])
+                                    +  Math.Abs(ap[7] - bp[7])
+                                    +  Math.Abs(ap[8] - bp[8])
+                                    +  Math.Abs(ap[9] - bp[9])
+                                    +  Math.Abs(ap[10] - bp[10])
+                                    +  Math.Abs(ap[11] - bp[11])
+                                    +  Math.Abs(ap[12] - bp[12])
+                                    +  Math.Abs(ap[13] - bp[13])
+                                    +  Math.Abs(ap[14] - bp[14])
+                                    +  Math.Abs(ap[15] - bp[15])
+                                    +  Math.Abs(ap[16] - bp[16])
+                                    +  Math.Abs(ap[17] - bp[17])
+                                    +  Math.Abs(ap[18] - bp[18])
+                                    +  Math.Abs(ap[19] - bp[19])
+                                    +  Math.Abs(ap[20] - bp[20]);
+                                ap += 21;
+                                bp += 21;
+                                l -= 21;
+                            }
+                            while (l-- > 0) {
+                                sum +=  Math.Abs(*ap - *bp);
+                                ap++;
+                                bp++;
+                            }
+                            *cp++ = sum; 
+                        }
+                    } else {
+                        // dim = 1
+                        ap = (Int32*)range.Item2;
+                        bp = (Int32*)range.Item3;
+                        cp = (Int32*)range.Item4;
+                        for (int s = 0; s < range.Item1; s++) { // TODO: further potential speedup: unroll in s direction!
+                           
+                            Int32 val = *bp++;
+                            int l = itLen;
+                            while (l > 10) {
+                                cp[0] +=  Math.Abs(ap[0] - val);
+                                cp[1] +=  Math.Abs(ap[1] - val);
+                                cp[2] +=  Math.Abs(ap[2] - val);
+                                cp[3] +=  Math.Abs(ap[3] - val);
+                                cp[4] +=  Math.Abs(ap[4] - val);
+                                cp[5] +=  Math.Abs(ap[5] - val);
+                                cp[6] +=  Math.Abs(ap[6] - val);
+                                cp[7] +=  Math.Abs(ap[7] - val);
+                                cp[8] +=  Math.Abs(ap[8] - val);
+                                cp[9] +=  Math.Abs(ap[9] - val);
+                                cp[10] +=  Math.Abs(ap[10] - val);
+                                cp[11] +=  Math.Abs(ap[11] - val);
+                                cp[12] +=  Math.Abs(ap[12] - val);
+                                cp[13] +=  Math.Abs(ap[13] - val);
+                                cp[14] +=  Math.Abs(ap[14] - val);
+                                cp[15] +=  Math.Abs(ap[15] - val);
+                                cp[16] +=  Math.Abs(ap[16] - val);
+                                cp[17] +=  Math.Abs(ap[17] - val);
+                                cp[18] +=  Math.Abs(ap[18] - val);
+                                cp[19] +=  Math.Abs(ap[19] - val);
+                                cp[20] +=  Math.Abs(ap[20] - val);
+                                ap += 21;
+                                cp += 21;
+                                l -= 21;
+                            }
+                            while (l-- > 0) {
+                                *cp +=  Math.Abs(*ap - val);
+                                ap++;
+                                cp++;
+                            }
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outDims.NumberOfElements >= Settings.s_minParallelElement1Count
+                    && outDims[1] > 1) {
+                        if (outDims[1] > workItemCount) {
+                        workItemLength = outDims[1] / workItemCount;
+                    } else {
+                        workItemLength = outDims[1] / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outDims[1];
+                    workItemCount = 1;
+                }
+
+                //int[] partResults = new int[workItemCount]; 
+                fixed ( Int32* arrAP = arrA)
+                fixed ( Int32* arrBP = arrB)
+                fixed ( Int32* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, IntPtr, IntPtr, IntPtr> range = new Tuple<int, IntPtr, IntPtr, IntPtr>
+                               (workItemLength
+                               , (IntPtr)(arrAP + i * outDims[0] * workItemLength)
+                               , (IntPtr)(arrBP + i * dim * workItemLength)
+                               , (IntPtr)(retArrP + i * workItemLength)); 
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, IntPtr, IntPtr, IntPtr>
+                                (outDims[1] - i * workItemLength
+                                , (IntPtr)(arrAP + i * outDims[0] * workItemLength)
+                                , (IntPtr)(arrBP + i * dim * workItemLength)
+                                , (IntPtr)(retArrP + i * workItemLength)));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<Int32>(retStorage);
+            }
+        }
+        /// <summary>
+        /// pairwise L1 distance 
+        /// </summary>
+        /// <param name="A">input points (matrix)</param>
+        /// <param name="B">input point (vector)</param>
+        /// <returns>pairwise L1 distances between the data point provided in the input vector <paramref name="B"/> and the data points stored in the matrix <paramref name="A"/>.</returns>
+        /// <remarks>
+        /// <para>If <paramref name="B"/> is a colum vector, the distances between <paramref name="B"/> and the columns of <paramref name="A"/> are calculated. The number of rows of <paramref name="A"/> 
+        /// must match the length of vector <paramref name="B"/> than. Therefore, the length of the returned vector of distances matches the number of columns of <paramref name="A"/>: <code>A.S[1]</code>.</para>
+        /// <para>If <paramref name="B"/> is a row vector, the distances between <paramref name="B"/> and the rows of <paramref name="A"/> are calculated. The number of columns of <paramref name="A"/> 
+        /// must match the length of vector <paramref name="B"/> than. Therefore, the length of the returned vector of distances matches the number of rows of <paramref name="A"/>: <code>A.S[0]</code>.</para>
+        /// <para>This function is cummulative, the single data point may be provided in <paramref name="A"/> and the data point matrix may be provided in <paramref name="B"/> as well.</para>
+        /// </remarks>
+        public static unsafe ILRetArray<float> distL1(ILInArray<float> A, ILInArray<float> B) {
+            using (ILScope.Enter(A, B)) {
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<float>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<float>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<float>(A.S);
+                }
+                // early exit: make the function cummutative
+                if (A.IsVector && !B.IsVector) {
+                    return distL1(B, A); 
+                } 
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                
+                dim = -(dim - 1);  // 0 -> 1, 1 -> 0
+                #endregion
+
+                #region parameter preparation
+                ILSize outDims; 
+                if (dim == 0) {
+                    outDims = size(1,A.S[1]);    
+                } else if (dim == 1) {
+                    outDims = size(A.S[0], 1);
+                } else if (A.S.IsSameSize(B.S)) {
+                    outDims = A.S;
+                    dim = 0; 
+                } else 
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+
+               
+                float[] retArr = ILMemoryPool.Pool.New<float>(outDims.NumberOfElements);
+
+               
+                float[] arrA = A.GetArrayForRead();
+
+               
+                float[] arrB = B.GetArrayForRead();
+                int itLen = A.S[0]; 
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<float> retStorage = new ILDenseStorage<float>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, IntPtr, IntPtr, IntPtr>)data;
+
+                   
+                    float* ap;
+
+                   
+                    float* bp;
+
+                   
+                    float* cp;
+                    if (dim == 0) {
+                        ap = (float*)range.Item2;
+                        cp = (float*)range.Item4;
+                        for (int s = 0; s < range.Item1; s++) {
+                            bp = (float*)range.Item3;
+                           
+                            float sum = 0; 
+                            int l = itLen;
+                            while (l > 20) {
+                                sum +=  Math.Abs(ap[0] - bp[0])
+                                    +  Math.Abs(ap[1] - bp[1])
+                                    +  Math.Abs(ap[2] - bp[2])
+                                    +  Math.Abs(ap[3] - bp[3])
+                                    +  Math.Abs(ap[4] - bp[4])
+                                    +  Math.Abs(ap[5] - bp[5])
+                                    +  Math.Abs(ap[6] - bp[6])
+                                    +  Math.Abs(ap[7] - bp[7])
+                                    +  Math.Abs(ap[8] - bp[8])
+                                    +  Math.Abs(ap[9] - bp[9])
+                                    +  Math.Abs(ap[10] - bp[10])
+                                    +  Math.Abs(ap[11] - bp[11])
+                                    +  Math.Abs(ap[12] - bp[12])
+                                    +  Math.Abs(ap[13] - bp[13])
+                                    +  Math.Abs(ap[14] - bp[14])
+                                    +  Math.Abs(ap[15] - bp[15])
+                                    +  Math.Abs(ap[16] - bp[16])
+                                    +  Math.Abs(ap[17] - bp[17])
+                                    +  Math.Abs(ap[18] - bp[18])
+                                    +  Math.Abs(ap[19] - bp[19])
+                                    +  Math.Abs(ap[20] - bp[20]);
+                                ap += 21;
+                                bp += 21;
+                                l -= 21;
+                            }
+                            while (l-- > 0) {
+                                sum +=  Math.Abs(*ap - *bp);
+                                ap++;
+                                bp++;
+                            }
+                            *cp++ = sum; 
+                        }
+                    } else {
+                        // dim = 1
+                        ap = (float*)range.Item2;
+                        bp = (float*)range.Item3;
+                        cp = (float*)range.Item4;
+                        for (int s = 0; s < range.Item1; s++) { // TODO: further potential speedup: unroll in s direction!
+                           
+                            float val = *bp++;
+                            int l = itLen;
+                            while (l > 10) {
+                                cp[0] +=  Math.Abs(ap[0] - val);
+                                cp[1] +=  Math.Abs(ap[1] - val);
+                                cp[2] +=  Math.Abs(ap[2] - val);
+                                cp[3] +=  Math.Abs(ap[3] - val);
+                                cp[4] +=  Math.Abs(ap[4] - val);
+                                cp[5] +=  Math.Abs(ap[5] - val);
+                                cp[6] +=  Math.Abs(ap[6] - val);
+                                cp[7] +=  Math.Abs(ap[7] - val);
+                                cp[8] +=  Math.Abs(ap[8] - val);
+                                cp[9] +=  Math.Abs(ap[9] - val);
+                                cp[10] +=  Math.Abs(ap[10] - val);
+                                cp[11] +=  Math.Abs(ap[11] - val);
+                                cp[12] +=  Math.Abs(ap[12] - val);
+                                cp[13] +=  Math.Abs(ap[13] - val);
+                                cp[14] +=  Math.Abs(ap[14] - val);
+                                cp[15] +=  Math.Abs(ap[15] - val);
+                                cp[16] +=  Math.Abs(ap[16] - val);
+                                cp[17] +=  Math.Abs(ap[17] - val);
+                                cp[18] +=  Math.Abs(ap[18] - val);
+                                cp[19] +=  Math.Abs(ap[19] - val);
+                                cp[20] +=  Math.Abs(ap[20] - val);
+                                ap += 21;
+                                cp += 21;
+                                l -= 21;
+                            }
+                            while (l-- > 0) {
+                                *cp +=  Math.Abs(*ap - val);
+                                ap++;
+                                cp++;
+                            }
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outDims.NumberOfElements >= Settings.s_minParallelElement1Count
+                    && outDims[1] > 1) {
+                        if (outDims[1] > workItemCount) {
+                        workItemLength = outDims[1] / workItemCount;
+                    } else {
+                        workItemLength = outDims[1] / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outDims[1];
+                    workItemCount = 1;
+                }
+
+                //int[] partResults = new int[workItemCount]; 
+                fixed ( float* arrAP = arrA)
+                fixed ( float* arrBP = arrB)
+                fixed ( float* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, IntPtr, IntPtr, IntPtr> range = new Tuple<int, IntPtr, IntPtr, IntPtr>
+                               (workItemLength
+                               , (IntPtr)(arrAP + i * outDims[0] * workItemLength)
+                               , (IntPtr)(arrBP + i * dim * workItemLength)
+                               , (IntPtr)(retArrP + i * workItemLength)); 
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, IntPtr, IntPtr, IntPtr>
+                                (outDims[1] - i * workItemLength
+                                , (IntPtr)(arrAP + i * outDims[0] * workItemLength)
+                                , (IntPtr)(arrBP + i * dim * workItemLength)
+                                , (IntPtr)(retArrP + i * workItemLength)));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<float>(retStorage);
+            }
+        }
+        /// <summary>
+        /// pairwise L1 distance 
+        /// </summary>
+        /// <param name="A">input points (matrix)</param>
+        /// <param name="B">input point (vector)</param>
+        /// <returns>pairwise L1 distances between the data point provided in the input vector <paramref name="B"/> and the data points stored in the matrix <paramref name="A"/>.</returns>
+        /// <remarks>
+        /// <para>If <paramref name="B"/> is a colum vector, the distances between <paramref name="B"/> and the columns of <paramref name="A"/> are calculated. The number of rows of <paramref name="A"/> 
+        /// must match the length of vector <paramref name="B"/> than. Therefore, the length of the returned vector of distances matches the number of columns of <paramref name="A"/>: <code>A.S[1]</code>.</para>
+        /// <para>If <paramref name="B"/> is a row vector, the distances between <paramref name="B"/> and the rows of <paramref name="A"/> are calculated. The number of columns of <paramref name="A"/> 
+        /// must match the length of vector <paramref name="B"/> than. Therefore, the length of the returned vector of distances matches the number of rows of <paramref name="A"/>: <code>A.S[0]</code>.</para>
+        /// <para>This function is cummulative, the single data point may be provided in <paramref name="A"/> and the data point matrix may be provided in <paramref name="B"/> as well.</para>
+        /// </remarks>
+        public static unsafe ILRetArray<fcomplex> distL1(ILInArray<fcomplex> A, ILInArray<fcomplex> B) {
+            using (ILScope.Enter(A, B)) {
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<fcomplex>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<fcomplex>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<fcomplex>(A.S);
+                }
+                // early exit: make the function cummutative
+                if (A.IsVector && !B.IsVector) {
+                    return distL1(B, A); 
+                } 
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                
+                dim = -(dim - 1);  // 0 -> 1, 1 -> 0
+                #endregion
+
+                #region parameter preparation
+                ILSize outDims; 
+                if (dim == 0) {
+                    outDims = size(1,A.S[1]);    
+                } else if (dim == 1) {
+                    outDims = size(A.S[0], 1);
+                } else if (A.S.IsSameSize(B.S)) {
+                    outDims = A.S;
+                    dim = 0; 
+                } else 
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+
+               
+                fcomplex[] retArr = ILMemoryPool.Pool.New<fcomplex>(outDims.NumberOfElements);
+
+               
+                fcomplex[] arrA = A.GetArrayForRead();
+
+               
+                fcomplex[] arrB = B.GetArrayForRead();
+                int itLen = A.S[0]; 
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<fcomplex> retStorage = new ILDenseStorage<fcomplex>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, IntPtr, IntPtr, IntPtr>)data;
+
+                   
+                    fcomplex* ap;
+
+                   
+                    fcomplex* bp;
+
+                   
+                    fcomplex* cp;
+                    if (dim == 0) {
+                        ap = (fcomplex*)range.Item2;
+                        cp = (fcomplex*)range.Item4;
+                        for (int s = 0; s < range.Item1; s++) {
+                            bp = (fcomplex*)range.Item3;
+                           
+                            fcomplex sum = 0; 
+                            int l = itLen;
+                            while (l > 20) {
+                                sum +=  fcomplex.Abs(ap[0] - bp[0])
+                                    +  fcomplex.Abs(ap[1] - bp[1])
+                                    +  fcomplex.Abs(ap[2] - bp[2])
+                                    +  fcomplex.Abs(ap[3] - bp[3])
+                                    +  fcomplex.Abs(ap[4] - bp[4])
+                                    +  fcomplex.Abs(ap[5] - bp[5])
+                                    +  fcomplex.Abs(ap[6] - bp[6])
+                                    +  fcomplex.Abs(ap[7] - bp[7])
+                                    +  fcomplex.Abs(ap[8] - bp[8])
+                                    +  fcomplex.Abs(ap[9] - bp[9])
+                                    +  fcomplex.Abs(ap[10] - bp[10])
+                                    +  fcomplex.Abs(ap[11] - bp[11])
+                                    +  fcomplex.Abs(ap[12] - bp[12])
+                                    +  fcomplex.Abs(ap[13] - bp[13])
+                                    +  fcomplex.Abs(ap[14] - bp[14])
+                                    +  fcomplex.Abs(ap[15] - bp[15])
+                                    +  fcomplex.Abs(ap[16] - bp[16])
+                                    +  fcomplex.Abs(ap[17] - bp[17])
+                                    +  fcomplex.Abs(ap[18] - bp[18])
+                                    +  fcomplex.Abs(ap[19] - bp[19])
+                                    +  fcomplex.Abs(ap[20] - bp[20]);
+                                ap += 21;
+                                bp += 21;
+                                l -= 21;
+                            }
+                            while (l-- > 0) {
+                                sum +=  fcomplex.Abs(*ap - *bp);
+                                ap++;
+                                bp++;
+                            }
+                            *cp++ = sum; 
+                        }
+                    } else {
+                        // dim = 1
+                        ap = (fcomplex*)range.Item2;
+                        bp = (fcomplex*)range.Item3;
+                        cp = (fcomplex*)range.Item4;
+                        for (int s = 0; s < range.Item1; s++) { // TODO: further potential speedup: unroll in s direction!
+                           
+                            fcomplex val = *bp++;
+                            int l = itLen;
+                            while (l > 10) {
+                                cp[0] +=  fcomplex.Abs(ap[0] - val);
+                                cp[1] +=  fcomplex.Abs(ap[1] - val);
+                                cp[2] +=  fcomplex.Abs(ap[2] - val);
+                                cp[3] +=  fcomplex.Abs(ap[3] - val);
+                                cp[4] +=  fcomplex.Abs(ap[4] - val);
+                                cp[5] +=  fcomplex.Abs(ap[5] - val);
+                                cp[6] +=  fcomplex.Abs(ap[6] - val);
+                                cp[7] +=  fcomplex.Abs(ap[7] - val);
+                                cp[8] +=  fcomplex.Abs(ap[8] - val);
+                                cp[9] +=  fcomplex.Abs(ap[9] - val);
+                                cp[10] +=  fcomplex.Abs(ap[10] - val);
+                                cp[11] +=  fcomplex.Abs(ap[11] - val);
+                                cp[12] +=  fcomplex.Abs(ap[12] - val);
+                                cp[13] +=  fcomplex.Abs(ap[13] - val);
+                                cp[14] +=  fcomplex.Abs(ap[14] - val);
+                                cp[15] +=  fcomplex.Abs(ap[15] - val);
+                                cp[16] +=  fcomplex.Abs(ap[16] - val);
+                                cp[17] +=  fcomplex.Abs(ap[17] - val);
+                                cp[18] +=  fcomplex.Abs(ap[18] - val);
+                                cp[19] +=  fcomplex.Abs(ap[19] - val);
+                                cp[20] +=  fcomplex.Abs(ap[20] - val);
+                                ap += 21;
+                                cp += 21;
+                                l -= 21;
+                            }
+                            while (l-- > 0) {
+                                *cp +=  fcomplex.Abs(*ap - val);
+                                ap++;
+                                cp++;
+                            }
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outDims.NumberOfElements >= Settings.s_minParallelElement1Count
+                    && outDims[1] > 1) {
+                        if (outDims[1] > workItemCount) {
+                        workItemLength = outDims[1] / workItemCount;
+                    } else {
+                        workItemLength = outDims[1] / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outDims[1];
+                    workItemCount = 1;
+                }
+
+                //int[] partResults = new int[workItemCount]; 
+                fixed ( fcomplex* arrAP = arrA)
+                fixed ( fcomplex* arrBP = arrB)
+                fixed ( fcomplex* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, IntPtr, IntPtr, IntPtr> range = new Tuple<int, IntPtr, IntPtr, IntPtr>
+                               (workItemLength
+                               , (IntPtr)(arrAP + i * outDims[0] * workItemLength)
+                               , (IntPtr)(arrBP + i * dim * workItemLength)
+                               , (IntPtr)(retArrP + i * workItemLength)); 
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, IntPtr, IntPtr, IntPtr>
+                                (outDims[1] - i * workItemLength
+                                , (IntPtr)(arrAP + i * outDims[0] * workItemLength)
+                                , (IntPtr)(arrBP + i * dim * workItemLength)
+                                , (IntPtr)(retArrP + i * workItemLength)));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<fcomplex>(retStorage);
+            }
+        }
+        /// <summary>
+        /// pairwise L1 distance 
+        /// </summary>
+        /// <param name="A">input points (matrix)</param>
+        /// <param name="B">input point (vector)</param>
+        /// <returns>pairwise L1 distances between the data point provided in the input vector <paramref name="B"/> and the data points stored in the matrix <paramref name="A"/>.</returns>
+        /// <remarks>
+        /// <para>If <paramref name="B"/> is a colum vector, the distances between <paramref name="B"/> and the columns of <paramref name="A"/> are calculated. The number of rows of <paramref name="A"/> 
+        /// must match the length of vector <paramref name="B"/> than. Therefore, the length of the returned vector of distances matches the number of columns of <paramref name="A"/>: <code>A.S[1]</code>.</para>
+        /// <para>If <paramref name="B"/> is a row vector, the distances between <paramref name="B"/> and the rows of <paramref name="A"/> are calculated. The number of columns of <paramref name="A"/> 
+        /// must match the length of vector <paramref name="B"/> than. Therefore, the length of the returned vector of distances matches the number of rows of <paramref name="A"/>: <code>A.S[0]</code>.</para>
+        /// <para>This function is cummulative, the single data point may be provided in <paramref name="A"/> and the data point matrix may be provided in <paramref name="B"/> as well.</para>
+        /// </remarks>
+        public static unsafe ILRetArray<complex> distL1(ILInArray<complex> A, ILInArray<complex> B) {
+            using (ILScope.Enter(A, B)) {
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<complex>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<complex>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<complex>(A.S);
+                }
+                // early exit: make the function cummutative
+                if (A.IsVector && !B.IsVector) {
+                    return distL1(B, A); 
+                } 
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                
+                dim = -(dim - 1);  // 0 -> 1, 1 -> 0
+                #endregion
+
+                #region parameter preparation
+                ILSize outDims; 
+                if (dim == 0) {
+                    outDims = size(1,A.S[1]);    
+                } else if (dim == 1) {
+                    outDims = size(A.S[0], 1);
+                } else if (A.S.IsSameSize(B.S)) {
+                    outDims = A.S;
+                    dim = 0; 
+                } else 
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+
+               
+                complex[] retArr = ILMemoryPool.Pool.New<complex>(outDims.NumberOfElements);
+
+               
+                complex[] arrA = A.GetArrayForRead();
+
+               
+                complex[] arrB = B.GetArrayForRead();
+                int itLen = A.S[0]; 
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<complex> retStorage = new ILDenseStorage<complex>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, IntPtr, IntPtr, IntPtr>)data;
+
+                   
+                    complex* ap;
+
+                   
+                    complex* bp;
+
+                   
+                    complex* cp;
+                    if (dim == 0) {
+                        ap = (complex*)range.Item2;
+                        cp = (complex*)range.Item4;
+                        for (int s = 0; s < range.Item1; s++) {
+                            bp = (complex*)range.Item3;
+                           
+                            complex sum = 0; 
+                            int l = itLen;
+                            while (l > 20) {
+                                sum +=  complex.Abs(ap[0] - bp[0])
+                                    +  complex.Abs(ap[1] - bp[1])
+                                    +  complex.Abs(ap[2] - bp[2])
+                                    +  complex.Abs(ap[3] - bp[3])
+                                    +  complex.Abs(ap[4] - bp[4])
+                                    +  complex.Abs(ap[5] - bp[5])
+                                    +  complex.Abs(ap[6] - bp[6])
+                                    +  complex.Abs(ap[7] - bp[7])
+                                    +  complex.Abs(ap[8] - bp[8])
+                                    +  complex.Abs(ap[9] - bp[9])
+                                    +  complex.Abs(ap[10] - bp[10])
+                                    +  complex.Abs(ap[11] - bp[11])
+                                    +  complex.Abs(ap[12] - bp[12])
+                                    +  complex.Abs(ap[13] - bp[13])
+                                    +  complex.Abs(ap[14] - bp[14])
+                                    +  complex.Abs(ap[15] - bp[15])
+                                    +  complex.Abs(ap[16] - bp[16])
+                                    +  complex.Abs(ap[17] - bp[17])
+                                    +  complex.Abs(ap[18] - bp[18])
+                                    +  complex.Abs(ap[19] - bp[19])
+                                    +  complex.Abs(ap[20] - bp[20]);
+                                ap += 21;
+                                bp += 21;
+                                l -= 21;
+                            }
+                            while (l-- > 0) {
+                                sum +=  complex.Abs(*ap - *bp);
+                                ap++;
+                                bp++;
+                            }
+                            *cp++ = sum; 
+                        }
+                    } else {
+                        // dim = 1
+                        ap = (complex*)range.Item2;
+                        bp = (complex*)range.Item3;
+                        cp = (complex*)range.Item4;
+                        for (int s = 0; s < range.Item1; s++) { // TODO: further potential speedup: unroll in s direction!
+                           
+                            complex val = *bp++;
+                            int l = itLen;
+                            while (l > 10) {
+                                cp[0] +=  complex.Abs(ap[0] - val);
+                                cp[1] +=  complex.Abs(ap[1] - val);
+                                cp[2] +=  complex.Abs(ap[2] - val);
+                                cp[3] +=  complex.Abs(ap[3] - val);
+                                cp[4] +=  complex.Abs(ap[4] - val);
+                                cp[5] +=  complex.Abs(ap[5] - val);
+                                cp[6] +=  complex.Abs(ap[6] - val);
+                                cp[7] +=  complex.Abs(ap[7] - val);
+                                cp[8] +=  complex.Abs(ap[8] - val);
+                                cp[9] +=  complex.Abs(ap[9] - val);
+                                cp[10] +=  complex.Abs(ap[10] - val);
+                                cp[11] +=  complex.Abs(ap[11] - val);
+                                cp[12] +=  complex.Abs(ap[12] - val);
+                                cp[13] +=  complex.Abs(ap[13] - val);
+                                cp[14] +=  complex.Abs(ap[14] - val);
+                                cp[15] +=  complex.Abs(ap[15] - val);
+                                cp[16] +=  complex.Abs(ap[16] - val);
+                                cp[17] +=  complex.Abs(ap[17] - val);
+                                cp[18] +=  complex.Abs(ap[18] - val);
+                                cp[19] +=  complex.Abs(ap[19] - val);
+                                cp[20] +=  complex.Abs(ap[20] - val);
+                                ap += 21;
+                                cp += 21;
+                                l -= 21;
+                            }
+                            while (l-- > 0) {
+                                *cp +=  complex.Abs(*ap - val);
+                                ap++;
+                                cp++;
+                            }
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outDims.NumberOfElements >= Settings.s_minParallelElement1Count
+                    && outDims[1] > 1) {
+                        if (outDims[1] > workItemCount) {
+                        workItemLength = outDims[1] / workItemCount;
+                    } else {
+                        workItemLength = outDims[1] / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outDims[1];
+                    workItemCount = 1;
+                }
+
+                //int[] partResults = new int[workItemCount]; 
+                fixed ( complex* arrAP = arrA)
+                fixed ( complex* arrBP = arrB)
+                fixed ( complex* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, IntPtr, IntPtr, IntPtr> range = new Tuple<int, IntPtr, IntPtr, IntPtr>
+                               (workItemLength
+                               , (IntPtr)(arrAP + i * outDims[0] * workItemLength)
+                               , (IntPtr)(arrBP + i * dim * workItemLength)
+                               , (IntPtr)(retArrP + i * workItemLength)); 
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, IntPtr, IntPtr, IntPtr>
+                                (outDims[1] - i * workItemLength
+                                , (IntPtr)(arrAP + i * outDims[0] * workItemLength)
+                                , (IntPtr)(arrBP + i * dim * workItemLength)
+                                , (IntPtr)(retArrP + i * workItemLength)));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<complex>(retStorage);
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/eig.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/eig.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/eig.cs	(revision 9102)
@@ -0,0 +1,1921 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions;
+
+
+
+namespace ILNumerics {
+    public partial class ILMath {
+
+
+        
+        /// <summary>
+        /// Compute eigenvalues of general square matrix A
+        /// </summary>
+        /// <param name="A">Input matrix A. Size [n x n]</param>
+        /// <returns>Vector of eigenvalues of A. Size [n x 1]</returns>
+        /// <remarks><para>The eigenvalues of A are found by use of the Lapack functions dgeevx, sgeevx, cgeevx and zgeevx. </para>
+        /// <para>The vector returned will be of complex inner type, since no further constraints are set on the structure of A (it may be nonsymmetric). Use <see cref="ILNumerics.ILMath.eigSymm(ILInArray&lt;double&gt;)"/> or <see cref="ILNumerics.ILMath.eigSymm(ILInArray&lt;double&gt;,ILOutArray&lt;double&gt;)"/> functions for computing the real eigenvalues of symmetric matrices explicitly.</para>
+        /// <para>A will be balanced first. This includes permutations and scaling of A in order to improve the conditioning of the eigenvalues.</para></remarks>
+        /// <seealso cref="ILNumerics.ILMath.eig(ILInArray&lt;double&gt;,ILOutArray&lt;complex&gt;)"/>
+        /// <seealso cref="ILNumerics.ILMath.eig(ILInArray&lt;double&gt;,ILOutArray&lt;complex&gt;,ref MatrixProperties,bool)"/>
+        public static ILRetArray< complex > eig(ILInArray< double > A) {
+            using (ILScope.Enter(A)) {
+                ILArray< complex> V = null;
+                MatrixProperties props = MatrixProperties.None;
+                return eig(A, V, ref props, true);
+            }
+        }
+        /// <summary>
+        /// Compute eigenvalues and eigenvectors of general square matrix A
+        /// </summary>
+        /// <param name="A">Input matrix A. Size [n x n]</param>
+        /// <param name="V">Output matrix, eigenvectors EV of size [n x n]. May be null on input. If not null, content of V will be destroyed.</param>
+        /// <returns>Diagonal matrix with eigenvalues of A. Size [n x n]</returns>
+        /// <remarks><para>The eigenvalues of A are found by use of the Lapack functions dgeevx, sgeevx, cgeevx and zgeevx. </para>
+        /// <para>The matrices returned will be of complex inner type, since no further constrains are set on the structure of A (it may be nonsymmetric). Use <see cref="ILNumerics.ILMath.eigSymm(ILInArray&lt;double&gt;)"/> or <see cref="ILNumerics.ILMath.eigSymm(ILInArray&lt;double&gt;,ILOutArray&lt;double&gt;)"/> functions for computing the real eigenvalues of symmetric matrices explicitly.</para>
+        /// <para>A will be balanced first. This includes permutations and scaling of A in order to improve the conditioning of the eigenvalues.</para></remarks>
+        /// <seealso cref="ILNumerics.ILMath.eig(ILInArray&lt;double&gt;)"/>
+        /// <seealso cref="ILNumerics.ILMath.eig(ILInArray&lt;double&gt;,ILOutArray&lt;complex&gt;,ref MatrixProperties,bool)"/>
+        public static ILRetArray< complex > eig(ILInArray< double > A, ILOutArray< complex > V) {
+            MatrixProperties props = MatrixProperties.None; 
+            return eig(A, V, ref props, true); 
+        }
+        /// <summary>
+        /// Find eigenvalues  and eigenvectors 
+        /// </summary>
+        /// <param name="A">Input: square matrix, size [n x n]</param>
+        /// <param name="V">Output (optional): eigenvectors</param>   
+        /// <param name="propsA">Matrix properties, on input - if specified, 
+        /// will be used to choose the proper method of solution. On exit will be 
+        /// filled according to the properties of A.</param>
+        /// <param name="balance">true: permute A in order to increase the 
+        /// numerical stability, false: do not permute A.</param>
+        /// <returns>eigenvalues as vector (if V is null) or as diagonoal 
+        /// matrix (if V was requested, i.e. not null).</returns>
+        /// <remarks><para>The eigenvalues of A are found by use of the 
+        /// Lapack functions dgeevx, sgeevx, cgeevx and zgeevx. </para>
+        /// <para>The arrays returned will be of complex inner type, 
+        /// since no further constraints are set on the structure of 
+        /// A (it may be nonsymmetric). Use 
+        /// <see cref="ILNumerics.ILMath.eigSymm(ILInArray&lt;double&gt;)"/> 
+        /// or <see cref="ILNumerics.ILMath.eigSymm(ILInArray&lt;double&gt;,ILOutArray&lt;double&gt;)"/> 
+        /// functions for computing the real eigenvalues of symmetric 
+        /// matrices explicitly.</para>
+        /// <para>Depending on the parameter <paramref name="balance"/>, 
+        /// A will be balanced first. This includes permutations and 
+        /// scaling of A in order to improve the conditioning of the 
+        /// eigenvalues.</para></remarks>
+        /// <seealso cref="ILNumerics.ILMath.eig(ILInArray&lt;double&gt;)"/>
+        /// <seealso cref="ILNumerics.ILMath.eig(ILInArray&lt;double&gt;,ILOutArray&lt;complex&gt;,ref MatrixProperties,bool)"/>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if a 
+        /// is not square</exception>
+        public static ILRetArray< complex > eig(ILInArray< double > A, ILOutArray< complex > V, ref MatrixProperties propsA, bool balance) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    if (!object.Equals(V,null))
+                        V.a = empty<complex>(A.Size); 
+                    return  empty<complex>(A.Size); 
+                }
+                ILArray< complex > ret = empty< complex >(ILSize.Empty00);  
+                int n = A.Size[0]; 
+                bool createVR = (object.Equals(V,null))? false:true; 
+                if (n != A.Size[1]) 
+                    throw new ILArgumentException("eig: matrix A must be square");
+                propsA |= MatrixProperties.Square; 
+                if (((propsA & MatrixProperties.Hermitian) != 0 || ILMath.ishermitian(A.C))) {
+                    propsA |= MatrixProperties.Hermitian; 
+                    ILArray< double > Vd = null; 
+                    if (createVR) 
+                        Vd = returnType< double >();
+                    ILArray< double > tmpRet = eigSymm(A,Vd);
+                    if (createVR)
+                        V.a =  ILMath.tocomplex (Vd); 
+                    ret =  ILMath.tocomplex (tmpRet);
+                } else {
+                    // nonsymmetric case
+                    char bal = (balance)? 'B':'N', jobvr;  
+                    ILRetArray< double > tmpA = A.C; 
+                     double [] vr = null;
+                     double [] wr = ILMemoryPool.Pool.New< double >(n); 
+                     
+                    double[] wi = ILMemoryPool.Pool.New<double>(n); 
+                     double [] scale  = ILMemoryPool.Pool.New< double >(n);
+                     double [] rconde = ILMemoryPool.Pool.New< double >(n); 
+                     double [] rcondv = ILMemoryPool.Pool.New< double >(n); 
+                     double abnrm = 0; 
+                    int ldvr, ilo = 0, ihi = 0, info = 0;
+                    if (createVR) {
+                        ldvr = n;
+                        vr = ILMemoryPool.Pool.New< double >(n * n);
+                        jobvr = 'V'; 
+                    } else {
+                        ldvr = 1; 
+                        vr = new  double [1]; 
+                        jobvr = 'N'; 
+                    }
+                    /*!HC:HC?geevx*/
+                    Lapack.dgeevx(bal,'N',jobvr,'N',n,tmpA.GetArrayForWrite(),n,wr,wi,new  double [1],1,vr,ldvr,ref ilo,ref ihi,scale,ref abnrm,rconde,rcondv,ref info);   
+                    ILMemoryPool.Pool.Free(rconde);
+                    ILMemoryPool.Pool.Free(rcondv);
+                    ILMemoryPool.Pool.Free(scale);
+                    if (info != 0) 
+                        throw new ILArgumentException("eig: error in Lapack '?geevx': (" + info + ")");
+                    // create eigenvalues 
+                     complex [] retArr = ILMemoryPool.Pool.New< complex >(n); 
+                    for (int i = 0; i < n; i++) {
+                        
+                        retArr[i].real = wr[i]; retArr[i].imag = wi[i]; 
+                    }
+                    ret = new ILArray< complex > (retArr,n,1);
+                    if (createVR) {
+                        #region HCSortEVec
+                        complex [] VArr = ILMemoryPool.Pool.New< complex >(n * n);
+                        for (int c = 0; c < n; c++) {
+                            if (wi[c] != 0 && wi[c+1] != 0 && c < n-1) {
+                                ilo = n * c; ihi = ilo + n;
+                                for (int r = 0; r < n; r++) {
+                                    VArr[ilo].real = vr[ilo];
+                                    VArr[ilo].imag = vr[ihi];  
+                                    VArr[ihi].real = vr[ilo];  
+                                    VArr[ihi].imag = -vr[ihi]; 
+                                    ilo++; ihi++; 
+                                }
+                                c++; 
+                            } else {
+                                ilo = n * c;
+                                for (int r = 0; r < n; r++) {
+                                    VArr[ilo].real = vr[ilo];
+                                    ilo++; 
+                                }
+                            }
+                        }
+                        V.a = array<complex> (VArr,n,n); 
+                        #endregion HYCALPER
+                        if (createVR)
+                            ret.a = ILMath.diag< complex>(ret); 
+                    }
+                    
+                    ILMemoryPool.Pool.Free(wi); 
+                    ILMemoryPool.Pool.Free(vr); 
+                    ILMemoryPool.Pool.Free(wr); 
+                }
+                return ret; 
+            }
+        }
+
+        /// <summary>
+        /// Find all eigenvalues of symmetric (hermitian) matrix
+        /// </summary>
+        /// <param name="A">Input matrix, Size [n x n], symmetric (hermitian for complex A) </param> 
+        /// <returns>Array of size [n,1] with eigenvalues of A.</returns>
+        /// <remarks><para>For computation the Lapack functions dsyevr, ssyevr, chesvr and zheesv are used. </para>
+        /// <para>Since A is symmetric, the eigenvalues will always be real. Therefore the return value will be of the same inner type as A.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A is not square.</exception>
+        public static ILRetArray< double > eigSymm (ILInArray< double > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    return empty< double>(A.Size); 
+                }
+                int n = A.Size[0]; 
+                if (n != A.Size[1])
+                    throw new ILArgumentException("input matrix A must be square and symmetric/hermitian.");
+                int m = 0,info = 0; 
+                ILArray< double > w = new ILArray< double > (new  double [n],1,n); 
+                 double [] z = new  double [1]; ; 
+                int [] isuppz = new int[2 * n];
+                 double [] AcArr = A.C.GetArrayForWrite(); 
+                /*!HC:lapack_???evr*/ Lapack.dsyevr ('N','A','U',n,AcArr,n,0,0,0,0,0,ref m,w.GetArrayForWrite(),z,1,isuppz,ref info);
+                ILMemoryPool.Pool.Free(AcArr); 
+                return  /*dummy*/ (w); 
+            }
+        }
+        /// <summary>
+        /// Find all eigenvalues and -vectors of symmetric (hermitian) matrix
+        /// </summary>
+        /// <param name="A">Input matrix, Size [n x n], symmetric (hermitian for complex A) </param> 
+        /// <param name="V">Output: n eigenvectors as columns. Size [n x n]. If V is null on input, the eigenvectors 
+        /// will not be computed and V is not changed. In order to make the function return the vectors, V should be initiialized with ILMath.returnType before calling eigSymm.</param>
+        /// <returns>Diagonal matrix of size [n,n] with eigenvalues of A on the main diagonal.</returns>
+        /// <remarks><para>For computation the Lapack functions dsyevr, ssyevr, chesvr and zheesv are used. </para>
+        /// <para>Since A is symmetric, the eigenvalues will always be real. Therefore the return value will be of the same inner type as A.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A is not square.</exception>
+        public static ILRetArray< double > eigSymm (ILInArray< double > A, ILOutArray< double > V) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    if (!object.Equals(V,null))
+                        V.a = empty<double>(A.Size); 
+                    return empty<double>(A.Size); 
+                }
+                int n = A.Size[0]; 
+                if (n != A.Size[1])
+                    throw new ILArgumentException("input matrix A must be square and symmetric/hermitian.");
+                int m = 0,ldz = 0,info = 0; 
+                ILArray< double > w = new ILArray< double >(ILMemoryPool.Pool.New< double >(n),n,1); 
+                 double [] z; 
+                char jobz;
+                if (object.Equals(V,null)) {
+                    z = new  double [1]; 
+                    jobz = 'N';
+                    ldz = 1; 
+                } else {
+                    z = ILMemoryPool.Pool.New<  double >(n * n);
+                    jobz = 'V';
+                    ldz = n; 
+                } 
+                int [] isuppz = ILMemoryPool.Pool.New<int>( 2 * n);
+                 double [] AcArr = A.C.GetArrayForWrite(); 
+                /*!HC:lapack_???evr*/ Lapack.dsyevr (jobz,'A','U',n,AcArr,n,1,n,0,0,0,ref m,w.GetArrayForWrite(),z,ldz,isuppz,ref info);
+                ILMemoryPool.Pool.Free(AcArr); 
+                ILMemoryPool.Pool.Free(isuppz);
+                if (info != 0) 
+                    throw new ILException("error returned from lapack: " + info); 
+                if (jobz == 'V') {
+                    System.Diagnostics.Debug.Assert(!object.Equals(V,null));
+                    V.a =  array< double > (z,n,n);
+                    V.a = V[full,r(0,m-1)]; 
+                    return ILMath.diag( /*dummy*/ (w)); 
+                } else {
+                    ILMemoryPool.Pool.Free(z); 
+                    return  /*dummy*/ (w);
+                }
+            }
+        }
+        /// <summary>
+        /// Find some eigenvalues and -vectors of symmetric (hermitian) matrix
+        /// </summary>
+        /// <param name="A">Input matrix, Size [n x n], symmetric (hermitian for complex A) </param> 
+        /// <param name="V">Output: n eigenvectors as columns. Size [n x n]. If V is null on input, the eigenvectors will not be computed and V is not changed. </param>
+        /// <param name="rangeStart">Specify the lowest limit for the range of eigenvalues to be queried.</param>
+        /// <param name="rangeEnd">Specify the upper limit for the range of eigenvalues to be queried.</param>
+        /// <returns>Diagonal matrix of size [n,n] with eigenvalues of A on the main diagonal.</returns>
+        /// <remarks><para>For computation the Lapack functions dsyevr, ssyevr, chesvr and zheesv are used. </para>
+        /// <para>Since A is symmetric, the eigenvalues will always be real. Therefore the return value will be of the same inner type as A.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A is not square or <paramref name="rangeEnd"/> &lt; <paramref name="rangeStart"/></exception>
+        public static ILRetArray< double > eigSymm (ILInArray< double > A, ILOutArray< double > V, int rangeStart, int rangeEnd) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    if (!object.Equals(V,null))
+                        V.a = empty<double>(A.Size); 
+                    return empty<double>(A.Size); 
+                }
+                int n = A.Size[0]; 
+                if (n != A.Size[1])
+                    throw new ILArgumentException("input matrix A must be square and symmetric/hermitian.");
+                int m = 0,ldz = 0,info = 0; 
+                if (rangeEnd < rangeStart || rangeStart < 1) 
+                    throw new ILArgumentException("invalid range of eigenvalues requested");
+                ILArray< double > w = array< double > (
+                                            ILMemoryPool.Pool.New< double>(n),1,n); 
+                 double [] z; 
+                char jobz;
+                if (object.Equals(V,null)) {
+                    z = new  double [1]; 
+                    jobz = 'N';
+                    ldz = 1; 
+                } else {
+                    z = ILMemoryPool.Pool.New<double>(n * n);
+                    jobz = 'V';
+                    ldz = n; 
+                } 
+                int [] isuppz = ILMemoryPool.Pool.New<int>(2 * n);
+                 double [] AcArr = A.C.GetArrayForWrite(); 
+                /*!HC:lapack_???evr*/ Lapack.dsyevr (jobz,'I','U',n,AcArr,n,0,0,rangeStart,rangeEnd,0,ref m,w.GetArrayForWrite(),z,ldz,isuppz,ref info);
+                ILMemoryPool.Pool.Free(isuppz); 
+                ILMemoryPool.Pool.Free(AcArr); 
+
+                if (jobz == 'V') {
+                    V.a = array<  double >(z,n,n);
+                    V.a = V[full,r(0,m-1)]; 
+                }
+                ILMemoryPool.Pool.Free(z); 
+                return ILMath.diag( /*dummy*/ (w)); 
+            }
+        }
+        /// <summary>
+        /// Find some eigenvalues and -vectors of symmetric (hermitian) matrix
+        /// </summary>
+        /// <param name="A">Input matrix, Size [n x n], symmetric (hermitian for complex A) </param> 
+        /// <param name="V">Output: n eigenvectors as columns. Size [n x n]. If V is null on input, the eigenvectors will not be computed and V is not changed. </param>
+        /// <param name="rangeStart">The eigenvalues will be returned by increasing size. This will determine the number of the first eigenvalue to be returned.</param>
+        /// <param name="rangeEnd">Determine the number of the last eigenvalue to be returned.</param>
+        /// <returns>Diagonal matrix of size [n,n] with eigenvalues of A on the main diagonal.</returns>
+        /// <remarks><para>For computation the Lapack functions dsyevr, ssyevr, chesvr and zheesv are used. </para>
+        /// <para>Since A is symmetric, the eigenvalues will always be real. Therefore the return value will be of the same inner type as A.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A is not square or <paramref name="rangeEnd"/> &lt; <paramref name="rangeStart"/> or if either one is &lt;= 0.</exception>
+        public static ILRetArray< double> eigSymm( ILInArray< double> A, ILOutArray< double> V,  double rangeStart,  double rangeEnd ) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    if (!object.Equals(V, null))
+                        V.a = empty<double>(A.Size);
+                    return empty<double>(A.Size);
+                }
+                int n = A.Size[0];
+                if (n != A.Size[1])
+                    throw new ILArgumentException("input matrix A must be square and symmetric/hermitian");
+                int m = 0, ldz = 0, info = 0;
+                if (rangeStart > rangeEnd)
+                    throw new ILArgumentException("invalid range of eigenvalues requested");
+                ILArray< double> w = zeros<double>(1, n);
+                
+                double[] z;
+                char jobz;
+                if (object.Equals(V, null)) {
+                    z = new  double[1];
+                    jobz = 'N';
+                    ldz = 1;
+                } else {
+                    z = ILMemoryPool.Pool.New<double>(n * n);
+                    jobz = 'V';
+                    ldz = n;
+                }
+                int[] isuppz = ILMemoryPool.Pool.New<int>(2 * n);
+
+                
+                double[] AcArr = A.C.GetArrayForWrite();
+                /*!HC:lapack_???evr*/
+                Lapack.dsyevr(jobz, 'V', 'U', n, AcArr, n, rangeStart, rangeEnd, 0, 0, 0, ref m, w.GetArrayForWrite(), z, ldz, isuppz, ref info);
+                ILMemoryPool.Pool.Free(AcArr);
+                ILMemoryPool.Pool.Free(isuppz);
+
+                if (jobz == 'V') {
+                    V.a = array< double>(z, n, n);
+                    V.a = V[full, r(0, m - 1)];
+                }
+                ILMemoryPool.Pool.Free(z);
+                return diag( /*dummy*/ (w));
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+        
+        /// <summary>
+        /// Compute eigenvalues of general square matrix A
+        /// </summary>
+        /// <param name="A">Input matrix A. Size [n x n]</param>
+        /// <returns>Vector of eigenvalues of A. Size [n x 1]</returns>
+        /// <remarks><para>The eigenvalues of A are found by use of the Lapack functions dgeevx, sgeevx, cgeevx and zgeevx. </para>
+        /// <para>The vector returned will be of complex inner type, since no further constraints are set on the structure of A (it may be nonsymmetric). Use <see cref="ILNumerics.ILMath.eigSymm(ILInArray&lt;double&gt;)"/> or <see cref="ILNumerics.ILMath.eigSymm(ILInArray&lt;double&gt;,ILOutArray&lt;double&gt;)"/> functions for computing the real eigenvalues of symmetric matrices explicitly.</para>
+        /// <para>A will be balanced first. This includes permutations and scaling of A in order to improve the conditioning of the eigenvalues.</para></remarks>
+        /// <seealso cref="ILNumerics.ILMath.eig(ILInArray&lt;double&gt;,ILOutArray&lt;complex&gt;)"/>
+        /// <seealso cref="ILNumerics.ILMath.eig(ILInArray&lt;double&gt;,ILOutArray&lt;complex&gt;,ref MatrixProperties,bool)"/>
+        public static ILRetArray< fcomplex > eig(ILInArray< float > A) {
+            using (ILScope.Enter(A)) {
+                ILArray< fcomplex> V = null;
+                MatrixProperties props = MatrixProperties.None;
+                return eig(A, V, ref props, true);
+            }
+        }
+        /// <summary>
+        /// Compute eigenvalues and eigenvectors of general square matrix A
+        /// </summary>
+        /// <param name="A">Input matrix A. Size [n x n]</param>
+        /// <param name="V">Output matrix, eigenvectors EV of size [n x n]. May be null on input. If not null, content of V will be destroyed.</param>
+        /// <returns>Diagonal matrix with eigenvalues of A. Size [n x n]</returns>
+        /// <remarks><para>The eigenvalues of A are found by use of the Lapack functions dgeevx, sgeevx, cgeevx and zgeevx. </para>
+        /// <para>The matrices returned will be of complex inner type, since no further constrains are set on the structure of A (it may be nonsymmetric). Use <see cref="ILNumerics.ILMath.eigSymm(ILInArray&lt;double&gt;)"/> or <see cref="ILNumerics.ILMath.eigSymm(ILInArray&lt;double&gt;,ILOutArray&lt;double&gt;)"/> functions for computing the real eigenvalues of symmetric matrices explicitly.</para>
+        /// <para>A will be balanced first. This includes permutations and scaling of A in order to improve the conditioning of the eigenvalues.</para></remarks>
+        /// <seealso cref="ILNumerics.ILMath.eig(ILInArray&lt;double&gt;)"/>
+        /// <seealso cref="ILNumerics.ILMath.eig(ILInArray&lt;double&gt;,ILOutArray&lt;complex&gt;,ref MatrixProperties,bool)"/>
+        public static ILRetArray< fcomplex > eig(ILInArray< float > A, ILOutArray< fcomplex > V) {
+            MatrixProperties props = MatrixProperties.None; 
+            return eig(A, V, ref props, true); 
+        }
+        /// <summary>
+        /// Find eigenvalues  and eigenvectors 
+        /// </summary>
+        /// <param name="A">Input: square matrix, size [n x n]</param>
+        /// <param name="V">Output (optional): eigenvectors</param>   
+        /// <param name="propsA">Matrix properties, on input - if specified, 
+        /// will be used to choose the proper method of solution. On exit will be 
+        /// filled according to the properties of A.</param>
+        /// <param name="balance">true: permute A in order to increase the 
+        /// numerical stability, false: do not permute A.</param>
+        /// <returns>eigenvalues as vector (if V is null) or as diagonoal 
+        /// matrix (if V was requested, i.e. not null).</returns>
+        /// <remarks><para>The eigenvalues of A are found by use of the 
+        /// Lapack functions dgeevx, sgeevx, cgeevx and zgeevx. </para>
+        /// <para>The arrays returned will be of complex inner type, 
+        /// since no further constraints are set on the structure of 
+        /// A (it may be nonsymmetric). Use 
+        /// <see cref="ILNumerics.ILMath.eigSymm(ILInArray&lt;double&gt;)"/> 
+        /// or <see cref="ILNumerics.ILMath.eigSymm(ILInArray&lt;double&gt;,ILOutArray&lt;double&gt;)"/> 
+        /// functions for computing the real eigenvalues of symmetric 
+        /// matrices explicitly.</para>
+        /// <para>Depending on the parameter <paramref name="balance"/>, 
+        /// A will be balanced first. This includes permutations and 
+        /// scaling of A in order to improve the conditioning of the 
+        /// eigenvalues.</para></remarks>
+        /// <seealso cref="ILNumerics.ILMath.eig(ILInArray&lt;double&gt;)"/>
+        /// <seealso cref="ILNumerics.ILMath.eig(ILInArray&lt;double&gt;,ILOutArray&lt;complex&gt;,ref MatrixProperties,bool)"/>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if a 
+        /// is not square</exception>
+        public static ILRetArray< fcomplex > eig(ILInArray< float > A, ILOutArray< fcomplex > V, ref MatrixProperties propsA, bool balance) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    if (!object.Equals(V,null))
+                        V.a = empty<fcomplex>(A.Size); 
+                    return  empty<fcomplex>(A.Size); 
+                }
+                ILArray< fcomplex > ret = empty< fcomplex >(ILSize.Empty00);  
+                int n = A.Size[0]; 
+                bool createVR = (object.Equals(V,null))? false:true; 
+                if (n != A.Size[1]) 
+                    throw new ILArgumentException("eig: matrix A must be square");
+                propsA |= MatrixProperties.Square; 
+                if (((propsA & MatrixProperties.Hermitian) != 0 || ILMath.ishermitian(A.C))) {
+                    propsA |= MatrixProperties.Hermitian; 
+                    ILArray< float > Vd = null; 
+                    if (createVR) 
+                        Vd = returnType< float >();
+                    ILArray< float > tmpRet = eigSymm(A,Vd);
+                    if (createVR)
+                        V.a =  ILMath.tofcomplex (Vd); 
+                    ret =  ILMath.tofcomplex (tmpRet);
+                } else {
+                    // nonsymmetric case
+                    char bal = (balance)? 'B':'N', jobvr;  
+                    ILRetArray< float > tmpA = A.C; 
+                    float [] vr = null;
+                    float [] wr = ILMemoryPool.Pool.New< float >(n); 
+                    float[] wi = ILMemoryPool.Pool.New< float>(n);
+                    float [] scale  = ILMemoryPool.Pool.New< float >(n);
+                    float [] rconde = ILMemoryPool.Pool.New< float >(n); 
+                    float [] rcondv = ILMemoryPool.Pool.New< float >(n); 
+                    float abnrm = 0; 
+                    int ldvr, ilo = 0, ihi = 0, info = 0;
+                    if (createVR) {
+                        ldvr = n;
+                        vr = ILMemoryPool.Pool.New< float >(n * n);
+                        jobvr = 'V'; 
+                    } else {
+                        ldvr = 1; 
+                        vr = new  float [1]; 
+                        jobvr = 'N'; 
+                    }
+                    Lapack.sgeevx(bal,'N',jobvr,'N',n,tmpA.GetArrayForWrite(),n,wr,wi,new float   [1],1,vr,ldvr,ref ilo,ref ihi,scale,ref abnrm,rconde,rcondv,ref info);   
+                    ILMemoryPool.Pool.Free(rconde);
+                    ILMemoryPool.Pool.Free(rcondv);
+                    ILMemoryPool.Pool.Free(scale);
+                    if (info != 0) 
+                        throw new ILArgumentException("eig: error in Lapack '?geevx': (" + info + ")");
+                    // create eigenvalues 
+                    fcomplex [] retArr = ILMemoryPool.Pool.New< fcomplex >(n); 
+                    for (int i = 0; i < n; i++) {
+                        retArr[i].real = wr[i]; retArr[i].imag = wi[i];
+                    }
+                    ret = new ILArray< fcomplex > (retArr,n,1);
+                    if (createVR) {
+                        fcomplex [] VArr = ILMemoryPool.Pool.New< fcomplex >(n * n);
+                    for (int c = 0; c < n; c++) {
+                        if (wi[c] != 0 && wi[c+1] != 0 && c < n-1) {
+                            ilo = n * c; ihi = ilo + n;
+                            for (int r = 0; r < n; r++) {
+                                VArr[ilo].real = vr[ilo];
+                                VArr[ilo].imag = vr[ihi];  
+                                VArr[ihi].real = vr[ilo];  
+                                VArr[ihi].imag = -vr[ihi]; 
+                                ilo++; ihi++; 
+                            }
+                            c++; 
+                        } else {
+                            ilo = n * c;
+                            for (int r = 0; r < n; r++) {
+                                VArr[ilo].real = vr[ilo];
+                                ilo++; 
+                            }
+                        }
+                    }
+                    V.a = array<fcomplex> (VArr,n,n);  
+                        if (createVR)
+                            ret.a = ILMath.diag< fcomplex>(ret); 
+                    }
+                    ILMemoryPool.Pool.Free(wi);
+                    ILMemoryPool.Pool.Free(vr); 
+                    ILMemoryPool.Pool.Free(wr); 
+                }
+                return ret; 
+            }
+        }
+
+        /// <summary>
+        /// Find all eigenvalues of symmetric (hermitian) matrix
+        /// </summary>
+        /// <param name="A">Input matrix, Size [n x n], symmetric (hermitian for complex A) </param> 
+        /// <returns>Array of size [n,1] with eigenvalues of A.</returns>
+        /// <remarks><para>For computation the Lapack functions dsyevr, ssyevr, chesvr and zheesv are used. </para>
+        /// <para>Since A is symmetric, the eigenvalues will always be real. Therefore the return value will be of the same inner type as A.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A is not square.</exception>
+        public static ILRetArray< float > eigSymm (ILInArray< float > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    return empty< float>(A.Size); 
+                }
+                int n = A.Size[0]; 
+                if (n != A.Size[1])
+                    throw new ILArgumentException("input matrix A must be square and symmetric/hermitian.");
+                int m = 0,info = 0; 
+                ILArray< float > w = new ILArray< float > (new  float [n],1,n); 
+                float [] z = new  float [1]; ; 
+                int [] isuppz = new int[2 * n];
+                float [] AcArr = A.C.GetArrayForWrite(); 
+                Lapack.ssyevr ('N','A','U',n,AcArr,n,0,0,0,0,0,ref m,w.GetArrayForWrite(),z,1,isuppz,ref info);
+                ILMemoryPool.Pool.Free(AcArr); 
+                return  (w); 
+            }
+        }
+        /// <summary>
+        /// Find all eigenvalues and -vectors of symmetric (hermitian) matrix
+        /// </summary>
+        /// <param name="A">Input matrix, Size [n x n], symmetric (hermitian for complex A) </param> 
+        /// <param name="V">Output: n eigenvectors as columns. Size [n x n]. If V is null on input, the eigenvectors 
+        /// will not be computed and V is not changed. In order to make the function return the vectors, V should be initiialized with ILMath.returnType before calling eigSymm.</param>
+        /// <returns>Diagonal matrix of size [n,n] with eigenvalues of A on the main diagonal.</returns>
+        /// <remarks><para>For computation the Lapack functions dsyevr, ssyevr, chesvr and zheesv are used. </para>
+        /// <para>Since A is symmetric, the eigenvalues will always be real. Therefore the return value will be of the same inner type as A.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A is not square.</exception>
+        public static ILRetArray< float > eigSymm (ILInArray< float > A, ILOutArray< float > V) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    if (!object.Equals(V,null))
+                        V.a = empty<float>(A.Size); 
+                    return empty<float>(A.Size); 
+                }
+                int n = A.Size[0]; 
+                if (n != A.Size[1])
+                    throw new ILArgumentException("input matrix A must be square and symmetric/hermitian.");
+                int m = 0,ldz = 0,info = 0; 
+                ILArray< float > w = new ILArray< float >(ILMemoryPool.Pool.New< float >(n),n,1); 
+                float [] z; 
+                char jobz;
+                if (object.Equals(V,null)) {
+                    z = new  float [1]; 
+                    jobz = 'N';
+                    ldz = 1; 
+                } else {
+                    z = ILMemoryPool.Pool.New<  float >(n * n);
+                    jobz = 'V';
+                    ldz = n; 
+                } 
+                int [] isuppz = ILMemoryPool.Pool.New<int>( 2 * n);
+                float [] AcArr = A.C.GetArrayForWrite(); 
+                Lapack.ssyevr (jobz,'A','U',n,AcArr,n,1,n,0,0,0,ref m,w.GetArrayForWrite(),z,ldz,isuppz,ref info);
+                ILMemoryPool.Pool.Free(AcArr); 
+                ILMemoryPool.Pool.Free(isuppz);
+                if (info != 0) 
+                    throw new ILException("error returned from lapack: " + info); 
+                if (jobz == 'V') {
+                    System.Diagnostics.Debug.Assert(!object.Equals(V,null));
+                    V.a =  array< float > (z,n,n);
+                    V.a = V[full,r(0,m-1)]; 
+                    return ILMath.diag( (w)); 
+                } else {
+                    ILMemoryPool.Pool.Free(z); 
+                    return  (w);
+                }
+            }
+        }
+        /// <summary>
+        /// Find some eigenvalues and -vectors of symmetric (hermitian) matrix
+        /// </summary>
+        /// <param name="A">Input matrix, Size [n x n], symmetric (hermitian for complex A) </param> 
+        /// <param name="V">Output: n eigenvectors as columns. Size [n x n]. If V is null on input, the eigenvectors will not be computed and V is not changed. </param>
+        /// <param name="rangeStart">Specify the lowest limit for the range of eigenvalues to be queried.</param>
+        /// <param name="rangeEnd">Specify the upper limit for the range of eigenvalues to be queried.</param>
+        /// <returns>Diagonal matrix of size [n,n] with eigenvalues of A on the main diagonal.</returns>
+        /// <remarks><para>For computation the Lapack functions dsyevr, ssyevr, chesvr and zheesv are used. </para>
+        /// <para>Since A is symmetric, the eigenvalues will always be real. Therefore the return value will be of the same inner type as A.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A is not square or <paramref name="rangeEnd"/> &lt; <paramref name="rangeStart"/></exception>
+        public static ILRetArray< float > eigSymm (ILInArray< float > A, ILOutArray< float > V, int rangeStart, int rangeEnd) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    if (!object.Equals(V,null))
+                        V.a = empty<float>(A.Size); 
+                    return empty<float>(A.Size); 
+                }
+                int n = A.Size[0]; 
+                if (n != A.Size[1])
+                    throw new ILArgumentException("input matrix A must be square and symmetric/hermitian.");
+                int m = 0,ldz = 0,info = 0; 
+                if (rangeEnd < rangeStart || rangeStart < 1) 
+                    throw new ILArgumentException("invalid range of eigenvalues requested");
+                ILArray< float > w = array< float > (
+                                            ILMemoryPool.Pool.New< float>(n),1,n); 
+                float [] z; 
+                char jobz;
+                if (object.Equals(V,null)) {
+                    z = new  float [1]; 
+                    jobz = 'N';
+                    ldz = 1; 
+                } else {
+                    z = ILMemoryPool.Pool.New<float>(n * n);
+                    jobz = 'V';
+                    ldz = n; 
+                } 
+                int [] isuppz = ILMemoryPool.Pool.New<int>(2 * n);
+                float [] AcArr = A.C.GetArrayForWrite(); 
+                Lapack.ssyevr (jobz,'I','U',n,AcArr,n,0,0,rangeStart,rangeEnd,0,ref m,w.GetArrayForWrite(),z,ldz,isuppz,ref info);
+                ILMemoryPool.Pool.Free(isuppz); 
+                ILMemoryPool.Pool.Free(AcArr); 
+
+                if (jobz == 'V') {
+                    V.a = array<  float >(z,n,n);
+                    V.a = V[full,r(0,m-1)]; 
+                }
+                ILMemoryPool.Pool.Free(z); 
+                return ILMath.diag( (w)); 
+            }
+        }
+        /// <summary>
+        /// Find some eigenvalues and -vectors of symmetric (hermitian) matrix
+        /// </summary>
+        /// <param name="A">Input matrix, Size [n x n], symmetric (hermitian for complex A) </param> 
+        /// <param name="V">Output: n eigenvectors as columns. Size [n x n]. If V is null on input, the eigenvectors will not be computed and V is not changed. </param>
+        /// <param name="rangeStart">The eigenvalues will be returned by increasing size. This will determine the number of the first eigenvalue to be returned.</param>
+        /// <param name="rangeEnd">Determine the number of the last eigenvalue to be returned.</param>
+        /// <returns>Diagonal matrix of size [n,n] with eigenvalues of A on the main diagonal.</returns>
+        /// <remarks><para>For computation the Lapack functions dsyevr, ssyevr, chesvr and zheesv are used. </para>
+        /// <para>Since A is symmetric, the eigenvalues will always be real. Therefore the return value will be of the same inner type as A.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A is not square or <paramref name="rangeEnd"/> &lt; <paramref name="rangeStart"/> or if either one is &lt;= 0.</exception>
+        public static ILRetArray< float> eigSymm( ILInArray< float> A, ILOutArray< float> V,  float rangeStart,  float rangeEnd ) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    if (!object.Equals(V, null))
+                        V.a = empty<float>(A.Size);
+                    return empty<float>(A.Size);
+                }
+                int n = A.Size[0];
+                if (n != A.Size[1])
+                    throw new ILArgumentException("input matrix A must be square and symmetric/hermitian");
+                int m = 0, ldz = 0, info = 0;
+                if (rangeStart > rangeEnd)
+                    throw new ILArgumentException("invalid range of eigenvalues requested");
+                ILArray< float> w = zeros<float>(1, n);
+               
+                float[] z;
+                char jobz;
+                if (object.Equals(V, null)) {
+                    z = new  float[1];
+                    jobz = 'N';
+                    ldz = 1;
+                } else {
+                    z = ILMemoryPool.Pool.New<float>(n * n);
+                    jobz = 'V';
+                    ldz = n;
+                }
+                int[] isuppz = ILMemoryPool.Pool.New<int>(2 * n);
+
+               
+                float[] AcArr = A.C.GetArrayForWrite();
+               
+                Lapack.ssyevr(jobz, 'V', 'U', n, AcArr, n, rangeStart, rangeEnd, 0, 0, 0, ref m, w.GetArrayForWrite(), z, ldz, isuppz, ref info);
+                ILMemoryPool.Pool.Free(AcArr);
+                ILMemoryPool.Pool.Free(isuppz);
+
+                if (jobz == 'V') {
+                    V.a = array< float>(z, n, n);
+                    V.a = V[full, r(0, m - 1)];
+                }
+                ILMemoryPool.Pool.Free(z);
+                return diag( (w));
+            }
+        }
+        
+        /// <summary>
+        /// Compute eigenvalues of general square matrix A
+        /// </summary>
+        /// <param name="A">Input matrix A. Size [n x n]</param>
+        /// <returns>Vector of eigenvalues of A. Size [n x 1]</returns>
+        /// <remarks><para>The eigenvalues of A are found by use of the Lapack functions dgeevx, sgeevx, cgeevx and zgeevx. </para>
+        /// <para>The vector returned will be of complex inner type, since no further constraints are set on the structure of A (it may be nonsymmetric). Use <see cref="ILNumerics.ILMath.eigSymm(ILInArray&lt;double&gt;)"/> or <see cref="ILNumerics.ILMath.eigSymm(ILInArray&lt;double&gt;,ILOutArray&lt;double&gt;)"/> functions for computing the real eigenvalues of symmetric matrices explicitly.</para>
+        /// <para>A will be balanced first. This includes permutations and scaling of A in order to improve the conditioning of the eigenvalues.</para></remarks>
+        /// <seealso cref="ILNumerics.ILMath.eig(ILInArray&lt;double&gt;,ILOutArray&lt;complex&gt;)"/>
+        /// <seealso cref="ILNumerics.ILMath.eig(ILInArray&lt;double&gt;,ILOutArray&lt;complex&gt;,ref MatrixProperties,bool)"/>
+        public static ILRetArray< fcomplex > eig(ILInArray< fcomplex > A) {
+            using (ILScope.Enter(A)) {
+                ILArray< fcomplex> V = null;
+                MatrixProperties props = MatrixProperties.None;
+                return eig(A, V, ref props, true);
+            }
+        }
+        /// <summary>
+        /// Compute eigenvalues and eigenvectors of general square matrix A
+        /// </summary>
+        /// <param name="A">Input matrix A. Size [n x n]</param>
+        /// <param name="V">Output matrix, eigenvectors EV of size [n x n]. May be null on input. If not null, content of V will be destroyed.</param>
+        /// <returns>Diagonal matrix with eigenvalues of A. Size [n x n]</returns>
+        /// <remarks><para>The eigenvalues of A are found by use of the Lapack functions dgeevx, sgeevx, cgeevx and zgeevx. </para>
+        /// <para>The matrices returned will be of complex inner type, since no further constrains are set on the structure of A (it may be nonsymmetric). Use <see cref="ILNumerics.ILMath.eigSymm(ILInArray&lt;double&gt;)"/> or <see cref="ILNumerics.ILMath.eigSymm(ILInArray&lt;double&gt;,ILOutArray&lt;double&gt;)"/> functions for computing the real eigenvalues of symmetric matrices explicitly.</para>
+        /// <para>A will be balanced first. This includes permutations and scaling of A in order to improve the conditioning of the eigenvalues.</para></remarks>
+        /// <seealso cref="ILNumerics.ILMath.eig(ILInArray&lt;double&gt;)"/>
+        /// <seealso cref="ILNumerics.ILMath.eig(ILInArray&lt;double&gt;,ILOutArray&lt;complex&gt;,ref MatrixProperties,bool)"/>
+        public static ILRetArray< fcomplex > eig(ILInArray< fcomplex > A, ILOutArray< fcomplex > V) {
+            MatrixProperties props = MatrixProperties.None; 
+            return eig(A, V, ref props, true); 
+        }
+        /// <summary>
+        /// Find eigenvalues  and eigenvectors 
+        /// </summary>
+        /// <param name="A">Input: square matrix, size [n x n]</param>
+        /// <param name="V">Output (optional): eigenvectors</param>   
+        /// <param name="propsA">Matrix properties, on input - if specified, 
+        /// will be used to choose the proper method of solution. On exit will be 
+        /// filled according to the properties of A.</param>
+        /// <param name="balance">true: permute A in order to increase the 
+        /// numerical stability, false: do not permute A.</param>
+        /// <returns>eigenvalues as vector (if V is null) or as diagonoal 
+        /// matrix (if V was requested, i.e. not null).</returns>
+        /// <remarks><para>The eigenvalues of A are found by use of the 
+        /// Lapack functions dgeevx, sgeevx, cgeevx and zgeevx. </para>
+        /// <para>The arrays returned will be of complex inner type, 
+        /// since no further constraints are set on the structure of 
+        /// A (it may be nonsymmetric). Use 
+        /// <see cref="ILNumerics.ILMath.eigSymm(ILInArray&lt;double&gt;)"/> 
+        /// or <see cref="ILNumerics.ILMath.eigSymm(ILInArray&lt;double&gt;,ILOutArray&lt;double&gt;)"/> 
+        /// functions for computing the real eigenvalues of symmetric 
+        /// matrices explicitly.</para>
+        /// <para>Depending on the parameter <paramref name="balance"/>, 
+        /// A will be balanced first. This includes permutations and 
+        /// scaling of A in order to improve the conditioning of the 
+        /// eigenvalues.</para></remarks>
+        /// <seealso cref="ILNumerics.ILMath.eig(ILInArray&lt;double&gt;)"/>
+        /// <seealso cref="ILNumerics.ILMath.eig(ILInArray&lt;double&gt;,ILOutArray&lt;complex&gt;,ref MatrixProperties,bool)"/>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if a 
+        /// is not square</exception>
+        public static ILRetArray< fcomplex > eig(ILInArray< fcomplex > A, ILOutArray< fcomplex > V, ref MatrixProperties propsA, bool balance) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    if (!object.Equals(V,null))
+                        V.a = empty<fcomplex>(A.Size); 
+                    return  empty<fcomplex>(A.Size); 
+                }
+                ILArray< fcomplex > ret = empty< fcomplex >(ILSize.Empty00);  
+                int n = A.Size[0]; 
+                bool createVR = (object.Equals(V,null))? false:true; 
+                if (n != A.Size[1]) 
+                    throw new ILArgumentException("eig: matrix A must be square");
+                propsA |= MatrixProperties.Square; 
+                if (((propsA & MatrixProperties.Hermitian) != 0 || ILMath.ishermitian(A.C))) {
+                    propsA |= MatrixProperties.Hermitian; 
+                    ILArray< fcomplex > Vd = null; 
+                    if (createVR) 
+                        Vd = returnType< fcomplex >();
+                    ILArray< fcomplex > tmpRet = eigSymm(A,Vd);
+                    if (createVR)
+                        V.a =   (Vd); 
+                    ret =   (tmpRet);
+                } else {
+                    // nonsymmetric case
+                    char bal = (balance)? 'B':'N', jobvr;  
+                    ILRetArray< fcomplex > tmpA = A.C; 
+                    fcomplex [] vr = null;
+                    fcomplex [] wr = ILMemoryPool.Pool.New< fcomplex >(n); 
+                    
+                    float [] scale  = ILMemoryPool.Pool.New< float >(n);
+                    float [] rconde = ILMemoryPool.Pool.New< float >(n); 
+                    float [] rcondv = ILMemoryPool.Pool.New< float >(n); 
+                    float abnrm = 0; 
+                    int ldvr, ilo = 0, ihi = 0, info = 0;
+                    if (createVR) {
+                        ldvr = n;
+                        vr = ILMemoryPool.Pool.New< fcomplex >(n * n);
+                        jobvr = 'V'; 
+                    } else {
+                        ldvr = 1; 
+                        vr = new  fcomplex [1]; 
+                        jobvr = 'N'; 
+                    }
+                    Lapack.cgeevx(bal,'N',jobvr,'N',n,tmpA.GetArrayForWrite(),n,wr,   new fcomplex[1],1,vr,ldvr,ref ilo,ref ihi,scale,ref abnrm,rconde,rcondv,ref info);   
+                    ILMemoryPool.Pool.Free(rconde);
+                    ILMemoryPool.Pool.Free(rcondv);
+                    ILMemoryPool.Pool.Free(scale);
+                    if (info != 0) 
+                        throw new ILArgumentException("eig: error in Lapack '?geevx': (" + info + ")");
+                    // create eigenvalues 
+                    fcomplex [] retArr = ILMemoryPool.Pool.New< fcomplex >(n); 
+                    for (int i = 0; i < n; i++) {
+                        retArr[i] = wr[i]; 
+                    }
+                    ret = new ILArray< fcomplex > (retArr,n,1);
+                    if (createVR) {
+                        V.a = array<fcomplex> (vr,n,n);
+                        if (createVR)
+                            ret.a = ILMath.diag< fcomplex>(ret); 
+                    }
+                    
+                    ILMemoryPool.Pool.Free(vr); 
+                    ILMemoryPool.Pool.Free(wr); 
+                }
+                return ret; 
+            }
+        }
+
+        /// <summary>
+        /// Find all eigenvalues of symmetric (hermitian) matrix
+        /// </summary>
+        /// <param name="A">Input matrix, Size [n x n], symmetric (hermitian for complex A) </param> 
+        /// <returns>Array of size [n,1] with eigenvalues of A.</returns>
+        /// <remarks><para>For computation the Lapack functions dsyevr, ssyevr, chesvr and zheesv are used. </para>
+        /// <para>Since A is symmetric, the eigenvalues will always be real. Therefore the return value will be of the same inner type as A.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A is not square.</exception>
+        public static ILRetArray< fcomplex > eigSymm (ILInArray< fcomplex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    return empty< fcomplex>(A.Size); 
+                }
+                int n = A.Size[0]; 
+                if (n != A.Size[1])
+                    throw new ILArgumentException("input matrix A must be square and symmetric/hermitian.");
+                int m = 0,info = 0; 
+                ILArray< float > w = new ILArray< float > (new  float [n],1,n); 
+                fcomplex [] z = new  fcomplex [1]; ; 
+                int [] isuppz = new int[2 * n];
+                fcomplex [] AcArr = A.C.GetArrayForWrite(); 
+                Lapack.cheevr ('N','A','U',n,AcArr,n,0,0,0,0,0,ref m,w.GetArrayForWrite(),z,1,isuppz,ref info);
+                ILMemoryPool.Pool.Free(AcArr); 
+                return  ILMath.tofcomplex(w); 
+            }
+        }
+        /// <summary>
+        /// Find all eigenvalues and -vectors of symmetric (hermitian) matrix
+        /// </summary>
+        /// <param name="A">Input matrix, Size [n x n], symmetric (hermitian for complex A) </param> 
+        /// <param name="V">Output: n eigenvectors as columns. Size [n x n]. If V is null on input, the eigenvectors 
+        /// will not be computed and V is not changed. In order to make the function return the vectors, V should be initiialized with ILMath.returnType before calling eigSymm.</param>
+        /// <returns>Diagonal matrix of size [n,n] with eigenvalues of A on the main diagonal.</returns>
+        /// <remarks><para>For computation the Lapack functions dsyevr, ssyevr, chesvr and zheesv are used. </para>
+        /// <para>Since A is symmetric, the eigenvalues will always be real. Therefore the return value will be of the same inner type as A.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A is not square.</exception>
+        public static ILRetArray< fcomplex > eigSymm (ILInArray< fcomplex > A, ILOutArray< fcomplex > V) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    if (!object.Equals(V,null))
+                        V.a = empty<fcomplex>(A.Size); 
+                    return empty<fcomplex>(A.Size); 
+                }
+                int n = A.Size[0]; 
+                if (n != A.Size[1])
+                    throw new ILArgumentException("input matrix A must be square and symmetric/hermitian.");
+                int m = 0,ldz = 0,info = 0; 
+                ILArray< float > w = new ILArray< float >(ILMemoryPool.Pool.New< float >(n),n,1); 
+                fcomplex [] z; 
+                char jobz;
+                if (object.Equals(V,null)) {
+                    z = new  fcomplex [1]; 
+                    jobz = 'N';
+                    ldz = 1; 
+                } else {
+                    z = ILMemoryPool.Pool.New<  fcomplex >(n * n);
+                    jobz = 'V';
+                    ldz = n; 
+                } 
+                int [] isuppz = ILMemoryPool.Pool.New<int>( 2 * n);
+                fcomplex [] AcArr = A.C.GetArrayForWrite(); 
+                Lapack.cheevr (jobz,'A','U',n,AcArr,n,1,n,0,0,0,ref m,w.GetArrayForWrite(),z,ldz,isuppz,ref info);
+                ILMemoryPool.Pool.Free(AcArr); 
+                ILMemoryPool.Pool.Free(isuppz);
+                if (info != 0) 
+                    throw new ILException("error returned from lapack: " + info); 
+                if (jobz == 'V') {
+                    System.Diagnostics.Debug.Assert(!object.Equals(V,null));
+                    V.a =  array< fcomplex > (z,n,n);
+                    V.a = V[full,r(0,m-1)]; 
+                    return ILMath.diag( ILMath.tofcomplex(w)); 
+                } else {
+                    ILMemoryPool.Pool.Free(z); 
+                    return  ILMath.tofcomplex(w);
+                }
+            }
+        }
+        /// <summary>
+        /// Find some eigenvalues and -vectors of symmetric (hermitian) matrix
+        /// </summary>
+        /// <param name="A">Input matrix, Size [n x n], symmetric (hermitian for complex A) </param> 
+        /// <param name="V">Output: n eigenvectors as columns. Size [n x n]. If V is null on input, the eigenvectors will not be computed and V is not changed. </param>
+        /// <param name="rangeStart">Specify the lowest limit for the range of eigenvalues to be queried.</param>
+        /// <param name="rangeEnd">Specify the upper limit for the range of eigenvalues to be queried.</param>
+        /// <returns>Diagonal matrix of size [n,n] with eigenvalues of A on the main diagonal.</returns>
+        /// <remarks><para>For computation the Lapack functions dsyevr, ssyevr, chesvr and zheesv are used. </para>
+        /// <para>Since A is symmetric, the eigenvalues will always be real. Therefore the return value will be of the same inner type as A.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A is not square or <paramref name="rangeEnd"/> &lt; <paramref name="rangeStart"/></exception>
+        public static ILRetArray< fcomplex > eigSymm (ILInArray< fcomplex > A, ILOutArray< fcomplex > V, int rangeStart, int rangeEnd) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    if (!object.Equals(V,null))
+                        V.a = empty<fcomplex>(A.Size); 
+                    return empty<fcomplex>(A.Size); 
+                }
+                int n = A.Size[0]; 
+                if (n != A.Size[1])
+                    throw new ILArgumentException("input matrix A must be square and symmetric/hermitian.");
+                int m = 0,ldz = 0,info = 0; 
+                if (rangeEnd < rangeStart || rangeStart < 1) 
+                    throw new ILArgumentException("invalid range of eigenvalues requested");
+                ILArray< float > w = array< float > (
+                                            ILMemoryPool.Pool.New< float>(n),1,n); 
+                fcomplex [] z; 
+                char jobz;
+                if (object.Equals(V,null)) {
+                    z = new  fcomplex [1]; 
+                    jobz = 'N';
+                    ldz = 1; 
+                } else {
+                    z = ILMemoryPool.Pool.New<fcomplex>(n * n);
+                    jobz = 'V';
+                    ldz = n; 
+                } 
+                int [] isuppz = ILMemoryPool.Pool.New<int>(2 * n);
+                fcomplex [] AcArr = A.C.GetArrayForWrite(); 
+                Lapack.cheevr (jobz,'I','U',n,AcArr,n,0,0,rangeStart,rangeEnd,0,ref m,w.GetArrayForWrite(),z,ldz,isuppz,ref info);
+                ILMemoryPool.Pool.Free(isuppz); 
+                ILMemoryPool.Pool.Free(AcArr); 
+
+                if (jobz == 'V') {
+                    V.a = array<  fcomplex >(z,n,n);
+                    V.a = V[full,r(0,m-1)]; 
+                }
+                ILMemoryPool.Pool.Free(z); 
+                return ILMath.diag( ILMath.tofcomplex(w)); 
+            }
+        }
+        /// <summary>
+        /// Find some eigenvalues and -vectors of symmetric (hermitian) matrix
+        /// </summary>
+        /// <param name="A">Input matrix, Size [n x n], symmetric (hermitian for complex A) </param> 
+        /// <param name="V">Output: n eigenvectors as columns. Size [n x n]. If V is null on input, the eigenvectors will not be computed and V is not changed. </param>
+        /// <param name="rangeStart">The eigenvalues will be returned by increasing size. This will determine the number of the first eigenvalue to be returned.</param>
+        /// <param name="rangeEnd">Determine the number of the last eigenvalue to be returned.</param>
+        /// <returns>Diagonal matrix of size [n,n] with eigenvalues of A on the main diagonal.</returns>
+        /// <remarks><para>For computation the Lapack functions dsyevr, ssyevr, chesvr and zheesv are used. </para>
+        /// <para>Since A is symmetric, the eigenvalues will always be real. Therefore the return value will be of the same inner type as A.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A is not square or <paramref name="rangeEnd"/> &lt; <paramref name="rangeStart"/> or if either one is &lt;= 0.</exception>
+        public static ILRetArray< fcomplex> eigSymm( ILInArray< fcomplex> A, ILOutArray< fcomplex> V,  float rangeStart,  float rangeEnd ) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    if (!object.Equals(V, null))
+                        V.a = empty<fcomplex>(A.Size);
+                    return empty<fcomplex>(A.Size);
+                }
+                int n = A.Size[0];
+                if (n != A.Size[1])
+                    throw new ILArgumentException("input matrix A must be square and symmetric/hermitian");
+                int m = 0, ldz = 0, info = 0;
+                if (rangeStart > rangeEnd)
+                    throw new ILArgumentException("invalid range of eigenvalues requested");
+                ILArray< float> w = zeros<float>(1, n);
+               
+                fcomplex[] z;
+                char jobz;
+                if (object.Equals(V, null)) {
+                    z = new  fcomplex[1];
+                    jobz = 'N';
+                    ldz = 1;
+                } else {
+                    z = ILMemoryPool.Pool.New<fcomplex>(n * n);
+                    jobz = 'V';
+                    ldz = n;
+                }
+                int[] isuppz = ILMemoryPool.Pool.New<int>(2 * n);
+
+               
+                fcomplex[] AcArr = A.C.GetArrayForWrite();
+               
+                Lapack.cheevr(jobz, 'V', 'U', n, AcArr, n, rangeStart, rangeEnd, 0, 0, 0, ref m, w.GetArrayForWrite(), z, ldz, isuppz, ref info);
+                ILMemoryPool.Pool.Free(AcArr);
+                ILMemoryPool.Pool.Free(isuppz);
+
+                if (jobz == 'V') {
+                    V.a = array< fcomplex>(z, n, n);
+                    V.a = V[full, r(0, m - 1)];
+                }
+                ILMemoryPool.Pool.Free(z);
+                return diag( ILMath.tofcomplex(w));
+            }
+        }
+        
+        /// <summary>
+        /// Compute eigenvalues of general square matrix A
+        /// </summary>
+        /// <param name="A">Input matrix A. Size [n x n]</param>
+        /// <returns>Vector of eigenvalues of A. Size [n x 1]</returns>
+        /// <remarks><para>The eigenvalues of A are found by use of the Lapack functions dgeevx, sgeevx, cgeevx and zgeevx. </para>
+        /// <para>The vector returned will be of complex inner type, since no further constraints are set on the structure of A (it may be nonsymmetric). Use <see cref="ILNumerics.ILMath.eigSymm(ILInArray&lt;double&gt;)"/> or <see cref="ILNumerics.ILMath.eigSymm(ILInArray&lt;double&gt;,ILOutArray&lt;double&gt;)"/> functions for computing the real eigenvalues of symmetric matrices explicitly.</para>
+        /// <para>A will be balanced first. This includes permutations and scaling of A in order to improve the conditioning of the eigenvalues.</para></remarks>
+        /// <seealso cref="ILNumerics.ILMath.eig(ILInArray&lt;double&gt;,ILOutArray&lt;complex&gt;)"/>
+        /// <seealso cref="ILNumerics.ILMath.eig(ILInArray&lt;double&gt;,ILOutArray&lt;complex&gt;,ref MatrixProperties,bool)"/>
+        public static ILRetArray< complex > eig(ILInArray< complex > A) {
+            using (ILScope.Enter(A)) {
+                ILArray< complex> V = null;
+                MatrixProperties props = MatrixProperties.None;
+                return eig(A, V, ref props, true);
+            }
+        }
+        /// <summary>
+        /// Compute eigenvalues and eigenvectors of general square matrix A
+        /// </summary>
+        /// <param name="A">Input matrix A. Size [n x n]</param>
+        /// <param name="V">Output matrix, eigenvectors EV of size [n x n]. May be null on input. If not null, content of V will be destroyed.</param>
+        /// <returns>Diagonal matrix with eigenvalues of A. Size [n x n]</returns>
+        /// <remarks><para>The eigenvalues of A are found by use of the Lapack functions dgeevx, sgeevx, cgeevx and zgeevx. </para>
+        /// <para>The matrices returned will be of complex inner type, since no further constrains are set on the structure of A (it may be nonsymmetric). Use <see cref="ILNumerics.ILMath.eigSymm(ILInArray&lt;double&gt;)"/> or <see cref="ILNumerics.ILMath.eigSymm(ILInArray&lt;double&gt;,ILOutArray&lt;double&gt;)"/> functions for computing the real eigenvalues of symmetric matrices explicitly.</para>
+        /// <para>A will be balanced first. This includes permutations and scaling of A in order to improve the conditioning of the eigenvalues.</para></remarks>
+        /// <seealso cref="ILNumerics.ILMath.eig(ILInArray&lt;double&gt;)"/>
+        /// <seealso cref="ILNumerics.ILMath.eig(ILInArray&lt;double&gt;,ILOutArray&lt;complex&gt;,ref MatrixProperties,bool)"/>
+        public static ILRetArray< complex > eig(ILInArray< complex > A, ILOutArray< complex > V) {
+            MatrixProperties props = MatrixProperties.None; 
+            return eig(A, V, ref props, true); 
+        }
+        /// <summary>
+        /// Find eigenvalues  and eigenvectors 
+        /// </summary>
+        /// <param name="A">Input: square matrix, size [n x n]</param>
+        /// <param name="V">Output (optional): eigenvectors</param>   
+        /// <param name="propsA">Matrix properties, on input - if specified, 
+        /// will be used to choose the proper method of solution. On exit will be 
+        /// filled according to the properties of A.</param>
+        /// <param name="balance">true: permute A in order to increase the 
+        /// numerical stability, false: do not permute A.</param>
+        /// <returns>eigenvalues as vector (if V is null) or as diagonoal 
+        /// matrix (if V was requested, i.e. not null).</returns>
+        /// <remarks><para>The eigenvalues of A are found by use of the 
+        /// Lapack functions dgeevx, sgeevx, cgeevx and zgeevx. </para>
+        /// <para>The arrays returned will be of complex inner type, 
+        /// since no further constraints are set on the structure of 
+        /// A (it may be nonsymmetric). Use 
+        /// <see cref="ILNumerics.ILMath.eigSymm(ILInArray&lt;double&gt;)"/> 
+        /// or <see cref="ILNumerics.ILMath.eigSymm(ILInArray&lt;double&gt;,ILOutArray&lt;double&gt;)"/> 
+        /// functions for computing the real eigenvalues of symmetric 
+        /// matrices explicitly.</para>
+        /// <para>Depending on the parameter <paramref name="balance"/>, 
+        /// A will be balanced first. This includes permutations and 
+        /// scaling of A in order to improve the conditioning of the 
+        /// eigenvalues.</para></remarks>
+        /// <seealso cref="ILNumerics.ILMath.eig(ILInArray&lt;double&gt;)"/>
+        /// <seealso cref="ILNumerics.ILMath.eig(ILInArray&lt;double&gt;,ILOutArray&lt;complex&gt;,ref MatrixProperties,bool)"/>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if a 
+        /// is not square</exception>
+        public static ILRetArray< complex > eig(ILInArray< complex > A, ILOutArray< complex > V, ref MatrixProperties propsA, bool balance) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    if (!object.Equals(V,null))
+                        V.a = empty<complex>(A.Size); 
+                    return  empty<complex>(A.Size); 
+                }
+                ILArray< complex > ret = empty< complex >(ILSize.Empty00);  
+                int n = A.Size[0]; 
+                bool createVR = (object.Equals(V,null))? false:true; 
+                if (n != A.Size[1]) 
+                    throw new ILArgumentException("eig: matrix A must be square");
+                propsA |= MatrixProperties.Square; 
+                if (((propsA & MatrixProperties.Hermitian) != 0 || ILMath.ishermitian(A.C))) {
+                    propsA |= MatrixProperties.Hermitian; 
+                    ILArray< complex > Vd = null; 
+                    if (createVR) 
+                        Vd = returnType< complex >();
+                    ILArray< complex > tmpRet = eigSymm(A,Vd);
+                    if (createVR)
+                        V.a =   (Vd); 
+                    ret =   (tmpRet);
+                } else {
+                    // nonsymmetric case
+                    char bal = (balance)? 'B':'N', jobvr;  
+                    ILRetArray< complex > tmpA = A.C; 
+                    complex [] vr = null;
+                    complex [] wr = ILMemoryPool.Pool.New< complex >(n); 
+                    
+                    double [] scale  = ILMemoryPool.Pool.New< double >(n);
+                    double [] rconde = ILMemoryPool.Pool.New< double >(n); 
+                    double [] rcondv = ILMemoryPool.Pool.New< double >(n); 
+                    double abnrm = 0; 
+                    int ldvr, ilo = 0, ihi = 0, info = 0;
+                    if (createVR) {
+                        ldvr = n;
+                        vr = ILMemoryPool.Pool.New< complex >(n * n);
+                        jobvr = 'V'; 
+                    } else {
+                        ldvr = 1; 
+                        vr = new  complex [1]; 
+                        jobvr = 'N'; 
+                    }
+                    Lapack.zgeevx(bal,'N',jobvr,'N',n,tmpA.GetArrayForWrite(),n,wr,   new complex [1],1,vr,ldvr,ref ilo,ref ihi,scale,ref abnrm,rconde,rcondv,ref info);   
+                    ILMemoryPool.Pool.Free(rconde);
+                    ILMemoryPool.Pool.Free(rcondv);
+                    ILMemoryPool.Pool.Free(scale);
+                    if (info != 0) 
+                        throw new ILArgumentException("eig: error in Lapack '?geevx': (" + info + ")");
+                    // create eigenvalues 
+                    complex [] retArr = ILMemoryPool.Pool.New< complex >(n); 
+                    for (int i = 0; i < n; i++) {
+                        retArr[i] = wr[i]; 
+                    }
+                    ret = new ILArray< complex > (retArr,n,1);
+                    if (createVR) {
+                        V.a = array<complex> (vr,n,n);
+                        if (createVR)
+                            ret.a = ILMath.diag< complex>(ret); 
+                    }
+                    
+                    ILMemoryPool.Pool.Free(vr); 
+                    ILMemoryPool.Pool.Free(wr); 
+                }
+                return ret; 
+            }
+        }
+
+        /// <summary>
+        /// Find all eigenvalues of symmetric (hermitian) matrix
+        /// </summary>
+        /// <param name="A">Input matrix, Size [n x n], symmetric (hermitian for complex A) </param> 
+        /// <returns>Array of size [n,1] with eigenvalues of A.</returns>
+        /// <remarks><para>For computation the Lapack functions dsyevr, ssyevr, chesvr and zheesv are used. </para>
+        /// <para>Since A is symmetric, the eigenvalues will always be real. Therefore the return value will be of the same inner type as A.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A is not square.</exception>
+        public static ILRetArray< complex > eigSymm (ILInArray< complex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    return empty< complex>(A.Size); 
+                }
+                int n = A.Size[0]; 
+                if (n != A.Size[1])
+                    throw new ILArgumentException("input matrix A must be square and symmetric/hermitian.");
+                int m = 0,info = 0; 
+                ILArray< double > w = new ILArray< double > (new  double [n],1,n); 
+                complex [] z = new  complex [1]; ; 
+                int [] isuppz = new int[2 * n];
+                complex [] AcArr = A.C.GetArrayForWrite(); 
+                Lapack.zheevr ('N','A','U',n,AcArr,n,0,0,0,0,0,ref m,w.GetArrayForWrite(),z,1,isuppz,ref info);
+                ILMemoryPool.Pool.Free(AcArr); 
+                return  ILMath.tocomplex(w); 
+            }
+        }
+        /// <summary>
+        /// Find all eigenvalues and -vectors of symmetric (hermitian) matrix
+        /// </summary>
+        /// <param name="A">Input matrix, Size [n x n], symmetric (hermitian for complex A) </param> 
+        /// <param name="V">Output: n eigenvectors as columns. Size [n x n]. If V is null on input, the eigenvectors 
+        /// will not be computed and V is not changed. In order to make the function return the vectors, V should be initiialized with ILMath.returnType before calling eigSymm.</param>
+        /// <returns>Diagonal matrix of size [n,n] with eigenvalues of A on the main diagonal.</returns>
+        /// <remarks><para>For computation the Lapack functions dsyevr, ssyevr, chesvr and zheesv are used. </para>
+        /// <para>Since A is symmetric, the eigenvalues will always be real. Therefore the return value will be of the same inner type as A.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A is not square.</exception>
+        public static ILRetArray< complex > eigSymm (ILInArray< complex > A, ILOutArray< complex > V) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    if (!object.Equals(V,null))
+                        V.a = empty<complex>(A.Size); 
+                    return empty<complex>(A.Size); 
+                }
+                int n = A.Size[0]; 
+                if (n != A.Size[1])
+                    throw new ILArgumentException("input matrix A must be square and symmetric/hermitian.");
+                int m = 0,ldz = 0,info = 0; 
+                ILArray< double > w = new ILArray< double >(ILMemoryPool.Pool.New< double >(n),n,1); 
+                complex [] z; 
+                char jobz;
+                if (object.Equals(V,null)) {
+                    z = new  complex [1]; 
+                    jobz = 'N';
+                    ldz = 1; 
+                } else {
+                    z = ILMemoryPool.Pool.New<  complex >(n * n);
+                    jobz = 'V';
+                    ldz = n; 
+                } 
+                int [] isuppz = ILMemoryPool.Pool.New<int>( 2 * n);
+                complex [] AcArr = A.C.GetArrayForWrite(); 
+                Lapack.zheevr (jobz,'A','U',n,AcArr,n,1,n,0,0,0,ref m,w.GetArrayForWrite(),z,ldz,isuppz,ref info);
+                ILMemoryPool.Pool.Free(AcArr); 
+                ILMemoryPool.Pool.Free(isuppz);
+                if (info != 0) 
+                    throw new ILException("error returned from lapack: " + info); 
+                if (jobz == 'V') {
+                    System.Diagnostics.Debug.Assert(!object.Equals(V,null));
+                    V.a =  array< complex > (z,n,n);
+                    V.a = V[full,r(0,m-1)]; 
+                    return ILMath.diag( ILMath.tocomplex(w)); 
+                } else {
+                    ILMemoryPool.Pool.Free(z); 
+                    return  ILMath.tocomplex(w);
+                }
+            }
+        }
+        /// <summary>
+        /// Find some eigenvalues and -vectors of symmetric (hermitian) matrix
+        /// </summary>
+        /// <param name="A">Input matrix, Size [n x n], symmetric (hermitian for complex A) </param> 
+        /// <param name="V">Output: n eigenvectors as columns. Size [n x n]. If V is null on input, the eigenvectors will not be computed and V is not changed. </param>
+        /// <param name="rangeStart">Specify the lowest limit for the range of eigenvalues to be queried.</param>
+        /// <param name="rangeEnd">Specify the upper limit for the range of eigenvalues to be queried.</param>
+        /// <returns>Diagonal matrix of size [n,n] with eigenvalues of A on the main diagonal.</returns>
+        /// <remarks><para>For computation the Lapack functions dsyevr, ssyevr, chesvr and zheesv are used. </para>
+        /// <para>Since A is symmetric, the eigenvalues will always be real. Therefore the return value will be of the same inner type as A.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A is not square or <paramref name="rangeEnd"/> &lt; <paramref name="rangeStart"/></exception>
+        public static ILRetArray< complex > eigSymm (ILInArray< complex > A, ILOutArray< complex > V, int rangeStart, int rangeEnd) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    if (!object.Equals(V,null))
+                        V.a = empty<complex>(A.Size); 
+                    return empty<complex>(A.Size); 
+                }
+                int n = A.Size[0]; 
+                if (n != A.Size[1])
+                    throw new ILArgumentException("input matrix A must be square and symmetric/hermitian.");
+                int m = 0,ldz = 0,info = 0; 
+                if (rangeEnd < rangeStart || rangeStart < 1) 
+                    throw new ILArgumentException("invalid range of eigenvalues requested");
+                ILArray< double > w = array< double > (
+                                            ILMemoryPool.Pool.New< double>(n),1,n); 
+                complex [] z; 
+                char jobz;
+                if (object.Equals(V,null)) {
+                    z = new  complex [1]; 
+                    jobz = 'N';
+                    ldz = 1; 
+                } else {
+                    z = ILMemoryPool.Pool.New<complex>(n * n);
+                    jobz = 'V';
+                    ldz = n; 
+                } 
+                int [] isuppz = ILMemoryPool.Pool.New<int>(2 * n);
+                complex [] AcArr = A.C.GetArrayForWrite(); 
+                Lapack.zheevr (jobz,'I','U',n,AcArr,n,0,0,rangeStart,rangeEnd,0,ref m,w.GetArrayForWrite(),z,ldz,isuppz,ref info);
+                ILMemoryPool.Pool.Free(isuppz); 
+                ILMemoryPool.Pool.Free(AcArr); 
+
+                if (jobz == 'V') {
+                    V.a = array<  complex >(z,n,n);
+                    V.a = V[full,r(0,m-1)]; 
+                }
+                ILMemoryPool.Pool.Free(z); 
+                return ILMath.diag( ILMath.tocomplex(w)); 
+            }
+        }
+        /// <summary>
+        /// Find some eigenvalues and -vectors of symmetric (hermitian) matrix
+        /// </summary>
+        /// <param name="A">Input matrix, Size [n x n], symmetric (hermitian for complex A) </param> 
+        /// <param name="V">Output: n eigenvectors as columns. Size [n x n]. If V is null on input, the eigenvectors will not be computed and V is not changed. </param>
+        /// <param name="rangeStart">The eigenvalues will be returned by increasing size. This will determine the number of the first eigenvalue to be returned.</param>
+        /// <param name="rangeEnd">Determine the number of the last eigenvalue to be returned.</param>
+        /// <returns>Diagonal matrix of size [n,n] with eigenvalues of A on the main diagonal.</returns>
+        /// <remarks><para>For computation the Lapack functions dsyevr, ssyevr, chesvr and zheesv are used. </para>
+        /// <para>Since A is symmetric, the eigenvalues will always be real. Therefore the return value will be of the same inner type as A.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A is not square or <paramref name="rangeEnd"/> &lt; <paramref name="rangeStart"/> or if either one is &lt;= 0.</exception>
+        public static ILRetArray< complex> eigSymm( ILInArray< complex> A, ILOutArray< complex> V,  double rangeStart,  double rangeEnd ) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    if (!object.Equals(V, null))
+                        V.a = empty<complex>(A.Size);
+                    return empty<complex>(A.Size);
+                }
+                int n = A.Size[0];
+                if (n != A.Size[1])
+                    throw new ILArgumentException("input matrix A must be square and symmetric/hermitian");
+                int m = 0, ldz = 0, info = 0;
+                if (rangeStart > rangeEnd)
+                    throw new ILArgumentException("invalid range of eigenvalues requested");
+                ILArray< double> w = zeros<double>(1, n);
+               
+                complex[] z;
+                char jobz;
+                if (object.Equals(V, null)) {
+                    z = new  complex[1];
+                    jobz = 'N';
+                    ldz = 1;
+                } else {
+                    z = ILMemoryPool.Pool.New<complex>(n * n);
+                    jobz = 'V';
+                    ldz = n;
+                }
+                int[] isuppz = ILMemoryPool.Pool.New<int>(2 * n);
+
+               
+                complex[] AcArr = A.C.GetArrayForWrite();
+               
+                Lapack.zheevr(jobz, 'V', 'U', n, AcArr, n, rangeStart, rangeEnd, 0, 0, 0, ref m, w.GetArrayForWrite(), z, ldz, isuppz, ref info);
+                ILMemoryPool.Pool.Free(AcArr);
+                ILMemoryPool.Pool.Free(isuppz);
+
+                if (jobz == 'V') {
+                    V.a = array< complex>(z, n, n);
+                    V.a = V[full, r(0, m - 1)];
+                }
+                ILMemoryPool.Pool.Free(z);
+                return diag( ILMath.tocomplex(w));
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// Specifies the type of eigenproblem 
+        /// </summary>
+        /// <remarks>The enumeration describes possible problem definitions for generelized eigenproblems:
+        /// <list type="bullet">
+        /// <item>Ax_eq_lambBx: A*V = r*B*V</item>
+        /// <item>ABx_eq_lambx: A*B*V = r*V</item>
+        /// <item>BAx_eq_lambx: B*A*V = r*V</item>
+        /// </list></remarks>
+        public enum GenEigenType {
+            /// <summary>
+            /// A*V = r*B*V
+            /// </summary>
+            Ax_eq_lambBx,
+            /// <summary>
+            /// A*B*V = r*V
+            /// </summary>
+            ABx_eq_lambx,
+            /// <summary>
+            /// B*A*V = r*V
+            /// </summary>
+            BAx_eq_lambx
+        }
+
+
+
+
+        /// <summary>
+        /// Compute eigenvalues <it>lambda</it> of symmetrical/hermitian inputs A and B: A*V=lamda*B*V
+        /// </summary>
+        /// <param name="A">Square, symmetric/hermitian input matrix, size [n x n]</param>
+        /// <param name="B">Square, symmetric/hermitian and positive definite matrix, size [n x n]</param>
+        /// <returns>Vector of eigenvalues. size [n x 1]</returns>
+        /// <remarks>
+        /// <para>Internally, the generalized eigenproblem A*V = r*B*V will be reduced to B<sup>-1</sup>*A*V = r*V using cholesky factorization. The 
+        /// computations are handled by LAPACK functions DSYGV,SSYGV,CHEGV and ZHEGV.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if B was not positive definite</exception> 
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A and B was not of the same size</exception>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if either A and/or B was found not to be symmetric/hermitian</exception>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if the algorithm did not converge. All exceptions will contain an informational message describing the problem verbosely.</exception>
+        public static ILRetArray<double> eigSymm(ILInArray<double> A, ILInArray<double> B) {
+            using (ILScope.Enter(A, B)) {
+                return eigSymm(A, B, null, GenEigenType.Ax_eq_lambBx, false);
+            }
+        }
+
+        /// <summary>
+        /// Compute eigenvalues and eigenvectors of symmetric/hermitian input
+        /// </summary>
+        /// <param name="A">Square, symmetric/hermitian input matrix, size [n x n]</param>
+        /// <param name="B">Square, symmetric/hermitian and positive definite matrix, size [n x n]</param>
+        /// <param name="outV">[Output] Returns eigenvectors in columns (size [n x n]). </param>
+        /// <param name="skipSymmCheck">true: skip tests for A and B being hermitian.</param>
+        /// <returns>Vector of eigenvalues. The return value will be a diagonal matrix with the eigenvalues on the main diagonal.</returns>
+        /// <remarks><para>The eigenvectors in 'V' are not normalized!</para>
+        /// <para>Internally, the generalized eigenproblem A*V = r*B*V will be reduced to B<sup>-1</sup>*A*V = r*V using cholesky factorization. The 
+        /// computations are handled by LAPACK functions DSYGV,SSYGV,CHEGV and ZHEGV.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if B was not positive definite</exception> 
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A and B was not of the same size</exception>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if <paramref name="skipSymmCheck"/> is false and either A and/or B was found not to be symmetric/hermitian</exception>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if the algorithm did not converge. All exceptions will contain an informational message describing the problem verbosely.</exception>
+        public static ILRetArray<double> eigSymm(ILInArray<double> A, ILInArray<double> B, ILOutArray<double> outV, bool skipSymmCheck) {
+            using (ILScope.Enter(A, B)) {
+                return eigSymm(A, B, outV, GenEigenType.Ax_eq_lambBx, skipSymmCheck);
+            }
+        }
+
+        /// <summary>
+        /// Compute eigenvalues and eigenvectors (optional) of symmetric/hermitian input
+        /// </summary>
+        /// <param name="A">Square, symmetric/hermitian input matrix, size [n x n]</param>
+        /// <param name="B">Square, symmetric/hermitian and positive definite matrix, size [n x n]</param>
+        /// <param name="outV">[Output] If on input not null-> returns eigenvectors in columns (size [n x n]). If null on input -> eigenvectors will not get computed.</param>
+        /// <param name="type">Determine the type of problem. This is one of the following types:
+        /// <list type="bullet">
+        /// <item>Ax_eq_lambBx: A*V = r*B*V</item>
+        /// <item>ABx_eq_lambx: A*B*V = r*V</item>
+        /// <item>BAx_eq_lambx: B*A*V = r*V</item>
+        /// </list>Here 'r' is the eigenvalue corresponding to the eigenvector 'V'.</param>
+        /// <param name="skipSymmCheck">true: skip tests for A and B being hermitian.</param>
+        /// <returns>Vector of eigenvalues. If the eigenvectors are requested as well (V not null on input), 
+        /// the return value will be a diagonal matrix with the eigenvalues on the main diagonal.</returns>
+        /// <remarks><para>The eigenvectors in 'V' are not normalized!</para>
+        /// <para>Internally, the generalized eigenproblem A*V = r*B*V will be reduced to B<sup>-1</sup>*A*V = r*V using cholesky factorization. The 
+        /// computations are handled by LAPACK functions DSYGV,SSYGV,CHEGV and ZHEGV.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if B was not positive definite</exception> 
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A and B was not of the same size</exception>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if <paramref name="skipSymmCheck"/> is false and either A and/or B was found not to be symmetric/hermitian</exception>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if the algorithm did not converge. All exceptions will contain an informational message describing the problem verbosely.</exception>
+        public static ILRetArray<double> eigSymm(ILInArray<double> A, ILInArray<double> B, ILOutArray< double> outV, GenEigenType type, bool skipSymmCheck) {
+            using (ILScope.Enter(A, B)) {
+                // check input arguments
+                if (object.Equals(A, null) || object.Equals(B, null))
+                    throw new ILArgumentException("A and B must not be null!");
+                if (!A.IsMatrix || !B.IsMatrix)
+                    throw new ILArgumentException("A & B must be matrices!");
+                int n = A.Size[0];
+                if (n != A.Size[1])
+                    throw new ILArgumentException("input matrices must be square!");
+                if (!A.Size.IsSameSize(B.Size))
+                    throw new ILArgumentException("A and B must have the same size!");
+                if (A.IsEmpty) {
+                    if (object.Equals(outV, null))
+                        return empty< double>(A.Size);
+                    else {
+                        outV.a = A.C;
+                        return empty< double>(A.Size);
+                    }
+                }
+                if (!skipSymmCheck && !ILMath.ishermitian(A)) {
+                    throw new ILArgumentException("A must be hermitian!");
+                }
+                if (!skipSymmCheck && !ILMath.ishermitian(B)) {
+                    throw new ILArgumentException("B must be hermitian!");
+                }
+                int info = -1;
+                int itype = 1;
+                switch (type) {
+                    case GenEigenType.Ax_eq_lambBx:
+                        itype = 1;
+                        break;
+                    case GenEigenType.ABx_eq_lambx:
+                        itype = 2;
+                        break;
+                    case GenEigenType.BAx_eq_lambx:
+                        itype = 3;
+                        break;
+                }
+                char jobz = 'N';
+                if (!object.Equals(outV, null)) {
+                    jobz = 'V';
+                    outV.a = copyUpperTriangle(A, n, n);
+                } else {
+                    ILArray< double> tmpOutV = copyUpperTriangle(A, n, n);
+                    outV = tmpOutV; 
+                }
+                ILArray< double> BC = B.C;
+                
+                double[] w = ILMemoryPool.Pool.New< double>(n);
+                /*!HC:lapack_func*/
+                Lapack.dsygv(itype, jobz, 'U', n, outV.GetArrayForWrite(), n, BC.GetArrayForWrite(), BC.Size[0], w, ref info);
+                if (info == 0) {
+                    if (jobz == 'N')
+                        return array< double>(w, 1, n);
+                    else
+                        return diag(array< double>(w, 1, n));
+                } else if (info < 0) {
+                    throw new ILArgumentException("invalid parameter reported from Lapack module: #" + (-info));
+                } else {
+                    if (info <= n) {
+                        throw new ILArgumentException(String.Format("eigSymm did not converge! {0} off-diagonal elements unequal 0", info));
+                    } else if (info < 2 * n) {
+                        throw new ILArgumentException("eigSymm: B must be positive definite!");
+                    } else {
+                        throw new ILArgumentException("eigSymm: unknown Lapack module error");
+                    }
+                }
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+
+
+        /// <summary>
+        /// Compute eigenvalues <it>lambda</it> of symmetrical/hermitian inputs A and B: A*V=lamda*B*V
+        /// </summary>
+        /// <param name="A">Square, symmetric/hermitian input matrix, size [n x n]</param>
+        /// <param name="B">Square, symmetric/hermitian and positive definite matrix, size [n x n]</param>
+        /// <returns>Vector of eigenvalues. size [n x 1]</returns>
+        /// <remarks>
+        /// <para>Internally, the generalized eigenproblem A*V = r*B*V will be reduced to B<sup>-1</sup>*A*V = r*V using cholesky factorization. The 
+        /// computations are handled by LAPACK functions DSYGV,SSYGV,CHEGV and ZHEGV.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if B was not positive definite</exception> 
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A and B was not of the same size</exception>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if either A and/or B was found not to be symmetric/hermitian</exception>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if the algorithm did not converge. All exceptions will contain an informational message describing the problem verbosely.</exception>
+        public static ILRetArray<float> eigSymm(ILInArray<float> A, ILInArray<float> B) {
+            using (ILScope.Enter(A, B)) {
+                return eigSymm(A, B, null, GenEigenType.Ax_eq_lambBx, false);
+            }
+        }
+
+        /// <summary>
+        /// Compute eigenvalues and eigenvectors of symmetric/hermitian input
+        /// </summary>
+        /// <param name="A">Square, symmetric/hermitian input matrix, size [n x n]</param>
+        /// <param name="B">Square, symmetric/hermitian and positive definite matrix, size [n x n]</param>
+        /// <param name="outV">[Output] Returns eigenvectors in columns (size [n x n]). </param>
+        /// <param name="skipSymmCheck">true: skip tests for A and B being hermitian.</param>
+        /// <returns>Vector of eigenvalues. The return value will be a diagonal matrix with the eigenvalues on the main diagonal.</returns>
+        /// <remarks><para>The eigenvectors in 'V' are not normalized!</para>
+        /// <para>Internally, the generalized eigenproblem A*V = r*B*V will be reduced to B<sup>-1</sup>*A*V = r*V using cholesky factorization. The 
+        /// computations are handled by LAPACK functions DSYGV,SSYGV,CHEGV and ZHEGV.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if B was not positive definite</exception> 
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A and B was not of the same size</exception>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if <paramref name="skipSymmCheck"/> is false and either A and/or B was found not to be symmetric/hermitian</exception>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if the algorithm did not converge. All exceptions will contain an informational message describing the problem verbosely.</exception>
+        public static ILRetArray<float> eigSymm(ILInArray<float> A, ILInArray<float> B, ILOutArray<float> outV, bool skipSymmCheck) {
+            using (ILScope.Enter(A, B)) {
+                return eigSymm(A, B, outV, GenEigenType.Ax_eq_lambBx, skipSymmCheck);
+            }
+        }
+
+        /// <summary>
+        /// Compute eigenvalues and eigenvectors (optional) of symmetric/hermitian input
+        /// </summary>
+        /// <param name="A">Square, symmetric/hermitian input matrix, size [n x n]</param>
+        /// <param name="B">Square, symmetric/hermitian and positive definite matrix, size [n x n]</param>
+        /// <param name="outV">[Output] If on input not null-> returns eigenvectors in columns (size [n x n]). If null on input -> eigenvectors will not get computed.</param>
+        /// <param name="type">Determine the type of problem. This is one of the following types:
+        /// <list type="bullet">
+        /// <item>Ax_eq_lambBx: A*V = r*B*V</item>
+        /// <item>ABx_eq_lambx: A*B*V = r*V</item>
+        /// <item>BAx_eq_lambx: B*A*V = r*V</item>
+        /// </list>Here 'r' is the eigenvalue corresponding to the eigenvector 'V'.</param>
+        /// <param name="skipSymmCheck">true: skip tests for A and B being hermitian.</param>
+        /// <returns>Vector of eigenvalues. If the eigenvectors are requested as well (V not null on input), 
+        /// the return value will be a diagonal matrix with the eigenvalues on the main diagonal.</returns>
+        /// <remarks><para>The eigenvectors in 'V' are not normalized!</para>
+        /// <para>Internally, the generalized eigenproblem A*V = r*B*V will be reduced to B<sup>-1</sup>*A*V = r*V using cholesky factorization. The 
+        /// computations are handled by LAPACK functions DSYGV,SSYGV,CHEGV and ZHEGV.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if B was not positive definite</exception> 
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A and B was not of the same size</exception>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if <paramref name="skipSymmCheck"/> is false and either A and/or B was found not to be symmetric/hermitian</exception>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if the algorithm did not converge. All exceptions will contain an informational message describing the problem verbosely.</exception>
+        public static ILRetArray<float> eigSymm(ILInArray<float> A, ILInArray<float> B, ILOutArray< float> outV, GenEigenType type, bool skipSymmCheck) {
+            using (ILScope.Enter(A, B)) {
+                // check input arguments
+                if (object.Equals(A, null) || object.Equals(B, null))
+                    throw new ILArgumentException("A and B must not be null!");
+                if (!A.IsMatrix || !B.IsMatrix)
+                    throw new ILArgumentException("A & B must be matrices!");
+                int n = A.Size[0];
+                if (n != A.Size[1])
+                    throw new ILArgumentException("input matrices must be square!");
+                if (!A.Size.IsSameSize(B.Size))
+                    throw new ILArgumentException("A and B must have the same size!");
+                if (A.IsEmpty) {
+                    if (object.Equals(outV, null))
+                        return empty< float>(A.Size);
+                    else {
+                        outV.a = A.C;
+                        return empty< float>(A.Size);
+                    }
+                }
+                if (!skipSymmCheck && !ILMath.ishermitian(A)) {
+                    throw new ILArgumentException("A must be hermitian!");
+                }
+                if (!skipSymmCheck && !ILMath.ishermitian(B)) {
+                    throw new ILArgumentException("B must be hermitian!");
+                }
+                int info = -1;
+                int itype = 1;
+                switch (type) {
+                    case GenEigenType.Ax_eq_lambBx:
+                        itype = 1;
+                        break;
+                    case GenEigenType.ABx_eq_lambx:
+                        itype = 2;
+                        break;
+                    case GenEigenType.BAx_eq_lambx:
+                        itype = 3;
+                        break;
+                }
+                char jobz = 'N';
+                if (!object.Equals(outV, null)) {
+                    jobz = 'V';
+                    outV.a = copyUpperTriangle(A, n, n);
+                } else {
+                    ILArray< float> tmpOutV = copyUpperTriangle(A, n, n);
+                    outV = tmpOutV; 
+                }
+                ILArray< float> BC = B.C;
+               
+                float[] w = ILMemoryPool.Pool.New< float>(n);
+               
+                Lapack.ssygv(itype, jobz, 'U', n, outV.GetArrayForWrite(), n, BC.GetArrayForWrite(), BC.Size[0], w, ref info);
+                if (info == 0) {
+                    if (jobz == 'N')
+                        return array< float>(w, 1, n);
+                    else
+                        return diag(array< float>(w, 1, n));
+                } else if (info < 0) {
+                    throw new ILArgumentException("invalid parameter reported from Lapack module: #" + (-info));
+                } else {
+                    if (info <= n) {
+                        throw new ILArgumentException(String.Format("eigSymm did not converge! {0} off-diagonal elements unequal 0", info));
+                    } else if (info < 2 * n) {
+                        throw new ILArgumentException("eigSymm: B must be positive definite!");
+                    } else {
+                        throw new ILArgumentException("eigSymm: unknown Lapack module error");
+                    }
+                }
+            }
+        }
+
+
+        /// <summary>
+        /// Compute eigenvalues <it>lambda</it> of symmetrical/hermitian inputs A and B: A*V=lamda*B*V
+        /// </summary>
+        /// <param name="A">Square, symmetric/hermitian input matrix, size [n x n]</param>
+        /// <param name="B">Square, symmetric/hermitian and positive definite matrix, size [n x n]</param>
+        /// <returns>Vector of eigenvalues. size [n x 1]</returns>
+        /// <remarks>
+        /// <para>Internally, the generalized eigenproblem A*V = r*B*V will be reduced to B<sup>-1</sup>*A*V = r*V using cholesky factorization. The 
+        /// computations are handled by LAPACK functions DSYGV,SSYGV,CHEGV and ZHEGV.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if B was not positive definite</exception> 
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A and B was not of the same size</exception>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if either A and/or B was found not to be symmetric/hermitian</exception>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if the algorithm did not converge. All exceptions will contain an informational message describing the problem verbosely.</exception>
+        public static ILRetArray<float> eigSymm(ILInArray<fcomplex> A, ILInArray<fcomplex> B) {
+            using (ILScope.Enter(A, B)) {
+                return eigSymm(A, B, null, GenEigenType.Ax_eq_lambBx, false);
+            }
+        }
+
+        /// <summary>
+        /// Compute eigenvalues and eigenvectors of symmetric/hermitian input
+        /// </summary>
+        /// <param name="A">Square, symmetric/hermitian input matrix, size [n x n]</param>
+        /// <param name="B">Square, symmetric/hermitian and positive definite matrix, size [n x n]</param>
+        /// <param name="outV">[Output] Returns eigenvectors in columns (size [n x n]). </param>
+        /// <param name="skipSymmCheck">true: skip tests for A and B being hermitian.</param>
+        /// <returns>Vector of eigenvalues. The return value will be a diagonal matrix with the eigenvalues on the main diagonal.</returns>
+        /// <remarks><para>The eigenvectors in 'V' are not normalized!</para>
+        /// <para>Internally, the generalized eigenproblem A*V = r*B*V will be reduced to B<sup>-1</sup>*A*V = r*V using cholesky factorization. The 
+        /// computations are handled by LAPACK functions DSYGV,SSYGV,CHEGV and ZHEGV.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if B was not positive definite</exception> 
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A and B was not of the same size</exception>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if <paramref name="skipSymmCheck"/> is false and either A and/or B was found not to be symmetric/hermitian</exception>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if the algorithm did not converge. All exceptions will contain an informational message describing the problem verbosely.</exception>
+        public static ILRetArray<float> eigSymm(ILInArray<fcomplex> A, ILInArray<fcomplex> B, ILOutArray<fcomplex> outV, bool skipSymmCheck) {
+            using (ILScope.Enter(A, B)) {
+                return eigSymm(A, B, outV, GenEigenType.Ax_eq_lambBx, skipSymmCheck);
+            }
+        }
+
+        /// <summary>
+        /// Compute eigenvalues and eigenvectors (optional) of symmetric/hermitian input
+        /// </summary>
+        /// <param name="A">Square, symmetric/hermitian input matrix, size [n x n]</param>
+        /// <param name="B">Square, symmetric/hermitian and positive definite matrix, size [n x n]</param>
+        /// <param name="outV">[Output] If on input not null-> returns eigenvectors in columns (size [n x n]). If null on input -> eigenvectors will not get computed.</param>
+        /// <param name="type">Determine the type of problem. This is one of the following types:
+        /// <list type="bullet">
+        /// <item>Ax_eq_lambBx: A*V = r*B*V</item>
+        /// <item>ABx_eq_lambx: A*B*V = r*V</item>
+        /// <item>BAx_eq_lambx: B*A*V = r*V</item>
+        /// </list>Here 'r' is the eigenvalue corresponding to the eigenvector 'V'.</param>
+        /// <param name="skipSymmCheck">true: skip tests for A and B being hermitian.</param>
+        /// <returns>Vector of eigenvalues. If the eigenvectors are requested as well (V not null on input), 
+        /// the return value will be a diagonal matrix with the eigenvalues on the main diagonal.</returns>
+        /// <remarks><para>The eigenvectors in 'V' are not normalized!</para>
+        /// <para>Internally, the generalized eigenproblem A*V = r*B*V will be reduced to B<sup>-1</sup>*A*V = r*V using cholesky factorization. The 
+        /// computations are handled by LAPACK functions DSYGV,SSYGV,CHEGV and ZHEGV.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if B was not positive definite</exception> 
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A and B was not of the same size</exception>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if <paramref name="skipSymmCheck"/> is false and either A and/or B was found not to be symmetric/hermitian</exception>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if the algorithm did not converge. All exceptions will contain an informational message describing the problem verbosely.</exception>
+        public static ILRetArray<float> eigSymm(ILInArray<fcomplex> A, ILInArray<fcomplex> B, ILOutArray< fcomplex> outV, GenEigenType type, bool skipSymmCheck) {
+            using (ILScope.Enter(A, B)) {
+                // check input arguments
+                if (object.Equals(A, null) || object.Equals(B, null))
+                    throw new ILArgumentException("A and B must not be null!");
+                if (!A.IsMatrix || !B.IsMatrix)
+                    throw new ILArgumentException("A & B must be matrices!");
+                int n = A.Size[0];
+                if (n != A.Size[1])
+                    throw new ILArgumentException("input matrices must be square!");
+                if (!A.Size.IsSameSize(B.Size))
+                    throw new ILArgumentException("A and B must have the same size!");
+                if (A.IsEmpty) {
+                    if (object.Equals(outV, null))
+                        return empty< float>(A.Size);
+                    else {
+                        outV.a = A.C;
+                        return empty< float>(A.Size);
+                    }
+                }
+                if (!skipSymmCheck && !ILMath.ishermitian(A)) {
+                    throw new ILArgumentException("A must be hermitian!");
+                }
+                if (!skipSymmCheck && !ILMath.ishermitian(B)) {
+                    throw new ILArgumentException("B must be hermitian!");
+                }
+                int info = -1;
+                int itype = 1;
+                switch (type) {
+                    case GenEigenType.Ax_eq_lambBx:
+                        itype = 1;
+                        break;
+                    case GenEigenType.ABx_eq_lambx:
+                        itype = 2;
+                        break;
+                    case GenEigenType.BAx_eq_lambx:
+                        itype = 3;
+                        break;
+                }
+                char jobz = 'N';
+                if (!object.Equals(outV, null)) {
+                    jobz = 'V';
+                    outV.a = copyUpperTriangle(A, n, n);
+                } else {
+                    ILArray< fcomplex> tmpOutV = copyUpperTriangle(A, n, n);
+                    outV = tmpOutV; 
+                }
+                ILArray< fcomplex> BC = B.C;
+               
+                float[] w = ILMemoryPool.Pool.New< float>(n);
+               
+                Lapack.chegv(itype, jobz, 'U', n, outV.GetArrayForWrite(), n, BC.GetArrayForWrite(), BC.Size[0], w, ref info);
+                if (info == 0) {
+                    if (jobz == 'N')
+                        return array< float>(w, 1, n);
+                    else
+                        return diag(array< float>(w, 1, n));
+                } else if (info < 0) {
+                    throw new ILArgumentException("invalid parameter reported from Lapack module: #" + (-info));
+                } else {
+                    if (info <= n) {
+                        throw new ILArgumentException(String.Format("eigSymm did not converge! {0} off-diagonal elements unequal 0", info));
+                    } else if (info < 2 * n) {
+                        throw new ILArgumentException("eigSymm: B must be positive definite!");
+                    } else {
+                        throw new ILArgumentException("eigSymm: unknown Lapack module error");
+                    }
+                }
+            }
+        }
+
+
+        /// <summary>
+        /// Compute eigenvalues <it>lambda</it> of symmetrical/hermitian inputs A and B: A*V=lamda*B*V
+        /// </summary>
+        /// <param name="A">Square, symmetric/hermitian input matrix, size [n x n]</param>
+        /// <param name="B">Square, symmetric/hermitian and positive definite matrix, size [n x n]</param>
+        /// <returns>Vector of eigenvalues. size [n x 1]</returns>
+        /// <remarks>
+        /// <para>Internally, the generalized eigenproblem A*V = r*B*V will be reduced to B<sup>-1</sup>*A*V = r*V using cholesky factorization. The 
+        /// computations are handled by LAPACK functions DSYGV,SSYGV,CHEGV and ZHEGV.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if B was not positive definite</exception> 
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A and B was not of the same size</exception>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if either A and/or B was found not to be symmetric/hermitian</exception>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if the algorithm did not converge. All exceptions will contain an informational message describing the problem verbosely.</exception>
+        public static ILRetArray<double> eigSymm(ILInArray<complex> A, ILInArray<complex> B) {
+            using (ILScope.Enter(A, B)) {
+                return eigSymm(A, B, null, GenEigenType.Ax_eq_lambBx, false);
+            }
+        }
+
+        /// <summary>
+        /// Compute eigenvalues and eigenvectors of symmetric/hermitian input
+        /// </summary>
+        /// <param name="A">Square, symmetric/hermitian input matrix, size [n x n]</param>
+        /// <param name="B">Square, symmetric/hermitian and positive definite matrix, size [n x n]</param>
+        /// <param name="outV">[Output] Returns eigenvectors in columns (size [n x n]). </param>
+        /// <param name="skipSymmCheck">true: skip tests for A and B being hermitian.</param>
+        /// <returns>Vector of eigenvalues. The return value will be a diagonal matrix with the eigenvalues on the main diagonal.</returns>
+        /// <remarks><para>The eigenvectors in 'V' are not normalized!</para>
+        /// <para>Internally, the generalized eigenproblem A*V = r*B*V will be reduced to B<sup>-1</sup>*A*V = r*V using cholesky factorization. The 
+        /// computations are handled by LAPACK functions DSYGV,SSYGV,CHEGV and ZHEGV.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if B was not positive definite</exception> 
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A and B was not of the same size</exception>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if <paramref name="skipSymmCheck"/> is false and either A and/or B was found not to be symmetric/hermitian</exception>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if the algorithm did not converge. All exceptions will contain an informational message describing the problem verbosely.</exception>
+        public static ILRetArray<double> eigSymm(ILInArray<complex> A, ILInArray<complex> B, ILOutArray<complex> outV, bool skipSymmCheck) {
+            using (ILScope.Enter(A, B)) {
+                return eigSymm(A, B, outV, GenEigenType.Ax_eq_lambBx, skipSymmCheck);
+            }
+        }
+
+        /// <summary>
+        /// Compute eigenvalues and eigenvectors (optional) of symmetric/hermitian input
+        /// </summary>
+        /// <param name="A">Square, symmetric/hermitian input matrix, size [n x n]</param>
+        /// <param name="B">Square, symmetric/hermitian and positive definite matrix, size [n x n]</param>
+        /// <param name="outV">[Output] If on input not null-> returns eigenvectors in columns (size [n x n]). If null on input -> eigenvectors will not get computed.</param>
+        /// <param name="type">Determine the type of problem. This is one of the following types:
+        /// <list type="bullet">
+        /// <item>Ax_eq_lambBx: A*V = r*B*V</item>
+        /// <item>ABx_eq_lambx: A*B*V = r*V</item>
+        /// <item>BAx_eq_lambx: B*A*V = r*V</item>
+        /// </list>Here 'r' is the eigenvalue corresponding to the eigenvector 'V'.</param>
+        /// <param name="skipSymmCheck">true: skip tests for A and B being hermitian.</param>
+        /// <returns>Vector of eigenvalues. If the eigenvectors are requested as well (V not null on input), 
+        /// the return value will be a diagonal matrix with the eigenvalues on the main diagonal.</returns>
+        /// <remarks><para>The eigenvectors in 'V' are not normalized!</para>
+        /// <para>Internally, the generalized eigenproblem A*V = r*B*V will be reduced to B<sup>-1</sup>*A*V = r*V using cholesky factorization. The 
+        /// computations are handled by LAPACK functions DSYGV,SSYGV,CHEGV and ZHEGV.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if B was not positive definite</exception> 
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A and B was not of the same size</exception>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if <paramref name="skipSymmCheck"/> is false and either A and/or B was found not to be symmetric/hermitian</exception>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if the algorithm did not converge. All exceptions will contain an informational message describing the problem verbosely.</exception>
+        public static ILRetArray<double> eigSymm(ILInArray<complex> A, ILInArray<complex> B, ILOutArray< complex> outV, GenEigenType type, bool skipSymmCheck) {
+            using (ILScope.Enter(A, B)) {
+                // check input arguments
+                if (object.Equals(A, null) || object.Equals(B, null))
+                    throw new ILArgumentException("A and B must not be null!");
+                if (!A.IsMatrix || !B.IsMatrix)
+                    throw new ILArgumentException("A & B must be matrices!");
+                int n = A.Size[0];
+                if (n != A.Size[1])
+                    throw new ILArgumentException("input matrices must be square!");
+                if (!A.Size.IsSameSize(B.Size))
+                    throw new ILArgumentException("A and B must have the same size!");
+                if (A.IsEmpty) {
+                    if (object.Equals(outV, null))
+                        return empty< double>(A.Size);
+                    else {
+                        outV.a = A.C;
+                        return empty< double>(A.Size);
+                    }
+                }
+                if (!skipSymmCheck && !ILMath.ishermitian(A)) {
+                    throw new ILArgumentException("A must be hermitian!");
+                }
+                if (!skipSymmCheck && !ILMath.ishermitian(B)) {
+                    throw new ILArgumentException("B must be hermitian!");
+                }
+                int info = -1;
+                int itype = 1;
+                switch (type) {
+                    case GenEigenType.Ax_eq_lambBx:
+                        itype = 1;
+                        break;
+                    case GenEigenType.ABx_eq_lambx:
+                        itype = 2;
+                        break;
+                    case GenEigenType.BAx_eq_lambx:
+                        itype = 3;
+                        break;
+                }
+                char jobz = 'N';
+                if (!object.Equals(outV, null)) {
+                    jobz = 'V';
+                    outV.a = copyUpperTriangle(A, n, n);
+                } else {
+                    ILArray< complex> tmpOutV = copyUpperTriangle(A, n, n);
+                    outV = tmpOutV; 
+                }
+                ILArray< complex> BC = B.C;
+               
+                double[] w = ILMemoryPool.Pool.New< double>(n);
+               
+                Lapack.zhegv(itype, jobz, 'U', n, outV.GetArrayForWrite(), n, BC.GetArrayForWrite(), BC.Size[0], w, ref info);
+                if (info == 0) {
+                    if (jobz == 'N')
+                        return array< double>(w, 1, n);
+                    else
+                        return diag(array< double>(w, 1, n));
+                } else if (info < 0) {
+                    throw new ILArgumentException("invalid parameter reported from Lapack module: #" + (-info));
+                } else {
+                    if (info <= n) {
+                        throw new ILArgumentException(String.Format("eigSymm did not converge! {0} off-diagonal elements unequal 0", info));
+                    } else if (info < 2 * n) {
+                        throw new ILArgumentException("eigSymm: B must be positive definite!");
+                    } else {
+                        throw new ILArgumentException("eigSymm: unknown Lapack module error");
+                    }
+                }
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+   }
+}
+
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/empty.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/empty.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/empty.cs	(revision 9102)
@@ -0,0 +1,123 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.InteropServices; 
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Native;
+using ILNumerics.Exceptions;
+
+namespace ILNumerics {
+
+    public partial class ILMath {
+
+        /// <summary>
+        /// Create empty double array of size [0,0].
+        /// </summary>
+        /// <returns>Empty array</returns>
+        public static ILRetArray<double> empty() {
+            return ILRetArray<double>.empty(ILSize.Empty00);
+        }
+        /// <summary>
+        /// Create empty double array of specific size
+        /// </summary>
+        /// <param name="size">(Empty-) size of new empty array</param>
+        /// <returns>Empty array</returns>
+        public static ILRetArray<T> empty<T>(ILSize size) {
+            if (size.NumberOfElements > 0)
+                throw new ILArgumentException("the 'size' parameter must define an empty array size"); 
+            return new ILRetArray<T>(size);
+        }
+        /// <summary>
+        /// Create empty double array of specific size
+        /// </summary>
+        /// <param name="size">(Empty-) size of new empty array</param>
+        /// <returns>Empty array</returns>
+        public static ILRetArray<T> empty<T>(params int[] size) {
+            ILSize newDims = new ILSize(size);
+            if (newDims.NumberOfElements > 0)
+                throw new ILArgumentException("the 'size' parameter must define an empty array size");
+            return new ILRetArray<T>(newDims);
+        }
+        /// <summary>
+        /// Create empty array of size [0,0] and arbitrary element type
+        /// </summary>
+        /// <returns>Empty array</returns>
+        public static ILRetArray<T> empty<T>() {
+            return new ILRetArray<T>(ILSize.Empty00);
+        }
+        /// <summary>
+        /// Create empty double array of specific size
+        /// </summary>
+        /// <param name="size">(Empty-) size of new empty array</param>
+        /// <returns>Empty array</returns>
+        public static ILRetArray<double> empty(ILSize size) {
+            if (size.NumberOfElements > 0)
+                throw new ILArgumentException("the 'size' parameter must define an empty array size");
+            return new ILRetArray<double>(size);
+        }
+        /// <summary>
+        /// Create empty double array of specific size
+        /// </summary>
+        /// <param name="size">(Empty-) size of new empty array</param>
+        /// <returns>Empty array</returns>
+        public static ILRetArray<double> empty(params int[] size) {
+            ILSize newDims = new ILSize(size);
+            if (newDims.NumberOfElements > 0)
+                throw new ILArgumentException("the 'size' parameter must define an empty array size");
+            return new ILRetArray<double>(newDims);
+        }
+        /// <summary>
+        /// Create new empty array, used for array class members
+        /// </summary>
+        /// <typeparam name="T">Element type</typeparam>
+        /// <returns>Empty array which can afterwards be used for arbitrary assignements (Assign(), or 'array.A = ..' assignements)</returns>
+        /// <remarks>The array returned will be an empty array initially. Its main purpose is to provide 
+        /// a persistant array initialization. The array will not be disposed after leaving the current scope
+        /// and can therefore be utilized for initializing class attributes. After initialization, use the 'ILArray.A = ...' property (C#) 
+        /// or the ILArray.Assign() function to assign new values to the array.</remarks>
+        public static ILArray<T> returnType<T>() {
+            return new ILArray<T>(new ILDenseStorage<T>(ILSize.Empty00), false);
+        }
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/end.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/end.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/end.cs	(revision 9102)
@@ -0,0 +1,70 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using ILNumerics.Misc; 
+using System.Linq.Expressions; 
+
+namespace ILNumerics {
+    // ToDo: DOKU add example
+    public partial class ILMath {
+
+        private static ILExpression s_end = new ILExpression(Expression.Parameter(typeof(int), "end")); 
+        
+        /// <summary>
+        /// Substitute for the index of the last element of a dimension
+        /// </summary>
+        /// <remarks>The 'end' placeholder can be used in subarray specification expressions. It will get 
+        /// evaluated in a delayed manner, once the index of the dimension (and therefore the dimension length)
+        /// is known. It than evaluates to the number of the index of the last element in the dimension.
+        /// </remarks>
+        public static ILExpression end { 
+            get {
+                if (object.Equals(s_end, null) || s_end.IsDisposed) {
+                    s_end = new ILExpression(Expression.Parameter(typeof(int), "end")); 
+                }
+                return s_end; 
+            }
+        }
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/eps.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/eps.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/eps.cs	(revision 9102)
@@ -0,0 +1,519 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions;
+
+namespace ILNumerics {
+
+    public partial class ILMath {
+        /// <summary>
+        /// Double precision epsilon - the smallest difference from 1.0
+        /// </summary>
+        public static double eps {
+            get {
+                return MachineParameterDouble.eps;
+            }
+        }
+        /// <summary>
+        /// Single precision epsilon - the smalles difference from 1.0f
+        /// </summary>
+        public static float epsf {
+            get {
+                return MachineParameterSingle.eps;
+            }
+        }
+    }
+
+    /// <summary>
+    /// Extensive numerical machine parameter infos - single precision
+    /// </summary>
+    public struct MachineParameterSingle {
+        /// <summary>
+        /// Radix
+        /// </summary>
+        public int ibeta; 
+        /// <summary>
+        /// Number of base digits(bits) in the mantissa
+        /// </summary>
+        public int it;
+        /// <summary>
+        /// Rounding and underflow information.  
+        /// </summary>
+        /// <remarks><list type="bullet"><listheader>Rounding properties</listheader>
+        /// <item>2,5: IEEE rounding conform </item>
+        /// <item>1,4: not IEEE conform rounding </item>
+        /// <item>0,3: truncating - no rounding </item></list>
+        /// <list type="bullet"><listheader>Under-/ Overflow. numbers below xmin will be interpreted as... </listheader>
+        /// <item>0,1,2: zero</item>
+        /// <item>3,4,5: xmin (IEEE conform)</item></list></remarks>
+        public int irnd; 
+        /// <summary>
+        /// Number of guard digits in the product of 2 mantissas
+        /// </summary>
+        public int ngrd; 
+        /// <summary>
+        /// Exponent of the smalles number ibeta^machep &gt; 1.0
+        /// </summary>
+        public int machep; 
+        /// <summary>
+        /// Exponent of smallest number ibeta^negep wich may be substracted from 1.0, giving a result not equal to 1.0
+        /// </summary>
+        public int negep; 
+        /// <summary>
+        /// Number of exponent bits 
+        /// </summary>
+        public int iexp; 
+        /// <summary>
+        /// Smallest power of ibeta without leading zeros in the mantissa
+        /// </summary>
+        public int minexp; 
+        /// <summary>
+        /// Smallest power of ibeta where overflow occours
+        /// </summary>
+        public int maxexp; 
+        /// <summary>
+        /// Distance between the smallest number &gt; 1.0, distinguishable from 1.0 and 1.0
+        /// </summary>
+        /// <remarks>This number is computed by ibeta <sup>machep</sup>.</remarks>
+        public float eps; 
+        /// <summary>
+        /// Alternative eps. ibeta <sup>negep</sup>
+        /// </summary>
+        public float epsneg; 
+        /// <summary>
+        /// Smallest floating point number
+        /// </summary>
+        public float xmin; 
+        /// <summary>
+        /// Largest floating point number
+        /// </summary>
+        public float xmax;
+    }
+    /// <summary>
+    /// Extensive numerical machine parameter infos - double precision
+    /// </summary>
+    public struct MachineParameterDouble {
+        /// <summary>
+        /// Radix
+        /// </summary>
+        public int ibeta; 
+        /// <summary>
+        /// Number of base digits(bits) in the mantissa
+        /// </summary>
+        public int it;
+        /// <summary>
+        /// Rounding and underflow information.  
+        /// </summary>
+        /// <remarks><list type="bullet"><listheader>Rounding properties</listheader>
+        /// <item>2,5: IEEE rounding conform </item>
+        /// <item>1,4: not IEEE conform rounding </item>
+        /// <item>0,3: truncating - no rounding </item></list>
+        /// <list type="bullet"><listheader>Under-/ Overflow. numbers below xmin will be interpreted as... </listheader>
+        /// <item>0,1,2: zero</item>
+        /// <item>3,4,5: xmin (IEEE conform)</item></list></remarks>
+        public int irnd; 
+        /// <summary>
+        /// Number of guard digits in the product of 2 mantissas
+        /// </summary>
+        public int ngrd; 
+        /// <summary>
+        /// Exponent of the smalles number ibeta^machep &gt; 1.0
+        /// </summary>
+        public int machep; 
+        /// <summary>
+        /// Exponent of smallest number ibeta^negep wich may be substracted from 1.0, giving a result not equal to 1.0
+        /// </summary>
+        public int negep; 
+        /// <summary>
+        /// Number of exponent bits 
+        /// </summary>
+        public int iexp; 
+        /// <summary>
+        /// Smallest power of ibeta without leading zeros in the mantissa
+        /// </summary>
+        public int minexp; 
+        /// <summary>
+        /// Smallest power of ibeta where overflow occours
+        /// </summary>
+        public int maxexp; 
+        /// <summary>
+        /// Distance between the smallest number &gt; 1.0, distinguishable from 1.0 and 1.0
+        /// </summary>
+        /// <remarks>This number is computed by ibeta <sup>machep</sup>.</remarks>
+        public double eps; 
+        /// <summary>
+        /// Alternative eps. ibeta <sup>negep</sup>
+        /// </summary>
+        public double epsneg; 
+        /// <summary>
+        /// Smallest floating point number
+        /// </summary>
+        public double xmin; 
+        /// <summary>
+        /// Largest floating point number
+        /// </summary>
+        public double xmax;
+    }
+}
+
+
+namespace ILNumerics  {
+    public partial class ILMath {
+
+        /// <summary>
+        /// Definition of pi
+        /// </summary>
+        /// <remarks>This is an convenience alias for Math.PI</remarks>
+        public static readonly double pi = Math.PI;
+
+        /// <summary>
+        /// Definition of pi, single precision
+        /// </summary>
+        /// <remarks>This is an convenience alias for Math.PI</remarks>
+        public static readonly float pif = (float)Math.PI; 
+
+        private static MachineParameterDouble m_machparDouble; 
+        /// <summary>
+        /// Give extensive numerical machine parameter informations - double precision
+        /// </summary>
+        public static MachineParameterDouble MachineParameterDouble {
+            get {
+                return m_machparDouble;
+            }
+        }
+        private static MachineParameterSingle m_machparSingle; 
+        /// <summary>
+        /// Give extensive numerical machine parameter informations - single precision
+        /// </summary>
+        public static MachineParameterSingle MachineParameterSingle {
+            get {
+                return m_machparSingle; 
+            }
+        }
+        /// <summary>
+        /// Prevent JIT "optimizations" - force single precision to be applied
+        /// </summary>
+        /// <typeparam name="T">mainly float here</typeparam>
+        private class precisionHelper<T> { 
+            public T V;
+        }
+        /// <summary>
+        /// Determine machine specific parameter
+        /// </summary>
+        /// <remarks>Source: Numerical Recipes in C, p.892</remarks>
+        internal static void macharF(ref int ibeta, ref int it, ref int irnd, ref int ngrd, ref int machep, ref int negep,
+                        ref int iexp, ref int minexp, ref int maxexp, ref float eps, ref float epsneg, ref float xmin, ref float xmax) {
+            int i, itemp, iz, j, k, mx, nxres; 
+            precisionHelper<float> a = new precisionHelper<float>(), 
+                b = new precisionHelper<float>(),
+                beta = new precisionHelper<float>(),
+                betah = new precisionHelper<float>(),
+                betain = new precisionHelper<float>(),
+                one = new precisionHelper<float>(),
+                t = new precisionHelper<float>(),
+                temp = new precisionHelper<float>(),
+                temp1 = new precisionHelper<float>(),
+                tempa = new precisionHelper<float>(),
+                two = new precisionHelper<float>(),
+                y = new precisionHelper<float>(),
+                z = new precisionHelper<float>(),
+                zero = new precisionHelper<float>();
+
+            one.V = 1f;
+            two.V = one.V + one.V;
+            zero.V = one.V - one.V;
+            a.V = one.V; 
+            do {
+                a.V += a.V;
+                temp.V = a.V + one.V;
+                temp1.V = temp.V - a.V;
+            } while (temp1.V - one.V == zero.V);
+            b.V = one.V; 
+            do {
+                b.V += b.V;
+                temp.V = a.V + b.V;
+                itemp = (int)(temp.V - a.V); 
+            } while (itemp == 0); 
+            ibeta = itemp;
+            beta.V = (float)ibeta; 
+            it = 0; 
+            b.V = one.V; 
+            do {
+                ++it;
+                b.V *= beta.V;
+                temp.V = b.V + one.V;
+                temp1.V = temp.V - b.V;
+            } while (temp1.V - one.V == zero.V);
+            irnd = 0;
+            betah.V = beta.V / two.V; 
+            temp.V = a.V + betah.V; 
+            if (temp.V-a.V != zero.V) irnd = 1; 
+            tempa.V = a.V + beta.V; 
+            temp.V = tempa.V + betah.V; 
+            if (irnd == 0 && temp.V - tempa.V != zero.V) irnd = 2; 
+            negep = it + 3; 
+            betain.V = one.V / beta.V; 
+            a.V = one.V; 
+            for (i = 1; i <= negep; i++) a.V *= betain.V; 
+            b.V = a.V; 
+            for (;;) {
+                temp.V = one.V -a.V; 
+                if (temp.V-one.V != zero.V)  break; 
+                a.V *= beta.V; 
+                --negep; 
+            } 
+            negep = -negep; 
+            epsneg = a.V; 
+            machep = -it -3; 
+            a.V = b.V; 
+            for (;;) {
+                temp.V = one.V +a.V; 
+                if (temp.V - one.V != zero.V) break; 
+                a.V *= beta.V; 
+                ++machep; 
+            }
+            eps = a.V; 
+            ngrd =0; 
+            temp.V = one.V + eps;
+            if (irnd == 0 && temp.V * one.V - one.V != zero.V) ngrd = 1;
+            i = 0; 
+            k = 1; 
+            z.V = betain.V; 
+            t.V = one.V + eps; 
+            nxres = 0; 
+            for (;;) {
+                y.V = z.V; 
+                z.V = y.V *y.V;
+                a.V = z.V * one.V; 
+                temp.V = z.V * t.V; 
+                if (a.V + a.V == zero.V || (float)Math.Abs(z.V) >= y.V) break; 
+                temp1.V = temp.V * betain.V; 
+                if (temp1.V * beta.V == z.V) break; 
+                ++i; 
+                k += k; 
+            }
+            if (ibeta != 10) {
+                iexp = i+1; 
+                mx = k + k; 
+            }else {
+                iexp = 2; 
+                iz = ibeta; 
+                while (k >= iz) {
+                    iz *= ibeta; 
+                    ++iexp; 
+                }
+                mx = iz + iz-1; 
+            }
+            for (;;) {
+                xmin = y.V; 
+                y.V *= betain.V;
+                a.V = y.V * one.V; 
+                temp.V = y.V * t.V; 
+                if (a.V+a.V != zero.V && (float)Math.Abs(y.V) < xmin) {
+                    ++k; 
+                    temp1.V = temp.V* betain.V; 
+                    if (temp1.V * beta.V == y.V && temp.V != y.V) {
+                        nxres = 3; 
+                        xmin = y.V; 
+                        break; 
+                    }
+                }
+                else break; 
+            }
+            minexp = -k; 
+            if (mx <= k + k - 3 && ibeta != 10) {
+                mx += mx; 
+                ++iexp; 
+            }
+            maxexp = mx + minexp; 
+            irnd += nxres; 
+            if (irnd >= 2) maxexp -= 2; 
+            i = maxexp + minexp; 
+            if (ibeta == 2 && i != 0) --maxexp; 
+            if (i > 20) --maxexp; 
+            if (a.V != y.V) maxexp -= 2;
+            xmax = one.V -epsneg; 
+            if (maxexp * one.V != xmax) xmax = one.V - beta.V * epsneg; 
+            xmax /= xmin * beta.V * beta.V * beta.V; 
+            i = maxexp + minexp + 3; 
+            for (j = 1; j <= i; j++){ 
+                if (ibeta == 2) xmax += xmax; 
+                else xmax *= beta.V; 
+            }
+        }
+
+        /// <summary>
+        /// Determine machine specific parameter (double precision)
+        /// </summary>
+        /// <remarks>Source: Numerical Recipes in C, p.892</remarks>
+        internal static void macharD(ref int ibeta, ref int it, ref int irnd, ref int ngrd, ref int machep, ref int negep,
+                        ref int iexp, ref int minexp, ref int maxexp, ref double eps, ref double epsneg, ref double xmin, ref double xmax) {
+            int i, itemp, iz, j, k, mx, nxres; 
+            double a,b,beta,betah,betain,one,t,temp,temp1,tempa,two,y,z,zero;
+
+            one= (double)1; 
+            two = one + one; 
+            zero = one - one; 
+            a = one; 
+            do {
+                a += a; 
+                temp = a+one; 
+                temp1= temp-a; 
+            } while (temp1-one == zero); 
+            b = one; 
+            do {
+                b += b; 
+                temp=a+b; 
+                itemp=(int)(temp-a); 
+            } while (itemp == 0); 
+            ibeta = itemp; 
+            beta = (double)ibeta; 
+            it = 0; 
+            b = one; 
+            do {
+                ++it; 
+                b *= beta;
+                temp = b +one; 
+                temp1 = temp -b; 
+            }while (temp1-one == zero);
+            irnd = 0; 
+            betah = beta / two; 
+            temp = a + betah; 
+            if (temp-a != zero) irnd = 1; 
+            tempa = a + beta; 
+            temp = tempa + betah; 
+            if (irnd == 0 && temp - tempa != zero) irnd = 2; 
+            negep = it + 3; 
+            betain = one / beta; 
+            a = one; 
+            for (i = 1; i <= negep; i++) a *= betain; 
+            b =a; 
+            for (;;) {
+                temp = one -a; 
+                if (temp-one != zero)  break; 
+                a *= beta; 
+                --negep; 
+            } 
+            negep = -negep; 
+            epsneg = a; 
+            machep = -it -3; 
+            a = b; 
+            for (;;) {
+                temp = one +a; 
+                if (temp - one != zero) break; 
+                a *= beta; 
+                ++machep; 
+            }
+            eps = a; 
+            ngrd =0; 
+            temp = one + eps;
+            if (irnd == 0 && temp * one - one != zero) ngrd = 1;
+            i = 0; 
+            k = 1; 
+            z = betain; 
+            t = one + eps; 
+            nxres = 0; 
+            for (;;) {
+                y = z; 
+                z = y *y;
+                a = z * one; 
+                temp = z * t; 
+                if (a + a == zero || (double)Math.Abs(z) >= y) break; 
+                temp1 = temp * betain; 
+                if (temp1 * beta == z) break; 
+                ++i; 
+                k += k; 
+            }
+            if (ibeta != 10) {
+                iexp = i+1; 
+                mx = k + k; 
+            }else {
+                iexp = 2; 
+                iz = ibeta; 
+                while (k >= iz) {
+                    iz *= ibeta; 
+                    ++iexp; 
+                }
+                mx = iz + iz-1; 
+            }
+            for (;;) {
+                xmin = y; 
+                y *= betain;
+                a = y * one; 
+                temp = y * t; 
+                if (a+a != zero && (double)Math.Abs(y) < xmin) {
+                    ++k; 
+                    temp1 = temp* betain; 
+                    if (temp1 * beta == y && temp != y) {
+                        nxres = 3; 
+                        xmin = y; 
+                        break; 
+                    }
+                }
+                else break; 
+            }
+            minexp = -k; 
+            if (mx <= k + k - 3 && ibeta != 10) {
+                mx += mx; 
+                ++iexp; 
+            }
+            maxexp = mx + minexp; 
+            irnd += nxres; 
+            if (irnd >= 2) maxexp -= 2; 
+            i = maxexp + minexp; 
+            if (ibeta == 2 && i != 0) --maxexp; 
+            if (i > 20) --maxexp; 
+            if (a != y) maxexp -= 2;
+            xmax = one -epsneg; 
+            if (maxexp * one != xmax) xmax = one - beta * epsneg; 
+            xmax /= xmin * beta * beta * beta; 
+            i = maxexp + minexp + 3; 
+            for (j = 1; j <= i; j++){ 
+                if (ibeta == 2) xmax += xmax; 
+                else xmax *= beta; 
+            }
+        }
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/eq.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/eq.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/eq.cs	(revision 9102)
@@ -0,0 +1,2014 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.InteropServices; 
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Native;
+using ILNumerics.Exceptions;
+
+namespace ILNumerics {
+
+    public partial class ILMath {
+
+
+        /// <summary>Elementwise logical 'equal' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array having '1' for equal elements in A and B, '0' else</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  eq(ILInArray<double> A, ILInArray<double> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+                
+                double[] arrA = A.GetArrayForRead();
+                
+                double[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                        
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0)  == B.GetValue(0)) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  eqEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                     double scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                             double* ap = ((double*)range.Item3 + range.Item1);
+                             double* bp = ((double*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                                
+                                *cp = (*ap  == *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((double*)range.Item3 + range.Item1);
+                            scalar = *((double*)range.Item4);
+                            while (cp < cLast) {
+                                
+                                *cp = (*ap  == scalar) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((double*)range.Item3);
+                            bp = ((double*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                                
+                                *cp = (scalar  == *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (double* arrAP = arrA)
+                fixed (double* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  eqEx(ILInArray<double> A, ILInArray<double> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+                
+                double[] arrA = A.GetArrayForRead();
+                
+                double[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                    
+                    double* ap;
+                    
+                    double* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (double*)range.Item3;
+                                bp = (double*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    
+                                    *cp = (*ap  == *bp) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (double*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (double*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    
+                                    *cp = (*ap  == *bp) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( double* arrAP = arrA)
+                fixed ( double* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>Elementwise logical 'equal' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array having '1' for equal elements in A and B, '0' else</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  eq(ILInArray<Int64> A, ILInArray<Int64> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                Int64[] arrA = A.GetArrayForRead();
+               
+                Int64[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                       
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0)  == B.GetValue(0)) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  eqEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    Int64 scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            Int64* ap = ((Int64*)range.Item3 + range.Item1);
+                            Int64* bp = ((Int64*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  == *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((Int64*)range.Item3 + range.Item1);
+                            scalar = *((Int64*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  == scalar) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((Int64*)range.Item3);
+                            bp = ((Int64*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (scalar  == *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (Int64* arrAP = arrA)
+                fixed (Int64* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  eqEx(ILInArray<Int64> A, ILInArray<Int64> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                Int64[] arrA = A.GetArrayForRead();
+               
+                Int64[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    Int64* ap;
+                   
+                    Int64* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (Int64*)range.Item3;
+                                bp = (Int64*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  == *bp) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (Int64*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (Int64*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  == *bp) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( Int64* arrAP = arrA)
+                fixed ( Int64* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'equal' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array having '1' for equal elements in A and B, '0' else</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  eq(ILInArray<Int32> A, ILInArray<Int32> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                Int32[] arrA = A.GetArrayForRead();
+               
+                Int32[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                       
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0)  == B.GetValue(0)) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  eqEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    Int32 scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            Int32* ap = ((Int32*)range.Item3 + range.Item1);
+                            Int32* bp = ((Int32*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  == *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((Int32*)range.Item3 + range.Item1);
+                            scalar = *((Int32*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  == scalar) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((Int32*)range.Item3);
+                            bp = ((Int32*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (scalar  == *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (Int32* arrAP = arrA)
+                fixed (Int32* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  eqEx(ILInArray<Int32> A, ILInArray<Int32> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                Int32[] arrA = A.GetArrayForRead();
+               
+                Int32[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    Int32* ap;
+                   
+                    Int32* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (Int32*)range.Item3;
+                                bp = (Int32*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  == *bp) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (Int32*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (Int32*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  == *bp) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( Int32* arrAP = arrA)
+                fixed ( Int32* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'equal' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array having '1' for equal elements in A and B, '0' else</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  eq(ILInArray<float> A, ILInArray<float> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                float[] arrA = A.GetArrayForRead();
+               
+                float[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                       
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0)  == B.GetValue(0)) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  eqEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    float scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            float* ap = ((float*)range.Item3 + range.Item1);
+                            float* bp = ((float*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  == *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((float*)range.Item3 + range.Item1);
+                            scalar = *((float*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  == scalar) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((float*)range.Item3);
+                            bp = ((float*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (scalar  == *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (float* arrAP = arrA)
+                fixed (float* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  eqEx(ILInArray<float> A, ILInArray<float> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                float[] arrA = A.GetArrayForRead();
+               
+                float[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    float* ap;
+                   
+                    float* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (float*)range.Item3;
+                                bp = (float*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  == *bp) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (float*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (float*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  == *bp) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( float* arrAP = arrA)
+                fixed ( float* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'equal' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array having '1' for equal elements in A and B, '0' else</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  eq(ILInArray<fcomplex> A, ILInArray<fcomplex> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                fcomplex[] arrA = A.GetArrayForRead();
+               
+                fcomplex[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                       
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0)  == B.GetValue(0)) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  eqEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    fcomplex scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            fcomplex* ap = ((fcomplex*)range.Item3 + range.Item1);
+                            fcomplex* bp = ((fcomplex*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  == *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((fcomplex*)range.Item3 + range.Item1);
+                            scalar = *((fcomplex*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  == scalar) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((fcomplex*)range.Item3);
+                            bp = ((fcomplex*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (scalar  == *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (fcomplex* arrAP = arrA)
+                fixed (fcomplex* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  eqEx(ILInArray<fcomplex> A, ILInArray<fcomplex> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                fcomplex[] arrA = A.GetArrayForRead();
+               
+                fcomplex[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    fcomplex* ap;
+                   
+                    fcomplex* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (fcomplex*)range.Item3;
+                                bp = (fcomplex*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  == *bp) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (fcomplex*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (fcomplex*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  == *bp) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( fcomplex* arrAP = arrA)
+                fixed ( fcomplex* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'equal' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array having '1' for equal elements in A and B, '0' else</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  eq(ILInArray<complex> A, ILInArray<complex> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                complex[] arrA = A.GetArrayForRead();
+               
+                complex[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                       
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0)  == B.GetValue(0)) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  eqEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    complex scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            complex* ap = ((complex*)range.Item3 + range.Item1);
+                            complex* bp = ((complex*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  == *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((complex*)range.Item3 + range.Item1);
+                            scalar = *((complex*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  == scalar) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((complex*)range.Item3);
+                            bp = ((complex*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (scalar  == *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (complex* arrAP = arrA)
+                fixed (complex* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  eqEx(ILInArray<complex> A, ILInArray<complex> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                complex[] arrA = A.GetArrayForRead();
+               
+                complex[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    complex* ap;
+                   
+                    complex* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (complex*)range.Item3;
+                                bp = (complex*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  == *bp) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (complex*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (complex*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  == *bp) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( complex* arrAP = arrA)
+                fixed ( complex* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'equal' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array having '1' for equal elements in A and B, '0' else</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  eq(ILInArray<byte> A, ILInArray<byte> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                byte[] arrA = A.GetArrayForRead();
+               
+                byte[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                       
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0)  == B.GetValue(0)) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  eqEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    byte scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            byte* ap = ((byte*)range.Item3 + range.Item1);
+                            byte* bp = ((byte*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  == *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((byte*)range.Item3 + range.Item1);
+                            scalar = *((byte*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  == scalar) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((byte*)range.Item3);
+                            bp = ((byte*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (scalar  == *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (byte* arrAP = arrA)
+                fixed (byte* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  eqEx(ILInArray<byte> A, ILInArray<byte> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                byte[] arrA = A.GetArrayForRead();
+               
+                byte[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    byte* ap;
+                   
+                    byte* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (byte*)range.Item3;
+                                bp = (byte*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  == *bp) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (byte*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (byte*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  == *bp) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( byte* arrAP = arrA)
+                fixed ( byte* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// Elementwise logical 'equal' operator
+        /// </summary>
+        /// <param name="A">Input array 1</param>
+        /// <param name="B">Input array 2</param>
+        /// <returns>Logical array having '1' for equal elements in A and B, '0' else</returns>
+        /// <remarks><para>On empty input - empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para>
+        /// <para>If neither of A or B is scalar or empty, the dimensions of both arrays must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither of A or B is scalar and the size of both arrays does not match.</exception>
+        public static ILRetLogical eq (ILInArray<String> A, ILInArray<String> B) {
+            if (object.Equals(A,null)) 
+                throw new ILArgumentException("eq: input argurment A must not be null!");
+            if (object.Equals(B,null)) 
+                throw new ILArgumentException("eq: input argurment B must not be null!");
+            if (!A.Size.IsSameShape(B.Size)) 
+                throw new ILArgumentException("input arrays must have the same size"); 
+            if (A.IsEmpty || B.IsEmpty)
+                return new ILRetLogical(ILSize.Empty00); 
+            string scalarValue; 
+            ILSize retDim = null; 
+            byte[] retArr = null; 
+            if (A.IsScalar) {
+                if (B.IsScalar) {
+                    retDim = new ILSize(1,1); 
+                    return new ILRetLogical(new byte[1]{(A.GetValue(0) == B.GetValue(0))?(byte)1:(byte)0},1,1); 
+                } else {
+                    retDim = B.Size; 
+                    int len = B.Size.NumberOfElements; 
+                    retArr = new byte[len]; 
+                    scalarValue = (string)A.GetValue(0); 
+                    for (int i = 0; i < len; i++) {
+                        if (scalarValue == (string)B.GetValue(i)) {
+                            retArr[i] = 1; 
+                        }
+                    }
+                }
+            } else {
+                retDim = A.Size; 
+                if (B.IsScalar) {
+                    int len = A.Size.NumberOfElements; 
+                    retArr = new byte[len]; 
+                    scalarValue = B.GetValue(0); 
+                    for (int i = 0; i < len; i++) {
+                        if (scalarValue == A.GetValue(i))
+                            retArr[i] = 1; 
+                    }
+                } else {
+                    if (!A.Size.IsSameSize(B.Size))
+                        throw new ILDimensionMismatchException("eq: size of arrays must match!");
+                    int len = A.Size.NumberOfElements; 
+                    retArr = new byte[len]; 
+                    for (int i = 0; i < len; i++) {
+                        if (A.GetValue(i) == B.GetValue(i))
+                            retArr[i] = 1; 
+                    }
+                }
+            }
+            return new ILRetLogical(retArr,retDim); 
+        }
+        
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/exp.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/exp.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/exp.cs	(revision 9102)
@@ -0,0 +1,559 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics;
+using ILNumerics.Exceptions; 
+using ILNumerics.Storage; 
+using ILNumerics.Misc; 
+
+
+
+namespace ILNumerics {
+
+    public partial class ILMath {
+
+
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>Exponential of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Exponential of array elements</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<complex>  exp (ILInArray< complex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<complex>(A.Size); 
+                ILSize inDim = A.Size;
+                complex[] arrA = A.GetArrayForRead(); 
+                complex [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<complex>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<complex> retStorage = new ILDenseStorage<complex>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    complex* cp = ((complex*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  complex.Exp(cp[0]  )  /*dummy*/;
+                            cp[1] =  complex.Exp(cp[1]  )  /*dummy*/;
+                            cp[2] =  complex.Exp(cp[2]  )  /*dummy*/;
+                            cp[3] =  complex.Exp(cp[3]  )  /*dummy*/;
+                            cp[4] =  complex.Exp(cp[4]  )  /*dummy*/;
+                            cp[5] =  complex.Exp(cp[5]  )  /*dummy*/;
+                            cp[6] =  complex.Exp(cp[6]  )  /*dummy*/;
+                            cp[7] =  complex.Exp(cp[7]  )  /*dummy*/;
+                            cp[8] =  complex.Exp(cp[8]  )  /*dummy*/;
+                            cp[9] =  complex.Exp(cp[9]  )  /*dummy*/;
+                            cp[10] =  complex.Exp(cp[10]  )  /*dummy*/;
+                            cp[11] =  complex.Exp(cp[11]  )  /*dummy*/;
+                            cp[12] =  complex.Exp(cp[12]  )  /*dummy*/;
+                            cp[13] =  complex.Exp(cp[13]  )  /*dummy*/;
+                            cp[14] =  complex.Exp(cp[14]  )  /*dummy*/;
+                            cp[15] =  complex.Exp(cp[15]  )  /*dummy*/;
+                            cp[16] =  complex.Exp(cp[16]  )  /*dummy*/;
+                            cp[17] =  complex.Exp(cp[17]  )  /*dummy*/;
+                            cp[18] =  complex.Exp(cp[18]  )  /*dummy*/;
+                            cp[19] =  complex.Exp(cp[19]  )  /*dummy*/;
+                            cp[20] =  complex.Exp(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.Exp(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        complex* ap = ((complex*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  complex.Exp(ap[0]  )  /*dummy*/;
+                            cp[1] =  complex.Exp(ap[1]  )  /*dummy*/;
+                            cp[2] =  complex.Exp(ap[2]  )  /*dummy*/;
+                            cp[3] =  complex.Exp(ap[3]  )  /*dummy*/;
+                            cp[4] =  complex.Exp(ap[4]  )  /*dummy*/;
+                            cp[5] =  complex.Exp(ap[5]  )  /*dummy*/;
+                            cp[6] =  complex.Exp(ap[6]  )  /*dummy*/;
+                            cp[7] =  complex.Exp(ap[7]  )  /*dummy*/;
+                            cp[8] =  complex.Exp(ap[8]  )  /*dummy*/;
+                            cp[9] =  complex.Exp(ap[9]  )  /*dummy*/;
+                            cp[10] =  complex.Exp(ap[10]  )  /*dummy*/;
+                            cp[11] =  complex.Exp(ap[11]  )  /*dummy*/;
+                            cp[12] =  complex.Exp(ap[12]  )  /*dummy*/;
+                            cp[13] =  complex.Exp(ap[13]  )  /*dummy*/;
+                            cp[14] =  complex.Exp(ap[14]  )  /*dummy*/;
+                            cp[15] =  complex.Exp(ap[15]  )  /*dummy*/;
+                            cp[16] =  complex.Exp(ap[16]  )  /*dummy*/;
+                            cp[17] =  complex.Exp(ap[17]  )  /*dummy*/;
+                            cp[18] =  complex.Exp(ap[18]  )  /*dummy*/;
+                            cp[19] =  complex.Exp(ap[19]  )  /*dummy*/;
+                            cp[20] =  complex.Exp(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.Exp(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( complex* arrAP = arrA)
+                fixed ( complex* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<complex>(retStorage);
+            }
+        }
+        /// <summary>Exponential of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Exponential of array elements</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<fcomplex>  exp (ILInArray< fcomplex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<fcomplex>(A.Size); 
+                ILSize inDim = A.Size;
+                fcomplex[] arrA = A.GetArrayForRead(); 
+                fcomplex [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<fcomplex>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<fcomplex> retStorage = new ILDenseStorage<fcomplex>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    fcomplex* cp = ((fcomplex*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  fcomplex.Exp(cp[0]  )  /*dummy*/;
+                            cp[1] =  fcomplex.Exp(cp[1]  )  /*dummy*/;
+                            cp[2] =  fcomplex.Exp(cp[2]  )  /*dummy*/;
+                            cp[3] =  fcomplex.Exp(cp[3]  )  /*dummy*/;
+                            cp[4] =  fcomplex.Exp(cp[4]  )  /*dummy*/;
+                            cp[5] =  fcomplex.Exp(cp[5]  )  /*dummy*/;
+                            cp[6] =  fcomplex.Exp(cp[6]  )  /*dummy*/;
+                            cp[7] =  fcomplex.Exp(cp[7]  )  /*dummy*/;
+                            cp[8] =  fcomplex.Exp(cp[8]  )  /*dummy*/;
+                            cp[9] =  fcomplex.Exp(cp[9]  )  /*dummy*/;
+                            cp[10] =  fcomplex.Exp(cp[10]  )  /*dummy*/;
+                            cp[11] =  fcomplex.Exp(cp[11]  )  /*dummy*/;
+                            cp[12] =  fcomplex.Exp(cp[12]  )  /*dummy*/;
+                            cp[13] =  fcomplex.Exp(cp[13]  )  /*dummy*/;
+                            cp[14] =  fcomplex.Exp(cp[14]  )  /*dummy*/;
+                            cp[15] =  fcomplex.Exp(cp[15]  )  /*dummy*/;
+                            cp[16] =  fcomplex.Exp(cp[16]  )  /*dummy*/;
+                            cp[17] =  fcomplex.Exp(cp[17]  )  /*dummy*/;
+                            cp[18] =  fcomplex.Exp(cp[18]  )  /*dummy*/;
+                            cp[19] =  fcomplex.Exp(cp[19]  )  /*dummy*/;
+                            cp[20] =  fcomplex.Exp(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.Exp(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        fcomplex* ap = ((fcomplex*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  fcomplex.Exp(ap[0]  )  /*dummy*/;
+                            cp[1] =  fcomplex.Exp(ap[1]  )  /*dummy*/;
+                            cp[2] =  fcomplex.Exp(ap[2]  )  /*dummy*/;
+                            cp[3] =  fcomplex.Exp(ap[3]  )  /*dummy*/;
+                            cp[4] =  fcomplex.Exp(ap[4]  )  /*dummy*/;
+                            cp[5] =  fcomplex.Exp(ap[5]  )  /*dummy*/;
+                            cp[6] =  fcomplex.Exp(ap[6]  )  /*dummy*/;
+                            cp[7] =  fcomplex.Exp(ap[7]  )  /*dummy*/;
+                            cp[8] =  fcomplex.Exp(ap[8]  )  /*dummy*/;
+                            cp[9] =  fcomplex.Exp(ap[9]  )  /*dummy*/;
+                            cp[10] =  fcomplex.Exp(ap[10]  )  /*dummy*/;
+                            cp[11] =  fcomplex.Exp(ap[11]  )  /*dummy*/;
+                            cp[12] =  fcomplex.Exp(ap[12]  )  /*dummy*/;
+                            cp[13] =  fcomplex.Exp(ap[13]  )  /*dummy*/;
+                            cp[14] =  fcomplex.Exp(ap[14]  )  /*dummy*/;
+                            cp[15] =  fcomplex.Exp(ap[15]  )  /*dummy*/;
+                            cp[16] =  fcomplex.Exp(ap[16]  )  /*dummy*/;
+                            cp[17] =  fcomplex.Exp(ap[17]  )  /*dummy*/;
+                            cp[18] =  fcomplex.Exp(ap[18]  )  /*dummy*/;
+                            cp[19] =  fcomplex.Exp(ap[19]  )  /*dummy*/;
+                            cp[20] =  fcomplex.Exp(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.Exp(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( fcomplex* arrAP = arrA)
+                fixed ( fcomplex* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<fcomplex>(retStorage);
+            }
+        }
+        /// <summary>Exponential of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Exponential of array elements</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<float>  exp (ILInArray< float > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<float>(A.Size); 
+                ILSize inDim = A.Size;
+                float[] arrA = A.GetArrayForRead(); 
+                float [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<float>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<float> retStorage = new ILDenseStorage<float>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    float* cp = ((float*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  (float)Math.Exp(cp[0]  )  /*dummy*/;
+                            cp[1] =  (float)Math.Exp(cp[1]  )  /*dummy*/;
+                            cp[2] =  (float)Math.Exp(cp[2]  )  /*dummy*/;
+                            cp[3] =  (float)Math.Exp(cp[3]  )  /*dummy*/;
+                            cp[4] =  (float)Math.Exp(cp[4]  )  /*dummy*/;
+                            cp[5] =  (float)Math.Exp(cp[5]  )  /*dummy*/;
+                            cp[6] =  (float)Math.Exp(cp[6]  )  /*dummy*/;
+                            cp[7] =  (float)Math.Exp(cp[7]  )  /*dummy*/;
+                            cp[8] =  (float)Math.Exp(cp[8]  )  /*dummy*/;
+                            cp[9] =  (float)Math.Exp(cp[9]  )  /*dummy*/;
+                            cp[10] =  (float)Math.Exp(cp[10]  )  /*dummy*/;
+                            cp[11] =  (float)Math.Exp(cp[11]  )  /*dummy*/;
+                            cp[12] =  (float)Math.Exp(cp[12]  )  /*dummy*/;
+                            cp[13] =  (float)Math.Exp(cp[13]  )  /*dummy*/;
+                            cp[14] =  (float)Math.Exp(cp[14]  )  /*dummy*/;
+                            cp[15] =  (float)Math.Exp(cp[15]  )  /*dummy*/;
+                            cp[16] =  (float)Math.Exp(cp[16]  )  /*dummy*/;
+                            cp[17] =  (float)Math.Exp(cp[17]  )  /*dummy*/;
+                            cp[18] =  (float)Math.Exp(cp[18]  )  /*dummy*/;
+                            cp[19] =  (float)Math.Exp(cp[19]  )  /*dummy*/;
+                            cp[20] =  (float)Math.Exp(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  (float)Math.Exp(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        float* ap = ((float*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  (float)Math.Exp(ap[0]  )  /*dummy*/;
+                            cp[1] =  (float)Math.Exp(ap[1]  )  /*dummy*/;
+                            cp[2] =  (float)Math.Exp(ap[2]  )  /*dummy*/;
+                            cp[3] =  (float)Math.Exp(ap[3]  )  /*dummy*/;
+                            cp[4] =  (float)Math.Exp(ap[4]  )  /*dummy*/;
+                            cp[5] =  (float)Math.Exp(ap[5]  )  /*dummy*/;
+                            cp[6] =  (float)Math.Exp(ap[6]  )  /*dummy*/;
+                            cp[7] =  (float)Math.Exp(ap[7]  )  /*dummy*/;
+                            cp[8] =  (float)Math.Exp(ap[8]  )  /*dummy*/;
+                            cp[9] =  (float)Math.Exp(ap[9]  )  /*dummy*/;
+                            cp[10] =  (float)Math.Exp(ap[10]  )  /*dummy*/;
+                            cp[11] =  (float)Math.Exp(ap[11]  )  /*dummy*/;
+                            cp[12] =  (float)Math.Exp(ap[12]  )  /*dummy*/;
+                            cp[13] =  (float)Math.Exp(ap[13]  )  /*dummy*/;
+                            cp[14] =  (float)Math.Exp(ap[14]  )  /*dummy*/;
+                            cp[15] =  (float)Math.Exp(ap[15]  )  /*dummy*/;
+                            cp[16] =  (float)Math.Exp(ap[16]  )  /*dummy*/;
+                            cp[17] =  (float)Math.Exp(ap[17]  )  /*dummy*/;
+                            cp[18] =  (float)Math.Exp(ap[18]  )  /*dummy*/;
+                            cp[19] =  (float)Math.Exp(ap[19]  )  /*dummy*/;
+                            cp[20] =  (float)Math.Exp(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  (float)Math.Exp(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( float* arrAP = arrA)
+                fixed ( float* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<float>(retStorage);
+            }
+        }
+        /// <summary>Exponential of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Exponential of array elements</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<double>  exp (ILInArray< double > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<double>(A.Size); 
+                ILSize inDim = A.Size;
+                double[] arrA = A.GetArrayForRead(); 
+                double [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<double>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<double> retStorage = new ILDenseStorage<double>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    double* cp = ((double*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  Math.Exp(cp[0]  )  /*dummy*/;
+                            cp[1] =  Math.Exp(cp[1]  )  /*dummy*/;
+                            cp[2] =  Math.Exp(cp[2]  )  /*dummy*/;
+                            cp[3] =  Math.Exp(cp[3]  )  /*dummy*/;
+                            cp[4] =  Math.Exp(cp[4]  )  /*dummy*/;
+                            cp[5] =  Math.Exp(cp[5]  )  /*dummy*/;
+                            cp[6] =  Math.Exp(cp[6]  )  /*dummy*/;
+                            cp[7] =  Math.Exp(cp[7]  )  /*dummy*/;
+                            cp[8] =  Math.Exp(cp[8]  )  /*dummy*/;
+                            cp[9] =  Math.Exp(cp[9]  )  /*dummy*/;
+                            cp[10] =  Math.Exp(cp[10]  )  /*dummy*/;
+                            cp[11] =  Math.Exp(cp[11]  )  /*dummy*/;
+                            cp[12] =  Math.Exp(cp[12]  )  /*dummy*/;
+                            cp[13] =  Math.Exp(cp[13]  )  /*dummy*/;
+                            cp[14] =  Math.Exp(cp[14]  )  /*dummy*/;
+                            cp[15] =  Math.Exp(cp[15]  )  /*dummy*/;
+                            cp[16] =  Math.Exp(cp[16]  )  /*dummy*/;
+                            cp[17] =  Math.Exp(cp[17]  )  /*dummy*/;
+                            cp[18] =  Math.Exp(cp[18]  )  /*dummy*/;
+                            cp[19] =  Math.Exp(cp[19]  )  /*dummy*/;
+                            cp[20] =  Math.Exp(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Math.Exp(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        double* ap = ((double*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  Math.Exp(ap[0]  )  /*dummy*/;
+                            cp[1] =  Math.Exp(ap[1]  )  /*dummy*/;
+                            cp[2] =  Math.Exp(ap[2]  )  /*dummy*/;
+                            cp[3] =  Math.Exp(ap[3]  )  /*dummy*/;
+                            cp[4] =  Math.Exp(ap[4]  )  /*dummy*/;
+                            cp[5] =  Math.Exp(ap[5]  )  /*dummy*/;
+                            cp[6] =  Math.Exp(ap[6]  )  /*dummy*/;
+                            cp[7] =  Math.Exp(ap[7]  )  /*dummy*/;
+                            cp[8] =  Math.Exp(ap[8]  )  /*dummy*/;
+                            cp[9] =  Math.Exp(ap[9]  )  /*dummy*/;
+                            cp[10] =  Math.Exp(ap[10]  )  /*dummy*/;
+                            cp[11] =  Math.Exp(ap[11]  )  /*dummy*/;
+                            cp[12] =  Math.Exp(ap[12]  )  /*dummy*/;
+                            cp[13] =  Math.Exp(ap[13]  )  /*dummy*/;
+                            cp[14] =  Math.Exp(ap[14]  )  /*dummy*/;
+                            cp[15] =  Math.Exp(ap[15]  )  /*dummy*/;
+                            cp[16] =  Math.Exp(ap[16]  )  /*dummy*/;
+                            cp[17] =  Math.Exp(ap[17]  )  /*dummy*/;
+                            cp[18] =  Math.Exp(ap[18]  )  /*dummy*/;
+                            cp[19] =  Math.Exp(ap[19]  )  /*dummy*/;
+                            cp[20] =  Math.Exp(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Math.Exp(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( double* arrAP = arrA)
+                fixed ( double* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<double>(retStorage);
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/eye.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/eye.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/eye.cs	(revision 9102)
@@ -0,0 +1,90 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.InteropServices; 
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Native;
+using ILNumerics.Exceptions;
+
+namespace ILNumerics {
+
+    public partial class ILMath {
+
+        /// <summary>
+        /// Create double matrix having unity diagonal values  
+        /// </summary>
+        /// <param name="rows">Number of rows</param>
+        /// <param name="columns">Number of columns</param>
+        /// <returns>Unity matrix (diagonal matrix) of type double</returns>
+        public static ILRetArray<double> eye(int rows, int columns) {
+            using (ILScope.Enter()) {
+                ILArray<double> ret = zeros(rows, columns);
+                int diagLen = Math.Min(rows, columns);
+                for (int i = 0; i < diagLen; i++)
+                    ret.SetValue(1.0, i, i);
+                return ret;
+            }
+        }
+        /// <summary>
+        /// Create unity matrix, arbitrary numeric type
+        /// </summary>
+        /// <param name="rows">Number of rows</param>
+        /// <param name="columns">Number of columns</param>
+        /// <returns>Unity matrix (diagonal matrix) of element type T</returns>
+        /// <typeparam name="T">Element type</typeparam>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the type specified is not supported. Supported types are: double, float, complex, fcomplex, int, long, short, byte</exception>
+        public static ILRetArray<T> eye<T>(int rows, int columns) {
+            using (ILScope.Enter()) {
+                int diagLen = Math.Min(rows, columns);
+                ILArray<T> o = ones<T>(new ILSize(1,diagLen)); 
+                if (isnull(o))
+                    throw new ILArgumentException("eye does not support elements of type '" + typeof(T).Name + "'"); 
+                ILArray<T> ret = zeros<T>(rows, columns);
+                for (int i = 0; i < diagLen; i++)
+                    ret.SetValue(o.GetValue(i), i, i);
+                return ret;
+            }
+        }
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/fft.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/fft.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/fft.cs	(revision 9102)
@@ -0,0 +1,1802 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using ILNumerics.Exceptions; 
+using ILNumerics.Misc; 
+
+namespace ILNumerics  {
+    public partial class ILMath {
+
+
+
+
+        #region fft(A)
+        /// <summary>
+        /// Fast fourier transform (1D)
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Transformed output array</returns>
+        /// <remarks><para>The transformation is computed along the first 
+        /// non singleton dimension.</para>
+        /// <para>The output array returned will be complex hermitian. I.e. the real 
+        /// part being even and the imaginary part being odd symmetrical.</para>
+        /// <para>The forward fourier transform and the inverse fourier transform of 
+        /// a given data array A are mathematically equivalent. It's only a 
+        /// scaling factor which is needed to make sure, A equals ifft(fft(A)). That 
+        /// scaling is introduced in the inverse transform.</para>
+        /// <para>The transformation is computed by use of the native library 
+        /// which currently is set up for your processor and OS version. The underlying 
+        /// library is automatically choosen at ILNumerics startup and accessed via the 
+        /// static member ILMath.FFT. See the online documentation for more 
+        /// details in how to tune/configure and select dedicated native libraries. 
+        /// Currently supported libraries are: Intel MKL 
+        /// (included), AMD ACML and FFTW3 (prepared, optional modules, not included due to licensing conflicts).</para>
+        /// </remarks>
+        public static ILRetArray< complex> fft(ILInArray< double> A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) return empty< complex>(A.Size);
+                if (A.IsScalar) return new  complex(A.GetValue(0), 0);
+                int fnsd = A.Size.WorkingDimension();
+                return ILMath.FFTImplementation.FFTForward1D(A, fnsd);
+            }
+        }
+        /// <summary>
+        /// Fast fourier transform (1D)
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Transformed output array</returns>
+        /// <remarks>
+        /// <para>The transformation is computed along the first non 
+        /// singleton dimension.</para>
+        /// <para>The forward fourier transform and the inverse fourier transform of 
+        /// a given data array A are mathematically equivalent. It's only a 
+        /// scaling factor which is needed to make sure, A equals ifft(fft(A)). That 
+        /// scaling is introduced in the inverse transform.</para>
+        /// <para>The transformation is computed by use of the native library 
+        /// which currently is set up for your processor and OS version. The underlying 
+        /// library is automatically choosen at ILNumerics startup and accessed via the 
+        /// static member ILMath.FFT. See the online documentation for more 
+        /// details in how to tune/configure and select dedicated native libraries. 
+        /// Currently supported libraries are: Intel MKL 
+        /// (included), AMD ACML and FFTW3 (prepared, optional modules, not included due to licensing conflicts).</para>
+        /// </remarks>
+        public static ILRetArray< complex > fft(ILInArray< complex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) return empty< complex>(A.Size);
+                if (A.IsScalar) return A.C;
+                int fnsd = A.Size.WorkingDimension();
+                return ILMath.FFTImplementation.FFTForward1D(A, fnsd);
+            }
+        }
+        /// <summary>
+        /// Fast inverse fourier transform (1D)
+        /// </summary>
+        /// <param name="A">Input (frequency domain)</param>
+        /// <returns>Inverse transformed output array</returns>
+        /// <remarks>
+        /// <para>The transformation is computed along the first non 
+        /// singleton dimension.</para>
+        /// <para>The forward fourier transform and the inverse fourier transform of 
+        /// a given data array A are mathematically equivalent. It's only a 
+        /// scaling factor which is needed to make sure, A equals ifft(fft(A)). That 
+        /// scaling is introduced in the inverse transform.</para>
+        /// <para>The transformation is computed by use of the native library 
+        /// which currently is set up for your processor and OS version. The underlying 
+        /// library is automatically choosen at ILNumerics startup and accessed via the 
+        /// static member ILMath.FFT. See the online documentation for more 
+        /// details in how to tune/configure and select dedicated native libraries. 
+        /// Currently supported libraries are: Intel MKL 
+        /// (included), AMD ACML and FFTW3 (prepared, optional modules, not included due to licensing conflicts).</para>
+        /// </remarks>
+        public static ILRetArray<complex> ifft(ILInArray<complex> A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) return empty< complex>(A.Size);
+                if (A.IsScalar) return A.C;
+                int fnsd = A.Size.WorkingDimension();
+                return ILMath.FFTImplementation.FFTBackward1D(A, fnsd);
+            }
+        }
+        /// <summary>
+        /// Inverse fast fourier transform, complex hermitian input
+        /// </summary>
+        /// <param name="A">Complex hermitian input array</param>
+        /// <returns>Real output array, same size as A</returns>
+        /// <remarks>
+        /// <para>Since a transform of complex hermitian input data results in 
+        /// the output having all imaginary part equal zero, only the real part is 
+        /// returned for convenience reasons.</para>
+        /// <para>No check is made for A being hermitian! If A is not hermitian (by means 
+        /// of round-off errors), the result will be wrong!</para>
+        /// <para>The transformation is computed along the first non 
+        /// singleton dimension.</para>
+        /// <para>The forward fourier transform and the inverse fourier transform of 
+        /// a given data array A are mathematically equivalent. It's only a 
+        /// scaling factor which is needed to make sure, A equals ifft(fft(A)). That 
+        /// scaling is introduced in the inverse transform.</para>
+        /// <para>The transformation is computed by use of the native library 
+        /// which currently is set up for your processor and OS version. The underlying 
+        /// library is automatically choosen at ILNumerics startup and accessed via the 
+        /// static member ILMath.FFT. See the online documentation for more 
+        /// details in how to tune/configure and select dedicated native libraries. 
+        /// Currently supported libraries are: Intel MKL 
+        /// (included), AMD ACML and FFTW3 (prepared, optional modules, not included due to licensing conflicts).</para>
+        /// </remarks>
+        public static ILRetArray< double > ifftsym(ILInArray< complex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) return empty< double>(A.Size);
+                if (A.IsScalar) return real(A);
+                int fnsd = A.Size.WorkingDimension();
+                return ILMath.FFTImplementation.FFTBackwSym1D(A, fnsd);
+            }
+        }
+        #endregion
+
+        #region fft(A, dim)
+        /// <summary>
+        /// Fast fourier transform along specific dimension
+        /// </summary>
+        /// <param name="A">Real input array</param>
+        /// <param name="dim">Dimension to compute FFT along. This parameter must be non-negative. </param>
+        /// <returns>Transformation result</returns>
+        /// <remarks>
+        /// <para>The output array returned will be complex hermitian. I.e. the real 
+        /// part being even and the imaginary part being odd symmetrical.</para>
+        /// <para>The forward fourier transform and the inverse fourier transform of 
+        /// a given data array A are mathematically equivalent. It's only a 
+        /// scaling factor which is needed to make sure, A equals ifft(fft(A)). That 
+        /// scaling is introduced in the inverse transform.</para>
+        /// <para>The transformation is computed by use of the native library 
+        /// which currently is set up for your processor and OS version. The underlying 
+        /// library is automatically choosen at ILNumerics startup and accessed via the 
+        /// static member ILMath.FFT. See the online documentation for more 
+        /// details in how to tune/configure and select dedicated native libraries. 
+        /// Currently supported libraries are: Intel MKL 
+        /// (included), AMD ACML and FFTW3 (prepared, optional modules, not included due to licensing conflicts).</para>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">is thrown if 
+        /// the dim parameter is negative</exception>
+        public static ILRetArray< complex > fft(ILInArray< double > A, int dim) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0) throw new ILArgumentException("the 'dim' parameter must point to an existing dimension index of A");
+                if (A.IsEmpty) return empty< complex>(A.Size);
+                if (A.IsScalar) return new  complex(A.GetValue(0), 0);
+                return ILMath.FFTImplementation.FFTForward1D(A, dim);
+            }
+        }
+        /// <summary>
+        /// Fast fourier transform along specific dimension
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="dim">Dimension to compute FFT along. This parameter
+        /// must be non-negative. </param>
+        /// <returns>Transformation result</returns>
+        /// <remarks>
+        /// <para>The forward fourier transform and the inverse fourier transform of 
+        /// a given data array A are mathematically equivalent. It's only a 
+        /// scaling factor which is needed to make sure, A equals ifft(fft(A)). That 
+        /// scaling is introduced in the inverse transform.</para>
+        /// <para>The transformation is computed by use of the native library 
+        /// which currently is set up for your processor and OS version. The underlying 
+        /// library is automatically choosen at ILNumerics startup and accessed via the 
+        /// static member ILMath.FFT. See the online documentation for more 
+        /// details in how to tune/configure and select dedicated native libraries. 
+        /// Currently supported libraries are: Intel MKL 
+        /// (included), AMD ACML and FFTW3 (prepared, optional modules, not included due to licensing conflicts).</para>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">is thrown if 
+        /// the dim parameter is negative</exception>
+        public static ILRetArray< complex > fft(ILInArray< complex > A, int dim) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0) throw new ILArgumentException("the 'dim' parameter must point to an existing dimension index of A");
+                if (A.IsEmpty) return empty< complex>(A.Size);
+                if (A.IsScalar) return A.C;
+                return ILMath.FFTImplementation.FFTForward1D(A, dim); 
+            }
+        }
+        /// <summary>
+        /// Inverse fast fourier transform along specific dimension
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="dim">Dimension to compute FFT along. This parameter
+        /// must be non-negative. </param>
+        /// <returns>Transformation result</returns>
+        /// <remarks>
+        /// <para>The forward fourier transform and the inverse fourier transform of 
+        /// a given data array A are mathematically equivalent. It's only a 
+        /// scaling factor which is needed to make sure, A equals ifft(fft(A)). That 
+        /// scaling is introduced in the inverse transform.</para>
+        /// <para>The transformation is computed by use of the native library 
+        /// which currently is set up for your processor and OS version. The underlying 
+        /// library is automatically choosen at ILNumerics startup and accessed via the 
+        /// static member ILMath.FFT. See the online documentation for more 
+        /// details in how to tune/configure and select dedicated native libraries. 
+        /// Currently supported libraries are: Intel MKL 
+        /// (included), AMD ACML and FFTW3 (prepared, optional modules, not included due to licensing conflicts).</para>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">is thrown if the dim parameter is negative</exception>
+        public static ILRetArray< complex> ifft(ILInArray< complex> A, int dim) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0) throw new ILArgumentException("the 'dim' parameter must point to an existing dimension index of A");
+                if (A.IsEmpty) return empty< complex>(A.Size);
+                if (A.IsScalar) return A.C;
+                return ILMath.FFTImplementation.FFTBackward1D(A, dim);
+            }
+        }
+        /// <summary>
+        /// Inverse fast fourier transform, complex hermitian input
+        /// </summary>
+        /// <param name="A">Complex hermitian input array (frequency domain)</param>
+        /// <param name="dim">Dimension to compute FFT along. This parameter
+        /// must be non-negative. </param>
+        /// <returns>Real output array, same size as A</returns>
+        /// <remarks>
+        /// <para>Since a transform of complex hermitian input data results in the 
+        /// output having the imaginary part equals zero, only the real part is 
+        /// returned for convenience reasons.</para>
+        /// <para>No check is made for A being hermitian! If A is not hermitian (by means 
+        /// of round-off errors), the result will be wrong!</para>
+        /// <para>The forward fourier transform and the inverse fourier transform of 
+        /// a given data array A are mathematically equivalent. It's only a 
+        /// scaling factor which is needed to make sure, A equals ifft(fft(A)). That 
+        /// scaling is introduced in the inverse transform.</para>
+        /// <para>The transformation is computed by use of the native library 
+        /// which currently is set up for your processor and OS version. The underlying 
+        /// library is automatically choosen at ILNumerics startup and accessed via the 
+        /// static member ILMath.FFT. See the online documentation for more 
+        /// details in how to tune/configure and select dedicated native libraries. 
+        /// Currently supported libraries are: Intel MKL (included), AMD ACML 
+        /// and FFTW3 (prepared, optional modules, not included due to licensing conflicts).</para>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">is thrown if the dim parameter is negative</exception>
+        public static ILRetArray< double > ifftsym(ILInArray< complex > A, int dim) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0) throw new ILArgumentException("the 'dim' parameter must point to an existing dimension index of A");
+                if (A.IsEmpty) return empty< double>(A.Size);
+                if (A.IsScalar) return real(A);
+                return ILMath.FFTImplementation.FFTBackwSym1D(A, dim);
+            }
+        }
+        #endregion
+
+        #region fft2(A)
+        /// <summary>
+        /// Fast fourier transform (2D)
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Transformation result</returns>
+        /// <remarks>
+        /// <para>The 2D transformation is computed for the first 2 dimensions, regardless 
+        /// of those dimensions being singleton or non-singleton. If A is an n-d array, 
+        /// the transformation is repeated for trailing dimensions of A respectively. </para>
+        /// <para>The output array returned will be complex hermitian.</para>
+        /// <para>The two dimensional transformation is equivalent to repeatedly transforming 
+        /// the columns and after that transforming the rows of A. However, using this 
+        /// function may be of magnitudes faster than using 1D transformations. This 
+        /// depends on the algorithm and API provided by the underlying native library.</para>
+        /// <para>The forward fourier transform and the inverse fourier transform of 
+        /// a given data array A are mathematically equivalent. It's only a 
+        /// scaling factor which is needed to make sure, A equals ifft(fft(A)). That 
+        /// scaling is introduced in the inverse transform.</para>
+        /// <para>The transformation is computed by use of the native library 
+        /// which currently is set up for your processor and OS version. The underlying 
+        /// library is automatically choosen at ILNumerics startup and accessed via the 
+        /// static member ILMath.FFT. See the online documentation for more 
+        /// details in how to tune/configure and select dedicated native libraries. 
+        /// Currently supported libraries are: Intel MKL (included), AMD ACML 
+        /// and FFTW3 (prepared, optional modules, not included due to licensing conflicts).</para>
+        /// </remarks>
+        public static ILRetArray< complex > fft2(ILInArray< double > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) return empty< complex>(A.Size);
+                if (A.IsScalar) return new  complex(A.GetValue(0), 0);
+                return FFTImplementation.FFTForward(A, 2);
+            } 
+        }
+        /// <summary>
+        /// Fast fourier transform (2D)
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Transformation result</returns>
+        /// <remarks>
+        /// <para>The transformation is computed for the first 2 dimensions, regardless 
+        /// of those dimensions being singleton or non-singleton. If A is an n-d array, 
+        /// the transformation is repeated for trailing dimensions of A respectively. </para>
+        /// <para>The two dimensional transformation is equivalent to repeatedly transforming 
+        /// the columns and after that transforming the rows of A. However, using this 
+        /// function may be of magnitudes faster than using 1D transformations. This 
+        /// depends on the algorithm and API provided by the underlying native library.</para>
+        /// <para>The forward fourier transform and the inverse fourier transform of 
+        /// a given data array A are mathematically equivalent. It's only a 
+        /// scaling factor which is needed to make sure, A equals ifft(fft(A)). That 
+        /// scaling is introduced in the inverse transform.</para>
+        /// <para>The transformation is computed by use of the native library 
+        /// which currently is set up for your processor and OS version. The underlying 
+        /// library is automatically choosen at ILNumerics startup and accessed via the 
+        /// static member ILMath.FFT. See the online documentation for more 
+        /// details in how to tune/configure and select dedicated native libraries. 
+        /// Currently supported libraries are: Intel MKL (included), AMD ACML 
+        /// and FFTW3 (prepared, optional modules, not included due to licensing conflicts).</para>
+        /// </remarks>
+        public static ILRetArray< complex> fft2(ILInArray< complex> A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) return empty< complex>(A.Size);
+                if (A.IsScalar) return A.C;
+                return FFTImplementation.FFTForward(A, 2);
+            }
+        }
+        /// <summary>
+        /// Inverse fast fourier transform (2D)
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Transformation result</returns>
+        /// <remarks>
+        /// <para>The transformation is computed for the first 2 dimensions, regardless 
+        /// of those dimensions being singleton or non-singleton. If A is an n-d array, 
+        /// the transformation is repeated for trailing dimensions of A respectively. </para>
+        /// <para>The two dimensional transformation is equivalent to repeatedly transforming 
+        /// the columns and after that transforming the rows of A. However, using this 
+        /// function may be of magnitudes faster than using 1D transformations. This 
+        /// depends on the algorithm and API provided by the underlying native library.</para>
+        /// <para>The forward fourier transform and the inverse fourier transform of 
+        /// a given data array A are mathematically equivalent. It's only a 
+        /// scaling factor which is needed to make sure, A equals ifft(fft(A)). That 
+        /// scaling is introduced in the inverse transform.</para>
+        /// <para>The transformation is computed by use of the native library 
+        /// which currently is set up for your processor and OS version. The underlying 
+        /// library is automatically choosen at ILNumerics startup and accessed via the 
+        /// static member ILMath.FFT. See the online documentation for more 
+        /// details in how to tune/configure and select dedicated native libraries. 
+        /// Currently supported libraries are: Intel MKL (included), AMD ACML 
+        /// and FFTW3 (prepared, optional modules, not included due to licensing conflicts).</para>
+        /// </remarks>
+        public static ILRetArray< complex> ifft2(ILInArray< complex> A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) return empty< complex>(A.Size);
+                if (A.IsScalar) return A.C;
+                return FFTImplementation.FFTBackward(A, 2);
+            }
+        }
+        /// <summary>
+        /// Inverse fast fourier transform (2D, hermitian input)
+        /// </summary>
+        /// <param name="A">Complex hermitian input array (frequency domain)</param>
+        /// <returns>Transformation result</returns>
+        /// <remarks>
+        /// <para>Since a transform of complex hermitian input data results in the 
+        /// output having the imaginary part equals zero, only the real part is 
+        /// returned for convenience reasons.</para>
+        /// <para>No check is made for A being hermitian! If A is not hermitian (by means 
+        /// of round-off errors), the result will be wrong!</para>
+        /// <para>The transformation is computed for the first 2 dimensions, regardless 
+        /// of those dimensions being singleton or non-singleton. If A is an n-d array, 
+        /// the transformation is repeated for trailing dimensions of A respectively. </para>
+        /// <para>The two dimensional transformation is equivalent to repeatedly transforming 
+        /// the columns and after that transforming the rows of A. However, using this 
+        /// function may be of magnitudes faster than using 1D transformations. This 
+        /// depends on the algorithm and API provided by the underlying native library.</para>
+        /// <para>The forward fourier transform and the inverse fourier transform of 
+        /// a given data array A are mathematically equivalent. It's only a 
+        /// scaling factor which is needed to make sure, A equals ifft(fft(A)). That 
+        /// scaling is introduced in the inverse transform.</para>
+        /// <para>The transformation is computed by use of the native library 
+        /// which currently is set up for your processor and OS version. The underlying 
+        /// library is automatically choosen at ILNumerics startup and accessed via the 
+        /// static member ILMath.FFT. See the online documentation for more 
+        /// details in how to tune/configure and select dedicated native libraries. 
+        /// Currently supported libraries are: Intel MKL (included), AMD ACML 
+        /// and FFTW3 (prepared, optional modules, not included due to licensing conflicts).</para>
+        /// </remarks>
+        public static ILRetArray< double> ifft2sym(ILInArray< complex> A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) return empty< double>(A.Size);
+                if (A.IsScalar) return real(A);
+                return FFTImplementation.FFTBackwSym(A, 2);
+            }
+        }
+        #endregion
+
+        #region fft2(A,m,n)
+        /// <summary>
+        /// Fast fourier transform (2D)
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="m">Transformation column length</param>
+        /// <param name="n">Transformation row length</param>
+        /// <returns>Transformation result, complex hermitian</returns>
+        /// <remarks>
+        /// <para>The transformation is computed for the first 2 dimensions, regardless 
+        /// of those dimensions being singleton or non-singleton. If A is an n-d array, 
+        /// the transformation is repeated for trailing dimensions of A respectively. </para>
+        /// <para>The data to be transformed (based on the A array) are resized according to 
+        /// the length parameter m and n. If m or n is larger then the length of the corresponding 
+        /// dimension of A, zeros will be padded, otherwise the dimensions are truncated respectively. </para>
+        /// <para>The two dimensional transformation is equivalent to repeatedly transforming 
+        /// the columns and after that transforming the rows of A. However, using this 
+        /// function may be of magnitudes faster than using 1D transformations. This 
+        /// depends on the algorithm and API provided by the underlying native library.</para>
+        /// <para>The forward fourier transform and the inverse fourier transform of 
+        /// a given data array A are mathematically equivalent. It's only a 
+        /// scaling factor which is needed to make sure, A equals ifft(fft(A)). That 
+        /// scaling is introduced in the inverse transform.</para>
+        /// <para>The transformation is computed by use of the native library 
+        /// which currently is set up for your processor and OS version. The underlying 
+        /// library is automatically choosen at ILNumerics startup and accessed via the 
+        /// static member ILMath.FFT. See the online documentation for more 
+        /// details in how to tune/configure and select dedicated native libraries. 
+        /// Currently supported libraries are: Intel MKL (included), AMD ACML 
+        /// and FFTW3 (prepared, optional modules, not included due to licensing conflicts).</para>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">is thrown if one of n or m is negative</exception>
+        public static ILRetArray< complex> fft2(ILInArray< double> A, int m, int n) {
+            using (ILScope.Enter(A)) {
+                if (m < 0 || n < 0) throw new ILArgumentException("dimension length specifier 'm' and 'n' must be non-negative!");
+                if (A.IsEmpty) return empty< complex>(A.Size);
+                int[] Asize = A.Size.ToIntArray();
+                Asize[0] = m; Asize[1] = n;
+                ILArray< double> resizedA = resize4Transform(A, Asize);
+                return FFTImplementation.FFTForward(resizedA, 2);
+            }
+        }
+        /// <summary>
+        /// Fast fourier transform (2D)
+        /// </summary>
+        /// <param name="A">input array</param>
+        /// <param name="m">Transformation column length</param>
+        /// <param name="n">Transformation row length</param>
+        /// <returns>Transformation result</returns>
+        /// <remarks>
+        /// <para>The transformation is computed for the first 2 dimensions, regardless 
+        /// of those dimensions being singleton or non-singleton. If A is an n-d array, 
+        /// the transformation is repeated for trailing dimensions of A respectively. </para>
+        /// <para>The data to be transformed (based on the A array) are resized according to 
+        /// the length parameter m and n. If m or n is larger then the length of the corresponding 
+        /// dimension of A, zeros will be padded, otherwise the dimensions are truncated respectively. </para>
+        /// <para>The two dimensional transformation is equivalent to repeatedly transforming 
+        /// the columns and after that transforming the rows of A. However, using this 
+        /// function may be of magnitudes faster than using 1D transformations. This 
+        /// depends on the algorithm and API provided by the underlying native library.</para>
+        /// <para>The forward fourier transform and the inverse fourier transform of 
+        /// a given data array A are mathematically equivalent. It's only a 
+        /// scaling factor which is needed to make sure, A equals ifft(fft(A)). That 
+        /// scaling is introduced in the inverse transform.</para>
+        /// <para>The transformation is computed by use of the native library 
+        /// which currently is set up for your processor and OS version. The underlying 
+        /// library is automatically choosen at ILNumerics startup and accessed via the 
+        /// static member ILMath.FFT. See the online documentation for more 
+        /// details in how to tune/configure and select dedicated native libraries. 
+        /// Currently supported libraries are: Intel MKL (included), AMD ACML 
+        /// and FFTW3 (prepared, optional modules, not included due to licensing conflicts).</para>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">is thrown if one of n or m is negative</exception>
+        public static ILRetArray< complex> fft2(ILInArray< complex> A, int m, int n) {
+            using (ILScope.Enter(A)) {
+                if (m < 0 || n < 0) throw new ILArgumentException("dimension length specifier 'm' and 'n' must be non-negative!");
+                if (A.IsEmpty) return empty< complex>(A.Size);
+                int[] Asize = A.Size.ToIntArray();
+                Asize[0] = m; Asize[1] = n;
+                ILRetArray< complex> resizedA = resize4Transform(A, Asize);
+                return FFTImplementation.FFTForward(resizedA, 2);
+            }
+        }
+        /// <summary>
+        /// Inverse fast fourier transform (2D)
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="m">Transformation column length</param>
+        /// <param name="n">Transformation row length</param>
+        /// <returns>Transformation result</returns>
+        /// <remarks>
+        /// <para>The transformation is computed for the first 2 dimensions, regardless 
+        /// of those dimensions being singleton or non-singleton. If A is an n-d array, 
+        /// the transformation is repeated for trailing dimensions of A respectively. </para>
+        /// <para>The data to be transformed (based on the array A) are resized according to 
+        /// the length parameter m and n. If m or n is larger then the length of the corresponding 
+        /// dimension of A, zeros will be padded, otherwise the dimensions are truncated respectively. </para>
+        /// <para>The two dimensional transformation is equivalent to repeatedly transforming 
+        /// the columns and after that transforming the rows of A. However, using this 
+        /// function may be of magnitudes faster than using 1D transformations. This 
+        /// depends on the algorithm and API provided by the underlying native library.</para>
+        /// <para>The forward fourier transform and the inverse fourier transform of 
+        /// a given data array A are mathematically equivalent. It's only a 
+        /// scaling factor which is needed to make sure, A equals ifft(fft(A)). That 
+        /// scaling is introduced in the inverse transform.</para>
+        /// <para>The transformation is computed by use of the native library 
+        /// which currently is set up for your processor and OS version. The underlying 
+        /// library is automatically choosen at ILNumerics startup and accessed via the 
+        /// static member ILMath.FFT. See the online documentation for more 
+        /// details in how to tune/configure and select dedicated native libraries. 
+        /// Currently supported libraries are: Intel MKL (included), AMD ACML 
+        /// and FFTW3 (prepared, optional modules, not included due to licensing conflicts).</para>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">is thrown if one of n or m is negative</exception>
+        public static ILRetArray< complex> ifft2(ILInArray< complex> A, int m, int n) {
+            using (ILScope.Enter(A)) {
+                if (m < 0 || n < 0) throw new ILArgumentException("dimension length specifier 'm' and 'n' must be non-negative!");
+                if (A.IsEmpty) return empty< complex>(A.Size);
+                int[] Asize = A.Size.ToIntArray();
+                Asize[0] = m; Asize[1] = n;
+                ILRetArray< complex> resizedA = resize4Transform(A, Asize);
+                return FFTImplementation.FFTBackward(resizedA, 2);
+            }
+        }
+        /// <summary>
+        /// Inverse fast fourier transform (2D)
+        /// </summary>
+        /// <param name="A">Complex hermitian input array, symmetric in first 2 dimensions</param>
+        /// <param name="m">Transformation column length</param>
+        /// <param name="n">Transformation row length</param>
+        /// <returns>Transformation result</returns>
+        /// <remarks>
+        /// <para>The transformation is computed for the first 2 dimensions, regardless 
+        /// of those dimensions being singleton or non-singleton. If A is an n-d array, 
+        /// the transformation is repeated for trailing dimensions of A respectively. The 
+        /// lengths of those trailing dimensions are not altered.</para>
+        /// <para>Since a transform of complex hermitian input data results in the 
+        /// output having the imaginary part equals zero, only the real part is 
+        /// returned for convenience reasons.</para>
+        /// <para>No check is made for A being hermitian! If A is not hermitian (by means 
+        /// of round-off errors), the result will be wrong!</para>
+        /// <para>The data to be transformed (based on the array A) are resized according to 
+        /// the length parameter m and n. If m or n is larger then the length of the corresponding 
+        /// dimension of A, zeros will be padded, otherwise the dimensions are truncated respectively. </para>
+        /// <para>The two dimensional transformation is equivalent to repeatedly transforming 
+        /// the columns and after that transforming the rows of A. However, using this 
+        /// function may be of magnitudes faster than using 1D transformations. This 
+        /// depends on the algorithm and API provided by the underlying native library.</para>
+        /// <para>The forward fourier transform and the inverse fourier transform of 
+        /// a given data array A are mathematically equivalent. It's only a 
+        /// scaling factor which is needed to make sure, A equals ifft(fft(A)). That 
+        /// scaling is introduced in the inverse transform.</para>
+        /// <para>The transformation is computed by use of the native library 
+        /// which currently is set up for your processor and OS version. The underlying 
+        /// library is automatically choosen at ILNumerics startup and accessed via the 
+        /// static member ILMath.FFT. See the online documentation for more 
+        /// details in how to tune/configure and select dedicated native libraries. 
+        /// Currently supported libraries are: Intel MKL (included), AMD ACML 
+        /// and FFTW3 (prepared, optional modules, not included due to licensing conflicts).</para>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">is thrown if one of n or m is negative</exception>
+        public static ILRetArray< double> ifft2sym(ILInArray< complex> A, int m, int n) {
+            using (ILScope.Enter(A)) {
+                if (m < 0 || n < 0) throw new ILArgumentException("dimension length specifier 'm' and 'n' must be non-negative!");
+                if (A.IsEmpty) return empty< double>(A.Size);
+                int[] Asize = A.Size.ToIntArray();
+                Asize[0] = m; Asize[1] = n;
+                ILRetArray< complex> resizedA = resize4Transform(A, Asize);
+                return FFTImplementation.FFTBackwSym(resizedA, 2);
+            }
+        }
+        #endregion
+
+        #region fftn(A)
+        /// <summary>
+        /// Fast fourier transform (n-D)
+        /// </summary>
+        /// <param name="A">Input array, n-D</param>
+        /// <returns>Transformation result, complex hermitian</returns>
+        /// <remarks>
+        /// <para>The n-dimensional transformation is computed for the n-dimensional array A. 
+        /// This is equivalent to repeatedly (inplace) 
+        /// computing one dimensional transformations along all dimensions of A.
+        /// However, using this 
+        /// function may be of magnitudes faster than using 1D transformations. This 
+        /// depends on the algorithm and API provided by the underlying native library.</para>
+        /// <para>The forward fourier transform and the inverse fourier transform of 
+        /// a given data array A are mathematically equivalent. It's only a 
+        /// scaling factor which is needed to make sure, A equals ifft(fft(A)). That 
+        /// scaling is introduced in the inverse transform.</para>
+        /// <para>The transformation is computed by use of the native library 
+        /// which currently is set up for your processor and OS version. The underlying 
+        /// library is automatically choosen at ILNumerics startup and accessed via the 
+        /// static member ILMath.FFT. See the online documentation for more 
+        /// details in how to tune/configure and select dedicated native libraries. 
+        /// Currently supported libraries are: Intel MKL (included), AMD ACML 
+        /// and FFTW3 (prepared, optional modules, not included due to licensing conflicts).</para>
+        /// </remarks>
+        public static ILRetArray< complex> fftn(ILInArray< double> A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) return empty< complex>(A.Size);
+                return FFTImplementation.FFTForward(A, A.Size.NumberOfDimensions);
+            }
+        }
+        /// <summary>
+        /// Fast fourier transform (n-D)
+        /// </summary>
+        /// <param name="A">Input array, n-D</param>
+        /// <returns>Transformation result</returns>
+        /// <remarks>
+        /// <para>The n-dimensional transformation is computed for the n-dimensional array A. 
+        /// This is equivalent to repeatedly (inplace) 
+        /// computing one dimensional transformations along all dimensions of A.
+        /// However, using this 
+        /// function may be of magnitudes faster than using 1D transformations. This 
+        /// depends on the algorithm and API provided by the underlying native library.</para>
+        /// <para>The forward fourier transform and the inverse fourier transform of 
+        /// a given data array A are mathematically equivalent. It's only a 
+        /// scaling factor which is needed to make sure, A equals ifft(fft(A)). That 
+        /// scaling is introduced in the inverse transform.</para>
+        /// <para>The transformation is computed by use of the native library 
+        /// which currently is set up for your processor and OS version. The underlying 
+        /// library is automatically choosen at ILNumerics startup and accessed via the 
+        /// static member ILMath.FFT. See the online documentation for more 
+        /// details in how to tune/configure and select dedicated native libraries. 
+        /// Currently supported libraries are: Intel MKL (included), AMD ACML 
+        /// and FFTW3 (prepared, optional modules, not included due to licensing conflicts).</para>
+        /// </remarks>
+        public static ILRetArray< complex> fftn(ILInArray< complex> A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) return empty< complex>(A.Size);
+                return FFTImplementation.FFTForward(A, A.Size.NumberOfDimensions);
+            }
+        }
+        /// <summary>
+        /// Inverse fast fourier transform (n-D)
+        /// </summary>
+        /// <param name="A">Input array, n-D (frequency domain)</param>
+        /// <returns>Transformation result</returns>
+        /// <remarks>
+        /// <para>The n-dimensional inverse transformation is computed for the n-dimensional array A. 
+        /// This is equivalent to repeatedly (inplace) 
+        /// computing one dimensional transformations along all dimensions of A.
+        /// However, using this 
+        /// function may be of magnitudes faster than using 1D transformations. This 
+        /// depends on the algorithm and API provided by the underlying native library.</para>
+        /// <para>The forward fourier transform and the inverse fourier transform of 
+        /// a given data array A are mathematically equivalent. It's only a 
+        /// scaling factor which is needed to make sure, A equals ifft(fft(A)). That 
+        /// scaling is introduced in the inverse transform.</para>
+        /// <para>The transformation is computed by use of the native library 
+        /// which currently is set up for your processor and OS version. The underlying 
+        /// library is automatically choosen at ILNumerics startup and accessed via the 
+        /// static member ILMath.FFT. See the online documentation for more 
+        /// details in how to tune/configure and select dedicated native libraries. 
+        /// Currently supported libraries are: Intel MKL (included), AMD ACML 
+        /// and FFTW3 (prepared, optional modules, not included due to licensing conflicts).</para>
+        /// </remarks>
+        public static ILRetArray< complex> ifftn(ILInArray< complex> A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) return empty< complex>(A.Size);
+                return FFTImplementation.FFTBackward(A, A.Size.NumberOfDimensions);
+            }
+        }
+        /// <summary>
+        /// Inverse fast fourier transform (n-D)
+        /// </summary>
+        /// <param name="A">Input array, n-D, complex hermitian (frequency domain)</param>
+        /// <returns>Transformation result</returns>
+        /// <remarks>
+        /// <para>The n-dimensional inverse transformation is computed for the n-dimensional array A. 
+        /// This is equivalent to repeatedly (inplace) 
+        /// computing one dimensional transformations along all dimensions of A.
+        /// However, using this 
+        /// function may be of magnitudes faster than using 1D transformations. This 
+        /// depends on the algorithm and API provided by the underlying native library.</para>
+        /// <para>Since a transform of complex hermitian input data results in the 
+        /// output having the imaginary part equals zero, only the real part is 
+        /// returned for convenience reasons.</para>
+        /// <para>No check is made for A being hermitian! If A is not hermitian (by means 
+        /// of round-off errors), the result will be wrong!</para>
+        /// <para>The forward fourier transform and the inverse fourier transform of 
+        /// a given data array A are mathematically equivalent. It's only a 
+        /// scaling factor which is needed to make sure, A equals ifft(fft(A)). That 
+        /// scaling is introduced in the inverse transform.</para>
+        /// <para>The transformation is computed by use of the native library 
+        /// which currently is set up for your processor and OS version. The underlying 
+        /// library is automatically choosen at ILNumerics startup and accessed via the 
+        /// static member ILMath.FFT. See the online documentation for more 
+        /// details in how to tune/configure and select dedicated native libraries. 
+        /// Currently supported libraries are: Intel MKL (included), AMD ACML 
+        /// and FFTW3 (prepared, optional modules, not included due to licensing conflicts).</para>
+        /// </remarks>
+        public static ILRetArray< double> ifftnsym(ILInArray< complex> A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) return empty< double>(A.Size);
+                return FFTImplementation.FFTBackwSym(A, A.Size.NumberOfDimensions);
+            }
+        }
+        #endregion
+
+        #region fftn(A, params dims)
+        /// <summary>
+        /// Fast fourier transform (n-D, specific size)
+        /// </summary>
+        /// <param name="A">Input array, n-D</param>
+        /// <param name="dims">Transformation lengths, specifies the length of the dimensions 
+        /// for the transformation array. The length of dims must be &gt; or equal to the number of 
+        /// dimensions of A. For elements in dim being smaller than corresponding dimension 
+        /// length in A, the dimensions will be truncated, otherwise zeros will be padded.</param>
+        /// <returns>Transformation result of size specified by 'dims' parameter, complex hermitian</returns>
+        /// <remarks>
+        /// <para>The n-dimensional transformation is computed for the n-dimensional array A. 
+        /// Before the transform, the input is resized according to the 'dims' parameter. 
+        /// Dimensions larger than corresponding entries in 'dim' are truncated, dimensions
+        /// smaller than corresponding entries in 'dim' are zero padded.</para>
+        /// <para>The n-dimensional transformation is equivalent to repeatedly (inplace) 
+        /// computing one dimensional transformations along all dimensions of A.
+        /// However, using this 
+        /// function may be of magnitudes faster than using 1D transformations. This 
+        /// depends on the algorithm and API provided by the underlying native library.</para>
+        /// <para>The forward fourier transform and the inverse fourier transform of 
+        /// a given data array A are mathematically equivalent. It's only a 
+        /// scaling factor which is needed to make sure, A equals ifft(fft(A)). That 
+        /// scaling is introduced in the inverse transform.</para>
+        /// <para>The transformation is computed by use of the native library 
+        /// which currently is set up for your processor and OS version. The underlying 
+        /// library is automatically choosen at ILNumerics startup and accessed via the 
+        /// static member ILMath.FFT. See the online documentation for more 
+        /// details in how to tune/configure and select dedicated native libraries. 
+        /// Currently supported libraries are: Intel MKL (included), AMD ACML 
+        /// and FFTW3 (prepared, optional modules, not included due to licensing conflicts).</para>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">is thrown if the 
+        /// dim parameter is null, its length is less then the number of dimensions of A 
+        /// or any element of dims is non-negative</exception>
+        public static ILRetArray< complex> fftn(ILInArray< double> A, params int[] dims) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) return empty< complex>(A.Size);
+                ILRetArray< double> resizedA = resize4Transform(A, dims);
+                return FFTImplementation.FFTForward(resizedA, dims.Length);
+            }
+        }
+        /// <summary>
+        /// Fast fourier transform (n-D, specific size)
+        /// </summary>
+        /// <param name="A">Tnput array, n-D</param>
+        /// <param name="dims">Transformation lengths, specifies the length of the dimensions 
+        /// for the transformation array. The length of dims must be &gt; or equal to  the number of 
+        /// dimensions of A. For elements in dim being smaller than corresponding dimension 
+        /// length in A, the dimensions will be truncated, otherwise zeros will be padded.</param>
+        /// <returns>Transformation result of size specified by 'dims' parameter</returns>
+        /// <remarks>
+        /// <para>The n-dimensional transformation is computed for the n-dimensional array A. 
+        /// Before the transform, the input is resized according to the 'dims' parameter. 
+        /// Dimensions larger than corresponding entries in 'dim' are truncated, dimensions
+        /// smaller than corresponding entries in 'dim' are zero padded.</para>
+        /// <para>The n-dimensional transformation is equivalent to repeatedly (inplace) 
+        /// computing one dimensional transformations along all dimensions of A.
+        /// However, using this 
+        /// function may be of magnitudes faster than using 1D transformations. This 
+        /// depends on the algorithm and API provided by the underlying native library.</para>
+        /// <para>The forward fourier transform and the inverse fourier transform of 
+        /// a given data array A are mathematically equivalent. It's only a 
+        /// scaling factor which is needed to make sure, A equals ifft(fft(A)). That 
+        /// scaling is introduced in the inverse transform.</para>
+        /// <para>The transformation is computed by use of the native library 
+        /// which currently is set up for your processor and OS version. The underlying 
+        /// library is automatically choosen at ILNumerics startup and accessed via the 
+        /// static member ILMath.FFT. See the online documentation for more 
+        /// details in how to tune/configure and select dedicated native libraries. 
+        /// Currently supported libraries are: Intel MKL (included), AMD ACML 
+        /// and FFTW3 (prepared, optional modules, not included due to licensing conflicts).</para>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">is thrown if the 
+        /// dim parameter is null, its length is less then the number of dimensions of A 
+        /// or any element of dims is non-negative</exception>
+        public static ILRetArray< complex> fftn(ILInArray< complex> A, params int[] dims) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) return empty< complex>(A.Size);
+                ILRetArray< complex> resizedA = resize4Transform(A, dims);
+                return FFTImplementation.FFTForward(resizedA, dims.Length);
+            }
+        }
+        /// <summary>
+        /// Inverse fast fourier transform (n-D, specific size)
+        /// </summary>
+        /// <param name="A">Input array, n-D</param>
+        /// <param name="dims">Transformation lengths, specifies the length of the dimensions 
+        /// for the transformation array. The length of dims must be &gt; or equal to  the number of 
+        /// dimensions of A. For elements in dim being smaller than corresponding dimension 
+        /// length in A, the dimensions will be truncated, otherwise zeros will be padded.</param>
+        /// <returns>Transformation result of size specified by 'dims' parameter</returns>
+        /// <remarks>
+        /// <para>The n-dimensional transformation is computed for the n-dimensional array A. 
+        /// Before the transform, the input is resized according to the 'dims' parameter. 
+        /// Dimensions larger than corresponding entries in 'dim' are truncated, dimensions
+        /// smaller than corresponding entries in 'dim' are zero padded.</para>
+        /// <para>The n-dimensional transformation is equivalent to repeatedly (inplace) 
+        /// computing one dimensional transformations along all dimensions of A.
+        /// However, using this 
+        /// function may be of magnitudes faster than using 1D transformations. This 
+        /// depends on the algorithm and API provided by the underlying native library.</para>
+        /// <para>The forward fourier transform and the inverse fourier transform of 
+        /// a given data array A are mathematically equivalent. It's only a 
+        /// scaling factor which is needed to make sure, A equals ifft(fft(A)). That 
+        /// scaling is introduced in the inverse transform.</para>
+        /// <para>The transformation is computed by use of the native library 
+        /// which currently is set up for your processor and OS version. The underlying 
+        /// library is automatically choosen at ILNumerics startup and accessed via the 
+        /// static member ILMath.FFT. See the online documentation for more 
+        /// details in how to tune/configure and select dedicated native libraries. 
+        /// Currently supported libraries are: Intel MKL (included), AMD ACML 
+        /// and FFTW3 (prepared, optional modules, not included due to licensing conflicts).</para>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">is thrown if the 
+        /// dim parameter is null, its length is less then the number of dimensions of A 
+        /// or any element of dims is non-negative</exception>
+        public static ILRetArray< complex> ifftn(ILInArray< complex> A, params int[] dims) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) return empty< complex>(A.Size);
+                ILRetArray< complex> resizedA = resize4Transform(A, dims);
+                return FFTImplementation.FFTBackward(resizedA, dims.Length);
+            }
+        }
+        /// <summary>
+        /// Inverse fast fourier transform (n-D, complex hermitian, specific size)
+        /// </summary>
+        /// <param name="A">Complex hermitian input array, n-D</param>
+        /// <param name="dims">Transformation lengths, specifies the length of the dimensions 
+        /// for the transformation array. The length of dims must be &gt; or equal to  the number of 
+        /// dimensions of A. For elements in dim being smaller than corresponding dimension 
+        /// length in A, the dimensions will be truncated, otherwise zeros will be padded.</param>
+        /// <returns>Transformation result, real array of the size specified by the 'dims' parameter</returns>
+        /// <remarks>
+        /// <para>The n-dimensional transformation is computed for the n-dimensional array A. 
+        /// Before the transform, the input is resized according to the 'dims' parameter. 
+        /// Dimensions larger than corresponding entries in 'dim' are truncated, dimensions
+        /// smaller than corresponding entries in 'dim' are zero padded.</para>
+        /// <para>The n-dimensional transformation is equivalent to repeatedly (inplace) 
+        /// computing one dimensional transformations along all dimensions of A.
+        /// However, using this 
+        /// function may be of magnitudes faster than using 1D transformations. This 
+        /// depends on the algorithm and API provided by the underlying native library.</para>
+        /// <para>Since a transform of complex hermitian input data results in the 
+        /// output having the imaginary part equals zero, only the real part is 
+        /// returned for convenience reasons.</para>
+        /// <para>No check is made for A being hermitian! If A is not hermitian (by means 
+        /// of round-off errors), the result will be wrong!</para>
+        /// <para>The forward fourier transform and the inverse fourier transform of 
+        /// a given data array A are mathematically equivalent. It's only a 
+        /// scaling factor which is needed to make sure, A equals ifft(fft(A)). That 
+        /// scaling is introduced in the inverse transform.</para>
+        /// <para>The transformation is computed by use of the native library 
+        /// which currently is set up for your processor and OS version. The underlying 
+        /// library is automatically choosen at ILNumerics startup and accessed via the 
+        /// static member ILMath.FFT. See the online documentation for more 
+        /// details in how to tune/configure and select dedicated native libraries. 
+        /// Currently supported libraries are: Intel MKL (included), AMD ACML 
+        /// and FFTW3 (prepared, optional modules, not included due to licensing conflicts).</para>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">is thrown if the 
+        /// dim parameter is null, its length is less then the number of dimensions of A 
+        /// or any element of dims is non-negative</exception>
+        public static ILRetArray< double> ifftnsym(ILInArray< complex> A, params int[] dims) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) return empty< double>(A.Size);
+                ILRetArray< complex> resizedA = resize4Transform(A, dims);
+                return FFTImplementation.FFTBackwSym(resizedA, dims.Length);
+            }
+        }
+        #endregion
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+
+
+        #region fft(A)
+        /// <summary>
+        /// Fast fourier transform (1D)
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Transformed output array</returns>
+        /// <remarks><para>The transformation is computed along the first 
+        /// non singleton dimension.</para>
+        /// <para>The output array returned will be complex hermitian. I.e. the real 
+        /// part being even and the imaginary part being odd symmetrical.</para>
+        /// <para>The forward fourier transform and the inverse fourier transform of 
+        /// a given data array A are mathematically equivalent. It's only a 
+        /// scaling factor which is needed to make sure, A equals ifft(fft(A)). That 
+        /// scaling is introduced in the inverse transform.</para>
+        /// <para>The transformation is computed by use of the native library 
+        /// which currently is set up for your processor and OS version. The underlying 
+        /// library is automatically choosen at ILNumerics startup and accessed via the 
+        /// static member ILMath.FFT. See the online documentation for more 
+        /// details in how to tune/configure and select dedicated native libraries. 
+        /// Currently supported libraries are: Intel MKL 
+        /// (included), AMD ACML and FFTW3 (prepared, optional modules, not included due to licensing conflicts).</para>
+        /// </remarks>
+        public static ILRetArray< fcomplex> fft(ILInArray< float> A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) return empty< fcomplex>(A.Size);
+                if (A.IsScalar) return new  fcomplex(A.GetValue(0), 0);
+                int fnsd = A.Size.WorkingDimension();
+                return ILMath.FFTImplementation.FFTForward1D(A, fnsd);
+            }
+        }
+        /// <summary>
+        /// Fast fourier transform (1D)
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Transformed output array</returns>
+        /// <remarks>
+        /// <para>The transformation is computed along the first non 
+        /// singleton dimension.</para>
+        /// <para>The forward fourier transform and the inverse fourier transform of 
+        /// a given data array A are mathematically equivalent. It's only a 
+        /// scaling factor which is needed to make sure, A equals ifft(fft(A)). That 
+        /// scaling is introduced in the inverse transform.</para>
+        /// <para>The transformation is computed by use of the native library 
+        /// which currently is set up for your processor and OS version. The underlying 
+        /// library is automatically choosen at ILNumerics startup and accessed via the 
+        /// static member ILMath.FFT. See the online documentation for more 
+        /// details in how to tune/configure and select dedicated native libraries. 
+        /// Currently supported libraries are: Intel MKL 
+        /// (included), AMD ACML and FFTW3 (prepared, optional modules, not included due to licensing conflicts).</para>
+        /// </remarks>
+        public static ILRetArray< fcomplex > fft(ILInArray< fcomplex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) return empty< fcomplex>(A.Size);
+                if (A.IsScalar) return A.C;
+                int fnsd = A.Size.WorkingDimension();
+                return ILMath.FFTImplementation.FFTForward1D(A, fnsd);
+            }
+        }
+        /// <summary>
+        /// Fast inverse fourier transform (1D)
+        /// </summary>
+        /// <param name="A">Input (frequency domain)</param>
+        /// <returns>Inverse transformed output array</returns>
+        /// <remarks>
+        /// <para>The transformation is computed along the first non 
+        /// singleton dimension.</para>
+        /// <para>The forward fourier transform and the inverse fourier transform of 
+        /// a given data array A are mathematically equivalent. It's only a 
+        /// scaling factor which is needed to make sure, A equals ifft(fft(A)). That 
+        /// scaling is introduced in the inverse transform.</para>
+        /// <para>The transformation is computed by use of the native library 
+        /// which currently is set up for your processor and OS version. The underlying 
+        /// library is automatically choosen at ILNumerics startup and accessed via the 
+        /// static member ILMath.FFT. See the online documentation for more 
+        /// details in how to tune/configure and select dedicated native libraries. 
+        /// Currently supported libraries are: Intel MKL 
+        /// (included), AMD ACML and FFTW3 (prepared, optional modules, not included due to licensing conflicts).</para>
+        /// </remarks>
+        public static ILRetArray<fcomplex> ifft(ILInArray<fcomplex> A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) return empty< fcomplex>(A.Size);
+                if (A.IsScalar) return A.C;
+                int fnsd = A.Size.WorkingDimension();
+                return ILMath.FFTImplementation.FFTBackward1D(A, fnsd);
+            }
+        }
+        /// <summary>
+        /// Inverse fast fourier transform, complex hermitian input
+        /// </summary>
+        /// <param name="A">Complex hermitian input array</param>
+        /// <returns>Real output array, same size as A</returns>
+        /// <remarks>
+        /// <para>Since a transform of complex hermitian input data results in 
+        /// the output having all imaginary part equal zero, only the real part is 
+        /// returned for convenience reasons.</para>
+        /// <para>No check is made for A being hermitian! If A is not hermitian (by means 
+        /// of round-off errors), the result will be wrong!</para>
+        /// <para>The transformation is computed along the first non 
+        /// singleton dimension.</para>
+        /// <para>The forward fourier transform and the inverse fourier transform of 
+        /// a given data array A are mathematically equivalent. It's only a 
+        /// scaling factor which is needed to make sure, A equals ifft(fft(A)). That 
+        /// scaling is introduced in the inverse transform.</para>
+        /// <para>The transformation is computed by use of the native library 
+        /// which currently is set up for your processor and OS version. The underlying 
+        /// library is automatically choosen at ILNumerics startup and accessed via the 
+        /// static member ILMath.FFT. See the online documentation for more 
+        /// details in how to tune/configure and select dedicated native libraries. 
+        /// Currently supported libraries are: Intel MKL 
+        /// (included), AMD ACML and FFTW3 (prepared, optional modules, not included due to licensing conflicts).</para>
+        /// </remarks>
+        public static ILRetArray< float > ifftsym(ILInArray< fcomplex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) return empty< float>(A.Size);
+                if (A.IsScalar) return real(A);
+                int fnsd = A.Size.WorkingDimension();
+                return ILMath.FFTImplementation.FFTBackwSym1D(A, fnsd);
+            }
+        }
+        #endregion
+
+        #region fft(A, dim)
+        /// <summary>
+        /// Fast fourier transform along specific dimension
+        /// </summary>
+        /// <param name="A">Real input array</param>
+        /// <param name="dim">Dimension to compute FFT along. This parameter must be non-negative. </param>
+        /// <returns>Transformation result</returns>
+        /// <remarks>
+        /// <para>The output array returned will be complex hermitian. I.e. the real 
+        /// part being even and the imaginary part being odd symmetrical.</para>
+        /// <para>The forward fourier transform and the inverse fourier transform of 
+        /// a given data array A are mathematically equivalent. It's only a 
+        /// scaling factor which is needed to make sure, A equals ifft(fft(A)). That 
+        /// scaling is introduced in the inverse transform.</para>
+        /// <para>The transformation is computed by use of the native library 
+        /// which currently is set up for your processor and OS version. The underlying 
+        /// library is automatically choosen at ILNumerics startup and accessed via the 
+        /// static member ILMath.FFT. See the online documentation for more 
+        /// details in how to tune/configure and select dedicated native libraries. 
+        /// Currently supported libraries are: Intel MKL 
+        /// (included), AMD ACML and FFTW3 (prepared, optional modules, not included due to licensing conflicts).</para>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">is thrown if 
+        /// the dim parameter is negative</exception>
+        public static ILRetArray< fcomplex > fft(ILInArray< float > A, int dim) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0) throw new ILArgumentException("the 'dim' parameter must point to an existing dimension index of A");
+                if (A.IsEmpty) return empty< fcomplex>(A.Size);
+                if (A.IsScalar) return new  fcomplex(A.GetValue(0), 0);
+                return ILMath.FFTImplementation.FFTForward1D(A, dim);
+            }
+        }
+        /// <summary>
+        /// Fast fourier transform along specific dimension
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="dim">Dimension to compute FFT along. This parameter
+        /// must be non-negative. </param>
+        /// <returns>Transformation result</returns>
+        /// <remarks>
+        /// <para>The forward fourier transform and the inverse fourier transform of 
+        /// a given data array A are mathematically equivalent. It's only a 
+        /// scaling factor which is needed to make sure, A equals ifft(fft(A)). That 
+        /// scaling is introduced in the inverse transform.</para>
+        /// <para>The transformation is computed by use of the native library 
+        /// which currently is set up for your processor and OS version. The underlying 
+        /// library is automatically choosen at ILNumerics startup and accessed via the 
+        /// static member ILMath.FFT. See the online documentation for more 
+        /// details in how to tune/configure and select dedicated native libraries. 
+        /// Currently supported libraries are: Intel MKL 
+        /// (included), AMD ACML and FFTW3 (prepared, optional modules, not included due to licensing conflicts).</para>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">is thrown if 
+        /// the dim parameter is negative</exception>
+        public static ILRetArray< fcomplex > fft(ILInArray< fcomplex > A, int dim) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0) throw new ILArgumentException("the 'dim' parameter must point to an existing dimension index of A");
+                if (A.IsEmpty) return empty< fcomplex>(A.Size);
+                if (A.IsScalar) return A.C;
+                return ILMath.FFTImplementation.FFTForward1D(A, dim); 
+            }
+        }
+        /// <summary>
+        /// Inverse fast fourier transform along specific dimension
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="dim">Dimension to compute FFT along. This parameter
+        /// must be non-negative. </param>
+        /// <returns>Transformation result</returns>
+        /// <remarks>
+        /// <para>The forward fourier transform and the inverse fourier transform of 
+        /// a given data array A are mathematically equivalent. It's only a 
+        /// scaling factor which is needed to make sure, A equals ifft(fft(A)). That 
+        /// scaling is introduced in the inverse transform.</para>
+        /// <para>The transformation is computed by use of the native library 
+        /// which currently is set up for your processor and OS version. The underlying 
+        /// library is automatically choosen at ILNumerics startup and accessed via the 
+        /// static member ILMath.FFT. See the online documentation for more 
+        /// details in how to tune/configure and select dedicated native libraries. 
+        /// Currently supported libraries are: Intel MKL 
+        /// (included), AMD ACML and FFTW3 (prepared, optional modules, not included due to licensing conflicts).</para>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">is thrown if the dim parameter is negative</exception>
+        public static ILRetArray< fcomplex> ifft(ILInArray< fcomplex> A, int dim) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0) throw new ILArgumentException("the 'dim' parameter must point to an existing dimension index of A");
+                if (A.IsEmpty) return empty< fcomplex>(A.Size);
+                if (A.IsScalar) return A.C;
+                return ILMath.FFTImplementation.FFTBackward1D(A, dim);
+            }
+        }
+        /// <summary>
+        /// Inverse fast fourier transform, complex hermitian input
+        /// </summary>
+        /// <param name="A">Complex hermitian input array (frequency domain)</param>
+        /// <param name="dim">Dimension to compute FFT along. This parameter
+        /// must be non-negative. </param>
+        /// <returns>Real output array, same size as A</returns>
+        /// <remarks>
+        /// <para>Since a transform of complex hermitian input data results in the 
+        /// output having the imaginary part equals zero, only the real part is 
+        /// returned for convenience reasons.</para>
+        /// <para>No check is made for A being hermitian! If A is not hermitian (by means 
+        /// of round-off errors), the result will be wrong!</para>
+        /// <para>The forward fourier transform and the inverse fourier transform of 
+        /// a given data array A are mathematically equivalent. It's only a 
+        /// scaling factor which is needed to make sure, A equals ifft(fft(A)). That 
+        /// scaling is introduced in the inverse transform.</para>
+        /// <para>The transformation is computed by use of the native library 
+        /// which currently is set up for your processor and OS version. The underlying 
+        /// library is automatically choosen at ILNumerics startup and accessed via the 
+        /// static member ILMath.FFT. See the online documentation for more 
+        /// details in how to tune/configure and select dedicated native libraries. 
+        /// Currently supported libraries are: Intel MKL (included), AMD ACML 
+        /// and FFTW3 (prepared, optional modules, not included due to licensing conflicts).</para>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">is thrown if the dim parameter is negative</exception>
+        public static ILRetArray< float > ifftsym(ILInArray< fcomplex > A, int dim) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0) throw new ILArgumentException("the 'dim' parameter must point to an existing dimension index of A");
+                if (A.IsEmpty) return empty< float>(A.Size);
+                if (A.IsScalar) return real(A);
+                return ILMath.FFTImplementation.FFTBackwSym1D(A, dim);
+            }
+        }
+        #endregion
+
+        #region fft2(A)
+        /// <summary>
+        /// Fast fourier transform (2D)
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Transformation result</returns>
+        /// <remarks>
+        /// <para>The 2D transformation is computed for the first 2 dimensions, regardless 
+        /// of those dimensions being singleton or non-singleton. If A is an n-d array, 
+        /// the transformation is repeated for trailing dimensions of A respectively. </para>
+        /// <para>The output array returned will be complex hermitian.</para>
+        /// <para>The two dimensional transformation is equivalent to repeatedly transforming 
+        /// the columns and after that transforming the rows of A. However, using this 
+        /// function may be of magnitudes faster than using 1D transformations. This 
+        /// depends on the algorithm and API provided by the underlying native library.</para>
+        /// <para>The forward fourier transform and the inverse fourier transform of 
+        /// a given data array A are mathematically equivalent. It's only a 
+        /// scaling factor which is needed to make sure, A equals ifft(fft(A)). That 
+        /// scaling is introduced in the inverse transform.</para>
+        /// <para>The transformation is computed by use of the native library 
+        /// which currently is set up for your processor and OS version. The underlying 
+        /// library is automatically choosen at ILNumerics startup and accessed via the 
+        /// static member ILMath.FFT. See the online documentation for more 
+        /// details in how to tune/configure and select dedicated native libraries. 
+        /// Currently supported libraries are: Intel MKL (included), AMD ACML 
+        /// and FFTW3 (prepared, optional modules, not included due to licensing conflicts).</para>
+        /// </remarks>
+        public static ILRetArray< fcomplex > fft2(ILInArray< float > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) return empty< fcomplex>(A.Size);
+                if (A.IsScalar) return new  fcomplex(A.GetValue(0), 0);
+                return FFTImplementation.FFTForward(A, 2);
+            } 
+        }
+        /// <summary>
+        /// Fast fourier transform (2D)
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Transformation result</returns>
+        /// <remarks>
+        /// <para>The transformation is computed for the first 2 dimensions, regardless 
+        /// of those dimensions being singleton or non-singleton. If A is an n-d array, 
+        /// the transformation is repeated for trailing dimensions of A respectively. </para>
+        /// <para>The two dimensional transformation is equivalent to repeatedly transforming 
+        /// the columns and after that transforming the rows of A. However, using this 
+        /// function may be of magnitudes faster than using 1D transformations. This 
+        /// depends on the algorithm and API provided by the underlying native library.</para>
+        /// <para>The forward fourier transform and the inverse fourier transform of 
+        /// a given data array A are mathematically equivalent. It's only a 
+        /// scaling factor which is needed to make sure, A equals ifft(fft(A)). That 
+        /// scaling is introduced in the inverse transform.</para>
+        /// <para>The transformation is computed by use of the native library 
+        /// which currently is set up for your processor and OS version. The underlying 
+        /// library is automatically choosen at ILNumerics startup and accessed via the 
+        /// static member ILMath.FFT. See the online documentation for more 
+        /// details in how to tune/configure and select dedicated native libraries. 
+        /// Currently supported libraries are: Intel MKL (included), AMD ACML 
+        /// and FFTW3 (prepared, optional modules, not included due to licensing conflicts).</para>
+        /// </remarks>
+        public static ILRetArray< fcomplex> fft2(ILInArray< fcomplex> A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) return empty< fcomplex>(A.Size);
+                if (A.IsScalar) return A.C;
+                return FFTImplementation.FFTForward(A, 2);
+            }
+        }
+        /// <summary>
+        /// Inverse fast fourier transform (2D)
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Transformation result</returns>
+        /// <remarks>
+        /// <para>The transformation is computed for the first 2 dimensions, regardless 
+        /// of those dimensions being singleton or non-singleton. If A is an n-d array, 
+        /// the transformation is repeated for trailing dimensions of A respectively. </para>
+        /// <para>The two dimensional transformation is equivalent to repeatedly transforming 
+        /// the columns and after that transforming the rows of A. However, using this 
+        /// function may be of magnitudes faster than using 1D transformations. This 
+        /// depends on the algorithm and API provided by the underlying native library.</para>
+        /// <para>The forward fourier transform and the inverse fourier transform of 
+        /// a given data array A are mathematically equivalent. It's only a 
+        /// scaling factor which is needed to make sure, A equals ifft(fft(A)). That 
+        /// scaling is introduced in the inverse transform.</para>
+        /// <para>The transformation is computed by use of the native library 
+        /// which currently is set up for your processor and OS version. The underlying 
+        /// library is automatically choosen at ILNumerics startup and accessed via the 
+        /// static member ILMath.FFT. See the online documentation for more 
+        /// details in how to tune/configure and select dedicated native libraries. 
+        /// Currently supported libraries are: Intel MKL (included), AMD ACML 
+        /// and FFTW3 (prepared, optional modules, not included due to licensing conflicts).</para>
+        /// </remarks>
+        public static ILRetArray< fcomplex> ifft2(ILInArray< fcomplex> A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) return empty< fcomplex>(A.Size);
+                if (A.IsScalar) return A.C;
+                return FFTImplementation.FFTBackward(A, 2);
+            }
+        }
+        /// <summary>
+        /// Inverse fast fourier transform (2D, hermitian input)
+        /// </summary>
+        /// <param name="A">Complex hermitian input array (frequency domain)</param>
+        /// <returns>Transformation result</returns>
+        /// <remarks>
+        /// <para>Since a transform of complex hermitian input data results in the 
+        /// output having the imaginary part equals zero, only the real part is 
+        /// returned for convenience reasons.</para>
+        /// <para>No check is made for A being hermitian! If A is not hermitian (by means 
+        /// of round-off errors), the result will be wrong!</para>
+        /// <para>The transformation is computed for the first 2 dimensions, regardless 
+        /// of those dimensions being singleton or non-singleton. If A is an n-d array, 
+        /// the transformation is repeated for trailing dimensions of A respectively. </para>
+        /// <para>The two dimensional transformation is equivalent to repeatedly transforming 
+        /// the columns and after that transforming the rows of A. However, using this 
+        /// function may be of magnitudes faster than using 1D transformations. This 
+        /// depends on the algorithm and API provided by the underlying native library.</para>
+        /// <para>The forward fourier transform and the inverse fourier transform of 
+        /// a given data array A are mathematically equivalent. It's only a 
+        /// scaling factor which is needed to make sure, A equals ifft(fft(A)). That 
+        /// scaling is introduced in the inverse transform.</para>
+        /// <para>The transformation is computed by use of the native library 
+        /// which currently is set up for your processor and OS version. The underlying 
+        /// library is automatically choosen at ILNumerics startup and accessed via the 
+        /// static member ILMath.FFT. See the online documentation for more 
+        /// details in how to tune/configure and select dedicated native libraries. 
+        /// Currently supported libraries are: Intel MKL (included), AMD ACML 
+        /// and FFTW3 (prepared, optional modules, not included due to licensing conflicts).</para>
+        /// </remarks>
+        public static ILRetArray< float> ifft2sym(ILInArray< fcomplex> A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) return empty< float>(A.Size);
+                if (A.IsScalar) return real(A);
+                return FFTImplementation.FFTBackwSym(A, 2);
+            }
+        }
+        #endregion
+
+        #region fft2(A,m,n)
+        /// <summary>
+        /// Fast fourier transform (2D)
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="m">Transformation column length</param>
+        /// <param name="n">Transformation row length</param>
+        /// <returns>Transformation result, complex hermitian</returns>
+        /// <remarks>
+        /// <para>The transformation is computed for the first 2 dimensions, regardless 
+        /// of those dimensions being singleton or non-singleton. If A is an n-d array, 
+        /// the transformation is repeated for trailing dimensions of A respectively. </para>
+        /// <para>The data to be transformed (based on the A array) are resized according to 
+        /// the length parameter m and n. If m or n is larger then the length of the corresponding 
+        /// dimension of A, zeros will be padded, otherwise the dimensions are truncated respectively. </para>
+        /// <para>The two dimensional transformation is equivalent to repeatedly transforming 
+        /// the columns and after that transforming the rows of A. However, using this 
+        /// function may be of magnitudes faster than using 1D transformations. This 
+        /// depends on the algorithm and API provided by the underlying native library.</para>
+        /// <para>The forward fourier transform and the inverse fourier transform of 
+        /// a given data array A are mathematically equivalent. It's only a 
+        /// scaling factor which is needed to make sure, A equals ifft(fft(A)). That 
+        /// scaling is introduced in the inverse transform.</para>
+        /// <para>The transformation is computed by use of the native library 
+        /// which currently is set up for your processor and OS version. The underlying 
+        /// library is automatically choosen at ILNumerics startup and accessed via the 
+        /// static member ILMath.FFT. See the online documentation for more 
+        /// details in how to tune/configure and select dedicated native libraries. 
+        /// Currently supported libraries are: Intel MKL (included), AMD ACML 
+        /// and FFTW3 (prepared, optional modules, not included due to licensing conflicts).</para>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">is thrown if one of n or m is negative</exception>
+        public static ILRetArray< fcomplex> fft2(ILInArray< float> A, int m, int n) {
+            using (ILScope.Enter(A)) {
+                if (m < 0 || n < 0) throw new ILArgumentException("dimension length specifier 'm' and 'n' must be non-negative!");
+                if (A.IsEmpty) return empty< fcomplex>(A.Size);
+                int[] Asize = A.Size.ToIntArray();
+                Asize[0] = m; Asize[1] = n;
+                ILArray< float> resizedA = resize4Transform(A, Asize);
+                return FFTImplementation.FFTForward(resizedA, 2);
+            }
+        }
+        /// <summary>
+        /// Fast fourier transform (2D)
+        /// </summary>
+        /// <param name="A">input array</param>
+        /// <param name="m">Transformation column length</param>
+        /// <param name="n">Transformation row length</param>
+        /// <returns>Transformation result</returns>
+        /// <remarks>
+        /// <para>The transformation is computed for the first 2 dimensions, regardless 
+        /// of those dimensions being singleton or non-singleton. If A is an n-d array, 
+        /// the transformation is repeated for trailing dimensions of A respectively. </para>
+        /// <para>The data to be transformed (based on the A array) are resized according to 
+        /// the length parameter m and n. If m or n is larger then the length of the corresponding 
+        /// dimension of A, zeros will be padded, otherwise the dimensions are truncated respectively. </para>
+        /// <para>The two dimensional transformation is equivalent to repeatedly transforming 
+        /// the columns and after that transforming the rows of A. However, using this 
+        /// function may be of magnitudes faster than using 1D transformations. This 
+        /// depends on the algorithm and API provided by the underlying native library.</para>
+        /// <para>The forward fourier transform and the inverse fourier transform of 
+        /// a given data array A are mathematically equivalent. It's only a 
+        /// scaling factor which is needed to make sure, A equals ifft(fft(A)). That 
+        /// scaling is introduced in the inverse transform.</para>
+        /// <para>The transformation is computed by use of the native library 
+        /// which currently is set up for your processor and OS version. The underlying 
+        /// library is automatically choosen at ILNumerics startup and accessed via the 
+        /// static member ILMath.FFT. See the online documentation for more 
+        /// details in how to tune/configure and select dedicated native libraries. 
+        /// Currently supported libraries are: Intel MKL (included), AMD ACML 
+        /// and FFTW3 (prepared, optional modules, not included due to licensing conflicts).</para>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">is thrown if one of n or m is negative</exception>
+        public static ILRetArray< fcomplex> fft2(ILInArray< fcomplex> A, int m, int n) {
+            using (ILScope.Enter(A)) {
+                if (m < 0 || n < 0) throw new ILArgumentException("dimension length specifier 'm' and 'n' must be non-negative!");
+                if (A.IsEmpty) return empty< fcomplex>(A.Size);
+                int[] Asize = A.Size.ToIntArray();
+                Asize[0] = m; Asize[1] = n;
+                ILRetArray< fcomplex> resizedA = resize4Transform(A, Asize);
+                return FFTImplementation.FFTForward(resizedA, 2);
+            }
+        }
+        /// <summary>
+        /// Inverse fast fourier transform (2D)
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="m">Transformation column length</param>
+        /// <param name="n">Transformation row length</param>
+        /// <returns>Transformation result</returns>
+        /// <remarks>
+        /// <para>The transformation is computed for the first 2 dimensions, regardless 
+        /// of those dimensions being singleton or non-singleton. If A is an n-d array, 
+        /// the transformation is repeated for trailing dimensions of A respectively. </para>
+        /// <para>The data to be transformed (based on the array A) are resized according to 
+        /// the length parameter m and n. If m or n is larger then the length of the corresponding 
+        /// dimension of A, zeros will be padded, otherwise the dimensions are truncated respectively. </para>
+        /// <para>The two dimensional transformation is equivalent to repeatedly transforming 
+        /// the columns and after that transforming the rows of A. However, using this 
+        /// function may be of magnitudes faster than using 1D transformations. This 
+        /// depends on the algorithm and API provided by the underlying native library.</para>
+        /// <para>The forward fourier transform and the inverse fourier transform of 
+        /// a given data array A are mathematically equivalent. It's only a 
+        /// scaling factor which is needed to make sure, A equals ifft(fft(A)). That 
+        /// scaling is introduced in the inverse transform.</para>
+        /// <para>The transformation is computed by use of the native library 
+        /// which currently is set up for your processor and OS version. The underlying 
+        /// library is automatically choosen at ILNumerics startup and accessed via the 
+        /// static member ILMath.FFT. See the online documentation for more 
+        /// details in how to tune/configure and select dedicated native libraries. 
+        /// Currently supported libraries are: Intel MKL (included), AMD ACML 
+        /// and FFTW3 (prepared, optional modules, not included due to licensing conflicts).</para>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">is thrown if one of n or m is negative</exception>
+        public static ILRetArray< fcomplex> ifft2(ILInArray< fcomplex> A, int m, int n) {
+            using (ILScope.Enter(A)) {
+                if (m < 0 || n < 0) throw new ILArgumentException("dimension length specifier 'm' and 'n' must be non-negative!");
+                if (A.IsEmpty) return empty< fcomplex>(A.Size);
+                int[] Asize = A.Size.ToIntArray();
+                Asize[0] = m; Asize[1] = n;
+                ILRetArray< fcomplex> resizedA = resize4Transform(A, Asize);
+                return FFTImplementation.FFTBackward(resizedA, 2);
+            }
+        }
+        /// <summary>
+        /// Inverse fast fourier transform (2D)
+        /// </summary>
+        /// <param name="A">Complex hermitian input array, symmetric in first 2 dimensions</param>
+        /// <param name="m">Transformation column length</param>
+        /// <param name="n">Transformation row length</param>
+        /// <returns>Transformation result</returns>
+        /// <remarks>
+        /// <para>The transformation is computed for the first 2 dimensions, regardless 
+        /// of those dimensions being singleton or non-singleton. If A is an n-d array, 
+        /// the transformation is repeated for trailing dimensions of A respectively. The 
+        /// lengths of those trailing dimensions are not altered.</para>
+        /// <para>Since a transform of complex hermitian input data results in the 
+        /// output having the imaginary part equals zero, only the real part is 
+        /// returned for convenience reasons.</para>
+        /// <para>No check is made for A being hermitian! If A is not hermitian (by means 
+        /// of round-off errors), the result will be wrong!</para>
+        /// <para>The data to be transformed (based on the array A) are resized according to 
+        /// the length parameter m and n. If m or n is larger then the length of the corresponding 
+        /// dimension of A, zeros will be padded, otherwise the dimensions are truncated respectively. </para>
+        /// <para>The two dimensional transformation is equivalent to repeatedly transforming 
+        /// the columns and after that transforming the rows of A. However, using this 
+        /// function may be of magnitudes faster than using 1D transformations. This 
+        /// depends on the algorithm and API provided by the underlying native library.</para>
+        /// <para>The forward fourier transform and the inverse fourier transform of 
+        /// a given data array A are mathematically equivalent. It's only a 
+        /// scaling factor which is needed to make sure, A equals ifft(fft(A)). That 
+        /// scaling is introduced in the inverse transform.</para>
+        /// <para>The transformation is computed by use of the native library 
+        /// which currently is set up for your processor and OS version. The underlying 
+        /// library is automatically choosen at ILNumerics startup and accessed via the 
+        /// static member ILMath.FFT. See the online documentation for more 
+        /// details in how to tune/configure and select dedicated native libraries. 
+        /// Currently supported libraries are: Intel MKL (included), AMD ACML 
+        /// and FFTW3 (prepared, optional modules, not included due to licensing conflicts).</para>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">is thrown if one of n or m is negative</exception>
+        public static ILRetArray< float> ifft2sym(ILInArray< fcomplex> A, int m, int n) {
+            using (ILScope.Enter(A)) {
+                if (m < 0 || n < 0) throw new ILArgumentException("dimension length specifier 'm' and 'n' must be non-negative!");
+                if (A.IsEmpty) return empty< float>(A.Size);
+                int[] Asize = A.Size.ToIntArray();
+                Asize[0] = m; Asize[1] = n;
+                ILRetArray< fcomplex> resizedA = resize4Transform(A, Asize);
+                return FFTImplementation.FFTBackwSym(resizedA, 2);
+            }
+        }
+        #endregion
+
+        #region fftn(A)
+        /// <summary>
+        /// Fast fourier transform (n-D)
+        /// </summary>
+        /// <param name="A">Input array, n-D</param>
+        /// <returns>Transformation result, complex hermitian</returns>
+        /// <remarks>
+        /// <para>The n-dimensional transformation is computed for the n-dimensional array A. 
+        /// This is equivalent to repeatedly (inplace) 
+        /// computing one dimensional transformations along all dimensions of A.
+        /// However, using this 
+        /// function may be of magnitudes faster than using 1D transformations. This 
+        /// depends on the algorithm and API provided by the underlying native library.</para>
+        /// <para>The forward fourier transform and the inverse fourier transform of 
+        /// a given data array A are mathematically equivalent. It's only a 
+        /// scaling factor which is needed to make sure, A equals ifft(fft(A)). That 
+        /// scaling is introduced in the inverse transform.</para>
+        /// <para>The transformation is computed by use of the native library 
+        /// which currently is set up for your processor and OS version. The underlying 
+        /// library is automatically choosen at ILNumerics startup and accessed via the 
+        /// static member ILMath.FFT. See the online documentation for more 
+        /// details in how to tune/configure and select dedicated native libraries. 
+        /// Currently supported libraries are: Intel MKL (included), AMD ACML 
+        /// and FFTW3 (prepared, optional modules, not included due to licensing conflicts).</para>
+        /// </remarks>
+        public static ILRetArray< fcomplex> fftn(ILInArray< float> A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) return empty< fcomplex>(A.Size);
+                return FFTImplementation.FFTForward(A, A.Size.NumberOfDimensions);
+            }
+        }
+        /// <summary>
+        /// Fast fourier transform (n-D)
+        /// </summary>
+        /// <param name="A">Input array, n-D</param>
+        /// <returns>Transformation result</returns>
+        /// <remarks>
+        /// <para>The n-dimensional transformation is computed for the n-dimensional array A. 
+        /// This is equivalent to repeatedly (inplace) 
+        /// computing one dimensional transformations along all dimensions of A.
+        /// However, using this 
+        /// function may be of magnitudes faster than using 1D transformations. This 
+        /// depends on the algorithm and API provided by the underlying native library.</para>
+        /// <para>The forward fourier transform and the inverse fourier transform of 
+        /// a given data array A are mathematically equivalent. It's only a 
+        /// scaling factor which is needed to make sure, A equals ifft(fft(A)). That 
+        /// scaling is introduced in the inverse transform.</para>
+        /// <para>The transformation is computed by use of the native library 
+        /// which currently is set up for your processor and OS version. The underlying 
+        /// library is automatically choosen at ILNumerics startup and accessed via the 
+        /// static member ILMath.FFT. See the online documentation for more 
+        /// details in how to tune/configure and select dedicated native libraries. 
+        /// Currently supported libraries are: Intel MKL (included), AMD ACML 
+        /// and FFTW3 (prepared, optional modules, not included due to licensing conflicts).</para>
+        /// </remarks>
+        public static ILRetArray< fcomplex> fftn(ILInArray< fcomplex> A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) return empty< fcomplex>(A.Size);
+                return FFTImplementation.FFTForward(A, A.Size.NumberOfDimensions);
+            }
+        }
+        /// <summary>
+        /// Inverse fast fourier transform (n-D)
+        /// </summary>
+        /// <param name="A">Input array, n-D (frequency domain)</param>
+        /// <returns>Transformation result</returns>
+        /// <remarks>
+        /// <para>The n-dimensional inverse transformation is computed for the n-dimensional array A. 
+        /// This is equivalent to repeatedly (inplace) 
+        /// computing one dimensional transformations along all dimensions of A.
+        /// However, using this 
+        /// function may be of magnitudes faster than using 1D transformations. This 
+        /// depends on the algorithm and API provided by the underlying native library.</para>
+        /// <para>The forward fourier transform and the inverse fourier transform of 
+        /// a given data array A are mathematically equivalent. It's only a 
+        /// scaling factor which is needed to make sure, A equals ifft(fft(A)). That 
+        /// scaling is introduced in the inverse transform.</para>
+        /// <para>The transformation is computed by use of the native library 
+        /// which currently is set up for your processor and OS version. The underlying 
+        /// library is automatically choosen at ILNumerics startup and accessed via the 
+        /// static member ILMath.FFT. See the online documentation for more 
+        /// details in how to tune/configure and select dedicated native libraries. 
+        /// Currently supported libraries are: Intel MKL (included), AMD ACML 
+        /// and FFTW3 (prepared, optional modules, not included due to licensing conflicts).</para>
+        /// </remarks>
+        public static ILRetArray< fcomplex> ifftn(ILInArray< fcomplex> A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) return empty< fcomplex>(A.Size);
+                return FFTImplementation.FFTBackward(A, A.Size.NumberOfDimensions);
+            }
+        }
+        /// <summary>
+        /// Inverse fast fourier transform (n-D)
+        /// </summary>
+        /// <param name="A">Input array, n-D, complex hermitian (frequency domain)</param>
+        /// <returns>Transformation result</returns>
+        /// <remarks>
+        /// <para>The n-dimensional inverse transformation is computed for the n-dimensional array A. 
+        /// This is equivalent to repeatedly (inplace) 
+        /// computing one dimensional transformations along all dimensions of A.
+        /// However, using this 
+        /// function may be of magnitudes faster than using 1D transformations. This 
+        /// depends on the algorithm and API provided by the underlying native library.</para>
+        /// <para>Since a transform of complex hermitian input data results in the 
+        /// output having the imaginary part equals zero, only the real part is 
+        /// returned for convenience reasons.</para>
+        /// <para>No check is made for A being hermitian! If A is not hermitian (by means 
+        /// of round-off errors), the result will be wrong!</para>
+        /// <para>The forward fourier transform and the inverse fourier transform of 
+        /// a given data array A are mathematically equivalent. It's only a 
+        /// scaling factor which is needed to make sure, A equals ifft(fft(A)). That 
+        /// scaling is introduced in the inverse transform.</para>
+        /// <para>The transformation is computed by use of the native library 
+        /// which currently is set up for your processor and OS version. The underlying 
+        /// library is automatically choosen at ILNumerics startup and accessed via the 
+        /// static member ILMath.FFT. See the online documentation for more 
+        /// details in how to tune/configure and select dedicated native libraries. 
+        /// Currently supported libraries are: Intel MKL (included), AMD ACML 
+        /// and FFTW3 (prepared, optional modules, not included due to licensing conflicts).</para>
+        /// </remarks>
+        public static ILRetArray< float> ifftnsym(ILInArray< fcomplex> A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) return empty< float>(A.Size);
+                return FFTImplementation.FFTBackwSym(A, A.Size.NumberOfDimensions);
+            }
+        }
+        #endregion
+
+        #region fftn(A, params dims)
+        /// <summary>
+        /// Fast fourier transform (n-D, specific size)
+        /// </summary>
+        /// <param name="A">Input array, n-D</param>
+        /// <param name="dims">Transformation lengths, specifies the length of the dimensions 
+        /// for the transformation array. The length of dims must be &gt; or equal to the number of 
+        /// dimensions of A. For elements in dim being smaller than corresponding dimension 
+        /// length in A, the dimensions will be truncated, otherwise zeros will be padded.</param>
+        /// <returns>Transformation result of size specified by 'dims' parameter, complex hermitian</returns>
+        /// <remarks>
+        /// <para>The n-dimensional transformation is computed for the n-dimensional array A. 
+        /// Before the transform, the input is resized according to the 'dims' parameter. 
+        /// Dimensions larger than corresponding entries in 'dim' are truncated, dimensions
+        /// smaller than corresponding entries in 'dim' are zero padded.</para>
+        /// <para>The n-dimensional transformation is equivalent to repeatedly (inplace) 
+        /// computing one dimensional transformations along all dimensions of A.
+        /// However, using this 
+        /// function may be of magnitudes faster than using 1D transformations. This 
+        /// depends on the algorithm and API provided by the underlying native library.</para>
+        /// <para>The forward fourier transform and the inverse fourier transform of 
+        /// a given data array A are mathematically equivalent. It's only a 
+        /// scaling factor which is needed to make sure, A equals ifft(fft(A)). That 
+        /// scaling is introduced in the inverse transform.</para>
+        /// <para>The transformation is computed by use of the native library 
+        /// which currently is set up for your processor and OS version. The underlying 
+        /// library is automatically choosen at ILNumerics startup and accessed via the 
+        /// static member ILMath.FFT. See the online documentation for more 
+        /// details in how to tune/configure and select dedicated native libraries. 
+        /// Currently supported libraries are: Intel MKL (included), AMD ACML 
+        /// and FFTW3 (prepared, optional modules, not included due to licensing conflicts).</para>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">is thrown if the 
+        /// dim parameter is null, its length is less then the number of dimensions of A 
+        /// or any element of dims is non-negative</exception>
+        public static ILRetArray< fcomplex> fftn(ILInArray< float> A, params int[] dims) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) return empty< fcomplex>(A.Size);
+                ILRetArray< float> resizedA = resize4Transform(A, dims);
+                return FFTImplementation.FFTForward(resizedA, dims.Length);
+            }
+        }
+        /// <summary>
+        /// Fast fourier transform (n-D, specific size)
+        /// </summary>
+        /// <param name="A">Tnput array, n-D</param>
+        /// <param name="dims">Transformation lengths, specifies the length of the dimensions 
+        /// for the transformation array. The length of dims must be &gt; or equal to  the number of 
+        /// dimensions of A. For elements in dim being smaller than corresponding dimension 
+        /// length in A, the dimensions will be truncated, otherwise zeros will be padded.</param>
+        /// <returns>Transformation result of size specified by 'dims' parameter</returns>
+        /// <remarks>
+        /// <para>The n-dimensional transformation is computed for the n-dimensional array A. 
+        /// Before the transform, the input is resized according to the 'dims' parameter. 
+        /// Dimensions larger than corresponding entries in 'dim' are truncated, dimensions
+        /// smaller than corresponding entries in 'dim' are zero padded.</para>
+        /// <para>The n-dimensional transformation is equivalent to repeatedly (inplace) 
+        /// computing one dimensional transformations along all dimensions of A.
+        /// However, using this 
+        /// function may be of magnitudes faster than using 1D transformations. This 
+        /// depends on the algorithm and API provided by the underlying native library.</para>
+        /// <para>The forward fourier transform and the inverse fourier transform of 
+        /// a given data array A are mathematically equivalent. It's only a 
+        /// scaling factor which is needed to make sure, A equals ifft(fft(A)). That 
+        /// scaling is introduced in the inverse transform.</para>
+        /// <para>The transformation is computed by use of the native library 
+        /// which currently is set up for your processor and OS version. The underlying 
+        /// library is automatically choosen at ILNumerics startup and accessed via the 
+        /// static member ILMath.FFT. See the online documentation for more 
+        /// details in how to tune/configure and select dedicated native libraries. 
+        /// Currently supported libraries are: Intel MKL (included), AMD ACML 
+        /// and FFTW3 (prepared, optional modules, not included due to licensing conflicts).</para>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">is thrown if the 
+        /// dim parameter is null, its length is less then the number of dimensions of A 
+        /// or any element of dims is non-negative</exception>
+        public static ILRetArray< fcomplex> fftn(ILInArray< fcomplex> A, params int[] dims) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) return empty< fcomplex>(A.Size);
+                ILRetArray< fcomplex> resizedA = resize4Transform(A, dims);
+                return FFTImplementation.FFTForward(resizedA, dims.Length);
+            }
+        }
+        /// <summary>
+        /// Inverse fast fourier transform (n-D, specific size)
+        /// </summary>
+        /// <param name="A">Input array, n-D</param>
+        /// <param name="dims">Transformation lengths, specifies the length of the dimensions 
+        /// for the transformation array. The length of dims must be &gt; or equal to  the number of 
+        /// dimensions of A. For elements in dim being smaller than corresponding dimension 
+        /// length in A, the dimensions will be truncated, otherwise zeros will be padded.</param>
+        /// <returns>Transformation result of size specified by 'dims' parameter</returns>
+        /// <remarks>
+        /// <para>The n-dimensional transformation is computed for the n-dimensional array A. 
+        /// Before the transform, the input is resized according to the 'dims' parameter. 
+        /// Dimensions larger than corresponding entries in 'dim' are truncated, dimensions
+        /// smaller than corresponding entries in 'dim' are zero padded.</para>
+        /// <para>The n-dimensional transformation is equivalent to repeatedly (inplace) 
+        /// computing one dimensional transformations along all dimensions of A.
+        /// However, using this 
+        /// function may be of magnitudes faster than using 1D transformations. This 
+        /// depends on the algorithm and API provided by the underlying native library.</para>
+        /// <para>The forward fourier transform and the inverse fourier transform of 
+        /// a given data array A are mathematically equivalent. It's only a 
+        /// scaling factor which is needed to make sure, A equals ifft(fft(A)). That 
+        /// scaling is introduced in the inverse transform.</para>
+        /// <para>The transformation is computed by use of the native library 
+        /// which currently is set up for your processor and OS version. The underlying 
+        /// library is automatically choosen at ILNumerics startup and accessed via the 
+        /// static member ILMath.FFT. See the online documentation for more 
+        /// details in how to tune/configure and select dedicated native libraries. 
+        /// Currently supported libraries are: Intel MKL (included), AMD ACML 
+        /// and FFTW3 (prepared, optional modules, not included due to licensing conflicts).</para>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">is thrown if the 
+        /// dim parameter is null, its length is less then the number of dimensions of A 
+        /// or any element of dims is non-negative</exception>
+        public static ILRetArray< fcomplex> ifftn(ILInArray< fcomplex> A, params int[] dims) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) return empty< fcomplex>(A.Size);
+                ILRetArray< fcomplex> resizedA = resize4Transform(A, dims);
+                return FFTImplementation.FFTBackward(resizedA, dims.Length);
+            }
+        }
+        /// <summary>
+        /// Inverse fast fourier transform (n-D, complex hermitian, specific size)
+        /// </summary>
+        /// <param name="A">Complex hermitian input array, n-D</param>
+        /// <param name="dims">Transformation lengths, specifies the length of the dimensions 
+        /// for the transformation array. The length of dims must be &gt; or equal to  the number of 
+        /// dimensions of A. For elements in dim being smaller than corresponding dimension 
+        /// length in A, the dimensions will be truncated, otherwise zeros will be padded.</param>
+        /// <returns>Transformation result, real array of the size specified by the 'dims' parameter</returns>
+        /// <remarks>
+        /// <para>The n-dimensional transformation is computed for the n-dimensional array A. 
+        /// Before the transform, the input is resized according to the 'dims' parameter. 
+        /// Dimensions larger than corresponding entries in 'dim' are truncated, dimensions
+        /// smaller than corresponding entries in 'dim' are zero padded.</para>
+        /// <para>The n-dimensional transformation is equivalent to repeatedly (inplace) 
+        /// computing one dimensional transformations along all dimensions of A.
+        /// However, using this 
+        /// function may be of magnitudes faster than using 1D transformations. This 
+        /// depends on the algorithm and API provided by the underlying native library.</para>
+        /// <para>Since a transform of complex hermitian input data results in the 
+        /// output having the imaginary part equals zero, only the real part is 
+        /// returned for convenience reasons.</para>
+        /// <para>No check is made for A being hermitian! If A is not hermitian (by means 
+        /// of round-off errors), the result will be wrong!</para>
+        /// <para>The forward fourier transform and the inverse fourier transform of 
+        /// a given data array A are mathematically equivalent. It's only a 
+        /// scaling factor which is needed to make sure, A equals ifft(fft(A)). That 
+        /// scaling is introduced in the inverse transform.</para>
+        /// <para>The transformation is computed by use of the native library 
+        /// which currently is set up for your processor and OS version. The underlying 
+        /// library is automatically choosen at ILNumerics startup and accessed via the 
+        /// static member ILMath.FFT. See the online documentation for more 
+        /// details in how to tune/configure and select dedicated native libraries. 
+        /// Currently supported libraries are: Intel MKL (included), AMD ACML 
+        /// and FFTW3 (prepared, optional modules, not included due to licensing conflicts).</para>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">is thrown if the 
+        /// dim parameter is null, its length is less then the number of dimensions of A 
+        /// or any element of dims is non-negative</exception>
+        public static ILRetArray< float> ifftnsym(ILInArray< fcomplex> A, params int[] dims) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) return empty< float>(A.Size);
+                ILRetArray< fcomplex> resizedA = resize4Transform(A, dims);
+                return FFTImplementation.FFTBackwSym(resizedA, dims.Length);
+            }
+        }
+        #endregion
+
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+        #region private helper
+        internal static ILRetArray<T> resize4Transform<T>(ILInArray<T> A, params int[] size) {
+            using (ILScope.Enter(A)) {
+                if (size == null || size.Length < A.Size.NumberOfDimensions)
+                    throw new ILArgumentException("length of output dimensions must be &gt; or equal to number of dimensions of input array!");
+                ILSize newDimensions = new ILSize(size);
+                if (A.Size.IsSameShape(newDimensions)) {
+                    return A;
+                } else {
+                    if (newDimensions.NumberOfElements == 0) return empty<T>(newDimensions);
+                    ILArray<T> tmp = array<T>(default(T), newDimensions);
+                    int minDimsLen = Math.Min(size.Length, A.Size.NumberOfDimensions);
+                    ILArray<ILRegularRange>[] indices = new ILArray<ILRegularRange>[minDimsLen];
+                    for (int i = 0; i < minDimsLen; i++) {
+                        if (size[i] < 0)
+                            throw new ILArgumentException("all dimension lengths of 'size' must be non-negative!");
+                        if (size[i] == 0) return empty<T>(newDimensions);
+                        indices[i] = (ILRetArray<ILRegularRange>)r(0, Math.Min(A.Size[i] - 1, size[i] - 1));
+                    }
+                    tmp[indices] = A[indices];
+                    return tmp;
+                }
+            }
+        }
+
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/fix.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/fix.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/fix.cs	(revision 9102)
@@ -0,0 +1,559 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics;
+using ILNumerics.Exceptions; 
+using ILNumerics.Storage; 
+using ILNumerics.Misc; 
+
+
+
+namespace ILNumerics {
+
+    public partial class ILMath {
+
+
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>Round towards zero</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Array of same size as A with elements rounded towards zero</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<complex>  fix (ILInArray< complex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<complex>(A.Size); 
+                ILSize inDim = A.Size;
+                complex[] arrA = A.GetArrayForRead(); 
+                complex [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<complex>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<complex> retStorage = new ILDenseStorage<complex>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    complex* cp = ((complex*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  complex.Truncate(cp[0]  )  /*dummy*/;
+                            cp[1] =  complex.Truncate(cp[1]  )  /*dummy*/;
+                            cp[2] =  complex.Truncate(cp[2]  )  /*dummy*/;
+                            cp[3] =  complex.Truncate(cp[3]  )  /*dummy*/;
+                            cp[4] =  complex.Truncate(cp[4]  )  /*dummy*/;
+                            cp[5] =  complex.Truncate(cp[5]  )  /*dummy*/;
+                            cp[6] =  complex.Truncate(cp[6]  )  /*dummy*/;
+                            cp[7] =  complex.Truncate(cp[7]  )  /*dummy*/;
+                            cp[8] =  complex.Truncate(cp[8]  )  /*dummy*/;
+                            cp[9] =  complex.Truncate(cp[9]  )  /*dummy*/;
+                            cp[10] =  complex.Truncate(cp[10]  )  /*dummy*/;
+                            cp[11] =  complex.Truncate(cp[11]  )  /*dummy*/;
+                            cp[12] =  complex.Truncate(cp[12]  )  /*dummy*/;
+                            cp[13] =  complex.Truncate(cp[13]  )  /*dummy*/;
+                            cp[14] =  complex.Truncate(cp[14]  )  /*dummy*/;
+                            cp[15] =  complex.Truncate(cp[15]  )  /*dummy*/;
+                            cp[16] =  complex.Truncate(cp[16]  )  /*dummy*/;
+                            cp[17] =  complex.Truncate(cp[17]  )  /*dummy*/;
+                            cp[18] =  complex.Truncate(cp[18]  )  /*dummy*/;
+                            cp[19] =  complex.Truncate(cp[19]  )  /*dummy*/;
+                            cp[20] =  complex.Truncate(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.Truncate(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        complex* ap = ((complex*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  complex.Truncate(ap[0]  )  /*dummy*/;
+                            cp[1] =  complex.Truncate(ap[1]  )  /*dummy*/;
+                            cp[2] =  complex.Truncate(ap[2]  )  /*dummy*/;
+                            cp[3] =  complex.Truncate(ap[3]  )  /*dummy*/;
+                            cp[4] =  complex.Truncate(ap[4]  )  /*dummy*/;
+                            cp[5] =  complex.Truncate(ap[5]  )  /*dummy*/;
+                            cp[6] =  complex.Truncate(ap[6]  )  /*dummy*/;
+                            cp[7] =  complex.Truncate(ap[7]  )  /*dummy*/;
+                            cp[8] =  complex.Truncate(ap[8]  )  /*dummy*/;
+                            cp[9] =  complex.Truncate(ap[9]  )  /*dummy*/;
+                            cp[10] =  complex.Truncate(ap[10]  )  /*dummy*/;
+                            cp[11] =  complex.Truncate(ap[11]  )  /*dummy*/;
+                            cp[12] =  complex.Truncate(ap[12]  )  /*dummy*/;
+                            cp[13] =  complex.Truncate(ap[13]  )  /*dummy*/;
+                            cp[14] =  complex.Truncate(ap[14]  )  /*dummy*/;
+                            cp[15] =  complex.Truncate(ap[15]  )  /*dummy*/;
+                            cp[16] =  complex.Truncate(ap[16]  )  /*dummy*/;
+                            cp[17] =  complex.Truncate(ap[17]  )  /*dummy*/;
+                            cp[18] =  complex.Truncate(ap[18]  )  /*dummy*/;
+                            cp[19] =  complex.Truncate(ap[19]  )  /*dummy*/;
+                            cp[20] =  complex.Truncate(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.Truncate(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( complex* arrAP = arrA)
+                fixed ( complex* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<complex>(retStorage);
+            }
+        }
+        /// <summary>Round towards zero</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Array of same size as A with elements rounded towards zero</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<fcomplex>  fix (ILInArray< fcomplex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<fcomplex>(A.Size); 
+                ILSize inDim = A.Size;
+                fcomplex[] arrA = A.GetArrayForRead(); 
+                fcomplex [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<fcomplex>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<fcomplex> retStorage = new ILDenseStorage<fcomplex>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    fcomplex* cp = ((fcomplex*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  fcomplex.Truncate(cp[0]  )  /*dummy*/;
+                            cp[1] =  fcomplex.Truncate(cp[1]  )  /*dummy*/;
+                            cp[2] =  fcomplex.Truncate(cp[2]  )  /*dummy*/;
+                            cp[3] =  fcomplex.Truncate(cp[3]  )  /*dummy*/;
+                            cp[4] =  fcomplex.Truncate(cp[4]  )  /*dummy*/;
+                            cp[5] =  fcomplex.Truncate(cp[5]  )  /*dummy*/;
+                            cp[6] =  fcomplex.Truncate(cp[6]  )  /*dummy*/;
+                            cp[7] =  fcomplex.Truncate(cp[7]  )  /*dummy*/;
+                            cp[8] =  fcomplex.Truncate(cp[8]  )  /*dummy*/;
+                            cp[9] =  fcomplex.Truncate(cp[9]  )  /*dummy*/;
+                            cp[10] =  fcomplex.Truncate(cp[10]  )  /*dummy*/;
+                            cp[11] =  fcomplex.Truncate(cp[11]  )  /*dummy*/;
+                            cp[12] =  fcomplex.Truncate(cp[12]  )  /*dummy*/;
+                            cp[13] =  fcomplex.Truncate(cp[13]  )  /*dummy*/;
+                            cp[14] =  fcomplex.Truncate(cp[14]  )  /*dummy*/;
+                            cp[15] =  fcomplex.Truncate(cp[15]  )  /*dummy*/;
+                            cp[16] =  fcomplex.Truncate(cp[16]  )  /*dummy*/;
+                            cp[17] =  fcomplex.Truncate(cp[17]  )  /*dummy*/;
+                            cp[18] =  fcomplex.Truncate(cp[18]  )  /*dummy*/;
+                            cp[19] =  fcomplex.Truncate(cp[19]  )  /*dummy*/;
+                            cp[20] =  fcomplex.Truncate(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.Truncate(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        fcomplex* ap = ((fcomplex*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  fcomplex.Truncate(ap[0]  )  /*dummy*/;
+                            cp[1] =  fcomplex.Truncate(ap[1]  )  /*dummy*/;
+                            cp[2] =  fcomplex.Truncate(ap[2]  )  /*dummy*/;
+                            cp[3] =  fcomplex.Truncate(ap[3]  )  /*dummy*/;
+                            cp[4] =  fcomplex.Truncate(ap[4]  )  /*dummy*/;
+                            cp[5] =  fcomplex.Truncate(ap[5]  )  /*dummy*/;
+                            cp[6] =  fcomplex.Truncate(ap[6]  )  /*dummy*/;
+                            cp[7] =  fcomplex.Truncate(ap[7]  )  /*dummy*/;
+                            cp[8] =  fcomplex.Truncate(ap[8]  )  /*dummy*/;
+                            cp[9] =  fcomplex.Truncate(ap[9]  )  /*dummy*/;
+                            cp[10] =  fcomplex.Truncate(ap[10]  )  /*dummy*/;
+                            cp[11] =  fcomplex.Truncate(ap[11]  )  /*dummy*/;
+                            cp[12] =  fcomplex.Truncate(ap[12]  )  /*dummy*/;
+                            cp[13] =  fcomplex.Truncate(ap[13]  )  /*dummy*/;
+                            cp[14] =  fcomplex.Truncate(ap[14]  )  /*dummy*/;
+                            cp[15] =  fcomplex.Truncate(ap[15]  )  /*dummy*/;
+                            cp[16] =  fcomplex.Truncate(ap[16]  )  /*dummy*/;
+                            cp[17] =  fcomplex.Truncate(ap[17]  )  /*dummy*/;
+                            cp[18] =  fcomplex.Truncate(ap[18]  )  /*dummy*/;
+                            cp[19] =  fcomplex.Truncate(ap[19]  )  /*dummy*/;
+                            cp[20] =  fcomplex.Truncate(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.Truncate(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( fcomplex* arrAP = arrA)
+                fixed ( fcomplex* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<fcomplex>(retStorage);
+            }
+        }
+        /// <summary>Round towards zero</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Array of same size as A with elements rounded towards zero</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<float>  fix (ILInArray< float > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<float>(A.Size); 
+                ILSize inDim = A.Size;
+                float[] arrA = A.GetArrayForRead(); 
+                float [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<float>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<float> retStorage = new ILDenseStorage<float>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    float* cp = ((float*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  (float)Math.Truncate(cp[0]  )  /*dummy*/;
+                            cp[1] =  (float)Math.Truncate(cp[1]  )  /*dummy*/;
+                            cp[2] =  (float)Math.Truncate(cp[2]  )  /*dummy*/;
+                            cp[3] =  (float)Math.Truncate(cp[3]  )  /*dummy*/;
+                            cp[4] =  (float)Math.Truncate(cp[4]  )  /*dummy*/;
+                            cp[5] =  (float)Math.Truncate(cp[5]  )  /*dummy*/;
+                            cp[6] =  (float)Math.Truncate(cp[6]  )  /*dummy*/;
+                            cp[7] =  (float)Math.Truncate(cp[7]  )  /*dummy*/;
+                            cp[8] =  (float)Math.Truncate(cp[8]  )  /*dummy*/;
+                            cp[9] =  (float)Math.Truncate(cp[9]  )  /*dummy*/;
+                            cp[10] =  (float)Math.Truncate(cp[10]  )  /*dummy*/;
+                            cp[11] =  (float)Math.Truncate(cp[11]  )  /*dummy*/;
+                            cp[12] =  (float)Math.Truncate(cp[12]  )  /*dummy*/;
+                            cp[13] =  (float)Math.Truncate(cp[13]  )  /*dummy*/;
+                            cp[14] =  (float)Math.Truncate(cp[14]  )  /*dummy*/;
+                            cp[15] =  (float)Math.Truncate(cp[15]  )  /*dummy*/;
+                            cp[16] =  (float)Math.Truncate(cp[16]  )  /*dummy*/;
+                            cp[17] =  (float)Math.Truncate(cp[17]  )  /*dummy*/;
+                            cp[18] =  (float)Math.Truncate(cp[18]  )  /*dummy*/;
+                            cp[19] =  (float)Math.Truncate(cp[19]  )  /*dummy*/;
+                            cp[20] =  (float)Math.Truncate(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  (float)Math.Truncate(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        float* ap = ((float*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  (float)Math.Truncate(ap[0]  )  /*dummy*/;
+                            cp[1] =  (float)Math.Truncate(ap[1]  )  /*dummy*/;
+                            cp[2] =  (float)Math.Truncate(ap[2]  )  /*dummy*/;
+                            cp[3] =  (float)Math.Truncate(ap[3]  )  /*dummy*/;
+                            cp[4] =  (float)Math.Truncate(ap[4]  )  /*dummy*/;
+                            cp[5] =  (float)Math.Truncate(ap[5]  )  /*dummy*/;
+                            cp[6] =  (float)Math.Truncate(ap[6]  )  /*dummy*/;
+                            cp[7] =  (float)Math.Truncate(ap[7]  )  /*dummy*/;
+                            cp[8] =  (float)Math.Truncate(ap[8]  )  /*dummy*/;
+                            cp[9] =  (float)Math.Truncate(ap[9]  )  /*dummy*/;
+                            cp[10] =  (float)Math.Truncate(ap[10]  )  /*dummy*/;
+                            cp[11] =  (float)Math.Truncate(ap[11]  )  /*dummy*/;
+                            cp[12] =  (float)Math.Truncate(ap[12]  )  /*dummy*/;
+                            cp[13] =  (float)Math.Truncate(ap[13]  )  /*dummy*/;
+                            cp[14] =  (float)Math.Truncate(ap[14]  )  /*dummy*/;
+                            cp[15] =  (float)Math.Truncate(ap[15]  )  /*dummy*/;
+                            cp[16] =  (float)Math.Truncate(ap[16]  )  /*dummy*/;
+                            cp[17] =  (float)Math.Truncate(ap[17]  )  /*dummy*/;
+                            cp[18] =  (float)Math.Truncate(ap[18]  )  /*dummy*/;
+                            cp[19] =  (float)Math.Truncate(ap[19]  )  /*dummy*/;
+                            cp[20] =  (float)Math.Truncate(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  (float)Math.Truncate(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( float* arrAP = arrA)
+                fixed ( float* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<float>(retStorage);
+            }
+        }
+        /// <summary>Round towards zero</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Array of same size as A with elements rounded towards zero</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<double>  fix (ILInArray< double > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<double>(A.Size); 
+                ILSize inDim = A.Size;
+                double[] arrA = A.GetArrayForRead(); 
+                double [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<double>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<double> retStorage = new ILDenseStorage<double>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    double* cp = ((double*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  Math.Truncate(cp[0]  )  /*dummy*/;
+                            cp[1] =  Math.Truncate(cp[1]  )  /*dummy*/;
+                            cp[2] =  Math.Truncate(cp[2]  )  /*dummy*/;
+                            cp[3] =  Math.Truncate(cp[3]  )  /*dummy*/;
+                            cp[4] =  Math.Truncate(cp[4]  )  /*dummy*/;
+                            cp[5] =  Math.Truncate(cp[5]  )  /*dummy*/;
+                            cp[6] =  Math.Truncate(cp[6]  )  /*dummy*/;
+                            cp[7] =  Math.Truncate(cp[7]  )  /*dummy*/;
+                            cp[8] =  Math.Truncate(cp[8]  )  /*dummy*/;
+                            cp[9] =  Math.Truncate(cp[9]  )  /*dummy*/;
+                            cp[10] =  Math.Truncate(cp[10]  )  /*dummy*/;
+                            cp[11] =  Math.Truncate(cp[11]  )  /*dummy*/;
+                            cp[12] =  Math.Truncate(cp[12]  )  /*dummy*/;
+                            cp[13] =  Math.Truncate(cp[13]  )  /*dummy*/;
+                            cp[14] =  Math.Truncate(cp[14]  )  /*dummy*/;
+                            cp[15] =  Math.Truncate(cp[15]  )  /*dummy*/;
+                            cp[16] =  Math.Truncate(cp[16]  )  /*dummy*/;
+                            cp[17] =  Math.Truncate(cp[17]  )  /*dummy*/;
+                            cp[18] =  Math.Truncate(cp[18]  )  /*dummy*/;
+                            cp[19] =  Math.Truncate(cp[19]  )  /*dummy*/;
+                            cp[20] =  Math.Truncate(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Math.Truncate(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        double* ap = ((double*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  Math.Truncate(ap[0]  )  /*dummy*/;
+                            cp[1] =  Math.Truncate(ap[1]  )  /*dummy*/;
+                            cp[2] =  Math.Truncate(ap[2]  )  /*dummy*/;
+                            cp[3] =  Math.Truncate(ap[3]  )  /*dummy*/;
+                            cp[4] =  Math.Truncate(ap[4]  )  /*dummy*/;
+                            cp[5] =  Math.Truncate(ap[5]  )  /*dummy*/;
+                            cp[6] =  Math.Truncate(ap[6]  )  /*dummy*/;
+                            cp[7] =  Math.Truncate(ap[7]  )  /*dummy*/;
+                            cp[8] =  Math.Truncate(ap[8]  )  /*dummy*/;
+                            cp[9] =  Math.Truncate(ap[9]  )  /*dummy*/;
+                            cp[10] =  Math.Truncate(ap[10]  )  /*dummy*/;
+                            cp[11] =  Math.Truncate(ap[11]  )  /*dummy*/;
+                            cp[12] =  Math.Truncate(ap[12]  )  /*dummy*/;
+                            cp[13] =  Math.Truncate(ap[13]  )  /*dummy*/;
+                            cp[14] =  Math.Truncate(ap[14]  )  /*dummy*/;
+                            cp[15] =  Math.Truncate(ap[15]  )  /*dummy*/;
+                            cp[16] =  Math.Truncate(ap[16]  )  /*dummy*/;
+                            cp[17] =  Math.Truncate(ap[17]  )  /*dummy*/;
+                            cp[18] =  Math.Truncate(ap[18]  )  /*dummy*/;
+                            cp[19] =  Math.Truncate(ap[19]  )  /*dummy*/;
+                            cp[20] =  Math.Truncate(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Math.Truncate(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( double* arrAP = arrA)
+                fixed ( double* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<double>(retStorage);
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/fliplr.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/fliplr.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/fliplr.cs	(revision 9102)
@@ -0,0 +1,77 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using ILNumerics.Exceptions; 
+
+namespace ILNumerics {
+    public partial class ILMath {
+
+        /// <summary>
+        /// Reverse order of columns of matrix
+        /// </summary>
+        /// <typeparam name="T">Inner element type</typeparam>
+        /// <param name="A">Input matrix</param>
+        /// <returns>Matrix of same size as A, having the order of its columns reversed</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If A has more than 2 dimensions</exception>
+        public static ILRetArray<T> fliplr<T>(ILInArray<T> A) {
+            using (ILScope.Enter(A)) {
+                if (!A.IsMatrix) 
+                    throw new ILArgumentException("argument to fliplr must be a matrix"); 
+                return A[full,r(end,-1,0)]; 
+            }
+        }
+        /// <summary>
+        /// Reverse order of columns of matrix
+        /// </summary>
+        /// <param name="A">Input matrix</param>
+        /// <returns>Matrix of same size as A, having the order of its columns reversed</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If A has more than 2 dimensions</exception>
+        public static ILRetArray<double> fliplr(ILInArray<double> A) {
+            using (ILScope.Enter(A)) {
+                if (!A.IsMatrix) 
+                    throw new ILArgumentException("argument to fliplr must be a matrix"); 
+                return A[full,r(end,-1,0)]; 
+            }
+        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/flipud.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/flipud.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/flipud.cs	(revision 9102)
@@ -0,0 +1,77 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using ILNumerics.Exceptions; 
+
+namespace ILNumerics {
+    public partial class ILMath {
+
+        /// <summary>
+        /// Reverse order of rows of a matrix
+        /// </summary>
+        /// <typeparam name="T">Inner element type</typeparam>
+        /// <param name="A">Input matrix</param>
+        /// <returns>Matrix of same size as A, having the order of its rows reversed</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If A has more than 2 dimensions</exception>
+        public static ILRetArray<T> flipud<T>(ILInArray<T> A) {
+            using (ILScope.Enter(A)) {
+                if (!A.IsMatrix) 
+                    throw new ILArgumentException("argument to flipud must be a matrix"); 
+                return A[r(end,-1,0),full]; 
+            }
+        }
+        /// <summary>
+        /// Reverse order of rows of a matrix
+        /// </summary>
+        /// <param name="A">Input matrix</param>
+        /// <returns>Matrix of same size as A, having the order of its rows reversed</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If A has more than 2 dimensions</exception>
+        public static ILRetArray<double> flipud(ILInArray<double> A) {
+            using (ILScope.Enter(A)) {
+                if (!A.IsMatrix)
+                    throw new ILArgumentException("argument to flipud must be a matrix");
+                return A[r(end, -1, 0), full];
+            }
+        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/floor.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/floor.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/floor.cs	(revision 9102)
@@ -0,0 +1,559 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics;
+using ILNumerics.Exceptions; 
+using ILNumerics.Storage; 
+using ILNumerics.Misc;
+ 
+
+
+namespace ILNumerics {
+
+    public partial class ILMath {
+
+
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>Round towards negative infinity</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Array of same size as A with elements rounded downwards to next integer</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<complex>  floor (ILInArray< complex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<complex>(A.Size); 
+                ILSize inDim = A.Size;
+                complex[] arrA = A.GetArrayForRead(); 
+                complex [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<complex>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<complex> retStorage = new ILDenseStorage<complex>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    complex* cp = ((complex*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  complex.Floor(cp[0]  )  /*dummy*/;
+                            cp[1] =  complex.Floor(cp[1]  )  /*dummy*/;
+                            cp[2] =  complex.Floor(cp[2]  )  /*dummy*/;
+                            cp[3] =  complex.Floor(cp[3]  )  /*dummy*/;
+                            cp[4] =  complex.Floor(cp[4]  )  /*dummy*/;
+                            cp[5] =  complex.Floor(cp[5]  )  /*dummy*/;
+                            cp[6] =  complex.Floor(cp[6]  )  /*dummy*/;
+                            cp[7] =  complex.Floor(cp[7]  )  /*dummy*/;
+                            cp[8] =  complex.Floor(cp[8]  )  /*dummy*/;
+                            cp[9] =  complex.Floor(cp[9]  )  /*dummy*/;
+                            cp[10] =  complex.Floor(cp[10]  )  /*dummy*/;
+                            cp[11] =  complex.Floor(cp[11]  )  /*dummy*/;
+                            cp[12] =  complex.Floor(cp[12]  )  /*dummy*/;
+                            cp[13] =  complex.Floor(cp[13]  )  /*dummy*/;
+                            cp[14] =  complex.Floor(cp[14]  )  /*dummy*/;
+                            cp[15] =  complex.Floor(cp[15]  )  /*dummy*/;
+                            cp[16] =  complex.Floor(cp[16]  )  /*dummy*/;
+                            cp[17] =  complex.Floor(cp[17]  )  /*dummy*/;
+                            cp[18] =  complex.Floor(cp[18]  )  /*dummy*/;
+                            cp[19] =  complex.Floor(cp[19]  )  /*dummy*/;
+                            cp[20] =  complex.Floor(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.Floor(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        complex* ap = ((complex*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  complex.Floor(ap[0]  )  /*dummy*/;
+                            cp[1] =  complex.Floor(ap[1]  )  /*dummy*/;
+                            cp[2] =  complex.Floor(ap[2]  )  /*dummy*/;
+                            cp[3] =  complex.Floor(ap[3]  )  /*dummy*/;
+                            cp[4] =  complex.Floor(ap[4]  )  /*dummy*/;
+                            cp[5] =  complex.Floor(ap[5]  )  /*dummy*/;
+                            cp[6] =  complex.Floor(ap[6]  )  /*dummy*/;
+                            cp[7] =  complex.Floor(ap[7]  )  /*dummy*/;
+                            cp[8] =  complex.Floor(ap[8]  )  /*dummy*/;
+                            cp[9] =  complex.Floor(ap[9]  )  /*dummy*/;
+                            cp[10] =  complex.Floor(ap[10]  )  /*dummy*/;
+                            cp[11] =  complex.Floor(ap[11]  )  /*dummy*/;
+                            cp[12] =  complex.Floor(ap[12]  )  /*dummy*/;
+                            cp[13] =  complex.Floor(ap[13]  )  /*dummy*/;
+                            cp[14] =  complex.Floor(ap[14]  )  /*dummy*/;
+                            cp[15] =  complex.Floor(ap[15]  )  /*dummy*/;
+                            cp[16] =  complex.Floor(ap[16]  )  /*dummy*/;
+                            cp[17] =  complex.Floor(ap[17]  )  /*dummy*/;
+                            cp[18] =  complex.Floor(ap[18]  )  /*dummy*/;
+                            cp[19] =  complex.Floor(ap[19]  )  /*dummy*/;
+                            cp[20] =  complex.Floor(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.Floor(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( complex* arrAP = arrA)
+                fixed ( complex* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<complex>(retStorage);
+            }
+        }
+        /// <summary>Round towards negative infinity</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Array of same size as A with elements rounded downwards to next integer</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<fcomplex>  floor (ILInArray< fcomplex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<fcomplex>(A.Size); 
+                ILSize inDim = A.Size;
+                fcomplex[] arrA = A.GetArrayForRead(); 
+                fcomplex [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<fcomplex>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<fcomplex> retStorage = new ILDenseStorage<fcomplex>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    fcomplex* cp = ((fcomplex*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  fcomplex.Floor(cp[0]  )  /*dummy*/;
+                            cp[1] =  fcomplex.Floor(cp[1]  )  /*dummy*/;
+                            cp[2] =  fcomplex.Floor(cp[2]  )  /*dummy*/;
+                            cp[3] =  fcomplex.Floor(cp[3]  )  /*dummy*/;
+                            cp[4] =  fcomplex.Floor(cp[4]  )  /*dummy*/;
+                            cp[5] =  fcomplex.Floor(cp[5]  )  /*dummy*/;
+                            cp[6] =  fcomplex.Floor(cp[6]  )  /*dummy*/;
+                            cp[7] =  fcomplex.Floor(cp[7]  )  /*dummy*/;
+                            cp[8] =  fcomplex.Floor(cp[8]  )  /*dummy*/;
+                            cp[9] =  fcomplex.Floor(cp[9]  )  /*dummy*/;
+                            cp[10] =  fcomplex.Floor(cp[10]  )  /*dummy*/;
+                            cp[11] =  fcomplex.Floor(cp[11]  )  /*dummy*/;
+                            cp[12] =  fcomplex.Floor(cp[12]  )  /*dummy*/;
+                            cp[13] =  fcomplex.Floor(cp[13]  )  /*dummy*/;
+                            cp[14] =  fcomplex.Floor(cp[14]  )  /*dummy*/;
+                            cp[15] =  fcomplex.Floor(cp[15]  )  /*dummy*/;
+                            cp[16] =  fcomplex.Floor(cp[16]  )  /*dummy*/;
+                            cp[17] =  fcomplex.Floor(cp[17]  )  /*dummy*/;
+                            cp[18] =  fcomplex.Floor(cp[18]  )  /*dummy*/;
+                            cp[19] =  fcomplex.Floor(cp[19]  )  /*dummy*/;
+                            cp[20] =  fcomplex.Floor(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.Floor(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        fcomplex* ap = ((fcomplex*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  fcomplex.Floor(ap[0]  )  /*dummy*/;
+                            cp[1] =  fcomplex.Floor(ap[1]  )  /*dummy*/;
+                            cp[2] =  fcomplex.Floor(ap[2]  )  /*dummy*/;
+                            cp[3] =  fcomplex.Floor(ap[3]  )  /*dummy*/;
+                            cp[4] =  fcomplex.Floor(ap[4]  )  /*dummy*/;
+                            cp[5] =  fcomplex.Floor(ap[5]  )  /*dummy*/;
+                            cp[6] =  fcomplex.Floor(ap[6]  )  /*dummy*/;
+                            cp[7] =  fcomplex.Floor(ap[7]  )  /*dummy*/;
+                            cp[8] =  fcomplex.Floor(ap[8]  )  /*dummy*/;
+                            cp[9] =  fcomplex.Floor(ap[9]  )  /*dummy*/;
+                            cp[10] =  fcomplex.Floor(ap[10]  )  /*dummy*/;
+                            cp[11] =  fcomplex.Floor(ap[11]  )  /*dummy*/;
+                            cp[12] =  fcomplex.Floor(ap[12]  )  /*dummy*/;
+                            cp[13] =  fcomplex.Floor(ap[13]  )  /*dummy*/;
+                            cp[14] =  fcomplex.Floor(ap[14]  )  /*dummy*/;
+                            cp[15] =  fcomplex.Floor(ap[15]  )  /*dummy*/;
+                            cp[16] =  fcomplex.Floor(ap[16]  )  /*dummy*/;
+                            cp[17] =  fcomplex.Floor(ap[17]  )  /*dummy*/;
+                            cp[18] =  fcomplex.Floor(ap[18]  )  /*dummy*/;
+                            cp[19] =  fcomplex.Floor(ap[19]  )  /*dummy*/;
+                            cp[20] =  fcomplex.Floor(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.Floor(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( fcomplex* arrAP = arrA)
+                fixed ( fcomplex* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<fcomplex>(retStorage);
+            }
+        }
+        /// <summary>Round towards negative infinity</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Array of same size as A with elements rounded downwards to next integer</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<float>  floor (ILInArray< float > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<float>(A.Size); 
+                ILSize inDim = A.Size;
+                float[] arrA = A.GetArrayForRead(); 
+                float [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<float>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<float> retStorage = new ILDenseStorage<float>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    float* cp = ((float*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  (float)Math.Floor(cp[0]  )  /*dummy*/;
+                            cp[1] =  (float)Math.Floor(cp[1]  )  /*dummy*/;
+                            cp[2] =  (float)Math.Floor(cp[2]  )  /*dummy*/;
+                            cp[3] =  (float)Math.Floor(cp[3]  )  /*dummy*/;
+                            cp[4] =  (float)Math.Floor(cp[4]  )  /*dummy*/;
+                            cp[5] =  (float)Math.Floor(cp[5]  )  /*dummy*/;
+                            cp[6] =  (float)Math.Floor(cp[6]  )  /*dummy*/;
+                            cp[7] =  (float)Math.Floor(cp[7]  )  /*dummy*/;
+                            cp[8] =  (float)Math.Floor(cp[8]  )  /*dummy*/;
+                            cp[9] =  (float)Math.Floor(cp[9]  )  /*dummy*/;
+                            cp[10] =  (float)Math.Floor(cp[10]  )  /*dummy*/;
+                            cp[11] =  (float)Math.Floor(cp[11]  )  /*dummy*/;
+                            cp[12] =  (float)Math.Floor(cp[12]  )  /*dummy*/;
+                            cp[13] =  (float)Math.Floor(cp[13]  )  /*dummy*/;
+                            cp[14] =  (float)Math.Floor(cp[14]  )  /*dummy*/;
+                            cp[15] =  (float)Math.Floor(cp[15]  )  /*dummy*/;
+                            cp[16] =  (float)Math.Floor(cp[16]  )  /*dummy*/;
+                            cp[17] =  (float)Math.Floor(cp[17]  )  /*dummy*/;
+                            cp[18] =  (float)Math.Floor(cp[18]  )  /*dummy*/;
+                            cp[19] =  (float)Math.Floor(cp[19]  )  /*dummy*/;
+                            cp[20] =  (float)Math.Floor(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  (float)Math.Floor(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        float* ap = ((float*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  (float)Math.Floor(ap[0]  )  /*dummy*/;
+                            cp[1] =  (float)Math.Floor(ap[1]  )  /*dummy*/;
+                            cp[2] =  (float)Math.Floor(ap[2]  )  /*dummy*/;
+                            cp[3] =  (float)Math.Floor(ap[3]  )  /*dummy*/;
+                            cp[4] =  (float)Math.Floor(ap[4]  )  /*dummy*/;
+                            cp[5] =  (float)Math.Floor(ap[5]  )  /*dummy*/;
+                            cp[6] =  (float)Math.Floor(ap[6]  )  /*dummy*/;
+                            cp[7] =  (float)Math.Floor(ap[7]  )  /*dummy*/;
+                            cp[8] =  (float)Math.Floor(ap[8]  )  /*dummy*/;
+                            cp[9] =  (float)Math.Floor(ap[9]  )  /*dummy*/;
+                            cp[10] =  (float)Math.Floor(ap[10]  )  /*dummy*/;
+                            cp[11] =  (float)Math.Floor(ap[11]  )  /*dummy*/;
+                            cp[12] =  (float)Math.Floor(ap[12]  )  /*dummy*/;
+                            cp[13] =  (float)Math.Floor(ap[13]  )  /*dummy*/;
+                            cp[14] =  (float)Math.Floor(ap[14]  )  /*dummy*/;
+                            cp[15] =  (float)Math.Floor(ap[15]  )  /*dummy*/;
+                            cp[16] =  (float)Math.Floor(ap[16]  )  /*dummy*/;
+                            cp[17] =  (float)Math.Floor(ap[17]  )  /*dummy*/;
+                            cp[18] =  (float)Math.Floor(ap[18]  )  /*dummy*/;
+                            cp[19] =  (float)Math.Floor(ap[19]  )  /*dummy*/;
+                            cp[20] =  (float)Math.Floor(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  (float)Math.Floor(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( float* arrAP = arrA)
+                fixed ( float* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<float>(retStorage);
+            }
+        }
+        /// <summary>Round towards negative infinity</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Array of same size as A with elements rounded downwards to next integer</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<double>  floor (ILInArray< double > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<double>(A.Size); 
+                ILSize inDim = A.Size;
+                double[] arrA = A.GetArrayForRead(); 
+                double [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<double>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<double> retStorage = new ILDenseStorage<double>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    double* cp = ((double*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  Math.Floor(cp[0]  )  /*dummy*/;
+                            cp[1] =  Math.Floor(cp[1]  )  /*dummy*/;
+                            cp[2] =  Math.Floor(cp[2]  )  /*dummy*/;
+                            cp[3] =  Math.Floor(cp[3]  )  /*dummy*/;
+                            cp[4] =  Math.Floor(cp[4]  )  /*dummy*/;
+                            cp[5] =  Math.Floor(cp[5]  )  /*dummy*/;
+                            cp[6] =  Math.Floor(cp[6]  )  /*dummy*/;
+                            cp[7] =  Math.Floor(cp[7]  )  /*dummy*/;
+                            cp[8] =  Math.Floor(cp[8]  )  /*dummy*/;
+                            cp[9] =  Math.Floor(cp[9]  )  /*dummy*/;
+                            cp[10] =  Math.Floor(cp[10]  )  /*dummy*/;
+                            cp[11] =  Math.Floor(cp[11]  )  /*dummy*/;
+                            cp[12] =  Math.Floor(cp[12]  )  /*dummy*/;
+                            cp[13] =  Math.Floor(cp[13]  )  /*dummy*/;
+                            cp[14] =  Math.Floor(cp[14]  )  /*dummy*/;
+                            cp[15] =  Math.Floor(cp[15]  )  /*dummy*/;
+                            cp[16] =  Math.Floor(cp[16]  )  /*dummy*/;
+                            cp[17] =  Math.Floor(cp[17]  )  /*dummy*/;
+                            cp[18] =  Math.Floor(cp[18]  )  /*dummy*/;
+                            cp[19] =  Math.Floor(cp[19]  )  /*dummy*/;
+                            cp[20] =  Math.Floor(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Math.Floor(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        double* ap = ((double*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  Math.Floor(ap[0]  )  /*dummy*/;
+                            cp[1] =  Math.Floor(ap[1]  )  /*dummy*/;
+                            cp[2] =  Math.Floor(ap[2]  )  /*dummy*/;
+                            cp[3] =  Math.Floor(ap[3]  )  /*dummy*/;
+                            cp[4] =  Math.Floor(ap[4]  )  /*dummy*/;
+                            cp[5] =  Math.Floor(ap[5]  )  /*dummy*/;
+                            cp[6] =  Math.Floor(ap[6]  )  /*dummy*/;
+                            cp[7] =  Math.Floor(ap[7]  )  /*dummy*/;
+                            cp[8] =  Math.Floor(ap[8]  )  /*dummy*/;
+                            cp[9] =  Math.Floor(ap[9]  )  /*dummy*/;
+                            cp[10] =  Math.Floor(ap[10]  )  /*dummy*/;
+                            cp[11] =  Math.Floor(ap[11]  )  /*dummy*/;
+                            cp[12] =  Math.Floor(ap[12]  )  /*dummy*/;
+                            cp[13] =  Math.Floor(ap[13]  )  /*dummy*/;
+                            cp[14] =  Math.Floor(ap[14]  )  /*dummy*/;
+                            cp[15] =  Math.Floor(ap[15]  )  /*dummy*/;
+                            cp[16] =  Math.Floor(ap[16]  )  /*dummy*/;
+                            cp[17] =  Math.Floor(ap[17]  )  /*dummy*/;
+                            cp[18] =  Math.Floor(ap[18]  )  /*dummy*/;
+                            cp[19] =  Math.Floor(ap[19]  )  /*dummy*/;
+                            cp[20] =  Math.Floor(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Math.Floor(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( double* arrAP = arrA)
+                fixed ( double* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<double>(retStorage);
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/free.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/free.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/free.cs	(revision 9102)
@@ -0,0 +1,59 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+
+namespace ILNumerics {
+    public partial class ILMath {
+        /// <summary>
+        /// Return a System.Array to the memory pool 
+        /// </summary>
+        /// <typeparam name="T">the element type</typeparam>
+        /// <param name="obj4Dispose">the System.Array to be returned to the pool.</param>
+        /// <remarks>Thes function allows the manual regristration of System.Arrays to the ILNumerics memory pool. See <see cref="ILNumerics.ILMath.New{T}(int)"/> for a usage example.</remarks>
+        /// <seealso cref="ILNumerics.ILMath.New{T}(int)"/>
+        public static void free<T>(T[] obj4Dispose) {
+            ILMemoryPool.Pool.Free<T>(obj4Dispose);
+        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/ge.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/ge.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/ge.cs	(revision 9102)
@@ -0,0 +1,1954 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.InteropServices; 
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Native;
+using ILNumerics.Exceptions;
+
+
+
+namespace ILNumerics {
+
+    public partial class ILMath {
+
+
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>Elementwise logical 'greater or equal' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array having '1' for elements in A being greater or equal corresponding elements in B, '0' else</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  ge(ILInArray<Int64> A, ILInArray<Int64> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                Int64[] arrA = A.GetArrayForRead();
+               
+                Int64[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                       
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0)  >= B.GetValue(0)) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  geEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    Int64 scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            Int64* ap = ((Int64*)range.Item3 + range.Item1);
+                            Int64* bp = ((Int64*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  >= *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((Int64*)range.Item3 + range.Item1);
+                            scalar = *((Int64*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  >= scalar) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((Int64*)range.Item3);
+                            bp = ((Int64*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (scalar  >= *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (Int64* arrAP = arrA)
+                fixed (Int64* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  geEx(ILInArray<Int64> A, ILInArray<Int64> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                Int64[] arrA = A.GetArrayForRead();
+               
+                Int64[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    Int64* ap;
+                   
+                    Int64* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (Int64*)range.Item3;
+                                bp = (Int64*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  >= *bp) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (Int64*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (Int64*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  >= *bp) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( Int64* arrAP = arrA)
+                fixed ( Int64* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'greater or equal' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array having '1' for elements in A being greater or equal corresponding elements in B, '0' else</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  ge(ILInArray<Int32> A, ILInArray<Int32> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                Int32[] arrA = A.GetArrayForRead();
+               
+                Int32[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                       
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0)  >= B.GetValue(0)) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  geEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    Int32 scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            Int32* ap = ((Int32*)range.Item3 + range.Item1);
+                            Int32* bp = ((Int32*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  >= *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((Int32*)range.Item3 + range.Item1);
+                            scalar = *((Int32*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  >= scalar) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((Int32*)range.Item3);
+                            bp = ((Int32*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (scalar  >= *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (Int32* arrAP = arrA)
+                fixed (Int32* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  geEx(ILInArray<Int32> A, ILInArray<Int32> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                Int32[] arrA = A.GetArrayForRead();
+               
+                Int32[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    Int32* ap;
+                   
+                    Int32* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (Int32*)range.Item3;
+                                bp = (Int32*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  >= *bp) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (Int32*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (Int32*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  >= *bp) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( Int32* arrAP = arrA)
+                fixed ( Int32* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'greater or equal' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array having '1' for elements in A being greater or equal corresponding elements in B, '0' else</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  ge(ILInArray<float> A, ILInArray<float> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                float[] arrA = A.GetArrayForRead();
+               
+                float[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                       
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0)  >= B.GetValue(0)) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  geEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    float scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            float* ap = ((float*)range.Item3 + range.Item1);
+                            float* bp = ((float*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  >= *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((float*)range.Item3 + range.Item1);
+                            scalar = *((float*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  >= scalar) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((float*)range.Item3);
+                            bp = ((float*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (scalar  >= *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (float* arrAP = arrA)
+                fixed (float* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  geEx(ILInArray<float> A, ILInArray<float> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                float[] arrA = A.GetArrayForRead();
+               
+                float[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    float* ap;
+                   
+                    float* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (float*)range.Item3;
+                                bp = (float*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  >= *bp) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (float*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (float*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  >= *bp) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( float* arrAP = arrA)
+                fixed ( float* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'greater or equal' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array having '1' for elements in A being greater or equal corresponding elements in B, '0' else</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  ge(ILInArray<fcomplex> A, ILInArray<fcomplex> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                fcomplex[] arrA = A.GetArrayForRead();
+               
+                fcomplex[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                       
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0)  >= B.GetValue(0)) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  geEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    fcomplex scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            fcomplex* ap = ((fcomplex*)range.Item3 + range.Item1);
+                            fcomplex* bp = ((fcomplex*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  >= *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((fcomplex*)range.Item3 + range.Item1);
+                            scalar = *((fcomplex*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  >= scalar) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((fcomplex*)range.Item3);
+                            bp = ((fcomplex*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (scalar  >= *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (fcomplex* arrAP = arrA)
+                fixed (fcomplex* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  geEx(ILInArray<fcomplex> A, ILInArray<fcomplex> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                fcomplex[] arrA = A.GetArrayForRead();
+               
+                fcomplex[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    fcomplex* ap;
+                   
+                    fcomplex* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (fcomplex*)range.Item3;
+                                bp = (fcomplex*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  >= *bp) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (fcomplex*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (fcomplex*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  >= *bp) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( fcomplex* arrAP = arrA)
+                fixed ( fcomplex* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'greater or equal' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array having '1' for elements in A being greater or equal corresponding elements in B, '0' else</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  ge(ILInArray<complex> A, ILInArray<complex> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                complex[] arrA = A.GetArrayForRead();
+               
+                complex[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                       
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0)  >= B.GetValue(0)) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  geEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    complex scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            complex* ap = ((complex*)range.Item3 + range.Item1);
+                            complex* bp = ((complex*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  >= *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((complex*)range.Item3 + range.Item1);
+                            scalar = *((complex*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  >= scalar) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((complex*)range.Item3);
+                            bp = ((complex*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (scalar  >= *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (complex* arrAP = arrA)
+                fixed (complex* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  geEx(ILInArray<complex> A, ILInArray<complex> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                complex[] arrA = A.GetArrayForRead();
+               
+                complex[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    complex* ap;
+                   
+                    complex* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (complex*)range.Item3;
+                                bp = (complex*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  >= *bp) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (complex*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (complex*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  >= *bp) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( complex* arrAP = arrA)
+                fixed ( complex* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'greater or equal' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array having '1' for elements in A being greater or equal corresponding elements in B, '0' else</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  ge(ILInArray<byte> A, ILInArray<byte> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                byte[] arrA = A.GetArrayForRead();
+               
+                byte[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                       
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0)  >= B.GetValue(0)) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  geEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    byte scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            byte* ap = ((byte*)range.Item3 + range.Item1);
+                            byte* bp = ((byte*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  >= *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((byte*)range.Item3 + range.Item1);
+                            scalar = *((byte*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  >= scalar) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((byte*)range.Item3);
+                            bp = ((byte*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (scalar  >= *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (byte* arrAP = arrA)
+                fixed (byte* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  geEx(ILInArray<byte> A, ILInArray<byte> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                byte[] arrA = A.GetArrayForRead();
+               
+                byte[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    byte* ap;
+                   
+                    byte* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (byte*)range.Item3;
+                                bp = (byte*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  >= *bp) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (byte*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (byte*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  >= *bp) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( byte* arrAP = arrA)
+                fixed ( byte* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'greater or equal' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array having '1' for elements in A being greater or equal corresponding elements in B, '0' else</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  ge(ILInArray<double> A, ILInArray<double> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                double[] arrA = A.GetArrayForRead();
+               
+                double[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                       
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0)  >= B.GetValue(0)) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  geEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    double scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            double* ap = ((double*)range.Item3 + range.Item1);
+                            double* bp = ((double*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  >= *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((double*)range.Item3 + range.Item1);
+                            scalar = *((double*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  >= scalar) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((double*)range.Item3);
+                            bp = ((double*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (scalar  >= *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (double* arrAP = arrA)
+                fixed (double* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  geEx(ILInArray<double> A, ILInArray<double> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                double[] arrA = A.GetArrayForRead();
+               
+                double[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    double* ap;
+                   
+                    double* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (double*)range.Item3;
+                                bp = (double*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  >= *bp) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (double*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (double*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  >= *bp) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( double* arrAP = arrA)
+                fixed ( double* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/gt.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/gt.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/gt.cs	(revision 9102)
@@ -0,0 +1,1954 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.InteropServices; 
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Native;
+using ILNumerics.Exceptions;
+
+
+
+namespace ILNumerics {
+
+    public partial class ILMath {
+
+
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>Elementwise logical 'greater than' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array having '1' for elements in A being greater than corresponding elements in B, '0' else</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  gt(ILInArray<Int64> A, ILInArray<Int64> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                Int64[] arrA = A.GetArrayForRead();
+               
+                Int64[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                       
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0)  > B.GetValue(0)) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  gtEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    Int64 scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            Int64* ap = ((Int64*)range.Item3 + range.Item1);
+                            Int64* bp = ((Int64*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  > *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((Int64*)range.Item3 + range.Item1);
+                            scalar = *((Int64*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  > scalar) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((Int64*)range.Item3);
+                            bp = ((Int64*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (scalar  > *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (Int64* arrAP = arrA)
+                fixed (Int64* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  gtEx(ILInArray<Int64> A, ILInArray<Int64> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                Int64[] arrA = A.GetArrayForRead();
+               
+                Int64[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    Int64* ap;
+                   
+                    Int64* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (Int64*)range.Item3;
+                                bp = (Int64*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  > *bp) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (Int64*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (Int64*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  > *bp) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( Int64* arrAP = arrA)
+                fixed ( Int64* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'greater than' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array having '1' for elements in A being greater than corresponding elements in B, '0' else</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  gt(ILInArray<Int32> A, ILInArray<Int32> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                Int32[] arrA = A.GetArrayForRead();
+               
+                Int32[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                       
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0)  > B.GetValue(0)) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  gtEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    Int32 scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            Int32* ap = ((Int32*)range.Item3 + range.Item1);
+                            Int32* bp = ((Int32*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  > *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((Int32*)range.Item3 + range.Item1);
+                            scalar = *((Int32*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  > scalar) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((Int32*)range.Item3);
+                            bp = ((Int32*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (scalar  > *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (Int32* arrAP = arrA)
+                fixed (Int32* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  gtEx(ILInArray<Int32> A, ILInArray<Int32> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                Int32[] arrA = A.GetArrayForRead();
+               
+                Int32[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    Int32* ap;
+                   
+                    Int32* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (Int32*)range.Item3;
+                                bp = (Int32*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  > *bp) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (Int32*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (Int32*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  > *bp) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( Int32* arrAP = arrA)
+                fixed ( Int32* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'greater than' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array having '1' for elements in A being greater than corresponding elements in B, '0' else</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  gt(ILInArray<float> A, ILInArray<float> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                float[] arrA = A.GetArrayForRead();
+               
+                float[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                       
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0)  > B.GetValue(0)) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  gtEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    float scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            float* ap = ((float*)range.Item3 + range.Item1);
+                            float* bp = ((float*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  > *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((float*)range.Item3 + range.Item1);
+                            scalar = *((float*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  > scalar) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((float*)range.Item3);
+                            bp = ((float*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (scalar  > *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (float* arrAP = arrA)
+                fixed (float* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  gtEx(ILInArray<float> A, ILInArray<float> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                float[] arrA = A.GetArrayForRead();
+               
+                float[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    float* ap;
+                   
+                    float* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (float*)range.Item3;
+                                bp = (float*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  > *bp) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (float*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (float*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  > *bp) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( float* arrAP = arrA)
+                fixed ( float* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'greater than' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array having '1' for elements in A being greater than corresponding elements in B, '0' else</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  gt(ILInArray<fcomplex> A, ILInArray<fcomplex> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                fcomplex[] arrA = A.GetArrayForRead();
+               
+                fcomplex[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                       
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0)  > B.GetValue(0)) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  gtEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    fcomplex scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            fcomplex* ap = ((fcomplex*)range.Item3 + range.Item1);
+                            fcomplex* bp = ((fcomplex*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  > *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((fcomplex*)range.Item3 + range.Item1);
+                            scalar = *((fcomplex*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  > scalar) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((fcomplex*)range.Item3);
+                            bp = ((fcomplex*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (scalar  > *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (fcomplex* arrAP = arrA)
+                fixed (fcomplex* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  gtEx(ILInArray<fcomplex> A, ILInArray<fcomplex> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                fcomplex[] arrA = A.GetArrayForRead();
+               
+                fcomplex[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    fcomplex* ap;
+                   
+                    fcomplex* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (fcomplex*)range.Item3;
+                                bp = (fcomplex*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  > *bp) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (fcomplex*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (fcomplex*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  > *bp) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( fcomplex* arrAP = arrA)
+                fixed ( fcomplex* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'greater than' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array having '1' for elements in A being greater than corresponding elements in B, '0' else</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  gt(ILInArray<complex> A, ILInArray<complex> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                complex[] arrA = A.GetArrayForRead();
+               
+                complex[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                       
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0)  > B.GetValue(0)) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  gtEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    complex scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            complex* ap = ((complex*)range.Item3 + range.Item1);
+                            complex* bp = ((complex*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  > *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((complex*)range.Item3 + range.Item1);
+                            scalar = *((complex*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  > scalar) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((complex*)range.Item3);
+                            bp = ((complex*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (scalar  > *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (complex* arrAP = arrA)
+                fixed (complex* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  gtEx(ILInArray<complex> A, ILInArray<complex> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                complex[] arrA = A.GetArrayForRead();
+               
+                complex[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    complex* ap;
+                   
+                    complex* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (complex*)range.Item3;
+                                bp = (complex*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  > *bp) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (complex*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (complex*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  > *bp) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( complex* arrAP = arrA)
+                fixed ( complex* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'greater than' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array having '1' for elements in A being greater than corresponding elements in B, '0' else</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  gt(ILInArray<byte> A, ILInArray<byte> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                byte[] arrA = A.GetArrayForRead();
+               
+                byte[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                       
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0)  > B.GetValue(0)) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  gtEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    byte scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            byte* ap = ((byte*)range.Item3 + range.Item1);
+                            byte* bp = ((byte*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  > *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((byte*)range.Item3 + range.Item1);
+                            scalar = *((byte*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  > scalar) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((byte*)range.Item3);
+                            bp = ((byte*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (scalar  > *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (byte* arrAP = arrA)
+                fixed (byte* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  gtEx(ILInArray<byte> A, ILInArray<byte> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                byte[] arrA = A.GetArrayForRead();
+               
+                byte[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    byte* ap;
+                   
+                    byte* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (byte*)range.Item3;
+                                bp = (byte*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  > *bp) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (byte*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (byte*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  > *bp) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( byte* arrAP = arrA)
+                fixed ( byte* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'greater than' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array having '1' for elements in A being greater than corresponding elements in B, '0' else</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  gt(ILInArray<double> A, ILInArray<double> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                double[] arrA = A.GetArrayForRead();
+               
+                double[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                       
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0)  > B.GetValue(0)) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  gtEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    double scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            double* ap = ((double*)range.Item3 + range.Item1);
+                            double* bp = ((double*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  > *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((double*)range.Item3 + range.Item1);
+                            scalar = *((double*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  > scalar) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((double*)range.Item3);
+                            bp = ((double*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (scalar  > *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (double* arrAP = arrA)
+                fixed (double* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  gtEx(ILInArray<double> A, ILInArray<double> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                double[] arrA = A.GetArrayForRead();
+               
+                double[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    double* ap;
+                   
+                    double* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (double*)range.Item3;
+                                bp = (double*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  > *bp) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (double*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (double*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  > *bp) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( double* arrAP = arrA)
+                fixed ( double* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/imag.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/imag.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/imag.cs	(revision 9102)
@@ -0,0 +1,98 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions;
+
+
+namespace ILNumerics  {
+    
+    public partial class ILMath {
+        
+
+        /// <summary>
+        /// Imaginary part of complex array elements
+        /// </summary>
+        /// <param name="X">Complex input array</param>
+        /// <returns>Imaginary part of complex array</returns>
+        public static ILRetArray<double> imag( ILInArray<complex> X ) {
+            using (ILScope.Enter(X)) {
+                ILArray< double> ret = zeros<double>(X.Size);
+                
+                double[] retArr = ret.GetArrayForWrite();
+                
+                complex[] XArr = X.GetArrayForRead();
+                int nrX = X.Size.NumberOfElements;
+                for (int i = 0; i < nrX; i++) {
+                    retArr[i] = XArr[i].imag;
+                }
+                return ret;
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// Imaginary part of complex array elements
+        /// </summary>
+        /// <param name="X">Complex input array</param>
+        /// <returns>Imaginary part of complex array</returns>
+        public static ILRetArray<float> imag( ILInArray<fcomplex> X ) {
+            using (ILScope.Enter(X)) {
+                ILArray< float> ret = zeros<float>(X.Size);
+               
+                float[] retArr = ret.GetArrayForWrite();
+               
+                fcomplex[] XArr = X.GetArrayForRead();
+                int nrX = X.Size.NumberOfElements;
+                for (int i = 0; i < nrX; i++) {
+                    retArr[i] = XArr[i].imag;
+                }
+                return ret;
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+   }
+
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/ind2sub.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/ind2sub.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/ind2sub.cs	(revision 9102)
@@ -0,0 +1,76 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics;
+using ILNumerics.Exceptions;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+
+namespace ILNumerics {
+    public partial class ILMath {
+        /// <summary>
+        /// Convert sequential index into subscript indices
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="seqindex">Sequential index</param>
+        /// <returns>Subscript indices</returns>
+        /// <remarks><para>The index array returned will have the length of number of dimensions of A</para>
+        /// <para>If A is a null or an empty array, the return value will be also be empty</para>
+        /// </remarks>
+        /// <exception cref="System.IndexOutOfRangeException">If seqindex is &lt; 0 or &gt;= numel(A)</exception>
+        public static ILRetArray<double> ind2sub(ILBaseArray A, int seqindex) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A, null) || A.IsEmpty)
+                    return empty();
+                if (seqindex < 0 || seqindex >= A.Size.NumberOfElements)
+                    throw new ILArgumentException("index out of range: " + seqindex);
+                int IdxCpy = seqindex;
+                ILArray<double> ret = zeros(1, A.Size.NumberOfDimensions);
+                for (int d = 0; d < ret.Length; d++) {
+                    ret.SetValue(IdxCpy % A.Size[d], d);
+                    IdxCpy /= A.Size[d];
+                }
+                return ret;
+            }
+        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/isempty.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/isempty.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/isempty.cs	(revision 9102)
@@ -0,0 +1,68 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics;
+using ILNumerics.Exceptions;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+
+namespace ILNumerics {
+
+    public partial class ILMath {
+       
+        /// <summary>
+        /// Test if array is empty
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns>True if at least one dimension of A has length 0, false otherwise</returns>
+        /// <remarks>
+        /// <para>This function is an alias for A.IsEmpty. Consider using the matrix property directly for improved performance.</para>
+        /// </remarks>
+        /// <seealso cref="P:ILNumerics.ILBaseArray.IsEmpty"/>
+        public static bool isempty(ILBaseArray A) {
+            using (ILScope.Enter(A)) {
+                return A.IsEmpty; 
+            }
+        }
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/isequal.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/isequal.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/isequal.cs	(revision 9102)
@@ -0,0 +1,61 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics;
+using ILNumerics.Exceptions;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+
+namespace ILNumerics {
+    public partial class ILMath {
+        /// <summary>
+        /// Compares two arrays, return System.bool as result
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="B">Input array</param>
+        /// <returns>True, if all elements and sizes of both arrays match; false otherwise</returns>
+        public static bool isequal(ILBaseArray A, ILBaseArray B) {
+            return A.Equals(B); 
+        }
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/isequalwithequalnans.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/isequalwithequalnans.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/isequalwithequalnans.cs	(revision 9102)
@@ -0,0 +1,208 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics;
+using ILNumerics.Exceptions;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+
+namespace ILNumerics {
+    public partial class ILMath {
+
+
+
+        /// <summary>
+        /// Compares elements of two arrays, assume NaN and +/- infinity values are comparable and equal
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="B">Input array</param>
+        /// <returns>True, if all elements of both arrays are equal; false if any elements or the sizes are not equal</returns>
+        public static bool isequalwithequalnans(ILInArray</*HC:inArr1*/double> A, ILInArray</*HC:inArr1*/double> B) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A, null) || object.Equals(B, null)) {
+                    return !(object.Equals(A, null) ^ object.Equals(B, null));
+                }
+                if (A.IsEmpty && B.IsEmpty) return true;
+                if (!A.Size.IsSameSize(B.Size)) return false;
+                int pos = 0;
+                foreach ( double a in A) {
+                    
+                    double b = B.GetValue(pos++);
+                    if ( double.IsNaN(a) &&  double.IsNaN(b)) continue;
+                    if ( double.IsInfinity(a) &&  double.IsInfinity(b)) continue;
+                    if (b != a) return false;
+                }
+                return true;
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+
+        /// <summary>
+        /// Compares elements of two arrays, assume NaN and +/- infinity values are comparable and equal
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="B">Input array</param>
+        /// <returns>True, if all elements of both arrays are equal; false if any elements or the sizes are not equal</returns>
+        public static bool isequalwithequalnans(ILInArray</*HC:*/fcomplex> A, ILInArray</*HC:*/fcomplex> B) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A, null) || object.Equals(B, null)) {
+                    return !(object.Equals(A, null) ^ object.Equals(B, null));
+                }
+                if (A.IsEmpty && B.IsEmpty) return true;
+                if (!A.Size.IsSameSize(B.Size)) return false;
+                int pos = 0;
+                foreach ( fcomplex a in A) {
+                   
+                    fcomplex b = B.GetValue(pos++);
+                    if ( fcomplex.IsNaN(a) &&  fcomplex.IsNaN(b)) continue;
+                    if ( fcomplex.IsInfinity(a) &&  fcomplex.IsInfinity(b)) continue;
+                    if (b != a) return false;
+                }
+                return true;
+            }
+        }
+
+        /// <summary>
+        /// Compares elements of two arrays, assume NaN and +/- infinity values are comparable and equal
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="B">Input array</param>
+        /// <returns>True, if all elements of both arrays are equal; false if any elements or the sizes are not equal</returns>
+        public static bool isequalwithequalnans(ILInArray</*HC:*/float> A, ILInArray</*HC:*/float> B) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A, null) || object.Equals(B, null)) {
+                    return !(object.Equals(A, null) ^ object.Equals(B, null));
+                }
+                if (A.IsEmpty && B.IsEmpty) return true;
+                if (!A.Size.IsSameSize(B.Size)) return false;
+                int pos = 0;
+                foreach ( float a in A) {
+                   
+                    float b = B.GetValue(pos++);
+                    if ( float.IsNaN(a) &&  float.IsNaN(b)) continue;
+                    if ( float.IsInfinity(a) &&  float.IsInfinity(b)) continue;
+                    if (b != a) return false;
+                }
+                return true;
+            }
+        }
+
+        /// <summary>
+        /// Compares elements of two arrays, assume NaN and +/- infinity values are comparable and equal
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="B">Input array</param>
+        /// <returns>True, if all elements of both arrays are equal; false if any elements or the sizes are not equal</returns>
+        public static bool isequalwithequalnans(ILInArray</*HC:*/complex> A, ILInArray</*HC:*/complex> B) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A, null) || object.Equals(B, null)) {
+                    return !(object.Equals(A, null) ^ object.Equals(B, null));
+                }
+                if (A.IsEmpty && B.IsEmpty) return true;
+                if (!A.Size.IsSameSize(B.Size)) return false;
+                int pos = 0;
+                foreach ( complex a in A) {
+                   
+                    complex b = B.GetValue(pos++);
+                    if ( complex.IsNaN(a) &&  complex.IsNaN(b)) continue;
+                    if ( complex.IsInfinity(a) &&  complex.IsInfinity(b)) continue;
+                    if (b != a) return false;
+                }
+                return true;
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// Compare two arrays, assume NaN and +/- infinity values are comparable and equal
+        /// </summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>True if all non-NaN elements in A and B equal, false otherwise</returns>
+        public static bool isequalwithequalnans(ILBaseArray A, ILBaseArray B) {
+            using (ILScope.Enter(A, B)) {
+                if (A is ILDenseArray<double>) {
+                    if (B is ILDenseArray<double>) {
+                        return isequalwithequalnans((A as ILDenseArray<double>).C, (B as ILDenseArray<double>).C);
+                    } else if (B is ILDenseArray<complex>) {
+                        ILArray<complex> Bc = (B as ILDenseArray<complex>).C;
+                        if (Bc == null) return false;
+                        if (any(imag(Bc)).NumberNonZero > 0) return false;
+                        return isequalwithequalnans((A as ILDenseArray<double>).C, real(Bc));
+                    } return false;
+                } else if (A is ILDenseArray<float>) {
+                    if (B is ILDenseArray<float>) {
+                        return isequalwithequalnans((A as ILDenseArray<float>).C, (B as ILDenseArray<float>).C);
+                    } else if (B is ILDenseArray<fcomplex>) {
+                        ILArray<fcomplex> Bf = (B as ILDenseArray<fcomplex>).C;
+                        if (Bf == null) return false;
+                        if (any(imag(Bf)).NumberNonZero > 0) return false;
+                        return isequalwithequalnans((A as ILDenseArray<fcomplex>).C, real(Bf));
+                    } return false;
+                } else if (A is ILDenseArray<complex>) {
+                    if (B is ILDenseArray<complex>) {
+                        return isequalwithequalnans((A as ILDenseArray<complex>).C, (B as ILDenseArray<complex>).C);
+                    } else if (B is ILDenseArray<double>) {
+                        ILArray<complex> Ac = (A as ILDenseArray<complex>).C;
+                        if (A == null) return false;
+                        if (any(imag(Ac)).NumberNonZero > 0) return false;
+                        return isequalwithequalnans(real(Ac), (B as ILDenseArray<double>).C);
+                    } else return false;
+                } else if (A is ILDenseArray<fcomplex>) {
+                    if (B is ILDenseArray<fcomplex>) {
+                        return isequalwithequalnans((A as ILDenseArray<fcomplex>).C, (B as ILDenseArray<fcomplex>).C);
+                    } else if (B is ILDenseArray<float>) {
+                        ILArray<fcomplex> Af = (A as ILDenseArray<fcomplex>).C;
+                        if (Af == null) return false;
+                        if (any(imag(Af)).NumberNonZero > 0) return false;
+                        return isequalwithequalnans(real(Af), (B as ILDenseArray<float>).C);
+                    } else return false;
+                } else {
+                    return A.Equals(B);
+                }
+            }
+        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/isfinite.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/isfinite.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/isfinite.cs	(revision 9102)
@@ -0,0 +1,603 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics;
+using ILNumerics.Exceptions;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+
+
+
+namespace ILNumerics {
+
+    public partial class ILMath {
+        /// <summary>
+        /// Find out, if value is finite
+        /// </summary>
+        /// <param name="input">Input value</param>
+        /// <returns>True for finite values</returns>
+        internal static bool isfinite(double input) {
+            if (!double.IsInfinity(input) && !double.IsNaN(input))
+                return true;
+            else
+                return false;
+        }
+        /// <summary>
+        /// Find out, if value is finite
+        /// </summary>
+        /// <param name="input">Input value</param>
+        /// <returns>True for finite values</returns>
+        internal static bool isfinite(complex input) {
+            if (!complex.IsInfinity(input) && !complex.IsNaN(input))
+                return true;
+            else
+                return false;
+        }
+        /// <summary>
+        /// Find out, if value is finite
+        /// </summary>
+        /// <param name="input">Input value</param>
+        /// <returns>True for finite values</returns>
+        internal static bool isfinite(float input) {
+            if (!float.IsInfinity(input) && !float.IsNaN(input))
+                return true;
+            else
+                return false;
+        }
+        /// <summary>
+        /// Find out, if value is finite
+        /// </summary>
+        /// <param name="input">Input value</param>
+        /// <returns>True for finite values</returns>
+        internal static bool isfinite(fcomplex input) {
+            if (!fcomplex.IsInfinity(input) && !fcomplex.IsNaN(input))
+                return true;
+            else
+                return false;
+        }
+
+
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>Finds finite value elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Logical array with 1 if the corresponding elements of input array is finite, 0 else.</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetLogical  isfinite (ILInArray< double > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetLogical(A.Size); 
+                ILSize inDim = A.Size;
+                double[] arrA = A.GetArrayForRead(); 
+                byte [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (true){
+                    retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<byte> retStorage = new ILDenseStorage<byte>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    byte* cp = ((byte*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  isfinite(cp[0]  )  ?(byte)1:(byte)0;;
+                            cp[1] =  isfinite(cp[1]  )  ?(byte)1:(byte)0;;
+                            cp[2] =  isfinite(cp[2]  )  ?(byte)1:(byte)0;;
+                            cp[3] =  isfinite(cp[3]  )  ?(byte)1:(byte)0;;
+                            cp[4] =  isfinite(cp[4]  )  ?(byte)1:(byte)0;;
+                            cp[5] =  isfinite(cp[5]  )  ?(byte)1:(byte)0;;
+                            cp[6] =  isfinite(cp[6]  )  ?(byte)1:(byte)0;;
+                            cp[7] =  isfinite(cp[7]  )  ?(byte)1:(byte)0;;
+                            cp[8] =  isfinite(cp[8]  )  ?(byte)1:(byte)0;;
+                            cp[9] =  isfinite(cp[9]  )  ?(byte)1:(byte)0;;
+                            cp[10] =  isfinite(cp[10]  )  ?(byte)1:(byte)0;;
+                            cp[11] =  isfinite(cp[11]  )  ?(byte)1:(byte)0;;
+                            cp[12] =  isfinite(cp[12]  )  ?(byte)1:(byte)0;;
+                            cp[13] =  isfinite(cp[13]  )  ?(byte)1:(byte)0;;
+                            cp[14] =  isfinite(cp[14]  )  ?(byte)1:(byte)0;;
+                            cp[15] =  isfinite(cp[15]  )  ?(byte)1:(byte)0;;
+                            cp[16] =  isfinite(cp[16]  )  ?(byte)1:(byte)0;;
+                            cp[17] =  isfinite(cp[17]  )  ?(byte)1:(byte)0;;
+                            cp[18] =  isfinite(cp[18]  )  ?(byte)1:(byte)0;;
+                            cp[19] =  isfinite(cp[19]  )  ?(byte)1:(byte)0;;
+                            cp[20] =  isfinite(cp[20]  )  ?(byte)1:(byte)0;;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  isfinite(*cp  )  ?(byte)1:(byte)0;;
+                            cp++;
+                        }
+                    } else {
+                        double* ap = ((double*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  isfinite(ap[0]  )  ?(byte)1:(byte)0;;
+                            cp[1] =  isfinite(ap[1]  )  ?(byte)1:(byte)0;;
+                            cp[2] =  isfinite(ap[2]  )  ?(byte)1:(byte)0;;
+                            cp[3] =  isfinite(ap[3]  )  ?(byte)1:(byte)0;;
+                            cp[4] =  isfinite(ap[4]  )  ?(byte)1:(byte)0;;
+                            cp[5] =  isfinite(ap[5]  )  ?(byte)1:(byte)0;;
+                            cp[6] =  isfinite(ap[6]  )  ?(byte)1:(byte)0;;
+                            cp[7] =  isfinite(ap[7]  )  ?(byte)1:(byte)0;;
+                            cp[8] =  isfinite(ap[8]  )  ?(byte)1:(byte)0;;
+                            cp[9] =  isfinite(ap[9]  )  ?(byte)1:(byte)0;;
+                            cp[10] =  isfinite(ap[10]  )  ?(byte)1:(byte)0;;
+                            cp[11] =  isfinite(ap[11]  )  ?(byte)1:(byte)0;;
+                            cp[12] =  isfinite(ap[12]  )  ?(byte)1:(byte)0;;
+                            cp[13] =  isfinite(ap[13]  )  ?(byte)1:(byte)0;;
+                            cp[14] =  isfinite(ap[14]  )  ?(byte)1:(byte)0;;
+                            cp[15] =  isfinite(ap[15]  )  ?(byte)1:(byte)0;;
+                            cp[16] =  isfinite(ap[16]  )  ?(byte)1:(byte)0;;
+                            cp[17] =  isfinite(ap[17]  )  ?(byte)1:(byte)0;;
+                            cp[18] =  isfinite(ap[18]  )  ?(byte)1:(byte)0;;
+                            cp[19] =  isfinite(ap[19]  )  ?(byte)1:(byte)0;;
+                            cp[20] =  isfinite(ap[20]  )  ?(byte)1:(byte)0;;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  isfinite(*ap  )  ?(byte)1:(byte)0;;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( double* arrAP = arrA)
+                fixed ( byte* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetLogical(retStorage);
+            }
+        }
+        /// <summary>Finds finite value elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Logical array with 1 if the corresponding elements of input array is finite, 0 else.</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetLogical  isfinite (ILInArray< float > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetLogical(A.Size); 
+                ILSize inDim = A.Size;
+                float[] arrA = A.GetArrayForRead(); 
+                byte [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (true){
+                    retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<byte> retStorage = new ILDenseStorage<byte>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    byte* cp = ((byte*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  isfinite(cp[0]  )  ?(byte)1:(byte)0;;
+                            cp[1] =  isfinite(cp[1]  )  ?(byte)1:(byte)0;;
+                            cp[2] =  isfinite(cp[2]  )  ?(byte)1:(byte)0;;
+                            cp[3] =  isfinite(cp[3]  )  ?(byte)1:(byte)0;;
+                            cp[4] =  isfinite(cp[4]  )  ?(byte)1:(byte)0;;
+                            cp[5] =  isfinite(cp[5]  )  ?(byte)1:(byte)0;;
+                            cp[6] =  isfinite(cp[6]  )  ?(byte)1:(byte)0;;
+                            cp[7] =  isfinite(cp[7]  )  ?(byte)1:(byte)0;;
+                            cp[8] =  isfinite(cp[8]  )  ?(byte)1:(byte)0;;
+                            cp[9] =  isfinite(cp[9]  )  ?(byte)1:(byte)0;;
+                            cp[10] =  isfinite(cp[10]  )  ?(byte)1:(byte)0;;
+                            cp[11] =  isfinite(cp[11]  )  ?(byte)1:(byte)0;;
+                            cp[12] =  isfinite(cp[12]  )  ?(byte)1:(byte)0;;
+                            cp[13] =  isfinite(cp[13]  )  ?(byte)1:(byte)0;;
+                            cp[14] =  isfinite(cp[14]  )  ?(byte)1:(byte)0;;
+                            cp[15] =  isfinite(cp[15]  )  ?(byte)1:(byte)0;;
+                            cp[16] =  isfinite(cp[16]  )  ?(byte)1:(byte)0;;
+                            cp[17] =  isfinite(cp[17]  )  ?(byte)1:(byte)0;;
+                            cp[18] =  isfinite(cp[18]  )  ?(byte)1:(byte)0;;
+                            cp[19] =  isfinite(cp[19]  )  ?(byte)1:(byte)0;;
+                            cp[20] =  isfinite(cp[20]  )  ?(byte)1:(byte)0;;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  isfinite(*cp  )  ?(byte)1:(byte)0;;
+                            cp++;
+                        }
+                    } else {
+                        float* ap = ((float*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  isfinite(ap[0]  )  ?(byte)1:(byte)0;;
+                            cp[1] =  isfinite(ap[1]  )  ?(byte)1:(byte)0;;
+                            cp[2] =  isfinite(ap[2]  )  ?(byte)1:(byte)0;;
+                            cp[3] =  isfinite(ap[3]  )  ?(byte)1:(byte)0;;
+                            cp[4] =  isfinite(ap[4]  )  ?(byte)1:(byte)0;;
+                            cp[5] =  isfinite(ap[5]  )  ?(byte)1:(byte)0;;
+                            cp[6] =  isfinite(ap[6]  )  ?(byte)1:(byte)0;;
+                            cp[7] =  isfinite(ap[7]  )  ?(byte)1:(byte)0;;
+                            cp[8] =  isfinite(ap[8]  )  ?(byte)1:(byte)0;;
+                            cp[9] =  isfinite(ap[9]  )  ?(byte)1:(byte)0;;
+                            cp[10] =  isfinite(ap[10]  )  ?(byte)1:(byte)0;;
+                            cp[11] =  isfinite(ap[11]  )  ?(byte)1:(byte)0;;
+                            cp[12] =  isfinite(ap[12]  )  ?(byte)1:(byte)0;;
+                            cp[13] =  isfinite(ap[13]  )  ?(byte)1:(byte)0;;
+                            cp[14] =  isfinite(ap[14]  )  ?(byte)1:(byte)0;;
+                            cp[15] =  isfinite(ap[15]  )  ?(byte)1:(byte)0;;
+                            cp[16] =  isfinite(ap[16]  )  ?(byte)1:(byte)0;;
+                            cp[17] =  isfinite(ap[17]  )  ?(byte)1:(byte)0;;
+                            cp[18] =  isfinite(ap[18]  )  ?(byte)1:(byte)0;;
+                            cp[19] =  isfinite(ap[19]  )  ?(byte)1:(byte)0;;
+                            cp[20] =  isfinite(ap[20]  )  ?(byte)1:(byte)0;;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  isfinite(*ap  )  ?(byte)1:(byte)0;;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( float* arrAP = arrA)
+                fixed ( byte* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetLogical(retStorage);
+            }
+        }
+        /// <summary>Finds finite value elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Logical array with 1 if the corresponding elements of input array is finite, 0 else.</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetLogical  isfinite (ILInArray< fcomplex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetLogical(A.Size); 
+                ILSize inDim = A.Size;
+                fcomplex[] arrA = A.GetArrayForRead(); 
+                byte [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (true){
+                    retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<byte> retStorage = new ILDenseStorage<byte>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    byte* cp = ((byte*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  fcomplex.IsFinite(cp[0]  )  ?(byte)1:(byte)0;;
+                            cp[1] =  fcomplex.IsFinite(cp[1]  )  ?(byte)1:(byte)0;;
+                            cp[2] =  fcomplex.IsFinite(cp[2]  )  ?(byte)1:(byte)0;;
+                            cp[3] =  fcomplex.IsFinite(cp[3]  )  ?(byte)1:(byte)0;;
+                            cp[4] =  fcomplex.IsFinite(cp[4]  )  ?(byte)1:(byte)0;;
+                            cp[5] =  fcomplex.IsFinite(cp[5]  )  ?(byte)1:(byte)0;;
+                            cp[6] =  fcomplex.IsFinite(cp[6]  )  ?(byte)1:(byte)0;;
+                            cp[7] =  fcomplex.IsFinite(cp[7]  )  ?(byte)1:(byte)0;;
+                            cp[8] =  fcomplex.IsFinite(cp[8]  )  ?(byte)1:(byte)0;;
+                            cp[9] =  fcomplex.IsFinite(cp[9]  )  ?(byte)1:(byte)0;;
+                            cp[10] =  fcomplex.IsFinite(cp[10]  )  ?(byte)1:(byte)0;;
+                            cp[11] =  fcomplex.IsFinite(cp[11]  )  ?(byte)1:(byte)0;;
+                            cp[12] =  fcomplex.IsFinite(cp[12]  )  ?(byte)1:(byte)0;;
+                            cp[13] =  fcomplex.IsFinite(cp[13]  )  ?(byte)1:(byte)0;;
+                            cp[14] =  fcomplex.IsFinite(cp[14]  )  ?(byte)1:(byte)0;;
+                            cp[15] =  fcomplex.IsFinite(cp[15]  )  ?(byte)1:(byte)0;;
+                            cp[16] =  fcomplex.IsFinite(cp[16]  )  ?(byte)1:(byte)0;;
+                            cp[17] =  fcomplex.IsFinite(cp[17]  )  ?(byte)1:(byte)0;;
+                            cp[18] =  fcomplex.IsFinite(cp[18]  )  ?(byte)1:(byte)0;;
+                            cp[19] =  fcomplex.IsFinite(cp[19]  )  ?(byte)1:(byte)0;;
+                            cp[20] =  fcomplex.IsFinite(cp[20]  )  ?(byte)1:(byte)0;;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.IsFinite(*cp  )  ?(byte)1:(byte)0;;
+                            cp++;
+                        }
+                    } else {
+                        fcomplex* ap = ((fcomplex*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  fcomplex.IsFinite(ap[0]  )  ?(byte)1:(byte)0;;
+                            cp[1] =  fcomplex.IsFinite(ap[1]  )  ?(byte)1:(byte)0;;
+                            cp[2] =  fcomplex.IsFinite(ap[2]  )  ?(byte)1:(byte)0;;
+                            cp[3] =  fcomplex.IsFinite(ap[3]  )  ?(byte)1:(byte)0;;
+                            cp[4] =  fcomplex.IsFinite(ap[4]  )  ?(byte)1:(byte)0;;
+                            cp[5] =  fcomplex.IsFinite(ap[5]  )  ?(byte)1:(byte)0;;
+                            cp[6] =  fcomplex.IsFinite(ap[6]  )  ?(byte)1:(byte)0;;
+                            cp[7] =  fcomplex.IsFinite(ap[7]  )  ?(byte)1:(byte)0;;
+                            cp[8] =  fcomplex.IsFinite(ap[8]  )  ?(byte)1:(byte)0;;
+                            cp[9] =  fcomplex.IsFinite(ap[9]  )  ?(byte)1:(byte)0;;
+                            cp[10] =  fcomplex.IsFinite(ap[10]  )  ?(byte)1:(byte)0;;
+                            cp[11] =  fcomplex.IsFinite(ap[11]  )  ?(byte)1:(byte)0;;
+                            cp[12] =  fcomplex.IsFinite(ap[12]  )  ?(byte)1:(byte)0;;
+                            cp[13] =  fcomplex.IsFinite(ap[13]  )  ?(byte)1:(byte)0;;
+                            cp[14] =  fcomplex.IsFinite(ap[14]  )  ?(byte)1:(byte)0;;
+                            cp[15] =  fcomplex.IsFinite(ap[15]  )  ?(byte)1:(byte)0;;
+                            cp[16] =  fcomplex.IsFinite(ap[16]  )  ?(byte)1:(byte)0;;
+                            cp[17] =  fcomplex.IsFinite(ap[17]  )  ?(byte)1:(byte)0;;
+                            cp[18] =  fcomplex.IsFinite(ap[18]  )  ?(byte)1:(byte)0;;
+                            cp[19] =  fcomplex.IsFinite(ap[19]  )  ?(byte)1:(byte)0;;
+                            cp[20] =  fcomplex.IsFinite(ap[20]  )  ?(byte)1:(byte)0;;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.IsFinite(*ap  )  ?(byte)1:(byte)0;;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( fcomplex* arrAP = arrA)
+                fixed ( byte* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetLogical(retStorage);
+            }
+        }
+        /// <summary>Finds finite value elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Logical array with 1 if the corresponding elements of input array is finite, 0 else.</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetLogical  isfinite (ILInArray< complex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetLogical(A.Size); 
+                ILSize inDim = A.Size;
+                complex[] arrA = A.GetArrayForRead(); 
+                byte [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (true){
+                    retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<byte> retStorage = new ILDenseStorage<byte>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    byte* cp = ((byte*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  complex.IsFinite(cp[0]  )  ?(byte)1:(byte)0;;
+                            cp[1] =  complex.IsFinite(cp[1]  )  ?(byte)1:(byte)0;;
+                            cp[2] =  complex.IsFinite(cp[2]  )  ?(byte)1:(byte)0;;
+                            cp[3] =  complex.IsFinite(cp[3]  )  ?(byte)1:(byte)0;;
+                            cp[4] =  complex.IsFinite(cp[4]  )  ?(byte)1:(byte)0;;
+                            cp[5] =  complex.IsFinite(cp[5]  )  ?(byte)1:(byte)0;;
+                            cp[6] =  complex.IsFinite(cp[6]  )  ?(byte)1:(byte)0;;
+                            cp[7] =  complex.IsFinite(cp[7]  )  ?(byte)1:(byte)0;;
+                            cp[8] =  complex.IsFinite(cp[8]  )  ?(byte)1:(byte)0;;
+                            cp[9] =  complex.IsFinite(cp[9]  )  ?(byte)1:(byte)0;;
+                            cp[10] =  complex.IsFinite(cp[10]  )  ?(byte)1:(byte)0;;
+                            cp[11] =  complex.IsFinite(cp[11]  )  ?(byte)1:(byte)0;;
+                            cp[12] =  complex.IsFinite(cp[12]  )  ?(byte)1:(byte)0;;
+                            cp[13] =  complex.IsFinite(cp[13]  )  ?(byte)1:(byte)0;;
+                            cp[14] =  complex.IsFinite(cp[14]  )  ?(byte)1:(byte)0;;
+                            cp[15] =  complex.IsFinite(cp[15]  )  ?(byte)1:(byte)0;;
+                            cp[16] =  complex.IsFinite(cp[16]  )  ?(byte)1:(byte)0;;
+                            cp[17] =  complex.IsFinite(cp[17]  )  ?(byte)1:(byte)0;;
+                            cp[18] =  complex.IsFinite(cp[18]  )  ?(byte)1:(byte)0;;
+                            cp[19] =  complex.IsFinite(cp[19]  )  ?(byte)1:(byte)0;;
+                            cp[20] =  complex.IsFinite(cp[20]  )  ?(byte)1:(byte)0;;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.IsFinite(*cp  )  ?(byte)1:(byte)0;;
+                            cp++;
+                        }
+                    } else {
+                        complex* ap = ((complex*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  complex.IsFinite(ap[0]  )  ?(byte)1:(byte)0;;
+                            cp[1] =  complex.IsFinite(ap[1]  )  ?(byte)1:(byte)0;;
+                            cp[2] =  complex.IsFinite(ap[2]  )  ?(byte)1:(byte)0;;
+                            cp[3] =  complex.IsFinite(ap[3]  )  ?(byte)1:(byte)0;;
+                            cp[4] =  complex.IsFinite(ap[4]  )  ?(byte)1:(byte)0;;
+                            cp[5] =  complex.IsFinite(ap[5]  )  ?(byte)1:(byte)0;;
+                            cp[6] =  complex.IsFinite(ap[6]  )  ?(byte)1:(byte)0;;
+                            cp[7] =  complex.IsFinite(ap[7]  )  ?(byte)1:(byte)0;;
+                            cp[8] =  complex.IsFinite(ap[8]  )  ?(byte)1:(byte)0;;
+                            cp[9] =  complex.IsFinite(ap[9]  )  ?(byte)1:(byte)0;;
+                            cp[10] =  complex.IsFinite(ap[10]  )  ?(byte)1:(byte)0;;
+                            cp[11] =  complex.IsFinite(ap[11]  )  ?(byte)1:(byte)0;;
+                            cp[12] =  complex.IsFinite(ap[12]  )  ?(byte)1:(byte)0;;
+                            cp[13] =  complex.IsFinite(ap[13]  )  ?(byte)1:(byte)0;;
+                            cp[14] =  complex.IsFinite(ap[14]  )  ?(byte)1:(byte)0;;
+                            cp[15] =  complex.IsFinite(ap[15]  )  ?(byte)1:(byte)0;;
+                            cp[16] =  complex.IsFinite(ap[16]  )  ?(byte)1:(byte)0;;
+                            cp[17] =  complex.IsFinite(ap[17]  )  ?(byte)1:(byte)0;;
+                            cp[18] =  complex.IsFinite(ap[18]  )  ?(byte)1:(byte)0;;
+                            cp[19] =  complex.IsFinite(ap[19]  )  ?(byte)1:(byte)0;;
+                            cp[20] =  complex.IsFinite(ap[20]  )  ?(byte)1:(byte)0;;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.IsFinite(*ap  )  ?(byte)1:(byte)0;;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( complex* arrAP = arrA)
+                fixed ( byte* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetLogical(retStorage);
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/isinf.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/isinf.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/isinf.cs	(revision 9102)
@@ -0,0 +1,556 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics;
+using ILNumerics.Exceptions;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+
+
+namespace ILNumerics {
+    public partial class ILMath {
+
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>Locate infinite value elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Logical array with 1 if the corresponding elements of input array is infinite, 0 else.</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetLogical  isinf (ILInArray< double > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetLogical(A.Size); 
+                ILSize inDim = A.Size;
+                double[] arrA = A.GetArrayForRead(); 
+                byte [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (true){
+                    retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<byte> retStorage = new ILDenseStorage<byte>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    byte* cp = ((byte*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  Double.IsInfinity(cp[0]  )  ?(byte)1:(byte)0;;
+                            cp[1] =  Double.IsInfinity(cp[1]  )  ?(byte)1:(byte)0;;
+                            cp[2] =  Double.IsInfinity(cp[2]  )  ?(byte)1:(byte)0;;
+                            cp[3] =  Double.IsInfinity(cp[3]  )  ?(byte)1:(byte)0;;
+                            cp[4] =  Double.IsInfinity(cp[4]  )  ?(byte)1:(byte)0;;
+                            cp[5] =  Double.IsInfinity(cp[5]  )  ?(byte)1:(byte)0;;
+                            cp[6] =  Double.IsInfinity(cp[6]  )  ?(byte)1:(byte)0;;
+                            cp[7] =  Double.IsInfinity(cp[7]  )  ?(byte)1:(byte)0;;
+                            cp[8] =  Double.IsInfinity(cp[8]  )  ?(byte)1:(byte)0;;
+                            cp[9] =  Double.IsInfinity(cp[9]  )  ?(byte)1:(byte)0;;
+                            cp[10] =  Double.IsInfinity(cp[10]  )  ?(byte)1:(byte)0;;
+                            cp[11] =  Double.IsInfinity(cp[11]  )  ?(byte)1:(byte)0;;
+                            cp[12] =  Double.IsInfinity(cp[12]  )  ?(byte)1:(byte)0;;
+                            cp[13] =  Double.IsInfinity(cp[13]  )  ?(byte)1:(byte)0;;
+                            cp[14] =  Double.IsInfinity(cp[14]  )  ?(byte)1:(byte)0;;
+                            cp[15] =  Double.IsInfinity(cp[15]  )  ?(byte)1:(byte)0;;
+                            cp[16] =  Double.IsInfinity(cp[16]  )  ?(byte)1:(byte)0;;
+                            cp[17] =  Double.IsInfinity(cp[17]  )  ?(byte)1:(byte)0;;
+                            cp[18] =  Double.IsInfinity(cp[18]  )  ?(byte)1:(byte)0;;
+                            cp[19] =  Double.IsInfinity(cp[19]  )  ?(byte)1:(byte)0;;
+                            cp[20] =  Double.IsInfinity(cp[20]  )  ?(byte)1:(byte)0;;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Double.IsInfinity(*cp  )  ?(byte)1:(byte)0;;
+                            cp++;
+                        }
+                    } else {
+                        double* ap = ((double*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  Double.IsInfinity(ap[0]  )  ?(byte)1:(byte)0;;
+                            cp[1] =  Double.IsInfinity(ap[1]  )  ?(byte)1:(byte)0;;
+                            cp[2] =  Double.IsInfinity(ap[2]  )  ?(byte)1:(byte)0;;
+                            cp[3] =  Double.IsInfinity(ap[3]  )  ?(byte)1:(byte)0;;
+                            cp[4] =  Double.IsInfinity(ap[4]  )  ?(byte)1:(byte)0;;
+                            cp[5] =  Double.IsInfinity(ap[5]  )  ?(byte)1:(byte)0;;
+                            cp[6] =  Double.IsInfinity(ap[6]  )  ?(byte)1:(byte)0;;
+                            cp[7] =  Double.IsInfinity(ap[7]  )  ?(byte)1:(byte)0;;
+                            cp[8] =  Double.IsInfinity(ap[8]  )  ?(byte)1:(byte)0;;
+                            cp[9] =  Double.IsInfinity(ap[9]  )  ?(byte)1:(byte)0;;
+                            cp[10] =  Double.IsInfinity(ap[10]  )  ?(byte)1:(byte)0;;
+                            cp[11] =  Double.IsInfinity(ap[11]  )  ?(byte)1:(byte)0;;
+                            cp[12] =  Double.IsInfinity(ap[12]  )  ?(byte)1:(byte)0;;
+                            cp[13] =  Double.IsInfinity(ap[13]  )  ?(byte)1:(byte)0;;
+                            cp[14] =  Double.IsInfinity(ap[14]  )  ?(byte)1:(byte)0;;
+                            cp[15] =  Double.IsInfinity(ap[15]  )  ?(byte)1:(byte)0;;
+                            cp[16] =  Double.IsInfinity(ap[16]  )  ?(byte)1:(byte)0;;
+                            cp[17] =  Double.IsInfinity(ap[17]  )  ?(byte)1:(byte)0;;
+                            cp[18] =  Double.IsInfinity(ap[18]  )  ?(byte)1:(byte)0;;
+                            cp[19] =  Double.IsInfinity(ap[19]  )  ?(byte)1:(byte)0;;
+                            cp[20] =  Double.IsInfinity(ap[20]  )  ?(byte)1:(byte)0;;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Double.IsInfinity(*ap  )  ?(byte)1:(byte)0;;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( double* arrAP = arrA)
+                fixed ( byte* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetLogical(retStorage);
+            }
+        }
+        /// <summary>Locate infinite value elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Logical array with 1 if the corresponding elements of input array is infinite, 0 else.</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetLogical  isinf (ILInArray< float > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetLogical(A.Size); 
+                ILSize inDim = A.Size;
+                float[] arrA = A.GetArrayForRead(); 
+                byte [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (true){
+                    retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<byte> retStorage = new ILDenseStorage<byte>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    byte* cp = ((byte*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  Single.IsInfinity(cp[0]  )  ?(byte)1:(byte)0;;
+                            cp[1] =  Single.IsInfinity(cp[1]  )  ?(byte)1:(byte)0;;
+                            cp[2] =  Single.IsInfinity(cp[2]  )  ?(byte)1:(byte)0;;
+                            cp[3] =  Single.IsInfinity(cp[3]  )  ?(byte)1:(byte)0;;
+                            cp[4] =  Single.IsInfinity(cp[4]  )  ?(byte)1:(byte)0;;
+                            cp[5] =  Single.IsInfinity(cp[5]  )  ?(byte)1:(byte)0;;
+                            cp[6] =  Single.IsInfinity(cp[6]  )  ?(byte)1:(byte)0;;
+                            cp[7] =  Single.IsInfinity(cp[7]  )  ?(byte)1:(byte)0;;
+                            cp[8] =  Single.IsInfinity(cp[8]  )  ?(byte)1:(byte)0;;
+                            cp[9] =  Single.IsInfinity(cp[9]  )  ?(byte)1:(byte)0;;
+                            cp[10] =  Single.IsInfinity(cp[10]  )  ?(byte)1:(byte)0;;
+                            cp[11] =  Single.IsInfinity(cp[11]  )  ?(byte)1:(byte)0;;
+                            cp[12] =  Single.IsInfinity(cp[12]  )  ?(byte)1:(byte)0;;
+                            cp[13] =  Single.IsInfinity(cp[13]  )  ?(byte)1:(byte)0;;
+                            cp[14] =  Single.IsInfinity(cp[14]  )  ?(byte)1:(byte)0;;
+                            cp[15] =  Single.IsInfinity(cp[15]  )  ?(byte)1:(byte)0;;
+                            cp[16] =  Single.IsInfinity(cp[16]  )  ?(byte)1:(byte)0;;
+                            cp[17] =  Single.IsInfinity(cp[17]  )  ?(byte)1:(byte)0;;
+                            cp[18] =  Single.IsInfinity(cp[18]  )  ?(byte)1:(byte)0;;
+                            cp[19] =  Single.IsInfinity(cp[19]  )  ?(byte)1:(byte)0;;
+                            cp[20] =  Single.IsInfinity(cp[20]  )  ?(byte)1:(byte)0;;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Single.IsInfinity(*cp  )  ?(byte)1:(byte)0;;
+                            cp++;
+                        }
+                    } else {
+                        float* ap = ((float*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  Single.IsInfinity(ap[0]  )  ?(byte)1:(byte)0;;
+                            cp[1] =  Single.IsInfinity(ap[1]  )  ?(byte)1:(byte)0;;
+                            cp[2] =  Single.IsInfinity(ap[2]  )  ?(byte)1:(byte)0;;
+                            cp[3] =  Single.IsInfinity(ap[3]  )  ?(byte)1:(byte)0;;
+                            cp[4] =  Single.IsInfinity(ap[4]  )  ?(byte)1:(byte)0;;
+                            cp[5] =  Single.IsInfinity(ap[5]  )  ?(byte)1:(byte)0;;
+                            cp[6] =  Single.IsInfinity(ap[6]  )  ?(byte)1:(byte)0;;
+                            cp[7] =  Single.IsInfinity(ap[7]  )  ?(byte)1:(byte)0;;
+                            cp[8] =  Single.IsInfinity(ap[8]  )  ?(byte)1:(byte)0;;
+                            cp[9] =  Single.IsInfinity(ap[9]  )  ?(byte)1:(byte)0;;
+                            cp[10] =  Single.IsInfinity(ap[10]  )  ?(byte)1:(byte)0;;
+                            cp[11] =  Single.IsInfinity(ap[11]  )  ?(byte)1:(byte)0;;
+                            cp[12] =  Single.IsInfinity(ap[12]  )  ?(byte)1:(byte)0;;
+                            cp[13] =  Single.IsInfinity(ap[13]  )  ?(byte)1:(byte)0;;
+                            cp[14] =  Single.IsInfinity(ap[14]  )  ?(byte)1:(byte)0;;
+                            cp[15] =  Single.IsInfinity(ap[15]  )  ?(byte)1:(byte)0;;
+                            cp[16] =  Single.IsInfinity(ap[16]  )  ?(byte)1:(byte)0;;
+                            cp[17] =  Single.IsInfinity(ap[17]  )  ?(byte)1:(byte)0;;
+                            cp[18] =  Single.IsInfinity(ap[18]  )  ?(byte)1:(byte)0;;
+                            cp[19] =  Single.IsInfinity(ap[19]  )  ?(byte)1:(byte)0;;
+                            cp[20] =  Single.IsInfinity(ap[20]  )  ?(byte)1:(byte)0;;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Single.IsInfinity(*ap  )  ?(byte)1:(byte)0;;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( float* arrAP = arrA)
+                fixed ( byte* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetLogical(retStorage);
+            }
+        }
+        /// <summary>Locate infinite value elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Logical array with 1 if the corresponding elements of input array is infinite, 0 else.</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetLogical  isinf (ILInArray< fcomplex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetLogical(A.Size); 
+                ILSize inDim = A.Size;
+                fcomplex[] arrA = A.GetArrayForRead(); 
+                byte [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (true){
+                    retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<byte> retStorage = new ILDenseStorage<byte>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    byte* cp = ((byte*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  fcomplex.IsInfinity(cp[0]  )  ?(byte)1:(byte)0;;
+                            cp[1] =  fcomplex.IsInfinity(cp[1]  )  ?(byte)1:(byte)0;;
+                            cp[2] =  fcomplex.IsInfinity(cp[2]  )  ?(byte)1:(byte)0;;
+                            cp[3] =  fcomplex.IsInfinity(cp[3]  )  ?(byte)1:(byte)0;;
+                            cp[4] =  fcomplex.IsInfinity(cp[4]  )  ?(byte)1:(byte)0;;
+                            cp[5] =  fcomplex.IsInfinity(cp[5]  )  ?(byte)1:(byte)0;;
+                            cp[6] =  fcomplex.IsInfinity(cp[6]  )  ?(byte)1:(byte)0;;
+                            cp[7] =  fcomplex.IsInfinity(cp[7]  )  ?(byte)1:(byte)0;;
+                            cp[8] =  fcomplex.IsInfinity(cp[8]  )  ?(byte)1:(byte)0;;
+                            cp[9] =  fcomplex.IsInfinity(cp[9]  )  ?(byte)1:(byte)0;;
+                            cp[10] =  fcomplex.IsInfinity(cp[10]  )  ?(byte)1:(byte)0;;
+                            cp[11] =  fcomplex.IsInfinity(cp[11]  )  ?(byte)1:(byte)0;;
+                            cp[12] =  fcomplex.IsInfinity(cp[12]  )  ?(byte)1:(byte)0;;
+                            cp[13] =  fcomplex.IsInfinity(cp[13]  )  ?(byte)1:(byte)0;;
+                            cp[14] =  fcomplex.IsInfinity(cp[14]  )  ?(byte)1:(byte)0;;
+                            cp[15] =  fcomplex.IsInfinity(cp[15]  )  ?(byte)1:(byte)0;;
+                            cp[16] =  fcomplex.IsInfinity(cp[16]  )  ?(byte)1:(byte)0;;
+                            cp[17] =  fcomplex.IsInfinity(cp[17]  )  ?(byte)1:(byte)0;;
+                            cp[18] =  fcomplex.IsInfinity(cp[18]  )  ?(byte)1:(byte)0;;
+                            cp[19] =  fcomplex.IsInfinity(cp[19]  )  ?(byte)1:(byte)0;;
+                            cp[20] =  fcomplex.IsInfinity(cp[20]  )  ?(byte)1:(byte)0;;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.IsInfinity(*cp  )  ?(byte)1:(byte)0;;
+                            cp++;
+                        }
+                    } else {
+                        fcomplex* ap = ((fcomplex*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  fcomplex.IsInfinity(ap[0]  )  ?(byte)1:(byte)0;;
+                            cp[1] =  fcomplex.IsInfinity(ap[1]  )  ?(byte)1:(byte)0;;
+                            cp[2] =  fcomplex.IsInfinity(ap[2]  )  ?(byte)1:(byte)0;;
+                            cp[3] =  fcomplex.IsInfinity(ap[3]  )  ?(byte)1:(byte)0;;
+                            cp[4] =  fcomplex.IsInfinity(ap[4]  )  ?(byte)1:(byte)0;;
+                            cp[5] =  fcomplex.IsInfinity(ap[5]  )  ?(byte)1:(byte)0;;
+                            cp[6] =  fcomplex.IsInfinity(ap[6]  )  ?(byte)1:(byte)0;;
+                            cp[7] =  fcomplex.IsInfinity(ap[7]  )  ?(byte)1:(byte)0;;
+                            cp[8] =  fcomplex.IsInfinity(ap[8]  )  ?(byte)1:(byte)0;;
+                            cp[9] =  fcomplex.IsInfinity(ap[9]  )  ?(byte)1:(byte)0;;
+                            cp[10] =  fcomplex.IsInfinity(ap[10]  )  ?(byte)1:(byte)0;;
+                            cp[11] =  fcomplex.IsInfinity(ap[11]  )  ?(byte)1:(byte)0;;
+                            cp[12] =  fcomplex.IsInfinity(ap[12]  )  ?(byte)1:(byte)0;;
+                            cp[13] =  fcomplex.IsInfinity(ap[13]  )  ?(byte)1:(byte)0;;
+                            cp[14] =  fcomplex.IsInfinity(ap[14]  )  ?(byte)1:(byte)0;;
+                            cp[15] =  fcomplex.IsInfinity(ap[15]  )  ?(byte)1:(byte)0;;
+                            cp[16] =  fcomplex.IsInfinity(ap[16]  )  ?(byte)1:(byte)0;;
+                            cp[17] =  fcomplex.IsInfinity(ap[17]  )  ?(byte)1:(byte)0;;
+                            cp[18] =  fcomplex.IsInfinity(ap[18]  )  ?(byte)1:(byte)0;;
+                            cp[19] =  fcomplex.IsInfinity(ap[19]  )  ?(byte)1:(byte)0;;
+                            cp[20] =  fcomplex.IsInfinity(ap[20]  )  ?(byte)1:(byte)0;;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.IsInfinity(*ap  )  ?(byte)1:(byte)0;;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( fcomplex* arrAP = arrA)
+                fixed ( byte* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetLogical(retStorage);
+            }
+        }
+        /// <summary>Locate infinite value elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Logical array with 1 if the corresponding elements of input array is infinite, 0 else.</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetLogical  isinf (ILInArray< complex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetLogical(A.Size); 
+                ILSize inDim = A.Size;
+                complex[] arrA = A.GetArrayForRead(); 
+                byte [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (true){
+                    retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<byte> retStorage = new ILDenseStorage<byte>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    byte* cp = ((byte*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  complex.IsInfinity(cp[0]  )  ?(byte)1:(byte)0;;
+                            cp[1] =  complex.IsInfinity(cp[1]  )  ?(byte)1:(byte)0;;
+                            cp[2] =  complex.IsInfinity(cp[2]  )  ?(byte)1:(byte)0;;
+                            cp[3] =  complex.IsInfinity(cp[3]  )  ?(byte)1:(byte)0;;
+                            cp[4] =  complex.IsInfinity(cp[4]  )  ?(byte)1:(byte)0;;
+                            cp[5] =  complex.IsInfinity(cp[5]  )  ?(byte)1:(byte)0;;
+                            cp[6] =  complex.IsInfinity(cp[6]  )  ?(byte)1:(byte)0;;
+                            cp[7] =  complex.IsInfinity(cp[7]  )  ?(byte)1:(byte)0;;
+                            cp[8] =  complex.IsInfinity(cp[8]  )  ?(byte)1:(byte)0;;
+                            cp[9] =  complex.IsInfinity(cp[9]  )  ?(byte)1:(byte)0;;
+                            cp[10] =  complex.IsInfinity(cp[10]  )  ?(byte)1:(byte)0;;
+                            cp[11] =  complex.IsInfinity(cp[11]  )  ?(byte)1:(byte)0;;
+                            cp[12] =  complex.IsInfinity(cp[12]  )  ?(byte)1:(byte)0;;
+                            cp[13] =  complex.IsInfinity(cp[13]  )  ?(byte)1:(byte)0;;
+                            cp[14] =  complex.IsInfinity(cp[14]  )  ?(byte)1:(byte)0;;
+                            cp[15] =  complex.IsInfinity(cp[15]  )  ?(byte)1:(byte)0;;
+                            cp[16] =  complex.IsInfinity(cp[16]  )  ?(byte)1:(byte)0;;
+                            cp[17] =  complex.IsInfinity(cp[17]  )  ?(byte)1:(byte)0;;
+                            cp[18] =  complex.IsInfinity(cp[18]  )  ?(byte)1:(byte)0;;
+                            cp[19] =  complex.IsInfinity(cp[19]  )  ?(byte)1:(byte)0;;
+                            cp[20] =  complex.IsInfinity(cp[20]  )  ?(byte)1:(byte)0;;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.IsInfinity(*cp  )  ?(byte)1:(byte)0;;
+                            cp++;
+                        }
+                    } else {
+                        complex* ap = ((complex*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  complex.IsInfinity(ap[0]  )  ?(byte)1:(byte)0;;
+                            cp[1] =  complex.IsInfinity(ap[1]  )  ?(byte)1:(byte)0;;
+                            cp[2] =  complex.IsInfinity(ap[2]  )  ?(byte)1:(byte)0;;
+                            cp[3] =  complex.IsInfinity(ap[3]  )  ?(byte)1:(byte)0;;
+                            cp[4] =  complex.IsInfinity(ap[4]  )  ?(byte)1:(byte)0;;
+                            cp[5] =  complex.IsInfinity(ap[5]  )  ?(byte)1:(byte)0;;
+                            cp[6] =  complex.IsInfinity(ap[6]  )  ?(byte)1:(byte)0;;
+                            cp[7] =  complex.IsInfinity(ap[7]  )  ?(byte)1:(byte)0;;
+                            cp[8] =  complex.IsInfinity(ap[8]  )  ?(byte)1:(byte)0;;
+                            cp[9] =  complex.IsInfinity(ap[9]  )  ?(byte)1:(byte)0;;
+                            cp[10] =  complex.IsInfinity(ap[10]  )  ?(byte)1:(byte)0;;
+                            cp[11] =  complex.IsInfinity(ap[11]  )  ?(byte)1:(byte)0;;
+                            cp[12] =  complex.IsInfinity(ap[12]  )  ?(byte)1:(byte)0;;
+                            cp[13] =  complex.IsInfinity(ap[13]  )  ?(byte)1:(byte)0;;
+                            cp[14] =  complex.IsInfinity(ap[14]  )  ?(byte)1:(byte)0;;
+                            cp[15] =  complex.IsInfinity(ap[15]  )  ?(byte)1:(byte)0;;
+                            cp[16] =  complex.IsInfinity(ap[16]  )  ?(byte)1:(byte)0;;
+                            cp[17] =  complex.IsInfinity(ap[17]  )  ?(byte)1:(byte)0;;
+                            cp[18] =  complex.IsInfinity(ap[18]  )  ?(byte)1:(byte)0;;
+                            cp[19] =  complex.IsInfinity(ap[19]  )  ?(byte)1:(byte)0;;
+                            cp[20] =  complex.IsInfinity(ap[20]  )  ?(byte)1:(byte)0;;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.IsInfinity(*ap  )  ?(byte)1:(byte)0;;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( complex* arrAP = arrA)
+                fixed ( byte* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetLogical(retStorage);
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/isnan.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/isnan.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/isnan.cs	(revision 9102)
@@ -0,0 +1,557 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics;
+using ILNumerics.Exceptions;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+
+
+namespace ILNumerics {
+    public partial class ILMath {
+        
+
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>Finds invalid value elements (not-a-number)</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Logical array with 1 if the corresponding elements of input array is invalid ("Not-a-Number"), 0 else.</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetLogical  isnan (ILInArray< double > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetLogical(A.Size); 
+                ILSize inDim = A.Size;
+                double[] arrA = A.GetArrayForRead(); 
+                byte [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (true){
+                    retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<byte> retStorage = new ILDenseStorage<byte>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    byte* cp = ((byte*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  Double.IsNaN(cp[0]  )  ?(byte)1:(byte)0;
+                            cp[1] =  Double.IsNaN(cp[1]  )  ?(byte)1:(byte)0;
+                            cp[2] =  Double.IsNaN(cp[2]  )  ?(byte)1:(byte)0;
+                            cp[3] =  Double.IsNaN(cp[3]  )  ?(byte)1:(byte)0;
+                            cp[4] =  Double.IsNaN(cp[4]  )  ?(byte)1:(byte)0;
+                            cp[5] =  Double.IsNaN(cp[5]  )  ?(byte)1:(byte)0;
+                            cp[6] =  Double.IsNaN(cp[6]  )  ?(byte)1:(byte)0;
+                            cp[7] =  Double.IsNaN(cp[7]  )  ?(byte)1:(byte)0;
+                            cp[8] =  Double.IsNaN(cp[8]  )  ?(byte)1:(byte)0;
+                            cp[9] =  Double.IsNaN(cp[9]  )  ?(byte)1:(byte)0;
+                            cp[10] =  Double.IsNaN(cp[10]  )  ?(byte)1:(byte)0;
+                            cp[11] =  Double.IsNaN(cp[11]  )  ?(byte)1:(byte)0;
+                            cp[12] =  Double.IsNaN(cp[12]  )  ?(byte)1:(byte)0;
+                            cp[13] =  Double.IsNaN(cp[13]  )  ?(byte)1:(byte)0;
+                            cp[14] =  Double.IsNaN(cp[14]  )  ?(byte)1:(byte)0;
+                            cp[15] =  Double.IsNaN(cp[15]  )  ?(byte)1:(byte)0;
+                            cp[16] =  Double.IsNaN(cp[16]  )  ?(byte)1:(byte)0;
+                            cp[17] =  Double.IsNaN(cp[17]  )  ?(byte)1:(byte)0;
+                            cp[18] =  Double.IsNaN(cp[18]  )  ?(byte)1:(byte)0;
+                            cp[19] =  Double.IsNaN(cp[19]  )  ?(byte)1:(byte)0;
+                            cp[20] =  Double.IsNaN(cp[20]  )  ?(byte)1:(byte)0;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Double.IsNaN(*cp  )  ?(byte)1:(byte)0;
+                            cp++;
+                        }
+                    } else {
+                        double* ap = ((double*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  Double.IsNaN(ap[0]  )  ?(byte)1:(byte)0;
+                            cp[1] =  Double.IsNaN(ap[1]  )  ?(byte)1:(byte)0;
+                            cp[2] =  Double.IsNaN(ap[2]  )  ?(byte)1:(byte)0;
+                            cp[3] =  Double.IsNaN(ap[3]  )  ?(byte)1:(byte)0;
+                            cp[4] =  Double.IsNaN(ap[4]  )  ?(byte)1:(byte)0;
+                            cp[5] =  Double.IsNaN(ap[5]  )  ?(byte)1:(byte)0;
+                            cp[6] =  Double.IsNaN(ap[6]  )  ?(byte)1:(byte)0;
+                            cp[7] =  Double.IsNaN(ap[7]  )  ?(byte)1:(byte)0;
+                            cp[8] =  Double.IsNaN(ap[8]  )  ?(byte)1:(byte)0;
+                            cp[9] =  Double.IsNaN(ap[9]  )  ?(byte)1:(byte)0;
+                            cp[10] =  Double.IsNaN(ap[10]  )  ?(byte)1:(byte)0;
+                            cp[11] =  Double.IsNaN(ap[11]  )  ?(byte)1:(byte)0;
+                            cp[12] =  Double.IsNaN(ap[12]  )  ?(byte)1:(byte)0;
+                            cp[13] =  Double.IsNaN(ap[13]  )  ?(byte)1:(byte)0;
+                            cp[14] =  Double.IsNaN(ap[14]  )  ?(byte)1:(byte)0;
+                            cp[15] =  Double.IsNaN(ap[15]  )  ?(byte)1:(byte)0;
+                            cp[16] =  Double.IsNaN(ap[16]  )  ?(byte)1:(byte)0;
+                            cp[17] =  Double.IsNaN(ap[17]  )  ?(byte)1:(byte)0;
+                            cp[18] =  Double.IsNaN(ap[18]  )  ?(byte)1:(byte)0;
+                            cp[19] =  Double.IsNaN(ap[19]  )  ?(byte)1:(byte)0;
+                            cp[20] =  Double.IsNaN(ap[20]  )  ?(byte)1:(byte)0;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Double.IsNaN(*ap  )  ?(byte)1:(byte)0;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( double* arrAP = arrA)
+                fixed ( byte* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetLogical(retStorage);
+            }
+        }
+        /// <summary>Finds invalid value elements (not-a-number)</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Logical array with 1 if the corresponding elements of input array is invalid ("Not-a-Number"), 0 else.</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetLogical  isnan (ILInArray< float > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetLogical(A.Size); 
+                ILSize inDim = A.Size;
+                float[] arrA = A.GetArrayForRead(); 
+                byte [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (true){
+                    retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<byte> retStorage = new ILDenseStorage<byte>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    byte* cp = ((byte*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  Single.IsNaN(cp[0]  )  ?(byte)1:(byte)0;
+                            cp[1] =  Single.IsNaN(cp[1]  )  ?(byte)1:(byte)0;
+                            cp[2] =  Single.IsNaN(cp[2]  )  ?(byte)1:(byte)0;
+                            cp[3] =  Single.IsNaN(cp[3]  )  ?(byte)1:(byte)0;
+                            cp[4] =  Single.IsNaN(cp[4]  )  ?(byte)1:(byte)0;
+                            cp[5] =  Single.IsNaN(cp[5]  )  ?(byte)1:(byte)0;
+                            cp[6] =  Single.IsNaN(cp[6]  )  ?(byte)1:(byte)0;
+                            cp[7] =  Single.IsNaN(cp[7]  )  ?(byte)1:(byte)0;
+                            cp[8] =  Single.IsNaN(cp[8]  )  ?(byte)1:(byte)0;
+                            cp[9] =  Single.IsNaN(cp[9]  )  ?(byte)1:(byte)0;
+                            cp[10] =  Single.IsNaN(cp[10]  )  ?(byte)1:(byte)0;
+                            cp[11] =  Single.IsNaN(cp[11]  )  ?(byte)1:(byte)0;
+                            cp[12] =  Single.IsNaN(cp[12]  )  ?(byte)1:(byte)0;
+                            cp[13] =  Single.IsNaN(cp[13]  )  ?(byte)1:(byte)0;
+                            cp[14] =  Single.IsNaN(cp[14]  )  ?(byte)1:(byte)0;
+                            cp[15] =  Single.IsNaN(cp[15]  )  ?(byte)1:(byte)0;
+                            cp[16] =  Single.IsNaN(cp[16]  )  ?(byte)1:(byte)0;
+                            cp[17] =  Single.IsNaN(cp[17]  )  ?(byte)1:(byte)0;
+                            cp[18] =  Single.IsNaN(cp[18]  )  ?(byte)1:(byte)0;
+                            cp[19] =  Single.IsNaN(cp[19]  )  ?(byte)1:(byte)0;
+                            cp[20] =  Single.IsNaN(cp[20]  )  ?(byte)1:(byte)0;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Single.IsNaN(*cp  )  ?(byte)1:(byte)0;
+                            cp++;
+                        }
+                    } else {
+                        float* ap = ((float*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  Single.IsNaN(ap[0]  )  ?(byte)1:(byte)0;
+                            cp[1] =  Single.IsNaN(ap[1]  )  ?(byte)1:(byte)0;
+                            cp[2] =  Single.IsNaN(ap[2]  )  ?(byte)1:(byte)0;
+                            cp[3] =  Single.IsNaN(ap[3]  )  ?(byte)1:(byte)0;
+                            cp[4] =  Single.IsNaN(ap[4]  )  ?(byte)1:(byte)0;
+                            cp[5] =  Single.IsNaN(ap[5]  )  ?(byte)1:(byte)0;
+                            cp[6] =  Single.IsNaN(ap[6]  )  ?(byte)1:(byte)0;
+                            cp[7] =  Single.IsNaN(ap[7]  )  ?(byte)1:(byte)0;
+                            cp[8] =  Single.IsNaN(ap[8]  )  ?(byte)1:(byte)0;
+                            cp[9] =  Single.IsNaN(ap[9]  )  ?(byte)1:(byte)0;
+                            cp[10] =  Single.IsNaN(ap[10]  )  ?(byte)1:(byte)0;
+                            cp[11] =  Single.IsNaN(ap[11]  )  ?(byte)1:(byte)0;
+                            cp[12] =  Single.IsNaN(ap[12]  )  ?(byte)1:(byte)0;
+                            cp[13] =  Single.IsNaN(ap[13]  )  ?(byte)1:(byte)0;
+                            cp[14] =  Single.IsNaN(ap[14]  )  ?(byte)1:(byte)0;
+                            cp[15] =  Single.IsNaN(ap[15]  )  ?(byte)1:(byte)0;
+                            cp[16] =  Single.IsNaN(ap[16]  )  ?(byte)1:(byte)0;
+                            cp[17] =  Single.IsNaN(ap[17]  )  ?(byte)1:(byte)0;
+                            cp[18] =  Single.IsNaN(ap[18]  )  ?(byte)1:(byte)0;
+                            cp[19] =  Single.IsNaN(ap[19]  )  ?(byte)1:(byte)0;
+                            cp[20] =  Single.IsNaN(ap[20]  )  ?(byte)1:(byte)0;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Single.IsNaN(*ap  )  ?(byte)1:(byte)0;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( float* arrAP = arrA)
+                fixed ( byte* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetLogical(retStorage);
+            }
+        }
+        /// <summary>Finds invalid value elements (not-a-number)</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Logical array with 1 if the corresponding elements of input array is invalid ("Not-a-Number"), 0 else.</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetLogical  isnan (ILInArray< fcomplex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetLogical(A.Size); 
+                ILSize inDim = A.Size;
+                fcomplex[] arrA = A.GetArrayForRead(); 
+                byte [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (true){
+                    retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<byte> retStorage = new ILDenseStorage<byte>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    byte* cp = ((byte*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  fcomplex.IsNaN(cp[0]  )  ?(byte)1:(byte)0;
+                            cp[1] =  fcomplex.IsNaN(cp[1]  )  ?(byte)1:(byte)0;
+                            cp[2] =  fcomplex.IsNaN(cp[2]  )  ?(byte)1:(byte)0;
+                            cp[3] =  fcomplex.IsNaN(cp[3]  )  ?(byte)1:(byte)0;
+                            cp[4] =  fcomplex.IsNaN(cp[4]  )  ?(byte)1:(byte)0;
+                            cp[5] =  fcomplex.IsNaN(cp[5]  )  ?(byte)1:(byte)0;
+                            cp[6] =  fcomplex.IsNaN(cp[6]  )  ?(byte)1:(byte)0;
+                            cp[7] =  fcomplex.IsNaN(cp[7]  )  ?(byte)1:(byte)0;
+                            cp[8] =  fcomplex.IsNaN(cp[8]  )  ?(byte)1:(byte)0;
+                            cp[9] =  fcomplex.IsNaN(cp[9]  )  ?(byte)1:(byte)0;
+                            cp[10] =  fcomplex.IsNaN(cp[10]  )  ?(byte)1:(byte)0;
+                            cp[11] =  fcomplex.IsNaN(cp[11]  )  ?(byte)1:(byte)0;
+                            cp[12] =  fcomplex.IsNaN(cp[12]  )  ?(byte)1:(byte)0;
+                            cp[13] =  fcomplex.IsNaN(cp[13]  )  ?(byte)1:(byte)0;
+                            cp[14] =  fcomplex.IsNaN(cp[14]  )  ?(byte)1:(byte)0;
+                            cp[15] =  fcomplex.IsNaN(cp[15]  )  ?(byte)1:(byte)0;
+                            cp[16] =  fcomplex.IsNaN(cp[16]  )  ?(byte)1:(byte)0;
+                            cp[17] =  fcomplex.IsNaN(cp[17]  )  ?(byte)1:(byte)0;
+                            cp[18] =  fcomplex.IsNaN(cp[18]  )  ?(byte)1:(byte)0;
+                            cp[19] =  fcomplex.IsNaN(cp[19]  )  ?(byte)1:(byte)0;
+                            cp[20] =  fcomplex.IsNaN(cp[20]  )  ?(byte)1:(byte)0;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.IsNaN(*cp  )  ?(byte)1:(byte)0;
+                            cp++;
+                        }
+                    } else {
+                        fcomplex* ap = ((fcomplex*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  fcomplex.IsNaN(ap[0]  )  ?(byte)1:(byte)0;
+                            cp[1] =  fcomplex.IsNaN(ap[1]  )  ?(byte)1:(byte)0;
+                            cp[2] =  fcomplex.IsNaN(ap[2]  )  ?(byte)1:(byte)0;
+                            cp[3] =  fcomplex.IsNaN(ap[3]  )  ?(byte)1:(byte)0;
+                            cp[4] =  fcomplex.IsNaN(ap[4]  )  ?(byte)1:(byte)0;
+                            cp[5] =  fcomplex.IsNaN(ap[5]  )  ?(byte)1:(byte)0;
+                            cp[6] =  fcomplex.IsNaN(ap[6]  )  ?(byte)1:(byte)0;
+                            cp[7] =  fcomplex.IsNaN(ap[7]  )  ?(byte)1:(byte)0;
+                            cp[8] =  fcomplex.IsNaN(ap[8]  )  ?(byte)1:(byte)0;
+                            cp[9] =  fcomplex.IsNaN(ap[9]  )  ?(byte)1:(byte)0;
+                            cp[10] =  fcomplex.IsNaN(ap[10]  )  ?(byte)1:(byte)0;
+                            cp[11] =  fcomplex.IsNaN(ap[11]  )  ?(byte)1:(byte)0;
+                            cp[12] =  fcomplex.IsNaN(ap[12]  )  ?(byte)1:(byte)0;
+                            cp[13] =  fcomplex.IsNaN(ap[13]  )  ?(byte)1:(byte)0;
+                            cp[14] =  fcomplex.IsNaN(ap[14]  )  ?(byte)1:(byte)0;
+                            cp[15] =  fcomplex.IsNaN(ap[15]  )  ?(byte)1:(byte)0;
+                            cp[16] =  fcomplex.IsNaN(ap[16]  )  ?(byte)1:(byte)0;
+                            cp[17] =  fcomplex.IsNaN(ap[17]  )  ?(byte)1:(byte)0;
+                            cp[18] =  fcomplex.IsNaN(ap[18]  )  ?(byte)1:(byte)0;
+                            cp[19] =  fcomplex.IsNaN(ap[19]  )  ?(byte)1:(byte)0;
+                            cp[20] =  fcomplex.IsNaN(ap[20]  )  ?(byte)1:(byte)0;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.IsNaN(*ap  )  ?(byte)1:(byte)0;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( fcomplex* arrAP = arrA)
+                fixed ( byte* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetLogical(retStorage);
+            }
+        }
+        /// <summary>Finds invalid value elements (not-a-number)</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Logical array with 1 if the corresponding elements of input array is invalid ("Not-a-Number"), 0 else.</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetLogical  isnan (ILInArray< complex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetLogical(A.Size); 
+                ILSize inDim = A.Size;
+                complex[] arrA = A.GetArrayForRead(); 
+                byte [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (true){
+                    retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<byte> retStorage = new ILDenseStorage<byte>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    byte* cp = ((byte*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  complex.IsNaN(cp[0]  )  ?(byte)1:(byte)0;
+                            cp[1] =  complex.IsNaN(cp[1]  )  ?(byte)1:(byte)0;
+                            cp[2] =  complex.IsNaN(cp[2]  )  ?(byte)1:(byte)0;
+                            cp[3] =  complex.IsNaN(cp[3]  )  ?(byte)1:(byte)0;
+                            cp[4] =  complex.IsNaN(cp[4]  )  ?(byte)1:(byte)0;
+                            cp[5] =  complex.IsNaN(cp[5]  )  ?(byte)1:(byte)0;
+                            cp[6] =  complex.IsNaN(cp[6]  )  ?(byte)1:(byte)0;
+                            cp[7] =  complex.IsNaN(cp[7]  )  ?(byte)1:(byte)0;
+                            cp[8] =  complex.IsNaN(cp[8]  )  ?(byte)1:(byte)0;
+                            cp[9] =  complex.IsNaN(cp[9]  )  ?(byte)1:(byte)0;
+                            cp[10] =  complex.IsNaN(cp[10]  )  ?(byte)1:(byte)0;
+                            cp[11] =  complex.IsNaN(cp[11]  )  ?(byte)1:(byte)0;
+                            cp[12] =  complex.IsNaN(cp[12]  )  ?(byte)1:(byte)0;
+                            cp[13] =  complex.IsNaN(cp[13]  )  ?(byte)1:(byte)0;
+                            cp[14] =  complex.IsNaN(cp[14]  )  ?(byte)1:(byte)0;
+                            cp[15] =  complex.IsNaN(cp[15]  )  ?(byte)1:(byte)0;
+                            cp[16] =  complex.IsNaN(cp[16]  )  ?(byte)1:(byte)0;
+                            cp[17] =  complex.IsNaN(cp[17]  )  ?(byte)1:(byte)0;
+                            cp[18] =  complex.IsNaN(cp[18]  )  ?(byte)1:(byte)0;
+                            cp[19] =  complex.IsNaN(cp[19]  )  ?(byte)1:(byte)0;
+                            cp[20] =  complex.IsNaN(cp[20]  )  ?(byte)1:(byte)0;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.IsNaN(*cp  )  ?(byte)1:(byte)0;
+                            cp++;
+                        }
+                    } else {
+                        complex* ap = ((complex*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  complex.IsNaN(ap[0]  )  ?(byte)1:(byte)0;
+                            cp[1] =  complex.IsNaN(ap[1]  )  ?(byte)1:(byte)0;
+                            cp[2] =  complex.IsNaN(ap[2]  )  ?(byte)1:(byte)0;
+                            cp[3] =  complex.IsNaN(ap[3]  )  ?(byte)1:(byte)0;
+                            cp[4] =  complex.IsNaN(ap[4]  )  ?(byte)1:(byte)0;
+                            cp[5] =  complex.IsNaN(ap[5]  )  ?(byte)1:(byte)0;
+                            cp[6] =  complex.IsNaN(ap[6]  )  ?(byte)1:(byte)0;
+                            cp[7] =  complex.IsNaN(ap[7]  )  ?(byte)1:(byte)0;
+                            cp[8] =  complex.IsNaN(ap[8]  )  ?(byte)1:(byte)0;
+                            cp[9] =  complex.IsNaN(ap[9]  )  ?(byte)1:(byte)0;
+                            cp[10] =  complex.IsNaN(ap[10]  )  ?(byte)1:(byte)0;
+                            cp[11] =  complex.IsNaN(ap[11]  )  ?(byte)1:(byte)0;
+                            cp[12] =  complex.IsNaN(ap[12]  )  ?(byte)1:(byte)0;
+                            cp[13] =  complex.IsNaN(ap[13]  )  ?(byte)1:(byte)0;
+                            cp[14] =  complex.IsNaN(ap[14]  )  ?(byte)1:(byte)0;
+                            cp[15] =  complex.IsNaN(ap[15]  )  ?(byte)1:(byte)0;
+                            cp[16] =  complex.IsNaN(ap[16]  )  ?(byte)1:(byte)0;
+                            cp[17] =  complex.IsNaN(ap[17]  )  ?(byte)1:(byte)0;
+                            cp[18] =  complex.IsNaN(ap[18]  )  ?(byte)1:(byte)0;
+                            cp[19] =  complex.IsNaN(ap[19]  )  ?(byte)1:(byte)0;
+                            cp[20] =  complex.IsNaN(ap[20]  )  ?(byte)1:(byte)0;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.IsNaN(*ap  )  ?(byte)1:(byte)0;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( complex* arrAP = arrA)
+                fixed ( byte* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetLogical(retStorage);
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/isneginf.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/isneginf.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/isneginf.cs	(revision 9102)
@@ -0,0 +1,559 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics;
+using ILNumerics.Exceptions;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+
+
+
+namespace ILNumerics {
+
+    public partial class ILMath {
+        
+
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>Finds negative infinite value elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Logical array with 1 if the corresponding elements of input array is negative infinite, 0 else.</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetLogical  isneginf (ILInArray< double > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetLogical(A.Size); 
+                ILSize inDim = A.Size;
+                double[] arrA = A.GetArrayForRead(); 
+                byte [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (true) {
+                    retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<byte> retStorage = new ILDenseStorage<byte>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    byte* cp = ((byte*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  Double.IsNegativeInfinity(cp[0]  )  ?(byte)1:(byte)0;;
+                            cp[1] =  Double.IsNegativeInfinity(cp[1]  )  ?(byte)1:(byte)0;;
+                            cp[2] =  Double.IsNegativeInfinity(cp[2]  )  ?(byte)1:(byte)0;;
+                            cp[3] =  Double.IsNegativeInfinity(cp[3]  )  ?(byte)1:(byte)0;;
+                            cp[4] =  Double.IsNegativeInfinity(cp[4]  )  ?(byte)1:(byte)0;;
+                            cp[5] =  Double.IsNegativeInfinity(cp[5]  )  ?(byte)1:(byte)0;;
+                            cp[6] =  Double.IsNegativeInfinity(cp[6]  )  ?(byte)1:(byte)0;;
+                            cp[7] =  Double.IsNegativeInfinity(cp[7]  )  ?(byte)1:(byte)0;;
+                            cp[8] =  Double.IsNegativeInfinity(cp[8]  )  ?(byte)1:(byte)0;;
+                            cp[9] =  Double.IsNegativeInfinity(cp[9]  )  ?(byte)1:(byte)0;;
+                            cp[10] =  Double.IsNegativeInfinity(cp[10]  )  ?(byte)1:(byte)0;;
+                            cp[11] =  Double.IsNegativeInfinity(cp[11]  )  ?(byte)1:(byte)0;;
+                            cp[12] =  Double.IsNegativeInfinity(cp[12]  )  ?(byte)1:(byte)0;;
+                            cp[13] =  Double.IsNegativeInfinity(cp[13]  )  ?(byte)1:(byte)0;;
+                            cp[14] =  Double.IsNegativeInfinity(cp[14]  )  ?(byte)1:(byte)0;;
+                            cp[15] =  Double.IsNegativeInfinity(cp[15]  )  ?(byte)1:(byte)0;;
+                            cp[16] =  Double.IsNegativeInfinity(cp[16]  )  ?(byte)1:(byte)0;;
+                            cp[17] =  Double.IsNegativeInfinity(cp[17]  )  ?(byte)1:(byte)0;;
+                            cp[18] =  Double.IsNegativeInfinity(cp[18]  )  ?(byte)1:(byte)0;;
+                            cp[19] =  Double.IsNegativeInfinity(cp[19]  )  ?(byte)1:(byte)0;;
+                            cp[20] =  Double.IsNegativeInfinity(cp[20]  )  ?(byte)1:(byte)0;;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Double.IsNegativeInfinity(*cp  )  ?(byte)1:(byte)0;;
+                            cp++;
+                        }
+                    } else {
+                        double* ap = ((double*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  Double.IsNegativeInfinity(ap[0]  )  ?(byte)1:(byte)0;;
+                            cp[1] =  Double.IsNegativeInfinity(ap[1]  )  ?(byte)1:(byte)0;;
+                            cp[2] =  Double.IsNegativeInfinity(ap[2]  )  ?(byte)1:(byte)0;;
+                            cp[3] =  Double.IsNegativeInfinity(ap[3]  )  ?(byte)1:(byte)0;;
+                            cp[4] =  Double.IsNegativeInfinity(ap[4]  )  ?(byte)1:(byte)0;;
+                            cp[5] =  Double.IsNegativeInfinity(ap[5]  )  ?(byte)1:(byte)0;;
+                            cp[6] =  Double.IsNegativeInfinity(ap[6]  )  ?(byte)1:(byte)0;;
+                            cp[7] =  Double.IsNegativeInfinity(ap[7]  )  ?(byte)1:(byte)0;;
+                            cp[8] =  Double.IsNegativeInfinity(ap[8]  )  ?(byte)1:(byte)0;;
+                            cp[9] =  Double.IsNegativeInfinity(ap[9]  )  ?(byte)1:(byte)0;;
+                            cp[10] =  Double.IsNegativeInfinity(ap[10]  )  ?(byte)1:(byte)0;;
+                            cp[11] =  Double.IsNegativeInfinity(ap[11]  )  ?(byte)1:(byte)0;;
+                            cp[12] =  Double.IsNegativeInfinity(ap[12]  )  ?(byte)1:(byte)0;;
+                            cp[13] =  Double.IsNegativeInfinity(ap[13]  )  ?(byte)1:(byte)0;;
+                            cp[14] =  Double.IsNegativeInfinity(ap[14]  )  ?(byte)1:(byte)0;;
+                            cp[15] =  Double.IsNegativeInfinity(ap[15]  )  ?(byte)1:(byte)0;;
+                            cp[16] =  Double.IsNegativeInfinity(ap[16]  )  ?(byte)1:(byte)0;;
+                            cp[17] =  Double.IsNegativeInfinity(ap[17]  )  ?(byte)1:(byte)0;;
+                            cp[18] =  Double.IsNegativeInfinity(ap[18]  )  ?(byte)1:(byte)0;;
+                            cp[19] =  Double.IsNegativeInfinity(ap[19]  )  ?(byte)1:(byte)0;;
+                            cp[20] =  Double.IsNegativeInfinity(ap[20]  )  ?(byte)1:(byte)0;;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Double.IsNegativeInfinity(*ap  )  ?(byte)1:(byte)0;;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( double* arrAP = arrA)
+                fixed ( byte* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetLogical(retStorage);
+            }
+        }
+        /// <summary>Finds negative infinite value elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Logical array with 1 if the corresponding elements of input array is negative infinite, 0 else.</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetLogical  isneginf (ILInArray< float > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetLogical(A.Size); 
+                ILSize inDim = A.Size;
+                float[] arrA = A.GetArrayForRead(); 
+                byte [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (true) {
+                    retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<byte> retStorage = new ILDenseStorage<byte>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    byte* cp = ((byte*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  Single.IsNegativeInfinity(cp[0]  )  ?(byte)1:(byte)0;;
+                            cp[1] =  Single.IsNegativeInfinity(cp[1]  )  ?(byte)1:(byte)0;;
+                            cp[2] =  Single.IsNegativeInfinity(cp[2]  )  ?(byte)1:(byte)0;;
+                            cp[3] =  Single.IsNegativeInfinity(cp[3]  )  ?(byte)1:(byte)0;;
+                            cp[4] =  Single.IsNegativeInfinity(cp[4]  )  ?(byte)1:(byte)0;;
+                            cp[5] =  Single.IsNegativeInfinity(cp[5]  )  ?(byte)1:(byte)0;;
+                            cp[6] =  Single.IsNegativeInfinity(cp[6]  )  ?(byte)1:(byte)0;;
+                            cp[7] =  Single.IsNegativeInfinity(cp[7]  )  ?(byte)1:(byte)0;;
+                            cp[8] =  Single.IsNegativeInfinity(cp[8]  )  ?(byte)1:(byte)0;;
+                            cp[9] =  Single.IsNegativeInfinity(cp[9]  )  ?(byte)1:(byte)0;;
+                            cp[10] =  Single.IsNegativeInfinity(cp[10]  )  ?(byte)1:(byte)0;;
+                            cp[11] =  Single.IsNegativeInfinity(cp[11]  )  ?(byte)1:(byte)0;;
+                            cp[12] =  Single.IsNegativeInfinity(cp[12]  )  ?(byte)1:(byte)0;;
+                            cp[13] =  Single.IsNegativeInfinity(cp[13]  )  ?(byte)1:(byte)0;;
+                            cp[14] =  Single.IsNegativeInfinity(cp[14]  )  ?(byte)1:(byte)0;;
+                            cp[15] =  Single.IsNegativeInfinity(cp[15]  )  ?(byte)1:(byte)0;;
+                            cp[16] =  Single.IsNegativeInfinity(cp[16]  )  ?(byte)1:(byte)0;;
+                            cp[17] =  Single.IsNegativeInfinity(cp[17]  )  ?(byte)1:(byte)0;;
+                            cp[18] =  Single.IsNegativeInfinity(cp[18]  )  ?(byte)1:(byte)0;;
+                            cp[19] =  Single.IsNegativeInfinity(cp[19]  )  ?(byte)1:(byte)0;;
+                            cp[20] =  Single.IsNegativeInfinity(cp[20]  )  ?(byte)1:(byte)0;;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Single.IsNegativeInfinity(*cp  )  ?(byte)1:(byte)0;;
+                            cp++;
+                        }
+                    } else {
+                        float* ap = ((float*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  Single.IsNegativeInfinity(ap[0]  )  ?(byte)1:(byte)0;;
+                            cp[1] =  Single.IsNegativeInfinity(ap[1]  )  ?(byte)1:(byte)0;;
+                            cp[2] =  Single.IsNegativeInfinity(ap[2]  )  ?(byte)1:(byte)0;;
+                            cp[3] =  Single.IsNegativeInfinity(ap[3]  )  ?(byte)1:(byte)0;;
+                            cp[4] =  Single.IsNegativeInfinity(ap[4]  )  ?(byte)1:(byte)0;;
+                            cp[5] =  Single.IsNegativeInfinity(ap[5]  )  ?(byte)1:(byte)0;;
+                            cp[6] =  Single.IsNegativeInfinity(ap[6]  )  ?(byte)1:(byte)0;;
+                            cp[7] =  Single.IsNegativeInfinity(ap[7]  )  ?(byte)1:(byte)0;;
+                            cp[8] =  Single.IsNegativeInfinity(ap[8]  )  ?(byte)1:(byte)0;;
+                            cp[9] =  Single.IsNegativeInfinity(ap[9]  )  ?(byte)1:(byte)0;;
+                            cp[10] =  Single.IsNegativeInfinity(ap[10]  )  ?(byte)1:(byte)0;;
+                            cp[11] =  Single.IsNegativeInfinity(ap[11]  )  ?(byte)1:(byte)0;;
+                            cp[12] =  Single.IsNegativeInfinity(ap[12]  )  ?(byte)1:(byte)0;;
+                            cp[13] =  Single.IsNegativeInfinity(ap[13]  )  ?(byte)1:(byte)0;;
+                            cp[14] =  Single.IsNegativeInfinity(ap[14]  )  ?(byte)1:(byte)0;;
+                            cp[15] =  Single.IsNegativeInfinity(ap[15]  )  ?(byte)1:(byte)0;;
+                            cp[16] =  Single.IsNegativeInfinity(ap[16]  )  ?(byte)1:(byte)0;;
+                            cp[17] =  Single.IsNegativeInfinity(ap[17]  )  ?(byte)1:(byte)0;;
+                            cp[18] =  Single.IsNegativeInfinity(ap[18]  )  ?(byte)1:(byte)0;;
+                            cp[19] =  Single.IsNegativeInfinity(ap[19]  )  ?(byte)1:(byte)0;;
+                            cp[20] =  Single.IsNegativeInfinity(ap[20]  )  ?(byte)1:(byte)0;;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Single.IsNegativeInfinity(*ap  )  ?(byte)1:(byte)0;;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( float* arrAP = arrA)
+                fixed ( byte* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetLogical(retStorage);
+            }
+        }
+        /// <summary>Finds negative infinite value elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Logical array with 1 if the corresponding elements of input array is negative infinite, 0 else.</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetLogical  isneginf (ILInArray< fcomplex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetLogical(A.Size); 
+                ILSize inDim = A.Size;
+                fcomplex[] arrA = A.GetArrayForRead(); 
+                byte [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (true) {
+                    retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<byte> retStorage = new ILDenseStorage<byte>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    byte* cp = ((byte*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  fcomplex.IsNegativeInfinity(cp[0]  )  ?(byte)1:(byte)0;;
+                            cp[1] =  fcomplex.IsNegativeInfinity(cp[1]  )  ?(byte)1:(byte)0;;
+                            cp[2] =  fcomplex.IsNegativeInfinity(cp[2]  )  ?(byte)1:(byte)0;;
+                            cp[3] =  fcomplex.IsNegativeInfinity(cp[3]  )  ?(byte)1:(byte)0;;
+                            cp[4] =  fcomplex.IsNegativeInfinity(cp[4]  )  ?(byte)1:(byte)0;;
+                            cp[5] =  fcomplex.IsNegativeInfinity(cp[5]  )  ?(byte)1:(byte)0;;
+                            cp[6] =  fcomplex.IsNegativeInfinity(cp[6]  )  ?(byte)1:(byte)0;;
+                            cp[7] =  fcomplex.IsNegativeInfinity(cp[7]  )  ?(byte)1:(byte)0;;
+                            cp[8] =  fcomplex.IsNegativeInfinity(cp[8]  )  ?(byte)1:(byte)0;;
+                            cp[9] =  fcomplex.IsNegativeInfinity(cp[9]  )  ?(byte)1:(byte)0;;
+                            cp[10] =  fcomplex.IsNegativeInfinity(cp[10]  )  ?(byte)1:(byte)0;;
+                            cp[11] =  fcomplex.IsNegativeInfinity(cp[11]  )  ?(byte)1:(byte)0;;
+                            cp[12] =  fcomplex.IsNegativeInfinity(cp[12]  )  ?(byte)1:(byte)0;;
+                            cp[13] =  fcomplex.IsNegativeInfinity(cp[13]  )  ?(byte)1:(byte)0;;
+                            cp[14] =  fcomplex.IsNegativeInfinity(cp[14]  )  ?(byte)1:(byte)0;;
+                            cp[15] =  fcomplex.IsNegativeInfinity(cp[15]  )  ?(byte)1:(byte)0;;
+                            cp[16] =  fcomplex.IsNegativeInfinity(cp[16]  )  ?(byte)1:(byte)0;;
+                            cp[17] =  fcomplex.IsNegativeInfinity(cp[17]  )  ?(byte)1:(byte)0;;
+                            cp[18] =  fcomplex.IsNegativeInfinity(cp[18]  )  ?(byte)1:(byte)0;;
+                            cp[19] =  fcomplex.IsNegativeInfinity(cp[19]  )  ?(byte)1:(byte)0;;
+                            cp[20] =  fcomplex.IsNegativeInfinity(cp[20]  )  ?(byte)1:(byte)0;;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.IsNegativeInfinity(*cp  )  ?(byte)1:(byte)0;;
+                            cp++;
+                        }
+                    } else {
+                        fcomplex* ap = ((fcomplex*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  fcomplex.IsNegativeInfinity(ap[0]  )  ?(byte)1:(byte)0;;
+                            cp[1] =  fcomplex.IsNegativeInfinity(ap[1]  )  ?(byte)1:(byte)0;;
+                            cp[2] =  fcomplex.IsNegativeInfinity(ap[2]  )  ?(byte)1:(byte)0;;
+                            cp[3] =  fcomplex.IsNegativeInfinity(ap[3]  )  ?(byte)1:(byte)0;;
+                            cp[4] =  fcomplex.IsNegativeInfinity(ap[4]  )  ?(byte)1:(byte)0;;
+                            cp[5] =  fcomplex.IsNegativeInfinity(ap[5]  )  ?(byte)1:(byte)0;;
+                            cp[6] =  fcomplex.IsNegativeInfinity(ap[6]  )  ?(byte)1:(byte)0;;
+                            cp[7] =  fcomplex.IsNegativeInfinity(ap[7]  )  ?(byte)1:(byte)0;;
+                            cp[8] =  fcomplex.IsNegativeInfinity(ap[8]  )  ?(byte)1:(byte)0;;
+                            cp[9] =  fcomplex.IsNegativeInfinity(ap[9]  )  ?(byte)1:(byte)0;;
+                            cp[10] =  fcomplex.IsNegativeInfinity(ap[10]  )  ?(byte)1:(byte)0;;
+                            cp[11] =  fcomplex.IsNegativeInfinity(ap[11]  )  ?(byte)1:(byte)0;;
+                            cp[12] =  fcomplex.IsNegativeInfinity(ap[12]  )  ?(byte)1:(byte)0;;
+                            cp[13] =  fcomplex.IsNegativeInfinity(ap[13]  )  ?(byte)1:(byte)0;;
+                            cp[14] =  fcomplex.IsNegativeInfinity(ap[14]  )  ?(byte)1:(byte)0;;
+                            cp[15] =  fcomplex.IsNegativeInfinity(ap[15]  )  ?(byte)1:(byte)0;;
+                            cp[16] =  fcomplex.IsNegativeInfinity(ap[16]  )  ?(byte)1:(byte)0;;
+                            cp[17] =  fcomplex.IsNegativeInfinity(ap[17]  )  ?(byte)1:(byte)0;;
+                            cp[18] =  fcomplex.IsNegativeInfinity(ap[18]  )  ?(byte)1:(byte)0;;
+                            cp[19] =  fcomplex.IsNegativeInfinity(ap[19]  )  ?(byte)1:(byte)0;;
+                            cp[20] =  fcomplex.IsNegativeInfinity(ap[20]  )  ?(byte)1:(byte)0;;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.IsNegativeInfinity(*ap  )  ?(byte)1:(byte)0;;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( fcomplex* arrAP = arrA)
+                fixed ( byte* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetLogical(retStorage);
+            }
+        }
+        /// <summary>Finds negative infinite value elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Logical array with 1 if the corresponding elements of input array is negative infinite, 0 else.</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetLogical  isneginf (ILInArray< complex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetLogical(A.Size); 
+                ILSize inDim = A.Size;
+                complex[] arrA = A.GetArrayForRead(); 
+                byte [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (true) {
+                    retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<byte> retStorage = new ILDenseStorage<byte>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    byte* cp = ((byte*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  complex.IsNegativeInfinity(cp[0]  )  ?(byte)1:(byte)0;;
+                            cp[1] =  complex.IsNegativeInfinity(cp[1]  )  ?(byte)1:(byte)0;;
+                            cp[2] =  complex.IsNegativeInfinity(cp[2]  )  ?(byte)1:(byte)0;;
+                            cp[3] =  complex.IsNegativeInfinity(cp[3]  )  ?(byte)1:(byte)0;;
+                            cp[4] =  complex.IsNegativeInfinity(cp[4]  )  ?(byte)1:(byte)0;;
+                            cp[5] =  complex.IsNegativeInfinity(cp[5]  )  ?(byte)1:(byte)0;;
+                            cp[6] =  complex.IsNegativeInfinity(cp[6]  )  ?(byte)1:(byte)0;;
+                            cp[7] =  complex.IsNegativeInfinity(cp[7]  )  ?(byte)1:(byte)0;;
+                            cp[8] =  complex.IsNegativeInfinity(cp[8]  )  ?(byte)1:(byte)0;;
+                            cp[9] =  complex.IsNegativeInfinity(cp[9]  )  ?(byte)1:(byte)0;;
+                            cp[10] =  complex.IsNegativeInfinity(cp[10]  )  ?(byte)1:(byte)0;;
+                            cp[11] =  complex.IsNegativeInfinity(cp[11]  )  ?(byte)1:(byte)0;;
+                            cp[12] =  complex.IsNegativeInfinity(cp[12]  )  ?(byte)1:(byte)0;;
+                            cp[13] =  complex.IsNegativeInfinity(cp[13]  )  ?(byte)1:(byte)0;;
+                            cp[14] =  complex.IsNegativeInfinity(cp[14]  )  ?(byte)1:(byte)0;;
+                            cp[15] =  complex.IsNegativeInfinity(cp[15]  )  ?(byte)1:(byte)0;;
+                            cp[16] =  complex.IsNegativeInfinity(cp[16]  )  ?(byte)1:(byte)0;;
+                            cp[17] =  complex.IsNegativeInfinity(cp[17]  )  ?(byte)1:(byte)0;;
+                            cp[18] =  complex.IsNegativeInfinity(cp[18]  )  ?(byte)1:(byte)0;;
+                            cp[19] =  complex.IsNegativeInfinity(cp[19]  )  ?(byte)1:(byte)0;;
+                            cp[20] =  complex.IsNegativeInfinity(cp[20]  )  ?(byte)1:(byte)0;;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.IsNegativeInfinity(*cp  )  ?(byte)1:(byte)0;;
+                            cp++;
+                        }
+                    } else {
+                        complex* ap = ((complex*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  complex.IsNegativeInfinity(ap[0]  )  ?(byte)1:(byte)0;;
+                            cp[1] =  complex.IsNegativeInfinity(ap[1]  )  ?(byte)1:(byte)0;;
+                            cp[2] =  complex.IsNegativeInfinity(ap[2]  )  ?(byte)1:(byte)0;;
+                            cp[3] =  complex.IsNegativeInfinity(ap[3]  )  ?(byte)1:(byte)0;;
+                            cp[4] =  complex.IsNegativeInfinity(ap[4]  )  ?(byte)1:(byte)0;;
+                            cp[5] =  complex.IsNegativeInfinity(ap[5]  )  ?(byte)1:(byte)0;;
+                            cp[6] =  complex.IsNegativeInfinity(ap[6]  )  ?(byte)1:(byte)0;;
+                            cp[7] =  complex.IsNegativeInfinity(ap[7]  )  ?(byte)1:(byte)0;;
+                            cp[8] =  complex.IsNegativeInfinity(ap[8]  )  ?(byte)1:(byte)0;;
+                            cp[9] =  complex.IsNegativeInfinity(ap[9]  )  ?(byte)1:(byte)0;;
+                            cp[10] =  complex.IsNegativeInfinity(ap[10]  )  ?(byte)1:(byte)0;;
+                            cp[11] =  complex.IsNegativeInfinity(ap[11]  )  ?(byte)1:(byte)0;;
+                            cp[12] =  complex.IsNegativeInfinity(ap[12]  )  ?(byte)1:(byte)0;;
+                            cp[13] =  complex.IsNegativeInfinity(ap[13]  )  ?(byte)1:(byte)0;;
+                            cp[14] =  complex.IsNegativeInfinity(ap[14]  )  ?(byte)1:(byte)0;;
+                            cp[15] =  complex.IsNegativeInfinity(ap[15]  )  ?(byte)1:(byte)0;;
+                            cp[16] =  complex.IsNegativeInfinity(ap[16]  )  ?(byte)1:(byte)0;;
+                            cp[17] =  complex.IsNegativeInfinity(ap[17]  )  ?(byte)1:(byte)0;;
+                            cp[18] =  complex.IsNegativeInfinity(ap[18]  )  ?(byte)1:(byte)0;;
+                            cp[19] =  complex.IsNegativeInfinity(ap[19]  )  ?(byte)1:(byte)0;;
+                            cp[20] =  complex.IsNegativeInfinity(ap[20]  )  ?(byte)1:(byte)0;;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.IsNegativeInfinity(*ap  )  ?(byte)1:(byte)0;;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( complex* arrAP = arrA)
+                fixed ( byte* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetLogical(retStorage);
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/isnull.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/isnull.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/isnull.cs	(revision 9102)
@@ -0,0 +1,61 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics;
+using ILNumerics.Exceptions;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+
+namespace ILNumerics {
+    public partial class ILMath {
+        /// <summary>
+        /// Determine, if the array A is null (NULL, not assigned)
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns>True, if the array is null, false otherwise</returns>
+        public static bool isnull(ILBaseArray A) {
+            using (ILScope.Enter(A)) {
+                return object.Equals(A, null);
+            }
+        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/isnullorempty.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/isnullorempty.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/isnullorempty.cs	(revision 9102)
@@ -0,0 +1,60 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics;
+using ILNumerics.Exceptions;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+
+namespace ILNumerics {
+    public partial class ILMath {
+
+        /// <summary>
+        /// Determine, if the array A is null (NULL or not assigned) or empty
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns>True, if the array is null or empty, false otherwise</returns>
+        public static bool isnullorempty(ILBaseArray A) {
+            return object.Equals(A, null) || A.Storage.Size.NumberOfElements < 1;
+        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/isposinf.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/isposinf.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/isposinf.cs	(revision 9102)
@@ -0,0 +1,559 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics;
+using ILNumerics.Exceptions;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+
+
+
+namespace ILNumerics {
+    
+    public partial class ILMath {
+ 
+
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>Finds positive infinite value elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Logical array with 1 if the corresponding elements of input array is positive infinite, 0 else.</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetLogical  isposinf (ILInArray< double > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetLogical(A.Size); 
+                ILSize inDim = A.Size;
+                double[] arrA = A.GetArrayForRead(); 
+                byte [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (true){
+                    retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<byte> retStorage = new ILDenseStorage<byte>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    byte* cp = ((byte*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  Double.IsPositiveInfinity(cp[0]  )  ?(byte)1:(byte)0;;
+                            cp[1] =  Double.IsPositiveInfinity(cp[1]  )  ?(byte)1:(byte)0;;
+                            cp[2] =  Double.IsPositiveInfinity(cp[2]  )  ?(byte)1:(byte)0;;
+                            cp[3] =  Double.IsPositiveInfinity(cp[3]  )  ?(byte)1:(byte)0;;
+                            cp[4] =  Double.IsPositiveInfinity(cp[4]  )  ?(byte)1:(byte)0;;
+                            cp[5] =  Double.IsPositiveInfinity(cp[5]  )  ?(byte)1:(byte)0;;
+                            cp[6] =  Double.IsPositiveInfinity(cp[6]  )  ?(byte)1:(byte)0;;
+                            cp[7] =  Double.IsPositiveInfinity(cp[7]  )  ?(byte)1:(byte)0;;
+                            cp[8] =  Double.IsPositiveInfinity(cp[8]  )  ?(byte)1:(byte)0;;
+                            cp[9] =  Double.IsPositiveInfinity(cp[9]  )  ?(byte)1:(byte)0;;
+                            cp[10] =  Double.IsPositiveInfinity(cp[10]  )  ?(byte)1:(byte)0;;
+                            cp[11] =  Double.IsPositiveInfinity(cp[11]  )  ?(byte)1:(byte)0;;
+                            cp[12] =  Double.IsPositiveInfinity(cp[12]  )  ?(byte)1:(byte)0;;
+                            cp[13] =  Double.IsPositiveInfinity(cp[13]  )  ?(byte)1:(byte)0;;
+                            cp[14] =  Double.IsPositiveInfinity(cp[14]  )  ?(byte)1:(byte)0;;
+                            cp[15] =  Double.IsPositiveInfinity(cp[15]  )  ?(byte)1:(byte)0;;
+                            cp[16] =  Double.IsPositiveInfinity(cp[16]  )  ?(byte)1:(byte)0;;
+                            cp[17] =  Double.IsPositiveInfinity(cp[17]  )  ?(byte)1:(byte)0;;
+                            cp[18] =  Double.IsPositiveInfinity(cp[18]  )  ?(byte)1:(byte)0;;
+                            cp[19] =  Double.IsPositiveInfinity(cp[19]  )  ?(byte)1:(byte)0;;
+                            cp[20] =  Double.IsPositiveInfinity(cp[20]  )  ?(byte)1:(byte)0;;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Double.IsPositiveInfinity(*cp  )  ?(byte)1:(byte)0;;
+                            cp++;
+                        }
+                    } else {
+                        double* ap = ((double*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  Double.IsPositiveInfinity(ap[0]  )  ?(byte)1:(byte)0;;
+                            cp[1] =  Double.IsPositiveInfinity(ap[1]  )  ?(byte)1:(byte)0;;
+                            cp[2] =  Double.IsPositiveInfinity(ap[2]  )  ?(byte)1:(byte)0;;
+                            cp[3] =  Double.IsPositiveInfinity(ap[3]  )  ?(byte)1:(byte)0;;
+                            cp[4] =  Double.IsPositiveInfinity(ap[4]  )  ?(byte)1:(byte)0;;
+                            cp[5] =  Double.IsPositiveInfinity(ap[5]  )  ?(byte)1:(byte)0;;
+                            cp[6] =  Double.IsPositiveInfinity(ap[6]  )  ?(byte)1:(byte)0;;
+                            cp[7] =  Double.IsPositiveInfinity(ap[7]  )  ?(byte)1:(byte)0;;
+                            cp[8] =  Double.IsPositiveInfinity(ap[8]  )  ?(byte)1:(byte)0;;
+                            cp[9] =  Double.IsPositiveInfinity(ap[9]  )  ?(byte)1:(byte)0;;
+                            cp[10] =  Double.IsPositiveInfinity(ap[10]  )  ?(byte)1:(byte)0;;
+                            cp[11] =  Double.IsPositiveInfinity(ap[11]  )  ?(byte)1:(byte)0;;
+                            cp[12] =  Double.IsPositiveInfinity(ap[12]  )  ?(byte)1:(byte)0;;
+                            cp[13] =  Double.IsPositiveInfinity(ap[13]  )  ?(byte)1:(byte)0;;
+                            cp[14] =  Double.IsPositiveInfinity(ap[14]  )  ?(byte)1:(byte)0;;
+                            cp[15] =  Double.IsPositiveInfinity(ap[15]  )  ?(byte)1:(byte)0;;
+                            cp[16] =  Double.IsPositiveInfinity(ap[16]  )  ?(byte)1:(byte)0;;
+                            cp[17] =  Double.IsPositiveInfinity(ap[17]  )  ?(byte)1:(byte)0;;
+                            cp[18] =  Double.IsPositiveInfinity(ap[18]  )  ?(byte)1:(byte)0;;
+                            cp[19] =  Double.IsPositiveInfinity(ap[19]  )  ?(byte)1:(byte)0;;
+                            cp[20] =  Double.IsPositiveInfinity(ap[20]  )  ?(byte)1:(byte)0;;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Double.IsPositiveInfinity(*ap  )  ?(byte)1:(byte)0;;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( double* arrAP = arrA)
+                fixed ( byte* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetLogical(retStorage);
+            }
+        }
+        /// <summary>Finds positive infinite value elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Logical array with 1 if the corresponding elements of input array is positive infinite, 0 else.</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetLogical  isposinf (ILInArray< float > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetLogical(A.Size); 
+                ILSize inDim = A.Size;
+                float[] arrA = A.GetArrayForRead(); 
+                byte [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (true){
+                    retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<byte> retStorage = new ILDenseStorage<byte>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    byte* cp = ((byte*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  Single.IsPositiveInfinity(cp[0]  )  ?(byte)1:(byte)0;;
+                            cp[1] =  Single.IsPositiveInfinity(cp[1]  )  ?(byte)1:(byte)0;;
+                            cp[2] =  Single.IsPositiveInfinity(cp[2]  )  ?(byte)1:(byte)0;;
+                            cp[3] =  Single.IsPositiveInfinity(cp[3]  )  ?(byte)1:(byte)0;;
+                            cp[4] =  Single.IsPositiveInfinity(cp[4]  )  ?(byte)1:(byte)0;;
+                            cp[5] =  Single.IsPositiveInfinity(cp[5]  )  ?(byte)1:(byte)0;;
+                            cp[6] =  Single.IsPositiveInfinity(cp[6]  )  ?(byte)1:(byte)0;;
+                            cp[7] =  Single.IsPositiveInfinity(cp[7]  )  ?(byte)1:(byte)0;;
+                            cp[8] =  Single.IsPositiveInfinity(cp[8]  )  ?(byte)1:(byte)0;;
+                            cp[9] =  Single.IsPositiveInfinity(cp[9]  )  ?(byte)1:(byte)0;;
+                            cp[10] =  Single.IsPositiveInfinity(cp[10]  )  ?(byte)1:(byte)0;;
+                            cp[11] =  Single.IsPositiveInfinity(cp[11]  )  ?(byte)1:(byte)0;;
+                            cp[12] =  Single.IsPositiveInfinity(cp[12]  )  ?(byte)1:(byte)0;;
+                            cp[13] =  Single.IsPositiveInfinity(cp[13]  )  ?(byte)1:(byte)0;;
+                            cp[14] =  Single.IsPositiveInfinity(cp[14]  )  ?(byte)1:(byte)0;;
+                            cp[15] =  Single.IsPositiveInfinity(cp[15]  )  ?(byte)1:(byte)0;;
+                            cp[16] =  Single.IsPositiveInfinity(cp[16]  )  ?(byte)1:(byte)0;;
+                            cp[17] =  Single.IsPositiveInfinity(cp[17]  )  ?(byte)1:(byte)0;;
+                            cp[18] =  Single.IsPositiveInfinity(cp[18]  )  ?(byte)1:(byte)0;;
+                            cp[19] =  Single.IsPositiveInfinity(cp[19]  )  ?(byte)1:(byte)0;;
+                            cp[20] =  Single.IsPositiveInfinity(cp[20]  )  ?(byte)1:(byte)0;;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Single.IsPositiveInfinity(*cp  )  ?(byte)1:(byte)0;;
+                            cp++;
+                        }
+                    } else {
+                        float* ap = ((float*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  Single.IsPositiveInfinity(ap[0]  )  ?(byte)1:(byte)0;;
+                            cp[1] =  Single.IsPositiveInfinity(ap[1]  )  ?(byte)1:(byte)0;;
+                            cp[2] =  Single.IsPositiveInfinity(ap[2]  )  ?(byte)1:(byte)0;;
+                            cp[3] =  Single.IsPositiveInfinity(ap[3]  )  ?(byte)1:(byte)0;;
+                            cp[4] =  Single.IsPositiveInfinity(ap[4]  )  ?(byte)1:(byte)0;;
+                            cp[5] =  Single.IsPositiveInfinity(ap[5]  )  ?(byte)1:(byte)0;;
+                            cp[6] =  Single.IsPositiveInfinity(ap[6]  )  ?(byte)1:(byte)0;;
+                            cp[7] =  Single.IsPositiveInfinity(ap[7]  )  ?(byte)1:(byte)0;;
+                            cp[8] =  Single.IsPositiveInfinity(ap[8]  )  ?(byte)1:(byte)0;;
+                            cp[9] =  Single.IsPositiveInfinity(ap[9]  )  ?(byte)1:(byte)0;;
+                            cp[10] =  Single.IsPositiveInfinity(ap[10]  )  ?(byte)1:(byte)0;;
+                            cp[11] =  Single.IsPositiveInfinity(ap[11]  )  ?(byte)1:(byte)0;;
+                            cp[12] =  Single.IsPositiveInfinity(ap[12]  )  ?(byte)1:(byte)0;;
+                            cp[13] =  Single.IsPositiveInfinity(ap[13]  )  ?(byte)1:(byte)0;;
+                            cp[14] =  Single.IsPositiveInfinity(ap[14]  )  ?(byte)1:(byte)0;;
+                            cp[15] =  Single.IsPositiveInfinity(ap[15]  )  ?(byte)1:(byte)0;;
+                            cp[16] =  Single.IsPositiveInfinity(ap[16]  )  ?(byte)1:(byte)0;;
+                            cp[17] =  Single.IsPositiveInfinity(ap[17]  )  ?(byte)1:(byte)0;;
+                            cp[18] =  Single.IsPositiveInfinity(ap[18]  )  ?(byte)1:(byte)0;;
+                            cp[19] =  Single.IsPositiveInfinity(ap[19]  )  ?(byte)1:(byte)0;;
+                            cp[20] =  Single.IsPositiveInfinity(ap[20]  )  ?(byte)1:(byte)0;;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Single.IsPositiveInfinity(*ap  )  ?(byte)1:(byte)0;;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( float* arrAP = arrA)
+                fixed ( byte* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetLogical(retStorage);
+            }
+        }
+        /// <summary>Finds positive infinite value elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Logical array with 1 if the corresponding elements of input array is positive infinite, 0 else.</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetLogical  isposinf (ILInArray< fcomplex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetLogical(A.Size); 
+                ILSize inDim = A.Size;
+                fcomplex[] arrA = A.GetArrayForRead(); 
+                byte [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (true){
+                    retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<byte> retStorage = new ILDenseStorage<byte>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    byte* cp = ((byte*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  fcomplex.IsPositiveInfinity(cp[0]  )  ?(byte)1:(byte)0;;
+                            cp[1] =  fcomplex.IsPositiveInfinity(cp[1]  )  ?(byte)1:(byte)0;;
+                            cp[2] =  fcomplex.IsPositiveInfinity(cp[2]  )  ?(byte)1:(byte)0;;
+                            cp[3] =  fcomplex.IsPositiveInfinity(cp[3]  )  ?(byte)1:(byte)0;;
+                            cp[4] =  fcomplex.IsPositiveInfinity(cp[4]  )  ?(byte)1:(byte)0;;
+                            cp[5] =  fcomplex.IsPositiveInfinity(cp[5]  )  ?(byte)1:(byte)0;;
+                            cp[6] =  fcomplex.IsPositiveInfinity(cp[6]  )  ?(byte)1:(byte)0;;
+                            cp[7] =  fcomplex.IsPositiveInfinity(cp[7]  )  ?(byte)1:(byte)0;;
+                            cp[8] =  fcomplex.IsPositiveInfinity(cp[8]  )  ?(byte)1:(byte)0;;
+                            cp[9] =  fcomplex.IsPositiveInfinity(cp[9]  )  ?(byte)1:(byte)0;;
+                            cp[10] =  fcomplex.IsPositiveInfinity(cp[10]  )  ?(byte)1:(byte)0;;
+                            cp[11] =  fcomplex.IsPositiveInfinity(cp[11]  )  ?(byte)1:(byte)0;;
+                            cp[12] =  fcomplex.IsPositiveInfinity(cp[12]  )  ?(byte)1:(byte)0;;
+                            cp[13] =  fcomplex.IsPositiveInfinity(cp[13]  )  ?(byte)1:(byte)0;;
+                            cp[14] =  fcomplex.IsPositiveInfinity(cp[14]  )  ?(byte)1:(byte)0;;
+                            cp[15] =  fcomplex.IsPositiveInfinity(cp[15]  )  ?(byte)1:(byte)0;;
+                            cp[16] =  fcomplex.IsPositiveInfinity(cp[16]  )  ?(byte)1:(byte)0;;
+                            cp[17] =  fcomplex.IsPositiveInfinity(cp[17]  )  ?(byte)1:(byte)0;;
+                            cp[18] =  fcomplex.IsPositiveInfinity(cp[18]  )  ?(byte)1:(byte)0;;
+                            cp[19] =  fcomplex.IsPositiveInfinity(cp[19]  )  ?(byte)1:(byte)0;;
+                            cp[20] =  fcomplex.IsPositiveInfinity(cp[20]  )  ?(byte)1:(byte)0;;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.IsPositiveInfinity(*cp  )  ?(byte)1:(byte)0;;
+                            cp++;
+                        }
+                    } else {
+                        fcomplex* ap = ((fcomplex*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  fcomplex.IsPositiveInfinity(ap[0]  )  ?(byte)1:(byte)0;;
+                            cp[1] =  fcomplex.IsPositiveInfinity(ap[1]  )  ?(byte)1:(byte)0;;
+                            cp[2] =  fcomplex.IsPositiveInfinity(ap[2]  )  ?(byte)1:(byte)0;;
+                            cp[3] =  fcomplex.IsPositiveInfinity(ap[3]  )  ?(byte)1:(byte)0;;
+                            cp[4] =  fcomplex.IsPositiveInfinity(ap[4]  )  ?(byte)1:(byte)0;;
+                            cp[5] =  fcomplex.IsPositiveInfinity(ap[5]  )  ?(byte)1:(byte)0;;
+                            cp[6] =  fcomplex.IsPositiveInfinity(ap[6]  )  ?(byte)1:(byte)0;;
+                            cp[7] =  fcomplex.IsPositiveInfinity(ap[7]  )  ?(byte)1:(byte)0;;
+                            cp[8] =  fcomplex.IsPositiveInfinity(ap[8]  )  ?(byte)1:(byte)0;;
+                            cp[9] =  fcomplex.IsPositiveInfinity(ap[9]  )  ?(byte)1:(byte)0;;
+                            cp[10] =  fcomplex.IsPositiveInfinity(ap[10]  )  ?(byte)1:(byte)0;;
+                            cp[11] =  fcomplex.IsPositiveInfinity(ap[11]  )  ?(byte)1:(byte)0;;
+                            cp[12] =  fcomplex.IsPositiveInfinity(ap[12]  )  ?(byte)1:(byte)0;;
+                            cp[13] =  fcomplex.IsPositiveInfinity(ap[13]  )  ?(byte)1:(byte)0;;
+                            cp[14] =  fcomplex.IsPositiveInfinity(ap[14]  )  ?(byte)1:(byte)0;;
+                            cp[15] =  fcomplex.IsPositiveInfinity(ap[15]  )  ?(byte)1:(byte)0;;
+                            cp[16] =  fcomplex.IsPositiveInfinity(ap[16]  )  ?(byte)1:(byte)0;;
+                            cp[17] =  fcomplex.IsPositiveInfinity(ap[17]  )  ?(byte)1:(byte)0;;
+                            cp[18] =  fcomplex.IsPositiveInfinity(ap[18]  )  ?(byte)1:(byte)0;;
+                            cp[19] =  fcomplex.IsPositiveInfinity(ap[19]  )  ?(byte)1:(byte)0;;
+                            cp[20] =  fcomplex.IsPositiveInfinity(ap[20]  )  ?(byte)1:(byte)0;;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.IsPositiveInfinity(*ap  )  ?(byte)1:(byte)0;;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( fcomplex* arrAP = arrA)
+                fixed ( byte* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetLogical(retStorage);
+            }
+        }
+        /// <summary>Finds positive infinite value elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Logical array with 1 if the corresponding elements of input array is positive infinite, 0 else.</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetLogical  isposinf (ILInArray< complex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetLogical(A.Size); 
+                ILSize inDim = A.Size;
+                complex[] arrA = A.GetArrayForRead(); 
+                byte [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (true){
+                    retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<byte> retStorage = new ILDenseStorage<byte>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    byte* cp = ((byte*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  complex.IsPositiveInfinity(cp[0]  )  ?(byte)1:(byte)0;;
+                            cp[1] =  complex.IsPositiveInfinity(cp[1]  )  ?(byte)1:(byte)0;;
+                            cp[2] =  complex.IsPositiveInfinity(cp[2]  )  ?(byte)1:(byte)0;;
+                            cp[3] =  complex.IsPositiveInfinity(cp[3]  )  ?(byte)1:(byte)0;;
+                            cp[4] =  complex.IsPositiveInfinity(cp[4]  )  ?(byte)1:(byte)0;;
+                            cp[5] =  complex.IsPositiveInfinity(cp[5]  )  ?(byte)1:(byte)0;;
+                            cp[6] =  complex.IsPositiveInfinity(cp[6]  )  ?(byte)1:(byte)0;;
+                            cp[7] =  complex.IsPositiveInfinity(cp[7]  )  ?(byte)1:(byte)0;;
+                            cp[8] =  complex.IsPositiveInfinity(cp[8]  )  ?(byte)1:(byte)0;;
+                            cp[9] =  complex.IsPositiveInfinity(cp[9]  )  ?(byte)1:(byte)0;;
+                            cp[10] =  complex.IsPositiveInfinity(cp[10]  )  ?(byte)1:(byte)0;;
+                            cp[11] =  complex.IsPositiveInfinity(cp[11]  )  ?(byte)1:(byte)0;;
+                            cp[12] =  complex.IsPositiveInfinity(cp[12]  )  ?(byte)1:(byte)0;;
+                            cp[13] =  complex.IsPositiveInfinity(cp[13]  )  ?(byte)1:(byte)0;;
+                            cp[14] =  complex.IsPositiveInfinity(cp[14]  )  ?(byte)1:(byte)0;;
+                            cp[15] =  complex.IsPositiveInfinity(cp[15]  )  ?(byte)1:(byte)0;;
+                            cp[16] =  complex.IsPositiveInfinity(cp[16]  )  ?(byte)1:(byte)0;;
+                            cp[17] =  complex.IsPositiveInfinity(cp[17]  )  ?(byte)1:(byte)0;;
+                            cp[18] =  complex.IsPositiveInfinity(cp[18]  )  ?(byte)1:(byte)0;;
+                            cp[19] =  complex.IsPositiveInfinity(cp[19]  )  ?(byte)1:(byte)0;;
+                            cp[20] =  complex.IsPositiveInfinity(cp[20]  )  ?(byte)1:(byte)0;;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.IsPositiveInfinity(*cp  )  ?(byte)1:(byte)0;;
+                            cp++;
+                        }
+                    } else {
+                        complex* ap = ((complex*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  complex.IsPositiveInfinity(ap[0]  )  ?(byte)1:(byte)0;;
+                            cp[1] =  complex.IsPositiveInfinity(ap[1]  )  ?(byte)1:(byte)0;;
+                            cp[2] =  complex.IsPositiveInfinity(ap[2]  )  ?(byte)1:(byte)0;;
+                            cp[3] =  complex.IsPositiveInfinity(ap[3]  )  ?(byte)1:(byte)0;;
+                            cp[4] =  complex.IsPositiveInfinity(ap[4]  )  ?(byte)1:(byte)0;;
+                            cp[5] =  complex.IsPositiveInfinity(ap[5]  )  ?(byte)1:(byte)0;;
+                            cp[6] =  complex.IsPositiveInfinity(ap[6]  )  ?(byte)1:(byte)0;;
+                            cp[7] =  complex.IsPositiveInfinity(ap[7]  )  ?(byte)1:(byte)0;;
+                            cp[8] =  complex.IsPositiveInfinity(ap[8]  )  ?(byte)1:(byte)0;;
+                            cp[9] =  complex.IsPositiveInfinity(ap[9]  )  ?(byte)1:(byte)0;;
+                            cp[10] =  complex.IsPositiveInfinity(ap[10]  )  ?(byte)1:(byte)0;;
+                            cp[11] =  complex.IsPositiveInfinity(ap[11]  )  ?(byte)1:(byte)0;;
+                            cp[12] =  complex.IsPositiveInfinity(ap[12]  )  ?(byte)1:(byte)0;;
+                            cp[13] =  complex.IsPositiveInfinity(ap[13]  )  ?(byte)1:(byte)0;;
+                            cp[14] =  complex.IsPositiveInfinity(ap[14]  )  ?(byte)1:(byte)0;;
+                            cp[15] =  complex.IsPositiveInfinity(ap[15]  )  ?(byte)1:(byte)0;;
+                            cp[16] =  complex.IsPositiveInfinity(ap[16]  )  ?(byte)1:(byte)0;;
+                            cp[17] =  complex.IsPositiveInfinity(ap[17]  )  ?(byte)1:(byte)0;;
+                            cp[18] =  complex.IsPositiveInfinity(ap[18]  )  ?(byte)1:(byte)0;;
+                            cp[19] =  complex.IsPositiveInfinity(ap[19]  )  ?(byte)1:(byte)0;;
+                            cp[20] =  complex.IsPositiveInfinity(ap[20]  )  ?(byte)1:(byte)0;;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.IsPositiveInfinity(*ap  )  ?(byte)1:(byte)0;;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( complex* arrAP = arrA)
+                fixed ( byte* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetLogical(retStorage);
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/le.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/le.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/le.cs	(revision 9102)
@@ -0,0 +1,1954 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.InteropServices; 
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Native;
+using ILNumerics.Exceptions;
+
+
+
+namespace ILNumerics {
+
+	public partial class ILMath {
+
+
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>Elementwise logical 'lower or equal' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array having '1' for elements in A being lower or equal corresponding elements in B, '0' else</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  le(ILInArray<Int64> A, ILInArray<Int64> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                Int64[] arrA = A.GetArrayForRead();
+               
+                Int64[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                       
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0)  <= B.GetValue(0)) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  leEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    Int64 scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            Int64* ap = ((Int64*)range.Item3 + range.Item1);
+                            Int64* bp = ((Int64*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  <= *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((Int64*)range.Item3 + range.Item1);
+                            scalar = *((Int64*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  <= scalar) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((Int64*)range.Item3);
+                            bp = ((Int64*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (scalar  <= *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (Int64* arrAP = arrA)
+                fixed (Int64* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  leEx(ILInArray<Int64> A, ILInArray<Int64> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                Int64[] arrA = A.GetArrayForRead();
+               
+                Int64[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    Int64* ap;
+                   
+                    Int64* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (Int64*)range.Item3;
+                                bp = (Int64*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  <= *bp) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (Int64*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (Int64*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  <= *bp) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( Int64* arrAP = arrA)
+                fixed ( Int64* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'lower or equal' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array having '1' for elements in A being lower or equal corresponding elements in B, '0' else</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  le(ILInArray<Int32> A, ILInArray<Int32> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                Int32[] arrA = A.GetArrayForRead();
+               
+                Int32[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                       
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0)  <= B.GetValue(0)) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  leEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    Int32 scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            Int32* ap = ((Int32*)range.Item3 + range.Item1);
+                            Int32* bp = ((Int32*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  <= *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((Int32*)range.Item3 + range.Item1);
+                            scalar = *((Int32*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  <= scalar) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((Int32*)range.Item3);
+                            bp = ((Int32*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (scalar  <= *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (Int32* arrAP = arrA)
+                fixed (Int32* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  leEx(ILInArray<Int32> A, ILInArray<Int32> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                Int32[] arrA = A.GetArrayForRead();
+               
+                Int32[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    Int32* ap;
+                   
+                    Int32* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (Int32*)range.Item3;
+                                bp = (Int32*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  <= *bp) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (Int32*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (Int32*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  <= *bp) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( Int32* arrAP = arrA)
+                fixed ( Int32* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'lower or equal' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array having '1' for elements in A being lower or equal corresponding elements in B, '0' else</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  le(ILInArray<float> A, ILInArray<float> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                float[] arrA = A.GetArrayForRead();
+               
+                float[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                       
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0)  <= B.GetValue(0)) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  leEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    float scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            float* ap = ((float*)range.Item3 + range.Item1);
+                            float* bp = ((float*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  <= *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((float*)range.Item3 + range.Item1);
+                            scalar = *((float*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  <= scalar) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((float*)range.Item3);
+                            bp = ((float*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (scalar  <= *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (float* arrAP = arrA)
+                fixed (float* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  leEx(ILInArray<float> A, ILInArray<float> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                float[] arrA = A.GetArrayForRead();
+               
+                float[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    float* ap;
+                   
+                    float* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (float*)range.Item3;
+                                bp = (float*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  <= *bp) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (float*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (float*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  <= *bp) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( float* arrAP = arrA)
+                fixed ( float* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'lower or equal' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array having '1' for elements in A being lower or equal corresponding elements in B, '0' else</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  le(ILInArray<fcomplex> A, ILInArray<fcomplex> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                fcomplex[] arrA = A.GetArrayForRead();
+               
+                fcomplex[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                       
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0)  <= B.GetValue(0)) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  leEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    fcomplex scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            fcomplex* ap = ((fcomplex*)range.Item3 + range.Item1);
+                            fcomplex* bp = ((fcomplex*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  <= *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((fcomplex*)range.Item3 + range.Item1);
+                            scalar = *((fcomplex*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  <= scalar) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((fcomplex*)range.Item3);
+                            bp = ((fcomplex*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (scalar  <= *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (fcomplex* arrAP = arrA)
+                fixed (fcomplex* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  leEx(ILInArray<fcomplex> A, ILInArray<fcomplex> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                fcomplex[] arrA = A.GetArrayForRead();
+               
+                fcomplex[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    fcomplex* ap;
+                   
+                    fcomplex* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (fcomplex*)range.Item3;
+                                bp = (fcomplex*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  <= *bp) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (fcomplex*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (fcomplex*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  <= *bp) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( fcomplex* arrAP = arrA)
+                fixed ( fcomplex* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'lower or equal' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array having '1' for elements in A being lower or equal corresponding elements in B, '0' else</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  le(ILInArray<complex> A, ILInArray<complex> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                complex[] arrA = A.GetArrayForRead();
+               
+                complex[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                       
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0)  <= B.GetValue(0)) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  leEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    complex scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            complex* ap = ((complex*)range.Item3 + range.Item1);
+                            complex* bp = ((complex*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  <= *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((complex*)range.Item3 + range.Item1);
+                            scalar = *((complex*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  <= scalar) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((complex*)range.Item3);
+                            bp = ((complex*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (scalar  <= *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (complex* arrAP = arrA)
+                fixed (complex* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  leEx(ILInArray<complex> A, ILInArray<complex> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                complex[] arrA = A.GetArrayForRead();
+               
+                complex[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    complex* ap;
+                   
+                    complex* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (complex*)range.Item3;
+                                bp = (complex*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  <= *bp) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (complex*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (complex*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  <= *bp) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( complex* arrAP = arrA)
+                fixed ( complex* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'lower or equal' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array having '1' for elements in A being lower or equal corresponding elements in B, '0' else</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  le(ILInArray<byte> A, ILInArray<byte> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                byte[] arrA = A.GetArrayForRead();
+               
+                byte[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                       
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0)  <= B.GetValue(0)) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  leEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    byte scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            byte* ap = ((byte*)range.Item3 + range.Item1);
+                            byte* bp = ((byte*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  <= *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((byte*)range.Item3 + range.Item1);
+                            scalar = *((byte*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  <= scalar) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((byte*)range.Item3);
+                            bp = ((byte*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (scalar  <= *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (byte* arrAP = arrA)
+                fixed (byte* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  leEx(ILInArray<byte> A, ILInArray<byte> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                byte[] arrA = A.GetArrayForRead();
+               
+                byte[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    byte* ap;
+                   
+                    byte* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (byte*)range.Item3;
+                                bp = (byte*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  <= *bp) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (byte*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (byte*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  <= *bp) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( byte* arrAP = arrA)
+                fixed ( byte* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'lower or equal' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array having '1' for elements in A being lower or equal corresponding elements in B, '0' else</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  le(ILInArray<double> A, ILInArray<double> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                double[] arrA = A.GetArrayForRead();
+               
+                double[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                       
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0)  <= B.GetValue(0)) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  leEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    double scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            double* ap = ((double*)range.Item3 + range.Item1);
+                            double* bp = ((double*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  <= *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((double*)range.Item3 + range.Item1);
+                            scalar = *((double*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  <= scalar) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((double*)range.Item3);
+                            bp = ((double*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (scalar  <= *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (double* arrAP = arrA)
+                fixed (double* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  leEx(ILInArray<double> A, ILInArray<double> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                double[] arrA = A.GetArrayForRead();
+               
+                double[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    double* ap;
+                   
+                    double* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (double*)range.Item3;
+                                bp = (double*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  <= *bp) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (double*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (double*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  <= *bp) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( double* arrAP = arrA)
+                fixed ( double* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/linspace.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/linspace.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/linspace.cs	(revision 9102)
@@ -0,0 +1,100 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics;
+using ILNumerics.Exceptions;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+
+namespace ILNumerics {
+    public partial class ILMath {
+
+        /// <summary>
+        /// Create linearly spaced row vector of 100 elements 
+        /// </summary>
+        /// <param name="start">First value</param>
+        /// <param name="end">Last value</param>
+        /// <returns>Row vector with 100 elements linearly spaced between start and end</returns>
+        public static ILRetArray<double> linspace (ILBaseArray start, ILBaseArray end) {
+            return linspace<double>(start, end, 100); 
+        }
+
+        /// <summary>
+        /// Create linearly spaced row vector, generic output type
+        /// </summary>
+        /// <param name="start">First value, scalar, numeric</param>
+        /// <param name="end">Last value, scalar, numeric</param>
+        /// <param name="length">Number of elements to create, scalar, numeric</param>
+        /// <returns>Row vector with 'length' elements linearly spaced between start and end</returns>
+        public static ILRetArray<T> linspace<T> (ILBaseArray start, ILBaseArray end, ILBaseArray length) {
+            using (ILScope.Enter(start,end,length)) {
+                if (object.Equals(start, null) || !start.IsScalar || !start.IsNumeric) throw new ILArgumentException("'start' must be numeric scalar");              
+                if (object.Equals(end, null) || !end.IsScalar || !end.IsNumeric) throw new ILArgumentException("'end' must be numeric scalar");              
+                if (object.Equals(length, null) || !length.IsScalar || !length.IsNumeric) throw new ILArgumentException("'length' must be numeric scalar");              
+                ILArray<double> dStart = todouble(start); 
+                ILArray<double> dEnd = todouble(end); 
+                ILArray<double> dLength = todouble(length);
+                       
+                if (dLength < 2) 
+                    return convert<double,T>(dEnd); 
+                ILArray<double> fact = ( dEnd - dStart ) / (dLength - 1); 
+                ILArray<double> i;
+                //if (Settings.FavorRowForColumnVectorCreation) {
+                i = counter(0.0, 1.0, 1, (int)dLength.GetValue(0));
+                //} else {
+                //    i = counter(0.0, 1.0, (int)dLength.GetValue(0), 1);
+                //}
+                return convert<double, T>(dStart + i * fact);
+            }
+        }    
+        /// <summary>
+        /// Create linearly spaced row vector, double precision
+        /// </summary>
+        /// <param name="start">First value</param>
+        /// <param name="end">Last value</param>
+        /// <param name="length">Number of elements to create</param>
+        /// <returns>Row vector with 'length' elements linearly spaced between start and end</returns>
+        public static ILRetArray<double> linspace (ILBaseArray start, ILBaseArray end, ILBaseArray length) {
+            return linspace<double>(start,end,length); 
+        }    
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/load.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/load.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/load.cs	(revision 9102)
@@ -0,0 +1,72 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions; 
+
+namespace ILNumerics  {
+    public partial class ILMath {
+
+        /// <summary>
+        /// Load single array from matfile file
+        /// </summary>
+        /// <typeparam name="T">Element type of the array to return</typeparam>
+        /// <param name="filename">Path of the matfile on disk</param>
+        /// <param name="arrayname">[Optional] name of the requested array in the matfile (default: empty string)</param>
+        /// <returns>The array requested</returns>
+        /// <remarks><para>If the matfile contains only one array, the <paramref name="arrayname"/> may
+        /// be ommited. The only array is returned than.</para></remarks>
+        public static ILRetArray<T> loadArray<T>(string filename, string arrayname = "") {
+            using (ILScope.Enter()) {
+                using (ILMatFile matfile = new ILMatFile(filename)) {
+                    if (String.IsNullOrEmpty(arrayname) && matfile.Count == 1) {
+                        return matfile.GetArray<T>(0);
+                    } else {
+                        return matfile.GetArray<T>(arrayname); 
+                    }
+                }
+            }
+        }
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/log.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/log.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/log.cs	(revision 9102)
@@ -0,0 +1,806 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics;
+using ILNumerics.Exceptions; 
+using ILNumerics.Storage; 
+using ILNumerics.Misc;
+
+
+
+namespace ILNumerics {
+    public partial class ILMath {
+
+
+        
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>Logarithm of array elements - complex output</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Complex logarithm of array elements</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<fcomplex>  logc (ILInArray< float > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<fcomplex>(A.Size); 
+                ILSize inDim = A.Size;
+                float[] arrA = A.GetArrayForRead(); 
+                fcomplex [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (true) {
+                    retArr = ILMemoryPool.Pool.New<fcomplex>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<fcomplex> retStorage = new ILDenseStorage<fcomplex>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    fcomplex* cp = ((fcomplex*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  fcomplex.Log(cp[0]  )  /*dummy*/;
+                            cp[1] =  fcomplex.Log(cp[1]  )  /*dummy*/;
+                            cp[2] =  fcomplex.Log(cp[2]  )  /*dummy*/;
+                            cp[3] =  fcomplex.Log(cp[3]  )  /*dummy*/;
+                            cp[4] =  fcomplex.Log(cp[4]  )  /*dummy*/;
+                            cp[5] =  fcomplex.Log(cp[5]  )  /*dummy*/;
+                            cp[6] =  fcomplex.Log(cp[6]  )  /*dummy*/;
+                            cp[7] =  fcomplex.Log(cp[7]  )  /*dummy*/;
+                            cp[8] =  fcomplex.Log(cp[8]  )  /*dummy*/;
+                            cp[9] =  fcomplex.Log(cp[9]  )  /*dummy*/;
+                            cp[10] =  fcomplex.Log(cp[10]  )  /*dummy*/;
+                            cp[11] =  fcomplex.Log(cp[11]  )  /*dummy*/;
+                            cp[12] =  fcomplex.Log(cp[12]  )  /*dummy*/;
+                            cp[13] =  fcomplex.Log(cp[13]  )  /*dummy*/;
+                            cp[14] =  fcomplex.Log(cp[14]  )  /*dummy*/;
+                            cp[15] =  fcomplex.Log(cp[15]  )  /*dummy*/;
+                            cp[16] =  fcomplex.Log(cp[16]  )  /*dummy*/;
+                            cp[17] =  fcomplex.Log(cp[17]  )  /*dummy*/;
+                            cp[18] =  fcomplex.Log(cp[18]  )  /*dummy*/;
+                            cp[19] =  fcomplex.Log(cp[19]  )  /*dummy*/;
+                            cp[20] =  fcomplex.Log(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.Log(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        float* ap = ((float*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  fcomplex.Log(ap[0]  )  /*dummy*/;
+                            cp[1] =  fcomplex.Log(ap[1]  )  /*dummy*/;
+                            cp[2] =  fcomplex.Log(ap[2]  )  /*dummy*/;
+                            cp[3] =  fcomplex.Log(ap[3]  )  /*dummy*/;
+                            cp[4] =  fcomplex.Log(ap[4]  )  /*dummy*/;
+                            cp[5] =  fcomplex.Log(ap[5]  )  /*dummy*/;
+                            cp[6] =  fcomplex.Log(ap[6]  )  /*dummy*/;
+                            cp[7] =  fcomplex.Log(ap[7]  )  /*dummy*/;
+                            cp[8] =  fcomplex.Log(ap[8]  )  /*dummy*/;
+                            cp[9] =  fcomplex.Log(ap[9]  )  /*dummy*/;
+                            cp[10] =  fcomplex.Log(ap[10]  )  /*dummy*/;
+                            cp[11] =  fcomplex.Log(ap[11]  )  /*dummy*/;
+                            cp[12] =  fcomplex.Log(ap[12]  )  /*dummy*/;
+                            cp[13] =  fcomplex.Log(ap[13]  )  /*dummy*/;
+                            cp[14] =  fcomplex.Log(ap[14]  )  /*dummy*/;
+                            cp[15] =  fcomplex.Log(ap[15]  )  /*dummy*/;
+                            cp[16] =  fcomplex.Log(ap[16]  )  /*dummy*/;
+                            cp[17] =  fcomplex.Log(ap[17]  )  /*dummy*/;
+                            cp[18] =  fcomplex.Log(ap[18]  )  /*dummy*/;
+                            cp[19] =  fcomplex.Log(ap[19]  )  /*dummy*/;
+                            cp[20] =  fcomplex.Log(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.Log(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( float* arrAP = arrA)
+                fixed ( fcomplex* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<fcomplex>(retStorage);
+            }
+        }
+        /// <summary>Logarithm of array elements - complex output</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Complex logarithm of array elements</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<complex>  logc (ILInArray< double > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<complex>(A.Size); 
+                ILSize inDim = A.Size;
+                double[] arrA = A.GetArrayForRead(); 
+                complex [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (true) {
+                    retArr = ILMemoryPool.Pool.New<complex>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<complex> retStorage = new ILDenseStorage<complex>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    complex* cp = ((complex*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  complex.Log(cp[0]  )  /*dummy*/;
+                            cp[1] =  complex.Log(cp[1]  )  /*dummy*/;
+                            cp[2] =  complex.Log(cp[2]  )  /*dummy*/;
+                            cp[3] =  complex.Log(cp[3]  )  /*dummy*/;
+                            cp[4] =  complex.Log(cp[4]  )  /*dummy*/;
+                            cp[5] =  complex.Log(cp[5]  )  /*dummy*/;
+                            cp[6] =  complex.Log(cp[6]  )  /*dummy*/;
+                            cp[7] =  complex.Log(cp[7]  )  /*dummy*/;
+                            cp[8] =  complex.Log(cp[8]  )  /*dummy*/;
+                            cp[9] =  complex.Log(cp[9]  )  /*dummy*/;
+                            cp[10] =  complex.Log(cp[10]  )  /*dummy*/;
+                            cp[11] =  complex.Log(cp[11]  )  /*dummy*/;
+                            cp[12] =  complex.Log(cp[12]  )  /*dummy*/;
+                            cp[13] =  complex.Log(cp[13]  )  /*dummy*/;
+                            cp[14] =  complex.Log(cp[14]  )  /*dummy*/;
+                            cp[15] =  complex.Log(cp[15]  )  /*dummy*/;
+                            cp[16] =  complex.Log(cp[16]  )  /*dummy*/;
+                            cp[17] =  complex.Log(cp[17]  )  /*dummy*/;
+                            cp[18] =  complex.Log(cp[18]  )  /*dummy*/;
+                            cp[19] =  complex.Log(cp[19]  )  /*dummy*/;
+                            cp[20] =  complex.Log(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.Log(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        double* ap = ((double*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  complex.Log(ap[0]  )  /*dummy*/;
+                            cp[1] =  complex.Log(ap[1]  )  /*dummy*/;
+                            cp[2] =  complex.Log(ap[2]  )  /*dummy*/;
+                            cp[3] =  complex.Log(ap[3]  )  /*dummy*/;
+                            cp[4] =  complex.Log(ap[4]  )  /*dummy*/;
+                            cp[5] =  complex.Log(ap[5]  )  /*dummy*/;
+                            cp[6] =  complex.Log(ap[6]  )  /*dummy*/;
+                            cp[7] =  complex.Log(ap[7]  )  /*dummy*/;
+                            cp[8] =  complex.Log(ap[8]  )  /*dummy*/;
+                            cp[9] =  complex.Log(ap[9]  )  /*dummy*/;
+                            cp[10] =  complex.Log(ap[10]  )  /*dummy*/;
+                            cp[11] =  complex.Log(ap[11]  )  /*dummy*/;
+                            cp[12] =  complex.Log(ap[12]  )  /*dummy*/;
+                            cp[13] =  complex.Log(ap[13]  )  /*dummy*/;
+                            cp[14] =  complex.Log(ap[14]  )  /*dummy*/;
+                            cp[15] =  complex.Log(ap[15]  )  /*dummy*/;
+                            cp[16] =  complex.Log(ap[16]  )  /*dummy*/;
+                            cp[17] =  complex.Log(ap[17]  )  /*dummy*/;
+                            cp[18] =  complex.Log(ap[18]  )  /*dummy*/;
+                            cp[19] =  complex.Log(ap[19]  )  /*dummy*/;
+                            cp[20] =  complex.Log(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.Log(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( double* arrAP = arrA)
+                fixed ( complex* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<complex>(retStorage);
+            }
+        }
+        /// <summary>Logarithm of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Complex logarithm of array elements</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<complex>  log (ILInArray< complex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<complex>(A.Size); 
+                ILSize inDim = A.Size;
+                complex[] arrA = A.GetArrayForRead(); 
+                complex [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (true) {
+                    retArr = ILMemoryPool.Pool.New<complex>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<complex> retStorage = new ILDenseStorage<complex>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    complex* cp = ((complex*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  complex.Log(cp[0]  )  /*dummy*/;
+                            cp[1] =  complex.Log(cp[1]  )  /*dummy*/;
+                            cp[2] =  complex.Log(cp[2]  )  /*dummy*/;
+                            cp[3] =  complex.Log(cp[3]  )  /*dummy*/;
+                            cp[4] =  complex.Log(cp[4]  )  /*dummy*/;
+                            cp[5] =  complex.Log(cp[5]  )  /*dummy*/;
+                            cp[6] =  complex.Log(cp[6]  )  /*dummy*/;
+                            cp[7] =  complex.Log(cp[7]  )  /*dummy*/;
+                            cp[8] =  complex.Log(cp[8]  )  /*dummy*/;
+                            cp[9] =  complex.Log(cp[9]  )  /*dummy*/;
+                            cp[10] =  complex.Log(cp[10]  )  /*dummy*/;
+                            cp[11] =  complex.Log(cp[11]  )  /*dummy*/;
+                            cp[12] =  complex.Log(cp[12]  )  /*dummy*/;
+                            cp[13] =  complex.Log(cp[13]  )  /*dummy*/;
+                            cp[14] =  complex.Log(cp[14]  )  /*dummy*/;
+                            cp[15] =  complex.Log(cp[15]  )  /*dummy*/;
+                            cp[16] =  complex.Log(cp[16]  )  /*dummy*/;
+                            cp[17] =  complex.Log(cp[17]  )  /*dummy*/;
+                            cp[18] =  complex.Log(cp[18]  )  /*dummy*/;
+                            cp[19] =  complex.Log(cp[19]  )  /*dummy*/;
+                            cp[20] =  complex.Log(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.Log(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        complex* ap = ((complex*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  complex.Log(ap[0]  )  /*dummy*/;
+                            cp[1] =  complex.Log(ap[1]  )  /*dummy*/;
+                            cp[2] =  complex.Log(ap[2]  )  /*dummy*/;
+                            cp[3] =  complex.Log(ap[3]  )  /*dummy*/;
+                            cp[4] =  complex.Log(ap[4]  )  /*dummy*/;
+                            cp[5] =  complex.Log(ap[5]  )  /*dummy*/;
+                            cp[6] =  complex.Log(ap[6]  )  /*dummy*/;
+                            cp[7] =  complex.Log(ap[7]  )  /*dummy*/;
+                            cp[8] =  complex.Log(ap[8]  )  /*dummy*/;
+                            cp[9] =  complex.Log(ap[9]  )  /*dummy*/;
+                            cp[10] =  complex.Log(ap[10]  )  /*dummy*/;
+                            cp[11] =  complex.Log(ap[11]  )  /*dummy*/;
+                            cp[12] =  complex.Log(ap[12]  )  /*dummy*/;
+                            cp[13] =  complex.Log(ap[13]  )  /*dummy*/;
+                            cp[14] =  complex.Log(ap[14]  )  /*dummy*/;
+                            cp[15] =  complex.Log(ap[15]  )  /*dummy*/;
+                            cp[16] =  complex.Log(ap[16]  )  /*dummy*/;
+                            cp[17] =  complex.Log(ap[17]  )  /*dummy*/;
+                            cp[18] =  complex.Log(ap[18]  )  /*dummy*/;
+                            cp[19] =  complex.Log(ap[19]  )  /*dummy*/;
+                            cp[20] =  complex.Log(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.Log(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( complex* arrAP = arrA)
+                fixed ( complex* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<complex>(retStorage);
+            }
+        }
+        /// <summary>Logarithm of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Complex logarithm of array elements</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<fcomplex>  log (ILInArray< fcomplex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<fcomplex>(A.Size); 
+                ILSize inDim = A.Size;
+                fcomplex[] arrA = A.GetArrayForRead(); 
+                fcomplex [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (true) {
+                    retArr = ILMemoryPool.Pool.New<fcomplex>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<fcomplex> retStorage = new ILDenseStorage<fcomplex>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    fcomplex* cp = ((fcomplex*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  fcomplex.Log(cp[0]  )  /*dummy*/;
+                            cp[1] =  fcomplex.Log(cp[1]  )  /*dummy*/;
+                            cp[2] =  fcomplex.Log(cp[2]  )  /*dummy*/;
+                            cp[3] =  fcomplex.Log(cp[3]  )  /*dummy*/;
+                            cp[4] =  fcomplex.Log(cp[4]  )  /*dummy*/;
+                            cp[5] =  fcomplex.Log(cp[5]  )  /*dummy*/;
+                            cp[6] =  fcomplex.Log(cp[6]  )  /*dummy*/;
+                            cp[7] =  fcomplex.Log(cp[7]  )  /*dummy*/;
+                            cp[8] =  fcomplex.Log(cp[8]  )  /*dummy*/;
+                            cp[9] =  fcomplex.Log(cp[9]  )  /*dummy*/;
+                            cp[10] =  fcomplex.Log(cp[10]  )  /*dummy*/;
+                            cp[11] =  fcomplex.Log(cp[11]  )  /*dummy*/;
+                            cp[12] =  fcomplex.Log(cp[12]  )  /*dummy*/;
+                            cp[13] =  fcomplex.Log(cp[13]  )  /*dummy*/;
+                            cp[14] =  fcomplex.Log(cp[14]  )  /*dummy*/;
+                            cp[15] =  fcomplex.Log(cp[15]  )  /*dummy*/;
+                            cp[16] =  fcomplex.Log(cp[16]  )  /*dummy*/;
+                            cp[17] =  fcomplex.Log(cp[17]  )  /*dummy*/;
+                            cp[18] =  fcomplex.Log(cp[18]  )  /*dummy*/;
+                            cp[19] =  fcomplex.Log(cp[19]  )  /*dummy*/;
+                            cp[20] =  fcomplex.Log(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.Log(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        fcomplex* ap = ((fcomplex*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  fcomplex.Log(ap[0]  )  /*dummy*/;
+                            cp[1] =  fcomplex.Log(ap[1]  )  /*dummy*/;
+                            cp[2] =  fcomplex.Log(ap[2]  )  /*dummy*/;
+                            cp[3] =  fcomplex.Log(ap[3]  )  /*dummy*/;
+                            cp[4] =  fcomplex.Log(ap[4]  )  /*dummy*/;
+                            cp[5] =  fcomplex.Log(ap[5]  )  /*dummy*/;
+                            cp[6] =  fcomplex.Log(ap[6]  )  /*dummy*/;
+                            cp[7] =  fcomplex.Log(ap[7]  )  /*dummy*/;
+                            cp[8] =  fcomplex.Log(ap[8]  )  /*dummy*/;
+                            cp[9] =  fcomplex.Log(ap[9]  )  /*dummy*/;
+                            cp[10] =  fcomplex.Log(ap[10]  )  /*dummy*/;
+                            cp[11] =  fcomplex.Log(ap[11]  )  /*dummy*/;
+                            cp[12] =  fcomplex.Log(ap[12]  )  /*dummy*/;
+                            cp[13] =  fcomplex.Log(ap[13]  )  /*dummy*/;
+                            cp[14] =  fcomplex.Log(ap[14]  )  /*dummy*/;
+                            cp[15] =  fcomplex.Log(ap[15]  )  /*dummy*/;
+                            cp[16] =  fcomplex.Log(ap[16]  )  /*dummy*/;
+                            cp[17] =  fcomplex.Log(ap[17]  )  /*dummy*/;
+                            cp[18] =  fcomplex.Log(ap[18]  )  /*dummy*/;
+                            cp[19] =  fcomplex.Log(ap[19]  )  /*dummy*/;
+                            cp[20] =  fcomplex.Log(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.Log(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( fcomplex* arrAP = arrA)
+                fixed ( fcomplex* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<fcomplex>(retStorage);
+            }
+        }
+        /// <summary>Logarithm of array elements - real output</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Logarithm of array elements - real output</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<float>  log (ILInArray< float > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<float>(A.Size); 
+                ILSize inDim = A.Size;
+                float[] arrA = A.GetArrayForRead(); 
+                float [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (true) {
+                    retArr = ILMemoryPool.Pool.New<float>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<float> retStorage = new ILDenseStorage<float>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    float* cp = ((float*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  (float)Math.Log(cp[0]  )  /*dummy*/;
+                            cp[1] =  (float)Math.Log(cp[1]  )  /*dummy*/;
+                            cp[2] =  (float)Math.Log(cp[2]  )  /*dummy*/;
+                            cp[3] =  (float)Math.Log(cp[3]  )  /*dummy*/;
+                            cp[4] =  (float)Math.Log(cp[4]  )  /*dummy*/;
+                            cp[5] =  (float)Math.Log(cp[5]  )  /*dummy*/;
+                            cp[6] =  (float)Math.Log(cp[6]  )  /*dummy*/;
+                            cp[7] =  (float)Math.Log(cp[7]  )  /*dummy*/;
+                            cp[8] =  (float)Math.Log(cp[8]  )  /*dummy*/;
+                            cp[9] =  (float)Math.Log(cp[9]  )  /*dummy*/;
+                            cp[10] =  (float)Math.Log(cp[10]  )  /*dummy*/;
+                            cp[11] =  (float)Math.Log(cp[11]  )  /*dummy*/;
+                            cp[12] =  (float)Math.Log(cp[12]  )  /*dummy*/;
+                            cp[13] =  (float)Math.Log(cp[13]  )  /*dummy*/;
+                            cp[14] =  (float)Math.Log(cp[14]  )  /*dummy*/;
+                            cp[15] =  (float)Math.Log(cp[15]  )  /*dummy*/;
+                            cp[16] =  (float)Math.Log(cp[16]  )  /*dummy*/;
+                            cp[17] =  (float)Math.Log(cp[17]  )  /*dummy*/;
+                            cp[18] =  (float)Math.Log(cp[18]  )  /*dummy*/;
+                            cp[19] =  (float)Math.Log(cp[19]  )  /*dummy*/;
+                            cp[20] =  (float)Math.Log(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  (float)Math.Log(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        float* ap = ((float*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  (float)Math.Log(ap[0]  )  /*dummy*/;
+                            cp[1] =  (float)Math.Log(ap[1]  )  /*dummy*/;
+                            cp[2] =  (float)Math.Log(ap[2]  )  /*dummy*/;
+                            cp[3] =  (float)Math.Log(ap[3]  )  /*dummy*/;
+                            cp[4] =  (float)Math.Log(ap[4]  )  /*dummy*/;
+                            cp[5] =  (float)Math.Log(ap[5]  )  /*dummy*/;
+                            cp[6] =  (float)Math.Log(ap[6]  )  /*dummy*/;
+                            cp[7] =  (float)Math.Log(ap[7]  )  /*dummy*/;
+                            cp[8] =  (float)Math.Log(ap[8]  )  /*dummy*/;
+                            cp[9] =  (float)Math.Log(ap[9]  )  /*dummy*/;
+                            cp[10] =  (float)Math.Log(ap[10]  )  /*dummy*/;
+                            cp[11] =  (float)Math.Log(ap[11]  )  /*dummy*/;
+                            cp[12] =  (float)Math.Log(ap[12]  )  /*dummy*/;
+                            cp[13] =  (float)Math.Log(ap[13]  )  /*dummy*/;
+                            cp[14] =  (float)Math.Log(ap[14]  )  /*dummy*/;
+                            cp[15] =  (float)Math.Log(ap[15]  )  /*dummy*/;
+                            cp[16] =  (float)Math.Log(ap[16]  )  /*dummy*/;
+                            cp[17] =  (float)Math.Log(ap[17]  )  /*dummy*/;
+                            cp[18] =  (float)Math.Log(ap[18]  )  /*dummy*/;
+                            cp[19] =  (float)Math.Log(ap[19]  )  /*dummy*/;
+                            cp[20] =  (float)Math.Log(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  (float)Math.Log(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( float* arrAP = arrA)
+                fixed ( float* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<float>(retStorage);
+            }
+        }
+        /// <summary>Logarithm of array elements - real output</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Logarithm of array elements - real output</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<double>  log (ILInArray< double > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<double>(A.Size); 
+                ILSize inDim = A.Size;
+                double[] arrA = A.GetArrayForRead(); 
+                double [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (true) {
+                    retArr = ILMemoryPool.Pool.New<double>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<double> retStorage = new ILDenseStorage<double>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    double* cp = ((double*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  Math.Log(cp[0]  )  /*dummy*/;
+                            cp[1] =  Math.Log(cp[1]  )  /*dummy*/;
+                            cp[2] =  Math.Log(cp[2]  )  /*dummy*/;
+                            cp[3] =  Math.Log(cp[3]  )  /*dummy*/;
+                            cp[4] =  Math.Log(cp[4]  )  /*dummy*/;
+                            cp[5] =  Math.Log(cp[5]  )  /*dummy*/;
+                            cp[6] =  Math.Log(cp[6]  )  /*dummy*/;
+                            cp[7] =  Math.Log(cp[7]  )  /*dummy*/;
+                            cp[8] =  Math.Log(cp[8]  )  /*dummy*/;
+                            cp[9] =  Math.Log(cp[9]  )  /*dummy*/;
+                            cp[10] =  Math.Log(cp[10]  )  /*dummy*/;
+                            cp[11] =  Math.Log(cp[11]  )  /*dummy*/;
+                            cp[12] =  Math.Log(cp[12]  )  /*dummy*/;
+                            cp[13] =  Math.Log(cp[13]  )  /*dummy*/;
+                            cp[14] =  Math.Log(cp[14]  )  /*dummy*/;
+                            cp[15] =  Math.Log(cp[15]  )  /*dummy*/;
+                            cp[16] =  Math.Log(cp[16]  )  /*dummy*/;
+                            cp[17] =  Math.Log(cp[17]  )  /*dummy*/;
+                            cp[18] =  Math.Log(cp[18]  )  /*dummy*/;
+                            cp[19] =  Math.Log(cp[19]  )  /*dummy*/;
+                            cp[20] =  Math.Log(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Math.Log(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        double* ap = ((double*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  Math.Log(ap[0]  )  /*dummy*/;
+                            cp[1] =  Math.Log(ap[1]  )  /*dummy*/;
+                            cp[2] =  Math.Log(ap[2]  )  /*dummy*/;
+                            cp[3] =  Math.Log(ap[3]  )  /*dummy*/;
+                            cp[4] =  Math.Log(ap[4]  )  /*dummy*/;
+                            cp[5] =  Math.Log(ap[5]  )  /*dummy*/;
+                            cp[6] =  Math.Log(ap[6]  )  /*dummy*/;
+                            cp[7] =  Math.Log(ap[7]  )  /*dummy*/;
+                            cp[8] =  Math.Log(ap[8]  )  /*dummy*/;
+                            cp[9] =  Math.Log(ap[9]  )  /*dummy*/;
+                            cp[10] =  Math.Log(ap[10]  )  /*dummy*/;
+                            cp[11] =  Math.Log(ap[11]  )  /*dummy*/;
+                            cp[12] =  Math.Log(ap[12]  )  /*dummy*/;
+                            cp[13] =  Math.Log(ap[13]  )  /*dummy*/;
+                            cp[14] =  Math.Log(ap[14]  )  /*dummy*/;
+                            cp[15] =  Math.Log(ap[15]  )  /*dummy*/;
+                            cp[16] =  Math.Log(ap[16]  )  /*dummy*/;
+                            cp[17] =  Math.Log(ap[17]  )  /*dummy*/;
+                            cp[18] =  Math.Log(ap[18]  )  /*dummy*/;
+                            cp[19] =  Math.Log(ap[19]  )  /*dummy*/;
+                            cp[20] =  Math.Log(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Math.Log(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( double* arrAP = arrA)
+                fixed ( double* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<double>(retStorage);
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/log10.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/log10.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/log10.cs	(revision 9102)
@@ -0,0 +1,807 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics;
+using ILNumerics.Exceptions; 
+using ILNumerics.Storage; 
+using ILNumerics.Misc;
+
+
+
+namespace ILNumerics {
+
+    public partial class ILMath {
+
+
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>Logarithm of base 10 of array elements - complex output</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Complex logarithm of base 10 of array elements - complex output</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<fcomplex>  log10c (ILInArray< float > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<fcomplex>(A.Size); 
+                ILSize inDim = A.Size;
+                float[] arrA = A.GetArrayForRead(); 
+                fcomplex [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (true) {
+                    retArr = ILMemoryPool.Pool.New<fcomplex>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<fcomplex> retStorage = new ILDenseStorage<fcomplex>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    fcomplex* cp = ((fcomplex*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  fcomplex.Log10(cp[0]  )  /*dummy*/;
+                            cp[1] =  fcomplex.Log10(cp[1]  )  /*dummy*/;
+                            cp[2] =  fcomplex.Log10(cp[2]  )  /*dummy*/;
+                            cp[3] =  fcomplex.Log10(cp[3]  )  /*dummy*/;
+                            cp[4] =  fcomplex.Log10(cp[4]  )  /*dummy*/;
+                            cp[5] =  fcomplex.Log10(cp[5]  )  /*dummy*/;
+                            cp[6] =  fcomplex.Log10(cp[6]  )  /*dummy*/;
+                            cp[7] =  fcomplex.Log10(cp[7]  )  /*dummy*/;
+                            cp[8] =  fcomplex.Log10(cp[8]  )  /*dummy*/;
+                            cp[9] =  fcomplex.Log10(cp[9]  )  /*dummy*/;
+                            cp[10] =  fcomplex.Log10(cp[10]  )  /*dummy*/;
+                            cp[11] =  fcomplex.Log10(cp[11]  )  /*dummy*/;
+                            cp[12] =  fcomplex.Log10(cp[12]  )  /*dummy*/;
+                            cp[13] =  fcomplex.Log10(cp[13]  )  /*dummy*/;
+                            cp[14] =  fcomplex.Log10(cp[14]  )  /*dummy*/;
+                            cp[15] =  fcomplex.Log10(cp[15]  )  /*dummy*/;
+                            cp[16] =  fcomplex.Log10(cp[16]  )  /*dummy*/;
+                            cp[17] =  fcomplex.Log10(cp[17]  )  /*dummy*/;
+                            cp[18] =  fcomplex.Log10(cp[18]  )  /*dummy*/;
+                            cp[19] =  fcomplex.Log10(cp[19]  )  /*dummy*/;
+                            cp[20] =  fcomplex.Log10(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.Log10(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        float* ap = ((float*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  fcomplex.Log10(ap[0]  )  /*dummy*/;
+                            cp[1] =  fcomplex.Log10(ap[1]  )  /*dummy*/;
+                            cp[2] =  fcomplex.Log10(ap[2]  )  /*dummy*/;
+                            cp[3] =  fcomplex.Log10(ap[3]  )  /*dummy*/;
+                            cp[4] =  fcomplex.Log10(ap[4]  )  /*dummy*/;
+                            cp[5] =  fcomplex.Log10(ap[5]  )  /*dummy*/;
+                            cp[6] =  fcomplex.Log10(ap[6]  )  /*dummy*/;
+                            cp[7] =  fcomplex.Log10(ap[7]  )  /*dummy*/;
+                            cp[8] =  fcomplex.Log10(ap[8]  )  /*dummy*/;
+                            cp[9] =  fcomplex.Log10(ap[9]  )  /*dummy*/;
+                            cp[10] =  fcomplex.Log10(ap[10]  )  /*dummy*/;
+                            cp[11] =  fcomplex.Log10(ap[11]  )  /*dummy*/;
+                            cp[12] =  fcomplex.Log10(ap[12]  )  /*dummy*/;
+                            cp[13] =  fcomplex.Log10(ap[13]  )  /*dummy*/;
+                            cp[14] =  fcomplex.Log10(ap[14]  )  /*dummy*/;
+                            cp[15] =  fcomplex.Log10(ap[15]  )  /*dummy*/;
+                            cp[16] =  fcomplex.Log10(ap[16]  )  /*dummy*/;
+                            cp[17] =  fcomplex.Log10(ap[17]  )  /*dummy*/;
+                            cp[18] =  fcomplex.Log10(ap[18]  )  /*dummy*/;
+                            cp[19] =  fcomplex.Log10(ap[19]  )  /*dummy*/;
+                            cp[20] =  fcomplex.Log10(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.Log10(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( float* arrAP = arrA)
+                fixed ( fcomplex* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<fcomplex>(retStorage);
+            }
+        }
+        /// <summary>Logarithm of base 10 of array elements - complex output</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Complex logarithm of base 10 of array elements - complex output</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<complex>  log10c (ILInArray< double > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<complex>(A.Size); 
+                ILSize inDim = A.Size;
+                double[] arrA = A.GetArrayForRead(); 
+                complex [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (true) {
+                    retArr = ILMemoryPool.Pool.New<complex>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<complex> retStorage = new ILDenseStorage<complex>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    complex* cp = ((complex*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  complex.Log10(cp[0]  )  /*dummy*/;
+                            cp[1] =  complex.Log10(cp[1]  )  /*dummy*/;
+                            cp[2] =  complex.Log10(cp[2]  )  /*dummy*/;
+                            cp[3] =  complex.Log10(cp[3]  )  /*dummy*/;
+                            cp[4] =  complex.Log10(cp[4]  )  /*dummy*/;
+                            cp[5] =  complex.Log10(cp[5]  )  /*dummy*/;
+                            cp[6] =  complex.Log10(cp[6]  )  /*dummy*/;
+                            cp[7] =  complex.Log10(cp[7]  )  /*dummy*/;
+                            cp[8] =  complex.Log10(cp[8]  )  /*dummy*/;
+                            cp[9] =  complex.Log10(cp[9]  )  /*dummy*/;
+                            cp[10] =  complex.Log10(cp[10]  )  /*dummy*/;
+                            cp[11] =  complex.Log10(cp[11]  )  /*dummy*/;
+                            cp[12] =  complex.Log10(cp[12]  )  /*dummy*/;
+                            cp[13] =  complex.Log10(cp[13]  )  /*dummy*/;
+                            cp[14] =  complex.Log10(cp[14]  )  /*dummy*/;
+                            cp[15] =  complex.Log10(cp[15]  )  /*dummy*/;
+                            cp[16] =  complex.Log10(cp[16]  )  /*dummy*/;
+                            cp[17] =  complex.Log10(cp[17]  )  /*dummy*/;
+                            cp[18] =  complex.Log10(cp[18]  )  /*dummy*/;
+                            cp[19] =  complex.Log10(cp[19]  )  /*dummy*/;
+                            cp[20] =  complex.Log10(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.Log10(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        double* ap = ((double*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  complex.Log10(ap[0]  )  /*dummy*/;
+                            cp[1] =  complex.Log10(ap[1]  )  /*dummy*/;
+                            cp[2] =  complex.Log10(ap[2]  )  /*dummy*/;
+                            cp[3] =  complex.Log10(ap[3]  )  /*dummy*/;
+                            cp[4] =  complex.Log10(ap[4]  )  /*dummy*/;
+                            cp[5] =  complex.Log10(ap[5]  )  /*dummy*/;
+                            cp[6] =  complex.Log10(ap[6]  )  /*dummy*/;
+                            cp[7] =  complex.Log10(ap[7]  )  /*dummy*/;
+                            cp[8] =  complex.Log10(ap[8]  )  /*dummy*/;
+                            cp[9] =  complex.Log10(ap[9]  )  /*dummy*/;
+                            cp[10] =  complex.Log10(ap[10]  )  /*dummy*/;
+                            cp[11] =  complex.Log10(ap[11]  )  /*dummy*/;
+                            cp[12] =  complex.Log10(ap[12]  )  /*dummy*/;
+                            cp[13] =  complex.Log10(ap[13]  )  /*dummy*/;
+                            cp[14] =  complex.Log10(ap[14]  )  /*dummy*/;
+                            cp[15] =  complex.Log10(ap[15]  )  /*dummy*/;
+                            cp[16] =  complex.Log10(ap[16]  )  /*dummy*/;
+                            cp[17] =  complex.Log10(ap[17]  )  /*dummy*/;
+                            cp[18] =  complex.Log10(ap[18]  )  /*dummy*/;
+                            cp[19] =  complex.Log10(ap[19]  )  /*dummy*/;
+                            cp[20] =  complex.Log10(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.Log10(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( double* arrAP = arrA)
+                fixed ( complex* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<complex>(retStorage);
+            }
+        }
+        /// <summary>Logarithm of base 10 of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Complex logarithm of base 10 of array elements</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<complex>  log10 (ILInArray< complex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<complex>(A.Size); 
+                ILSize inDim = A.Size;
+                complex[] arrA = A.GetArrayForRead(); 
+                complex [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (true) {
+                    retArr = ILMemoryPool.Pool.New<complex>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<complex> retStorage = new ILDenseStorage<complex>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    complex* cp = ((complex*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  complex.Log10(cp[0]  )  /*dummy*/;
+                            cp[1] =  complex.Log10(cp[1]  )  /*dummy*/;
+                            cp[2] =  complex.Log10(cp[2]  )  /*dummy*/;
+                            cp[3] =  complex.Log10(cp[3]  )  /*dummy*/;
+                            cp[4] =  complex.Log10(cp[4]  )  /*dummy*/;
+                            cp[5] =  complex.Log10(cp[5]  )  /*dummy*/;
+                            cp[6] =  complex.Log10(cp[6]  )  /*dummy*/;
+                            cp[7] =  complex.Log10(cp[7]  )  /*dummy*/;
+                            cp[8] =  complex.Log10(cp[8]  )  /*dummy*/;
+                            cp[9] =  complex.Log10(cp[9]  )  /*dummy*/;
+                            cp[10] =  complex.Log10(cp[10]  )  /*dummy*/;
+                            cp[11] =  complex.Log10(cp[11]  )  /*dummy*/;
+                            cp[12] =  complex.Log10(cp[12]  )  /*dummy*/;
+                            cp[13] =  complex.Log10(cp[13]  )  /*dummy*/;
+                            cp[14] =  complex.Log10(cp[14]  )  /*dummy*/;
+                            cp[15] =  complex.Log10(cp[15]  )  /*dummy*/;
+                            cp[16] =  complex.Log10(cp[16]  )  /*dummy*/;
+                            cp[17] =  complex.Log10(cp[17]  )  /*dummy*/;
+                            cp[18] =  complex.Log10(cp[18]  )  /*dummy*/;
+                            cp[19] =  complex.Log10(cp[19]  )  /*dummy*/;
+                            cp[20] =  complex.Log10(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.Log10(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        complex* ap = ((complex*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  complex.Log10(ap[0]  )  /*dummy*/;
+                            cp[1] =  complex.Log10(ap[1]  )  /*dummy*/;
+                            cp[2] =  complex.Log10(ap[2]  )  /*dummy*/;
+                            cp[3] =  complex.Log10(ap[3]  )  /*dummy*/;
+                            cp[4] =  complex.Log10(ap[4]  )  /*dummy*/;
+                            cp[5] =  complex.Log10(ap[5]  )  /*dummy*/;
+                            cp[6] =  complex.Log10(ap[6]  )  /*dummy*/;
+                            cp[7] =  complex.Log10(ap[7]  )  /*dummy*/;
+                            cp[8] =  complex.Log10(ap[8]  )  /*dummy*/;
+                            cp[9] =  complex.Log10(ap[9]  )  /*dummy*/;
+                            cp[10] =  complex.Log10(ap[10]  )  /*dummy*/;
+                            cp[11] =  complex.Log10(ap[11]  )  /*dummy*/;
+                            cp[12] =  complex.Log10(ap[12]  )  /*dummy*/;
+                            cp[13] =  complex.Log10(ap[13]  )  /*dummy*/;
+                            cp[14] =  complex.Log10(ap[14]  )  /*dummy*/;
+                            cp[15] =  complex.Log10(ap[15]  )  /*dummy*/;
+                            cp[16] =  complex.Log10(ap[16]  )  /*dummy*/;
+                            cp[17] =  complex.Log10(ap[17]  )  /*dummy*/;
+                            cp[18] =  complex.Log10(ap[18]  )  /*dummy*/;
+                            cp[19] =  complex.Log10(ap[19]  )  /*dummy*/;
+                            cp[20] =  complex.Log10(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.Log10(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( complex* arrAP = arrA)
+                fixed ( complex* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<complex>(retStorage);
+            }
+        }
+        /// <summary>Logarithm of base 10 of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Complex logarithm of base 10 of array elements</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<fcomplex>  log10 (ILInArray< fcomplex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<fcomplex>(A.Size); 
+                ILSize inDim = A.Size;
+                fcomplex[] arrA = A.GetArrayForRead(); 
+                fcomplex [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (true) {
+                    retArr = ILMemoryPool.Pool.New<fcomplex>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<fcomplex> retStorage = new ILDenseStorage<fcomplex>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    fcomplex* cp = ((fcomplex*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  fcomplex.Log10(cp[0]  )  /*dummy*/;
+                            cp[1] =  fcomplex.Log10(cp[1]  )  /*dummy*/;
+                            cp[2] =  fcomplex.Log10(cp[2]  )  /*dummy*/;
+                            cp[3] =  fcomplex.Log10(cp[3]  )  /*dummy*/;
+                            cp[4] =  fcomplex.Log10(cp[4]  )  /*dummy*/;
+                            cp[5] =  fcomplex.Log10(cp[5]  )  /*dummy*/;
+                            cp[6] =  fcomplex.Log10(cp[6]  )  /*dummy*/;
+                            cp[7] =  fcomplex.Log10(cp[7]  )  /*dummy*/;
+                            cp[8] =  fcomplex.Log10(cp[8]  )  /*dummy*/;
+                            cp[9] =  fcomplex.Log10(cp[9]  )  /*dummy*/;
+                            cp[10] =  fcomplex.Log10(cp[10]  )  /*dummy*/;
+                            cp[11] =  fcomplex.Log10(cp[11]  )  /*dummy*/;
+                            cp[12] =  fcomplex.Log10(cp[12]  )  /*dummy*/;
+                            cp[13] =  fcomplex.Log10(cp[13]  )  /*dummy*/;
+                            cp[14] =  fcomplex.Log10(cp[14]  )  /*dummy*/;
+                            cp[15] =  fcomplex.Log10(cp[15]  )  /*dummy*/;
+                            cp[16] =  fcomplex.Log10(cp[16]  )  /*dummy*/;
+                            cp[17] =  fcomplex.Log10(cp[17]  )  /*dummy*/;
+                            cp[18] =  fcomplex.Log10(cp[18]  )  /*dummy*/;
+                            cp[19] =  fcomplex.Log10(cp[19]  )  /*dummy*/;
+                            cp[20] =  fcomplex.Log10(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.Log10(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        fcomplex* ap = ((fcomplex*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  fcomplex.Log10(ap[0]  )  /*dummy*/;
+                            cp[1] =  fcomplex.Log10(ap[1]  )  /*dummy*/;
+                            cp[2] =  fcomplex.Log10(ap[2]  )  /*dummy*/;
+                            cp[3] =  fcomplex.Log10(ap[3]  )  /*dummy*/;
+                            cp[4] =  fcomplex.Log10(ap[4]  )  /*dummy*/;
+                            cp[5] =  fcomplex.Log10(ap[5]  )  /*dummy*/;
+                            cp[6] =  fcomplex.Log10(ap[6]  )  /*dummy*/;
+                            cp[7] =  fcomplex.Log10(ap[7]  )  /*dummy*/;
+                            cp[8] =  fcomplex.Log10(ap[8]  )  /*dummy*/;
+                            cp[9] =  fcomplex.Log10(ap[9]  )  /*dummy*/;
+                            cp[10] =  fcomplex.Log10(ap[10]  )  /*dummy*/;
+                            cp[11] =  fcomplex.Log10(ap[11]  )  /*dummy*/;
+                            cp[12] =  fcomplex.Log10(ap[12]  )  /*dummy*/;
+                            cp[13] =  fcomplex.Log10(ap[13]  )  /*dummy*/;
+                            cp[14] =  fcomplex.Log10(ap[14]  )  /*dummy*/;
+                            cp[15] =  fcomplex.Log10(ap[15]  )  /*dummy*/;
+                            cp[16] =  fcomplex.Log10(ap[16]  )  /*dummy*/;
+                            cp[17] =  fcomplex.Log10(ap[17]  )  /*dummy*/;
+                            cp[18] =  fcomplex.Log10(ap[18]  )  /*dummy*/;
+                            cp[19] =  fcomplex.Log10(ap[19]  )  /*dummy*/;
+                            cp[20] =  fcomplex.Log10(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.Log10(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( fcomplex* arrAP = arrA)
+                fixed ( fcomplex* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<fcomplex>(retStorage);
+            }
+        }
+        /// <summary>Logarithm of base 10 of array elements - real output</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Logarithm of base 10 of array elements - real output</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<float>  log10 (ILInArray< float > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<float>(A.Size); 
+                ILSize inDim = A.Size;
+                float[] arrA = A.GetArrayForRead(); 
+                float [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (true) {
+                    retArr = ILMemoryPool.Pool.New<float>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<float> retStorage = new ILDenseStorage<float>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    float* cp = ((float*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  (float)Math.Log10(cp[0]  )  /*dummy*/;
+                            cp[1] =  (float)Math.Log10(cp[1]  )  /*dummy*/;
+                            cp[2] =  (float)Math.Log10(cp[2]  )  /*dummy*/;
+                            cp[3] =  (float)Math.Log10(cp[3]  )  /*dummy*/;
+                            cp[4] =  (float)Math.Log10(cp[4]  )  /*dummy*/;
+                            cp[5] =  (float)Math.Log10(cp[5]  )  /*dummy*/;
+                            cp[6] =  (float)Math.Log10(cp[6]  )  /*dummy*/;
+                            cp[7] =  (float)Math.Log10(cp[7]  )  /*dummy*/;
+                            cp[8] =  (float)Math.Log10(cp[8]  )  /*dummy*/;
+                            cp[9] =  (float)Math.Log10(cp[9]  )  /*dummy*/;
+                            cp[10] =  (float)Math.Log10(cp[10]  )  /*dummy*/;
+                            cp[11] =  (float)Math.Log10(cp[11]  )  /*dummy*/;
+                            cp[12] =  (float)Math.Log10(cp[12]  )  /*dummy*/;
+                            cp[13] =  (float)Math.Log10(cp[13]  )  /*dummy*/;
+                            cp[14] =  (float)Math.Log10(cp[14]  )  /*dummy*/;
+                            cp[15] =  (float)Math.Log10(cp[15]  )  /*dummy*/;
+                            cp[16] =  (float)Math.Log10(cp[16]  )  /*dummy*/;
+                            cp[17] =  (float)Math.Log10(cp[17]  )  /*dummy*/;
+                            cp[18] =  (float)Math.Log10(cp[18]  )  /*dummy*/;
+                            cp[19] =  (float)Math.Log10(cp[19]  )  /*dummy*/;
+                            cp[20] =  (float)Math.Log10(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  (float)Math.Log10(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        float* ap = ((float*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  (float)Math.Log10(ap[0]  )  /*dummy*/;
+                            cp[1] =  (float)Math.Log10(ap[1]  )  /*dummy*/;
+                            cp[2] =  (float)Math.Log10(ap[2]  )  /*dummy*/;
+                            cp[3] =  (float)Math.Log10(ap[3]  )  /*dummy*/;
+                            cp[4] =  (float)Math.Log10(ap[4]  )  /*dummy*/;
+                            cp[5] =  (float)Math.Log10(ap[5]  )  /*dummy*/;
+                            cp[6] =  (float)Math.Log10(ap[6]  )  /*dummy*/;
+                            cp[7] =  (float)Math.Log10(ap[7]  )  /*dummy*/;
+                            cp[8] =  (float)Math.Log10(ap[8]  )  /*dummy*/;
+                            cp[9] =  (float)Math.Log10(ap[9]  )  /*dummy*/;
+                            cp[10] =  (float)Math.Log10(ap[10]  )  /*dummy*/;
+                            cp[11] =  (float)Math.Log10(ap[11]  )  /*dummy*/;
+                            cp[12] =  (float)Math.Log10(ap[12]  )  /*dummy*/;
+                            cp[13] =  (float)Math.Log10(ap[13]  )  /*dummy*/;
+                            cp[14] =  (float)Math.Log10(ap[14]  )  /*dummy*/;
+                            cp[15] =  (float)Math.Log10(ap[15]  )  /*dummy*/;
+                            cp[16] =  (float)Math.Log10(ap[16]  )  /*dummy*/;
+                            cp[17] =  (float)Math.Log10(ap[17]  )  /*dummy*/;
+                            cp[18] =  (float)Math.Log10(ap[18]  )  /*dummy*/;
+                            cp[19] =  (float)Math.Log10(ap[19]  )  /*dummy*/;
+                            cp[20] =  (float)Math.Log10(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  (float)Math.Log10(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( float* arrAP = arrA)
+                fixed ( float* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<float>(retStorage);
+            }
+        }
+        /// <summary>Logarithm of base 10 of array elements - real output</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Logarithm of base 10 of array elements - real output</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<double>  log10 (ILInArray< double > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<double>(A.Size); 
+                ILSize inDim = A.Size;
+                double[] arrA = A.GetArrayForRead(); 
+                double [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (true) {
+                    retArr = ILMemoryPool.Pool.New<double>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<double> retStorage = new ILDenseStorage<double>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    double* cp = ((double*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  Math.Log10(cp[0]  )  /*dummy*/;
+                            cp[1] =  Math.Log10(cp[1]  )  /*dummy*/;
+                            cp[2] =  Math.Log10(cp[2]  )  /*dummy*/;
+                            cp[3] =  Math.Log10(cp[3]  )  /*dummy*/;
+                            cp[4] =  Math.Log10(cp[4]  )  /*dummy*/;
+                            cp[5] =  Math.Log10(cp[5]  )  /*dummy*/;
+                            cp[6] =  Math.Log10(cp[6]  )  /*dummy*/;
+                            cp[7] =  Math.Log10(cp[7]  )  /*dummy*/;
+                            cp[8] =  Math.Log10(cp[8]  )  /*dummy*/;
+                            cp[9] =  Math.Log10(cp[9]  )  /*dummy*/;
+                            cp[10] =  Math.Log10(cp[10]  )  /*dummy*/;
+                            cp[11] =  Math.Log10(cp[11]  )  /*dummy*/;
+                            cp[12] =  Math.Log10(cp[12]  )  /*dummy*/;
+                            cp[13] =  Math.Log10(cp[13]  )  /*dummy*/;
+                            cp[14] =  Math.Log10(cp[14]  )  /*dummy*/;
+                            cp[15] =  Math.Log10(cp[15]  )  /*dummy*/;
+                            cp[16] =  Math.Log10(cp[16]  )  /*dummy*/;
+                            cp[17] =  Math.Log10(cp[17]  )  /*dummy*/;
+                            cp[18] =  Math.Log10(cp[18]  )  /*dummy*/;
+                            cp[19] =  Math.Log10(cp[19]  )  /*dummy*/;
+                            cp[20] =  Math.Log10(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Math.Log10(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        double* ap = ((double*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  Math.Log10(ap[0]  )  /*dummy*/;
+                            cp[1] =  Math.Log10(ap[1]  )  /*dummy*/;
+                            cp[2] =  Math.Log10(ap[2]  )  /*dummy*/;
+                            cp[3] =  Math.Log10(ap[3]  )  /*dummy*/;
+                            cp[4] =  Math.Log10(ap[4]  )  /*dummy*/;
+                            cp[5] =  Math.Log10(ap[5]  )  /*dummy*/;
+                            cp[6] =  Math.Log10(ap[6]  )  /*dummy*/;
+                            cp[7] =  Math.Log10(ap[7]  )  /*dummy*/;
+                            cp[8] =  Math.Log10(ap[8]  )  /*dummy*/;
+                            cp[9] =  Math.Log10(ap[9]  )  /*dummy*/;
+                            cp[10] =  Math.Log10(ap[10]  )  /*dummy*/;
+                            cp[11] =  Math.Log10(ap[11]  )  /*dummy*/;
+                            cp[12] =  Math.Log10(ap[12]  )  /*dummy*/;
+                            cp[13] =  Math.Log10(ap[13]  )  /*dummy*/;
+                            cp[14] =  Math.Log10(ap[14]  )  /*dummy*/;
+                            cp[15] =  Math.Log10(ap[15]  )  /*dummy*/;
+                            cp[16] =  Math.Log10(ap[16]  )  /*dummy*/;
+                            cp[17] =  Math.Log10(ap[17]  )  /*dummy*/;
+                            cp[18] =  Math.Log10(ap[18]  )  /*dummy*/;
+                            cp[19] =  Math.Log10(ap[19]  )  /*dummy*/;
+                            cp[20] =  Math.Log10(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Math.Log10(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( double* arrAP = arrA)
+                fixed ( double* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<double>(retStorage);
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/logspace.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/logspace.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/logspace.cs	(revision 9102)
@@ -0,0 +1,78 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics;
+using ILNumerics.Exceptions;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+
+namespace ILNumerics {
+    public partial class ILMath {
+        /// <summary>
+        /// Create logarithmically spaced row vector of 30 elements 
+        /// </summary>
+        /// <param name="start">First exponent value</param>
+        /// <param name="end">Last exponent value</param>
+        /// <returns>Row vector with 30 elements logathmically spaced between 10^start and 10^end</returns>
+        public static ILRetArray<double> logspace (ILInArray<double> start, ILInArray<double> end) {
+            return logspace(start, end,30); 
+        }
+
+        /// <summary>
+        /// Create logarithmically spaced row vector
+        /// </summary>
+        /// <param name="start">First exponent value</param>
+        /// <param name="end">Last exponent value</param>
+        /// <param name="length">Number of elements to create</param>
+        /// <returns>Row vector with 'length' elements logarithmically spaced between 10^start and 10^end</returns>
+        public static ILRetArray<double> logspace (ILInArray<double> start, ILInArray<double> end, ILInArray<double> length) {
+            using (ILScope.Enter(start,end, length)) {
+                if (end == ILMath.pi)
+                    end = Math.Log10(pi); 
+                if (length < 2) 
+                    return new ILRetArray<double>(new double[1]{Math.Pow(10,(double)end)},1,1); 
+                ILArray<double> fact = ( end - start ) / (length - 1); 
+                return pow(10.0, linspace<double>(start,end,length));  
+            }
+        }    
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/lt.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/lt.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/lt.cs	(revision 9102)
@@ -0,0 +1,1954 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.InteropServices; 
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Native;
+using ILNumerics.Exceptions;
+
+
+
+namespace ILNumerics {
+
+	public partial class ILMath {
+
+
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>Elementwise logical 'smaller than' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array having '1' for elements in A being smaller than corresponding elements in B, '0' else</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  lt(ILInArray<Int64> A, ILInArray<Int64> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                Int64[] arrA = A.GetArrayForRead();
+               
+                Int64[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                       
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0)  < B.GetValue(0)) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  ltEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    Int64 scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            Int64* ap = ((Int64*)range.Item3 + range.Item1);
+                            Int64* bp = ((Int64*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  < *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((Int64*)range.Item3 + range.Item1);
+                            scalar = *((Int64*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  < scalar) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((Int64*)range.Item3);
+                            bp = ((Int64*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (scalar  < *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (Int64* arrAP = arrA)
+                fixed (Int64* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  ltEx(ILInArray<Int64> A, ILInArray<Int64> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                Int64[] arrA = A.GetArrayForRead();
+               
+                Int64[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    Int64* ap;
+                   
+                    Int64* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (Int64*)range.Item3;
+                                bp = (Int64*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  < *bp) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (Int64*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (Int64*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  < *bp) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( Int64* arrAP = arrA)
+                fixed ( Int64* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'smaller than' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array having '1' for elements in A being smaller than corresponding elements in B, '0' else</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  lt(ILInArray<Int32> A, ILInArray<Int32> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                Int32[] arrA = A.GetArrayForRead();
+               
+                Int32[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                       
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0)  < B.GetValue(0)) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  ltEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    Int32 scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            Int32* ap = ((Int32*)range.Item3 + range.Item1);
+                            Int32* bp = ((Int32*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  < *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((Int32*)range.Item3 + range.Item1);
+                            scalar = *((Int32*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  < scalar) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((Int32*)range.Item3);
+                            bp = ((Int32*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (scalar  < *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (Int32* arrAP = arrA)
+                fixed (Int32* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  ltEx(ILInArray<Int32> A, ILInArray<Int32> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                Int32[] arrA = A.GetArrayForRead();
+               
+                Int32[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    Int32* ap;
+                   
+                    Int32* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (Int32*)range.Item3;
+                                bp = (Int32*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  < *bp) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (Int32*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (Int32*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  < *bp) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( Int32* arrAP = arrA)
+                fixed ( Int32* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'smaller than' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array having '1' for elements in A being smaller than corresponding elements in B, '0' else</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  lt(ILInArray<float> A, ILInArray<float> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                float[] arrA = A.GetArrayForRead();
+               
+                float[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                       
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0)  < B.GetValue(0)) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  ltEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    float scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            float* ap = ((float*)range.Item3 + range.Item1);
+                            float* bp = ((float*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  < *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((float*)range.Item3 + range.Item1);
+                            scalar = *((float*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  < scalar) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((float*)range.Item3);
+                            bp = ((float*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (scalar  < *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (float* arrAP = arrA)
+                fixed (float* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  ltEx(ILInArray<float> A, ILInArray<float> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                float[] arrA = A.GetArrayForRead();
+               
+                float[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    float* ap;
+                   
+                    float* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (float*)range.Item3;
+                                bp = (float*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  < *bp) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (float*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (float*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  < *bp) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( float* arrAP = arrA)
+                fixed ( float* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'smaller than' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array having '1' for elements in A being smaller than corresponding elements in B, '0' else</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  lt(ILInArray<fcomplex> A, ILInArray<fcomplex> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                fcomplex[] arrA = A.GetArrayForRead();
+               
+                fcomplex[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                       
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0)  < B.GetValue(0)) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  ltEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    fcomplex scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            fcomplex* ap = ((fcomplex*)range.Item3 + range.Item1);
+                            fcomplex* bp = ((fcomplex*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  < *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((fcomplex*)range.Item3 + range.Item1);
+                            scalar = *((fcomplex*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  < scalar) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((fcomplex*)range.Item3);
+                            bp = ((fcomplex*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (scalar  < *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (fcomplex* arrAP = arrA)
+                fixed (fcomplex* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  ltEx(ILInArray<fcomplex> A, ILInArray<fcomplex> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                fcomplex[] arrA = A.GetArrayForRead();
+               
+                fcomplex[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    fcomplex* ap;
+                   
+                    fcomplex* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (fcomplex*)range.Item3;
+                                bp = (fcomplex*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  < *bp) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (fcomplex*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (fcomplex*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  < *bp) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( fcomplex* arrAP = arrA)
+                fixed ( fcomplex* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'smaller than' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array having '1' for elements in A being smaller than corresponding elements in B, '0' else</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  lt(ILInArray<complex> A, ILInArray<complex> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                complex[] arrA = A.GetArrayForRead();
+               
+                complex[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                       
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0)  < B.GetValue(0)) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  ltEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    complex scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            complex* ap = ((complex*)range.Item3 + range.Item1);
+                            complex* bp = ((complex*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  < *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((complex*)range.Item3 + range.Item1);
+                            scalar = *((complex*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  < scalar) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((complex*)range.Item3);
+                            bp = ((complex*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (scalar  < *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (complex* arrAP = arrA)
+                fixed (complex* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  ltEx(ILInArray<complex> A, ILInArray<complex> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                complex[] arrA = A.GetArrayForRead();
+               
+                complex[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    complex* ap;
+                   
+                    complex* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (complex*)range.Item3;
+                                bp = (complex*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  < *bp) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (complex*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (complex*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  < *bp) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( complex* arrAP = arrA)
+                fixed ( complex* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'smaller than' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array having '1' for elements in A being smaller than corresponding elements in B, '0' else</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  lt(ILInArray<byte> A, ILInArray<byte> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                byte[] arrA = A.GetArrayForRead();
+               
+                byte[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                       
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0)  < B.GetValue(0)) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  ltEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    byte scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            byte* ap = ((byte*)range.Item3 + range.Item1);
+                            byte* bp = ((byte*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  < *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((byte*)range.Item3 + range.Item1);
+                            scalar = *((byte*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  < scalar) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((byte*)range.Item3);
+                            bp = ((byte*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (scalar  < *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (byte* arrAP = arrA)
+                fixed (byte* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  ltEx(ILInArray<byte> A, ILInArray<byte> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                byte[] arrA = A.GetArrayForRead();
+               
+                byte[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    byte* ap;
+                   
+                    byte* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (byte*)range.Item3;
+                                bp = (byte*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  < *bp) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (byte*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (byte*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  < *bp) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( byte* arrAP = arrA)
+                fixed ( byte* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'smaller than' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array having '1' for elements in A being smaller than corresponding elements in B, '0' else</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  lt(ILInArray<double> A, ILInArray<double> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                double[] arrA = A.GetArrayForRead();
+               
+                double[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                       
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0)  < B.GetValue(0)) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  ltEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    double scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            double* ap = ((double*)range.Item3 + range.Item1);
+                            double* bp = ((double*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  < *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((double*)range.Item3 + range.Item1);
+                            scalar = *((double*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  < scalar) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((double*)range.Item3);
+                            bp = ((double*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (scalar  < *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (double* arrAP = arrA)
+                fixed (double* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  ltEx(ILInArray<double> A, ILInArray<double> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                double[] arrA = A.GetArrayForRead();
+               
+                double[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    double* ap;
+                   
+                    double* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (double*)range.Item3;
+                                bp = (double*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  < *bp) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (double*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (double*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  < *bp) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( double* arrAP = arrA)
+                fixed ( double* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+
+#endregion HYCALPER AUTO GENERATED CODE
+       
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/lu.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/lu.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/lu.cs	(revision 9102)
@@ -0,0 +1,927 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions;
+ 
+
+
+namespace ILNumerics {
+    public partial class ILMath {
+
+
+        /// <summary>
+        /// LU matrix decomposition. Decompose general matrix A into strictly upper part and lower part. 
+        /// </summary>
+        /// <param name="A">Input matrix. Size [m x n]</param>
+        /// <returns>Triangular matrices L and U composed into a single matrix as returned from LAPACK function ?getrf. Size [m x n]</returns>
+        /// <remarks><para>The matrix returned is composed out of the lower triangular matrix L with unit diagonal and the strict upper triangular matrix U.</para>
+        /// <code>
+        /// :'''''''|
+        /// |1 \    |
+        /// | 1 \ R |
+        /// |  1 \  |
+        /// | L 1 \ |
+        /// |    1 \|
+        /// '''''''''
+        /// </code>
+        /// <para>This overload is mainly needed for further operations via Lapack libraries. If you need the 
+        /// L and U matrices directly, you'd better use one of the overloaded versions 
+        /// <see cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double})"/>
+        ///  or <see cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double}, ILOutArray{double})"/> instead.</para>
+        /// <para>The matrix L will be a solid ILArray.</para>
+        /// <para>lu uses the Lapack function ?getrf.</para>
+        /// </remarks>
+        /// <seealso cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double}, ILOutArray{double})"/>
+        /// <seealso cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double})"/>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException"> if input A is not a matrix.</exception>
+        public static ILRetArray< double > lu(ILInArray<double> A) {
+            ILArray< double > U = null;
+            ILArray< double > P = null; 
+            return lu(A, U, P); 
+        }
+        /// <summary>
+        /// LU matrix decomposition. Decompose general matrix A into strictly upper part and lower part.
+        /// </summary>
+        /// <param name="A">Input matrix to be decomposed. Size [m x n]</param>
+        /// <param name="U">[Output] Reference to U. On return this will be the strict upper triangular matrix of size [min(m,n) x n]. Must not be null on input.</param>
+        /// <returns>Lower triangular matrix L of size [m x min(m,n)]</returns>
+        /// <remarks>A is decomposed into L and U, so that ILMath.multiply (L,U) will result in A.
+        /// <para>L will only be a permuted version of a true triangular matrix. I.e. the rows of L will be permuted in order 
+        /// to fullfill <c>ILMath.multiply(L,U) == A</c></para>
+        /// <example> <code>
+        /// //we construct a matrix X: 
+        /// ILArray&lt;double&gt; X = new ILArray&lt;double&gt;(new double[]{1, 2, 3, 4, 4, 4, 5, 6, 7},3,3).T;
+        /// // now X.ToString() will give something like:
+        /// // {&lt;Double&gt; 63238509 [3x3] Ref(2) 
+        /// //(:,:) 
+        /// // 1,00000  2,00000  3,00000 
+        /// // 4,00000  4,00000  4,00000 
+        /// // 5,00000  6,00000  7,00000 
+        /// //}
+        /// // construct reference on U and call the decomposition
+        /// ILArray&lt;double&gt; U = new ILArray&lt;double&gt;.empty();
+        /// ILArray&lt;double&gt; L = ILMath.lu(X, ref U); 
+        /// 
+        /// // L.ToString() is now: 
+        /// // {&lt;Double&gt; 19634871 [3x3] Phys. 
+        /// //(:,:) 
+        /// // 0,20000  -1,00000  1,00000 
+        /// // 0,80000  1,00000  0,00000 
+        /// // 1,00000  0,00000  0,00000 
+        /// //}
+        /// // and U is now: 
+        /// //{&lt;Double&gt; 22584602 [3x3] Phys. 
+        /// //(:,:) 
+        /// // 5,00000  6,00000  7,00000 
+        /// // 0,00000  -0,80000  -1,60000 
+        /// // 0,00000  0,00000  0,00000 
+        /// //}
+        /// </code>
+        /// Pay attention to the structure of L. In the example above the first and third row are exchanged. This permutation reflects the pivoting done during the decomposition inside the Lapack function ?getrf. </example>
+        /// <para>In order to access the permutation of L, one can use the overloaded version <see cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double}, ILOutArray{double})"/> which returns the permuation matrix P also.</para>
+        /// <para>All of the matrices U and L returned will be solid ILArrays.</para>
+        /// <para>lu uses the Lapack function ?getrf.</para>
+        /// </remarks>
+        /// <seealso cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double}, ILOutArray{double})"/>
+        /// <seealso cref="ILNumerics.ILMath.lu(ILInArray{double})"/>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException"> if input A is not a matrix.</exception>
+        public static ILRetArray< double> lu(ILInArray<double> A, ILOutArray<double> U) {
+            return lu(A,U,null); 
+        }
+        /// <summary>
+        /// Decompose matrix A into uper and lower triangular part. Returns permutation matrix also. 
+        /// </summary>
+        /// <param name="A">Input matrix. Size [m x n]</param>
+        /// <param name="U">[Output] Reference to upper triangular matrix. Size [min(m,n) x n]. Must not be null.</param>
+        /// <param name="P">[Output] Reference to permutation matrix. Size [min(m,n) x min(m,n)]. Must not be null.</param>
+        /// <returns>Lower triangular matrix L of size [m x min(m,n)]</returns>
+        /// <remarks>A is decomposed into L and U, so that the equation 
+        /// <c>ILMath.multiply(L,U) == ILMath.multiply(P,A)</c> 
+        /// will hold except for round off error.
+        /// <para>L and U will be true lower triangular matrices.</para>
+        /// <example> <code>
+        /// //Let's construct a matrix X: 
+        /// ILArray&lt;double&gt; X = new ILArray&lt;double&gt;(new double[]{1, 2, 3, 4, 4, 4, 5, 6, 7},3,3).T;
+        /// // now X.ToString() will give something like:
+        /// // {&lt;Double&gt; 63238509 [3x3] Ref(2) 
+        /// //(:,:) 
+        /// // 1,00000  2,00000  3,00000 
+        /// // 4,00000  4,00000  4,00000 
+        /// // 5,00000  6,00000  7,00000 
+        /// //}
+        /// // construct references on U and P and call the decomposition
+        /// ILArray&lt;double&gt; U = new ILArray&lt;double&gt;.empty();
+        /// ILArray&lt;double&gt; P = new ILArray&lt;double&gt;.empty();
+        /// ILArray&lt;double&gt; L = ILMath.lu(X, ref U, ref P); 
+        /// 
+        /// // L.ToString() is now: 
+        /// // {&lt;Double&gt; 19634871 [3x3] Phys. 
+        /// //(:,:) 
+        /// // 1,00000   0,00000   0,00000 
+        /// // 0,80000   1,00000   0,00000 
+        /// // 0,20000  -1,00000   1,00000 
+        /// //}
+        /// // U is now: 
+        /// //{&lt;Double&gt; 22584602 [3x3] Phys. 
+        /// //(:,:) 
+        /// // 5,00000  6,00000  7,00000 
+        /// // 0,00000  -0,80000  -1,60000 
+        /// // 0,00000  0,00000  0,00000 
+        /// //}
+        /// // and P is: 
+        /// //{&lt;Double&gt; 2192437 [3x3] Phys. 
+        /// //(:,:) 
+        /// // 0,00000  0,00000  1,00000 
+        /// // 0,00000  1,00000  0,00000 
+        /// // 1,00000  0,00000  0,00000 
+        /// //}
+        /// </code>
+        /// In order to reflect the pivoting done during the decomposition inside ?getrf, the matrix P may be used on A:
+        /// <code>
+        /// (ILMath.multiply(P,A) - ILMath.multiply(L,U)).ToString();
+        /// // will give:
+        /// //{&lt;Double&gt; 59192235 [3x3] Phys. 
+        /// //(:,:) 
+        /// // 0,00000  0,00000  0,00000 
+        /// // 0,00000  0,00000  0,00000 
+        /// // 0,00000  0,00000  0,00000 
+        /// //}
+        /// </code>
+        /// </example>
+        /// <para>lu uses the Lapack function ?getrf.</para>
+        /// <para>All of the matrices U,L,P returned will be solid ILArrays.</para>
+        /// </remarks>
+        /// <seealso cref="ILNumerics.ILMath.lu(ILInArray{double})"/>
+        /// <seealso cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double})"/>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException"> if input A is not a matrix.</exception>
+        public static ILRetArray< double> lu(ILInArray<double> A, ILOutArray<double> U
+                                                            , ILOutArray< double> P) {
+            using (ILScope.Enter(A)) {
+                if (!A.IsMatrix)
+                    throw new ILArgumentSizeException("lu is defined for matrices only!");
+                int m = A.Size[0], n = A.Size[1], info = 0, minMN = (m < n) ? m : n;
+                ILArray< double> L = A.C;
+                int[] pivInd = ILMemoryPool.Pool.New<int>(minMN);
+                /*!HC:lapack_*getrf*/
+                Lapack.dgetrf(m, n, L.GetArrayForWrite(), m, pivInd, ref info);
+                if (info < 0) {
+                    ILMemoryPool.Pool.Free(pivInd);
+                    throw new ILArgumentException("invalid parameter");
+                    //} else if (info > 0) {
+                    //    // singular diagonal entry found 
+
+                } else {
+                    // completed successfuly 
+                    if (!Object.Equals(U, null)) {
+                        if (!Object.Equals(P, null)) {
+                            pivInd = perm2indicesForward(pivInd);
+                            U.a = copyUpperTriangle<double>(L, minMN, n);
+                            L.a = copyLowerTriangle<double>(L, m, minMN, 1);
+                            P.a = zeros< double>(new ILSize(minMN, minMN));
+                            // construct permutation matrix P 
+                            for (int r = 0; r < m; r++) {
+                                P[r, pivInd[r]] =  1.0;
+                            }
+                        } else {
+                            pivInd = perm2indicesBackward(pivInd);
+                            U.a = copyUpperTriangle<double>(L, minMN, n);
+                            L.a = copyLowerTrianglePerm< double>(L, m, minMN, 1, pivInd);
+                        }
+                    }
+                }
+                ILMemoryPool.Pool.Free(pivInd);
+                return L;
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// LU matrix decomposition. Decompose general matrix A into strictly upper part and lower part. 
+        /// </summary>
+        /// <param name="A">Input matrix. Size [m x n]</param>
+        /// <returns>Triangular matrices L and U composed into a single matrix as returned from LAPACK function ?getrf. Size [m x n]</returns>
+        /// <remarks><para>The matrix returned is composed out of the lower triangular matrix L with unit diagonal and the strict upper triangular matrix U.</para>
+        /// <code>
+        /// :'''''''|
+        /// |1 \    |
+        /// | 1 \ R |
+        /// |  1 \  |
+        /// | L 1 \ |
+        /// |    1 \|
+        /// '''''''''
+        /// </code>
+        /// <para>This overload is mainly needed for further operations via Lapack libraries. If you need the 
+        /// L and U matrices directly, you'd better use one of the overloaded versions 
+        /// <see cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double})"/>
+        ///  or <see cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double}, ILOutArray{double})"/> instead.</para>
+        /// <para>The matrix L will be a solid ILArray.</para>
+        /// <para>lu uses the Lapack function ?getrf.</para>
+        /// </remarks>
+        /// <seealso cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double}, ILOutArray{double})"/>
+        /// <seealso cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double})"/>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException"> if input A is not a matrix.</exception>
+        public static ILRetArray< float > lu(ILInArray<float> A) {
+            ILArray< float > U = null;
+            ILArray< float > P = null; 
+            return lu(A, U, P); 
+        }
+        /// <summary>
+        /// LU matrix decomposition. Decompose general matrix A into strictly upper part and lower part.
+        /// </summary>
+        /// <param name="A">Input matrix to be decomposed. Size [m x n]</param>
+        /// <param name="U">[Output] Reference to U. On return this will be the strict upper triangular matrix of size [min(m,n) x n]. Must not be null on input.</param>
+        /// <returns>Lower triangular matrix L of size [m x min(m,n)]</returns>
+        /// <remarks>A is decomposed into L and U, so that ILMath.multiply (L,U) will result in A.
+        /// <para>L will only be a permuted version of a true triangular matrix. I.e. the rows of L will be permuted in order 
+        /// to fullfill <c>ILMath.multiply(L,U) == A</c></para>
+        /// <example> <code>
+        /// //we construct a matrix X: 
+        /// ILArray&lt;double&gt; X = new ILArray&lt;double&gt;(new double[]{1, 2, 3, 4, 4, 4, 5, 6, 7},3,3).T;
+        /// // now X.ToString() will give something like:
+        /// // {&lt;Double&gt; 63238509 [3x3] Ref(2) 
+        /// //(:,:) 
+        /// // 1,00000  2,00000  3,00000 
+        /// // 4,00000  4,00000  4,00000 
+        /// // 5,00000  6,00000  7,00000 
+        /// //}
+        /// // construct reference on U and call the decomposition
+        /// ILArray&lt;double&gt; U = new ILArray&lt;double&gt;.empty();
+        /// ILArray&lt;double&gt; L = ILMath.lu(X, ref U); 
+        /// 
+        /// // L.ToString() is now: 
+        /// // {&lt;Double&gt; 19634871 [3x3] Phys. 
+        /// //(:,:) 
+        /// // 0,20000  -1,00000  1,00000 
+        /// // 0,80000  1,00000  0,00000 
+        /// // 1,00000  0,00000  0,00000 
+        /// //}
+        /// // and U is now: 
+        /// //{&lt;Double&gt; 22584602 [3x3] Phys. 
+        /// //(:,:) 
+        /// // 5,00000  6,00000  7,00000 
+        /// // 0,00000  -0,80000  -1,60000 
+        /// // 0,00000  0,00000  0,00000 
+        /// //}
+        /// </code>
+        /// Pay attention to the structure of L. In the example above the first and third row are exchanged. This permutation reflects the pivoting done during the decomposition inside the Lapack function ?getrf. </example>
+        /// <para>In order to access the permutation of L, one can use the overloaded version <see cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double}, ILOutArray{double})"/> which returns the permuation matrix P also.</para>
+        /// <para>All of the matrices U and L returned will be solid ILArrays.</para>
+        /// <para>lu uses the Lapack function ?getrf.</para>
+        /// </remarks>
+        /// <seealso cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double}, ILOutArray{double})"/>
+        /// <seealso cref="ILNumerics.ILMath.lu(ILInArray{double})"/>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException"> if input A is not a matrix.</exception>
+        public static ILRetArray< float> lu(ILInArray<float> A, ILOutArray<float> U) {
+            return lu(A,U,null); 
+        }
+        /// <summary>
+        /// Decompose matrix A into uper and lower triangular part. Returns permutation matrix also. 
+        /// </summary>
+        /// <param name="A">Input matrix. Size [m x n]</param>
+        /// <param name="U">[Output] Reference to upper triangular matrix. Size [min(m,n) x n]. Must not be null.</param>
+        /// <param name="P">[Output] Reference to permutation matrix. Size [min(m,n) x min(m,n)]. Must not be null.</param>
+        /// <returns>Lower triangular matrix L of size [m x min(m,n)]</returns>
+        /// <remarks>A is decomposed into L and U, so that the equation 
+        /// <c>ILMath.multiply(L,U) == ILMath.multiply(P,A)</c> 
+        /// will hold except for round off error.
+        /// <para>L and U will be true lower triangular matrices.</para>
+        /// <example> <code>
+        /// //Let's construct a matrix X: 
+        /// ILArray&lt;double&gt; X = new ILArray&lt;double&gt;(new double[]{1, 2, 3, 4, 4, 4, 5, 6, 7},3,3).T;
+        /// // now X.ToString() will give something like:
+        /// // {&lt;Double&gt; 63238509 [3x3] Ref(2) 
+        /// //(:,:) 
+        /// // 1,00000  2,00000  3,00000 
+        /// // 4,00000  4,00000  4,00000 
+        /// // 5,00000  6,00000  7,00000 
+        /// //}
+        /// // construct references on U and P and call the decomposition
+        /// ILArray&lt;double&gt; U = new ILArray&lt;double&gt;.empty();
+        /// ILArray&lt;double&gt; P = new ILArray&lt;double&gt;.empty();
+        /// ILArray&lt;double&gt; L = ILMath.lu(X, ref U, ref P); 
+        /// 
+        /// // L.ToString() is now: 
+        /// // {&lt;Double&gt; 19634871 [3x3] Phys. 
+        /// //(:,:) 
+        /// // 1,00000   0,00000   0,00000 
+        /// // 0,80000   1,00000   0,00000 
+        /// // 0,20000  -1,00000   1,00000 
+        /// //}
+        /// // U is now: 
+        /// //{&lt;Double&gt; 22584602 [3x3] Phys. 
+        /// //(:,:) 
+        /// // 5,00000  6,00000  7,00000 
+        /// // 0,00000  -0,80000  -1,60000 
+        /// // 0,00000  0,00000  0,00000 
+        /// //}
+        /// // and P is: 
+        /// //{&lt;Double&gt; 2192437 [3x3] Phys. 
+        /// //(:,:) 
+        /// // 0,00000  0,00000  1,00000 
+        /// // 0,00000  1,00000  0,00000 
+        /// // 1,00000  0,00000  0,00000 
+        /// //}
+        /// </code>
+        /// In order to reflect the pivoting done during the decomposition inside ?getrf, the matrix P may be used on A:
+        /// <code>
+        /// (ILMath.multiply(P,A) - ILMath.multiply(L,U)).ToString();
+        /// // will give:
+        /// //{&lt;Double&gt; 59192235 [3x3] Phys. 
+        /// //(:,:) 
+        /// // 0,00000  0,00000  0,00000 
+        /// // 0,00000  0,00000  0,00000 
+        /// // 0,00000  0,00000  0,00000 
+        /// //}
+        /// </code>
+        /// </example>
+        /// <para>lu uses the Lapack function ?getrf.</para>
+        /// <para>All of the matrices U,L,P returned will be solid ILArrays.</para>
+        /// </remarks>
+        /// <seealso cref="ILNumerics.ILMath.lu(ILInArray{double})"/>
+        /// <seealso cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double})"/>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException"> if input A is not a matrix.</exception>
+        public static ILRetArray< float> lu(ILInArray<float> A, ILOutArray<float> U
+                                                            , ILOutArray< float> P) {
+            using (ILScope.Enter(A)) {
+                if (!A.IsMatrix)
+                    throw new ILArgumentSizeException("lu is defined for matrices only!");
+                int m = A.Size[0], n = A.Size[1], info = 0, minMN = (m < n) ? m : n;
+                ILArray< float> L = A.C;
+                int[] pivInd = ILMemoryPool.Pool.New<int>(minMN);
+               
+                Lapack.sgetrf(m, n, L.GetArrayForWrite(), m, pivInd, ref info);
+                if (info < 0) {
+                    ILMemoryPool.Pool.Free(pivInd);
+                    throw new ILArgumentException("invalid parameter");
+                    //} else if (info > 0) {
+                    //    // singular diagonal entry found 
+
+                } else {
+                    // completed successfuly 
+                    if (!Object.Equals(U, null)) {
+                        if (!Object.Equals(P, null)) {
+                            pivInd = perm2indicesForward(pivInd);
+                            U.a = copyUpperTriangle<float>(L, minMN, n);
+                            L.a = copyLowerTriangle<float>(L, m, minMN, 1.0f);
+                            P.a = zeros< float>(new ILSize(minMN, minMN));
+                            // construct permutation matrix P 
+                            for (int r = 0; r < m; r++) {
+                                P[r, pivInd[r]] =  1.0f;
+                            }
+                        } else {
+                            pivInd = perm2indicesBackward(pivInd);
+                            U.a = copyUpperTriangle<float>(L, minMN, n);
+                            L.a = copyLowerTrianglePerm< float>(L, m, minMN, 1.0f, pivInd);
+                        }
+                    }
+                }
+                ILMemoryPool.Pool.Free(pivInd);
+                return L;
+            }
+        }
+        /// <summary>
+        /// LU matrix decomposition. Decompose general matrix A into strictly upper part and lower part. 
+        /// </summary>
+        /// <param name="A">Input matrix. Size [m x n]</param>
+        /// <returns>Triangular matrices L and U composed into a single matrix as returned from LAPACK function ?getrf. Size [m x n]</returns>
+        /// <remarks><para>The matrix returned is composed out of the lower triangular matrix L with unit diagonal and the strict upper triangular matrix U.</para>
+        /// <code>
+        /// :'''''''|
+        /// |1 \    |
+        /// | 1 \ R |
+        /// |  1 \  |
+        /// | L 1 \ |
+        /// |    1 \|
+        /// '''''''''
+        /// </code>
+        /// <para>This overload is mainly needed for further operations via Lapack libraries. If you need the 
+        /// L and U matrices directly, you'd better use one of the overloaded versions 
+        /// <see cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double})"/>
+        ///  or <see cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double}, ILOutArray{double})"/> instead.</para>
+        /// <para>The matrix L will be a solid ILArray.</para>
+        /// <para>lu uses the Lapack function ?getrf.</para>
+        /// </remarks>
+        /// <seealso cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double}, ILOutArray{double})"/>
+        /// <seealso cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double})"/>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException"> if input A is not a matrix.</exception>
+        public static ILRetArray< fcomplex > lu(ILInArray<fcomplex> A) {
+            ILArray< fcomplex > U = null;
+            ILArray< fcomplex > P = null; 
+            return lu(A, U, P); 
+        }
+        /// <summary>
+        /// LU matrix decomposition. Decompose general matrix A into strictly upper part and lower part.
+        /// </summary>
+        /// <param name="A">Input matrix to be decomposed. Size [m x n]</param>
+        /// <param name="U">[Output] Reference to U. On return this will be the strict upper triangular matrix of size [min(m,n) x n]. Must not be null on input.</param>
+        /// <returns>Lower triangular matrix L of size [m x min(m,n)]</returns>
+        /// <remarks>A is decomposed into L and U, so that ILMath.multiply (L,U) will result in A.
+        /// <para>L will only be a permuted version of a true triangular matrix. I.e. the rows of L will be permuted in order 
+        /// to fullfill <c>ILMath.multiply(L,U) == A</c></para>
+        /// <example> <code>
+        /// //we construct a matrix X: 
+        /// ILArray&lt;double&gt; X = new ILArray&lt;double&gt;(new double[]{1, 2, 3, 4, 4, 4, 5, 6, 7},3,3).T;
+        /// // now X.ToString() will give something like:
+        /// // {&lt;Double&gt; 63238509 [3x3] Ref(2) 
+        /// //(:,:) 
+        /// // 1,00000  2,00000  3,00000 
+        /// // 4,00000  4,00000  4,00000 
+        /// // 5,00000  6,00000  7,00000 
+        /// //}
+        /// // construct reference on U and call the decomposition
+        /// ILArray&lt;double&gt; U = new ILArray&lt;double&gt;.empty();
+        /// ILArray&lt;double&gt; L = ILMath.lu(X, ref U); 
+        /// 
+        /// // L.ToString() is now: 
+        /// // {&lt;Double&gt; 19634871 [3x3] Phys. 
+        /// //(:,:) 
+        /// // 0,20000  -1,00000  1,00000 
+        /// // 0,80000  1,00000  0,00000 
+        /// // 1,00000  0,00000  0,00000 
+        /// //}
+        /// // and U is now: 
+        /// //{&lt;Double&gt; 22584602 [3x3] Phys. 
+        /// //(:,:) 
+        /// // 5,00000  6,00000  7,00000 
+        /// // 0,00000  -0,80000  -1,60000 
+        /// // 0,00000  0,00000  0,00000 
+        /// //}
+        /// </code>
+        /// Pay attention to the structure of L. In the example above the first and third row are exchanged. This permutation reflects the pivoting done during the decomposition inside the Lapack function ?getrf. </example>
+        /// <para>In order to access the permutation of L, one can use the overloaded version <see cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double}, ILOutArray{double})"/> which returns the permuation matrix P also.</para>
+        /// <para>All of the matrices U and L returned will be solid ILArrays.</para>
+        /// <para>lu uses the Lapack function ?getrf.</para>
+        /// </remarks>
+        /// <seealso cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double}, ILOutArray{double})"/>
+        /// <seealso cref="ILNumerics.ILMath.lu(ILInArray{double})"/>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException"> if input A is not a matrix.</exception>
+        public static ILRetArray< fcomplex> lu(ILInArray<fcomplex> A, ILOutArray<fcomplex> U) {
+            return lu(A,U,null); 
+        }
+        /// <summary>
+        /// Decompose matrix A into uper and lower triangular part. Returns permutation matrix also. 
+        /// </summary>
+        /// <param name="A">Input matrix. Size [m x n]</param>
+        /// <param name="U">[Output] Reference to upper triangular matrix. Size [min(m,n) x n]. Must not be null.</param>
+        /// <param name="P">[Output] Reference to permutation matrix. Size [min(m,n) x min(m,n)]. Must not be null.</param>
+        /// <returns>Lower triangular matrix L of size [m x min(m,n)]</returns>
+        /// <remarks>A is decomposed into L and U, so that the equation 
+        /// <c>ILMath.multiply(L,U) == ILMath.multiply(P,A)</c> 
+        /// will hold except for round off error.
+        /// <para>L and U will be true lower triangular matrices.</para>
+        /// <example> <code>
+        /// //Let's construct a matrix X: 
+        /// ILArray&lt;double&gt; X = new ILArray&lt;double&gt;(new double[]{1, 2, 3, 4, 4, 4, 5, 6, 7},3,3).T;
+        /// // now X.ToString() will give something like:
+        /// // {&lt;Double&gt; 63238509 [3x3] Ref(2) 
+        /// //(:,:) 
+        /// // 1,00000  2,00000  3,00000 
+        /// // 4,00000  4,00000  4,00000 
+        /// // 5,00000  6,00000  7,00000 
+        /// //}
+        /// // construct references on U and P and call the decomposition
+        /// ILArray&lt;double&gt; U = new ILArray&lt;double&gt;.empty();
+        /// ILArray&lt;double&gt; P = new ILArray&lt;double&gt;.empty();
+        /// ILArray&lt;double&gt; L = ILMath.lu(X, ref U, ref P); 
+        /// 
+        /// // L.ToString() is now: 
+        /// // {&lt;Double&gt; 19634871 [3x3] Phys. 
+        /// //(:,:) 
+        /// // 1,00000   0,00000   0,00000 
+        /// // 0,80000   1,00000   0,00000 
+        /// // 0,20000  -1,00000   1,00000 
+        /// //}
+        /// // U is now: 
+        /// //{&lt;Double&gt; 22584602 [3x3] Phys. 
+        /// //(:,:) 
+        /// // 5,00000  6,00000  7,00000 
+        /// // 0,00000  -0,80000  -1,60000 
+        /// // 0,00000  0,00000  0,00000 
+        /// //}
+        /// // and P is: 
+        /// //{&lt;Double&gt; 2192437 [3x3] Phys. 
+        /// //(:,:) 
+        /// // 0,00000  0,00000  1,00000 
+        /// // 0,00000  1,00000  0,00000 
+        /// // 1,00000  0,00000  0,00000 
+        /// //}
+        /// </code>
+        /// In order to reflect the pivoting done during the decomposition inside ?getrf, the matrix P may be used on A:
+        /// <code>
+        /// (ILMath.multiply(P,A) - ILMath.multiply(L,U)).ToString();
+        /// // will give:
+        /// //{&lt;Double&gt; 59192235 [3x3] Phys. 
+        /// //(:,:) 
+        /// // 0,00000  0,00000  0,00000 
+        /// // 0,00000  0,00000  0,00000 
+        /// // 0,00000  0,00000  0,00000 
+        /// //}
+        /// </code>
+        /// </example>
+        /// <para>lu uses the Lapack function ?getrf.</para>
+        /// <para>All of the matrices U,L,P returned will be solid ILArrays.</para>
+        /// </remarks>
+        /// <seealso cref="ILNumerics.ILMath.lu(ILInArray{double})"/>
+        /// <seealso cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double})"/>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException"> if input A is not a matrix.</exception>
+        public static ILRetArray< fcomplex> lu(ILInArray<fcomplex> A, ILOutArray<fcomplex> U
+                                                            , ILOutArray< fcomplex> P) {
+            using (ILScope.Enter(A)) {
+                if (!A.IsMatrix)
+                    throw new ILArgumentSizeException("lu is defined for matrices only!");
+                int m = A.Size[0], n = A.Size[1], info = 0, minMN = (m < n) ? m : n;
+                ILArray< fcomplex> L = A.C;
+                int[] pivInd = ILMemoryPool.Pool.New<int>(minMN);
+               
+                Lapack.cgetrf(m, n, L.GetArrayForWrite(), m, pivInd, ref info);
+                if (info < 0) {
+                    ILMemoryPool.Pool.Free(pivInd);
+                    throw new ILArgumentException("invalid parameter");
+                    //} else if (info > 0) {
+                    //    // singular diagonal entry found 
+
+                } else {
+                    // completed successfuly 
+                    if (!Object.Equals(U, null)) {
+                        if (!Object.Equals(P, null)) {
+                            pivInd = perm2indicesForward(pivInd);
+                            U.a = copyUpperTriangle<fcomplex>(L, minMN, n);
+                            L.a = copyLowerTriangle<fcomplex>(L, m, minMN, new fcomplex(1.0f,0.0f));
+                            P.a = zeros< fcomplex>(new ILSize(minMN, minMN));
+                            // construct permutation matrix P 
+                            for (int r = 0; r < m; r++) {
+                                P[r, pivInd[r]] =  new fcomplex(1.0f,0.0f);
+                            }
+                        } else {
+                            pivInd = perm2indicesBackward(pivInd);
+                            U.a = copyUpperTriangle<fcomplex>(L, minMN, n);
+                            L.a = copyLowerTrianglePerm< fcomplex>(L, m, minMN, new fcomplex(1.0f,0.0f), pivInd);
+                        }
+                    }
+                }
+                ILMemoryPool.Pool.Free(pivInd);
+                return L;
+            }
+        }
+        /// <summary>
+        /// LU matrix decomposition. Decompose general matrix A into strictly upper part and lower part. 
+        /// </summary>
+        /// <param name="A">Input matrix. Size [m x n]</param>
+        /// <returns>Triangular matrices L and U composed into a single matrix as returned from LAPACK function ?getrf. Size [m x n]</returns>
+        /// <remarks><para>The matrix returned is composed out of the lower triangular matrix L with unit diagonal and the strict upper triangular matrix U.</para>
+        /// <code>
+        /// :'''''''|
+        /// |1 \    |
+        /// | 1 \ R |
+        /// |  1 \  |
+        /// | L 1 \ |
+        /// |    1 \|
+        /// '''''''''
+        /// </code>
+        /// <para>This overload is mainly needed for further operations via Lapack libraries. If you need the 
+        /// L and U matrices directly, you'd better use one of the overloaded versions 
+        /// <see cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double})"/>
+        ///  or <see cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double}, ILOutArray{double})"/> instead.</para>
+        /// <para>The matrix L will be a solid ILArray.</para>
+        /// <para>lu uses the Lapack function ?getrf.</para>
+        /// </remarks>
+        /// <seealso cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double}, ILOutArray{double})"/>
+        /// <seealso cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double})"/>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException"> if input A is not a matrix.</exception>
+        public static ILRetArray< complex > lu(ILInArray<complex> A) {
+            ILArray< complex > U = null;
+            ILArray< complex > P = null; 
+            return lu(A, U, P); 
+        }
+        /// <summary>
+        /// LU matrix decomposition. Decompose general matrix A into strictly upper part and lower part.
+        /// </summary>
+        /// <param name="A">Input matrix to be decomposed. Size [m x n]</param>
+        /// <param name="U">[Output] Reference to U. On return this will be the strict upper triangular matrix of size [min(m,n) x n]. Must not be null on input.</param>
+        /// <returns>Lower triangular matrix L of size [m x min(m,n)]</returns>
+        /// <remarks>A is decomposed into L and U, so that ILMath.multiply (L,U) will result in A.
+        /// <para>L will only be a permuted version of a true triangular matrix. I.e. the rows of L will be permuted in order 
+        /// to fullfill <c>ILMath.multiply(L,U) == A</c></para>
+        /// <example> <code>
+        /// //we construct a matrix X: 
+        /// ILArray&lt;double&gt; X = new ILArray&lt;double&gt;(new double[]{1, 2, 3, 4, 4, 4, 5, 6, 7},3,3).T;
+        /// // now X.ToString() will give something like:
+        /// // {&lt;Double&gt; 63238509 [3x3] Ref(2) 
+        /// //(:,:) 
+        /// // 1,00000  2,00000  3,00000 
+        /// // 4,00000  4,00000  4,00000 
+        /// // 5,00000  6,00000  7,00000 
+        /// //}
+        /// // construct reference on U and call the decomposition
+        /// ILArray&lt;double&gt; U = new ILArray&lt;double&gt;.empty();
+        /// ILArray&lt;double&gt; L = ILMath.lu(X, ref U); 
+        /// 
+        /// // L.ToString() is now: 
+        /// // {&lt;Double&gt; 19634871 [3x3] Phys. 
+        /// //(:,:) 
+        /// // 0,20000  -1,00000  1,00000 
+        /// // 0,80000  1,00000  0,00000 
+        /// // 1,00000  0,00000  0,00000 
+        /// //}
+        /// // and U is now: 
+        /// //{&lt;Double&gt; 22584602 [3x3] Phys. 
+        /// //(:,:) 
+        /// // 5,00000  6,00000  7,00000 
+        /// // 0,00000  -0,80000  -1,60000 
+        /// // 0,00000  0,00000  0,00000 
+        /// //}
+        /// </code>
+        /// Pay attention to the structure of L. In the example above the first and third row are exchanged. This permutation reflects the pivoting done during the decomposition inside the Lapack function ?getrf. </example>
+        /// <para>In order to access the permutation of L, one can use the overloaded version <see cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double}, ILOutArray{double})"/> which returns the permuation matrix P also.</para>
+        /// <para>All of the matrices U and L returned will be solid ILArrays.</para>
+        /// <para>lu uses the Lapack function ?getrf.</para>
+        /// </remarks>
+        /// <seealso cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double}, ILOutArray{double})"/>
+        /// <seealso cref="ILNumerics.ILMath.lu(ILInArray{double})"/>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException"> if input A is not a matrix.</exception>
+        public static ILRetArray< complex> lu(ILInArray<complex> A, ILOutArray<complex> U) {
+            return lu(A,U,null); 
+        }
+        /// <summary>
+        /// Decompose matrix A into uper and lower triangular part. Returns permutation matrix also. 
+        /// </summary>
+        /// <param name="A">Input matrix. Size [m x n]</param>
+        /// <param name="U">[Output] Reference to upper triangular matrix. Size [min(m,n) x n]. Must not be null.</param>
+        /// <param name="P">[Output] Reference to permutation matrix. Size [min(m,n) x min(m,n)]. Must not be null.</param>
+        /// <returns>Lower triangular matrix L of size [m x min(m,n)]</returns>
+        /// <remarks>A is decomposed into L and U, so that the equation 
+        /// <c>ILMath.multiply(L,U) == ILMath.multiply(P,A)</c> 
+        /// will hold except for round off error.
+        /// <para>L and U will be true lower triangular matrices.</para>
+        /// <example> <code>
+        /// //Let's construct a matrix X: 
+        /// ILArray&lt;double&gt; X = new ILArray&lt;double&gt;(new double[]{1, 2, 3, 4, 4, 4, 5, 6, 7},3,3).T;
+        /// // now X.ToString() will give something like:
+        /// // {&lt;Double&gt; 63238509 [3x3] Ref(2) 
+        /// //(:,:) 
+        /// // 1,00000  2,00000  3,00000 
+        /// // 4,00000  4,00000  4,00000 
+        /// // 5,00000  6,00000  7,00000 
+        /// //}
+        /// // construct references on U and P and call the decomposition
+        /// ILArray&lt;double&gt; U = new ILArray&lt;double&gt;.empty();
+        /// ILArray&lt;double&gt; P = new ILArray&lt;double&gt;.empty();
+        /// ILArray&lt;double&gt; L = ILMath.lu(X, ref U, ref P); 
+        /// 
+        /// // L.ToString() is now: 
+        /// // {&lt;Double&gt; 19634871 [3x3] Phys. 
+        /// //(:,:) 
+        /// // 1,00000   0,00000   0,00000 
+        /// // 0,80000   1,00000   0,00000 
+        /// // 0,20000  -1,00000   1,00000 
+        /// //}
+        /// // U is now: 
+        /// //{&lt;Double&gt; 22584602 [3x3] Phys. 
+        /// //(:,:) 
+        /// // 5,00000  6,00000  7,00000 
+        /// // 0,00000  -0,80000  -1,60000 
+        /// // 0,00000  0,00000  0,00000 
+        /// //}
+        /// // and P is: 
+        /// //{&lt;Double&gt; 2192437 [3x3] Phys. 
+        /// //(:,:) 
+        /// // 0,00000  0,00000  1,00000 
+        /// // 0,00000  1,00000  0,00000 
+        /// // 1,00000  0,00000  0,00000 
+        /// //}
+        /// </code>
+        /// In order to reflect the pivoting done during the decomposition inside ?getrf, the matrix P may be used on A:
+        /// <code>
+        /// (ILMath.multiply(P,A) - ILMath.multiply(L,U)).ToString();
+        /// // will give:
+        /// //{&lt;Double&gt; 59192235 [3x3] Phys. 
+        /// //(:,:) 
+        /// // 0,00000  0,00000  0,00000 
+        /// // 0,00000  0,00000  0,00000 
+        /// // 0,00000  0,00000  0,00000 
+        /// //}
+        /// </code>
+        /// </example>
+        /// <para>lu uses the Lapack function ?getrf.</para>
+        /// <para>All of the matrices U,L,P returned will be solid ILArrays.</para>
+        /// </remarks>
+        /// <seealso cref="ILNumerics.ILMath.lu(ILInArray{double})"/>
+        /// <seealso cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double})"/>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException"> if input A is not a matrix.</exception>
+        public static ILRetArray< complex> lu(ILInArray<complex> A, ILOutArray<complex> U
+                                                            , ILOutArray< complex> P) {
+            using (ILScope.Enter(A)) {
+                if (!A.IsMatrix)
+                    throw new ILArgumentSizeException("lu is defined for matrices only!");
+                int m = A.Size[0], n = A.Size[1], info = 0, minMN = (m < n) ? m : n;
+                ILArray< complex> L = A.C;
+                int[] pivInd = ILMemoryPool.Pool.New<int>(minMN);
+               
+                Lapack.zgetrf(m, n, L.GetArrayForWrite(), m, pivInd, ref info);
+                if (info < 0) {
+                    ILMemoryPool.Pool.Free(pivInd);
+                    throw new ILArgumentException("invalid parameter");
+                    //} else if (info > 0) {
+                    //    // singular diagonal entry found 
+
+                } else {
+                    // completed successfuly 
+                    if (!Object.Equals(U, null)) {
+                        if (!Object.Equals(P, null)) {
+                            pivInd = perm2indicesForward(pivInd);
+                            U.a = copyUpperTriangle<complex>(L, minMN, n);
+                            L.a = copyLowerTriangle<complex>(L, m, minMN, new complex(1.0,0.0));
+                            P.a = zeros< complex>(new ILSize(minMN, minMN));
+                            // construct permutation matrix P 
+                            for (int r = 0; r < m; r++) {
+                                P[r, pivInd[r]] =  new complex(1.0,0.0);
+                            }
+                        } else {
+                            pivInd = perm2indicesBackward(pivInd);
+                            U.a = copyUpperTriangle<complex>(L, minMN, n);
+                            L.a = copyLowerTrianglePerm< complex>(L, m, minMN, new complex(1.0,0.0), pivInd);
+                        }
+                    }
+                }
+                ILMemoryPool.Pool.Free(pivInd);
+                return L;
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// Copy upper triangle from PHYSICAL array A
+        /// </summary>
+        /// <typeparam name="T">Arbitrary inner type </typeparam>
+        /// <param name="A">PHYSICAL ILArray</param>
+        /// <param name="m">Number of rows</param>
+        /// <param name="n">Number of columns</param>
+        /// <returns>Newly created physical array with the upper triangle of A</returns>
+        /// <remarks>No checks are made for m,n fit inside A!</remarks>
+        internal static ILRetArray<T> copyUpperTriangle<T>(ILInArray<T> A, int m, int n) {
+            using (ILScope.Enter(A)) {
+                T[] arr = ILMemoryPool.Pool.New<T>(m * n);
+                for (int r = 0; r < m; r++) {
+                    for (int c = r; c < n; c++) {
+                        arr[r + c * m] = A.GetValue(r, c);
+                    }
+                }
+                return new ILRetArray<T>(arr, m, n);
+            }
+        }
+        /// <summary>
+        /// Copy upper triangle from system array A
+        /// </summary>
+        /// <typeparam name="T">Arbitrary inner type </typeparam>
+        /// <param name="arrIn">System array, size (m x n), column wise ordered</param>
+        /// <param name="arrInM">Number of rows</param>
+        /// <param name="arrInN">Number of columns</param>
+        /// <param name="outM">Number of rows in output matrix</param>
+        /// <returns>Newly created physical array with the upper triangle of A</returns>
+        /// <remarks>No checks are made for m,n fit inside A! copies the main diagonal also.
+        /// the array returned will be of size (min(m,n) x n)</remarks>
+        private static ILRetArray<T> copyUpperTriangle<T>(T[] arrIn, int arrInM, int arrInN, int outM) {
+            T[] arrOu = ILMemoryPool.Pool.New<T>(outM * arrInN);
+            for (int c = 0; c < arrInN; c++) {
+                for (int r = 0; r <= c && r < outM; r++) {
+                    arrOu[c * outM + r] = arrIn[c * arrInM + r];
+                }
+            }
+            return new ILRetArray<T> (arrOu,outM,arrInN);
+        }
+        /// <summary>
+        /// Copy lower triangle from PHYSICAL array A, set diagonal to val
+        /// </summary>
+        /// <typeparam name="T">Arbitrary inner type </typeparam>
+        /// <param name="A">PHYSICAL ILArray</param>
+        /// <param name="m">Number of rows</param>
+        /// <param name="n">Number of columns</param>
+        /// <param name="val">Value for diagonal entries</param>
+        /// <returns>Newly created physical array with the lower triangle of A</returns>
+        /// <remarks>No checks are made for m,n fit inside A!</remarks>
+        private static ILRetArray<T> copyLowerTriangle<T>(ILInArray<T> A, int m, int n, T val) {
+            using (ILScope.Enter(A)) {
+                T[] arr = ILMemoryPool.Pool.New<T>(m * n);
+                for (int r = 0; r < m; r++) {
+                    for (int c = r + 1; c-- > 0; ) {
+                        arr[r + m * c] = A.GetValue(r, c);
+                    }
+                    arr[r + m * r] = val;
+                }
+                return new ILRetArray<T>(arr, m, n);
+            }
+        }
+        /// <summary>
+        /// Copy lower triangle from PHYSICAL array A, set diagonal to val, permuted version
+        /// </summary>
+        /// <typeparam name="T">Arbitrary inner type </typeparam>
+        /// <param name="A">PHYSICAL ILArray</param>
+        /// <param name="m">Number of rows</param>
+        /// <param name="n">Number of columns</param>
+        /// <param name="perm">Mapping for rows, must be converted fom LAPACK version to single indices </param>
+        /// <param name="val">Value for diagonal entries</param>
+        /// <returns>Newly created physical array with the lower triangle of A</returns>
+        /// <remarks>No checks are made for m,n fit inside A!</remarks>
+        private static ILRetArray<T> copyLowerTrianglePerm<T>(ILInArray<T> A, int m, int n, T val, int[] perm) {
+            using (ILScope.Enter(A)) {
+                T[] arr = ILMemoryPool.Pool.New<T>(m * n);
+                int trueRow;
+                for (int r = 0; r < perm.Length; r++) {
+                    trueRow = perm[r];
+                    for (int c = 0; c < trueRow; c++) {
+                        arr[r + c * m] = A.GetValue(trueRow, c);
+                    }
+                    arr[r + m * trueRow] = val;
+                }
+                return new ILRetArray<T>(arr, m, n);
+            }
+        }
+
+        /// <summary>
+        /// Relabel permutation indices from LAPACK ?getrf
+        /// </summary>
+        /// <param name="perm">Lapack pivoting permutation array</param>
+        /// <returns>Index mapping for direct addressing the rows </returns>
+        /// <remarks>Exchange the row labels in the same manner as LAPACK did for pivoting</remarks>
+        private static int[] perm2indicesForward(int[] perm) {
+            int [] ret = ILMemoryPool.Pool.New<int>(perm.Length);
+            for (int i = 0; i < ret.Length; i++) {
+                ret[i] = i; 
+            }
+            int tmp; 
+            for (int i = 0; i < ret.Length; i++) {
+                if (perm[i] != i+1) {
+                    tmp = ret[perm[i]-1]; 
+                    ret[perm[i]-1] = i; 
+                    ret[i] = tmp; 
+                }
+            }
+            return ret; 
+        }
+        /// <summary>
+        /// Relabel permutation indices from LAPACK ?getrf - backward version
+        /// </summary>
+        /// <param name="perm">Lapack pivoting permutation array</param>
+        /// <returns>Index mapping for direct addressing the rows </returns>
+        /// <remarks>Exchange the row labels in the same manner as LAPACK did for pivoting, but backwards</remarks>
+        private static int[] perm2indicesBackward(int[] perm) {
+            int [] ret = ILMemoryPool.Pool.New<int>(perm.Length);
+            for (int i = 0; i < ret.Length; i++) {
+                ret[i] = i; 
+            }
+            int tmp; 
+            for (int i = ret.Length - 1; i-->0;) {
+                if (perm[i] != i+1) {
+                    tmp = ret[perm[i]-1]; 
+                    ret[perm[i]-1] = i; 
+                    ret[i] = tmp; 
+                }
+            }
+            return ret; 
+        }
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/matrixTest.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/matrixTest.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/matrixTest.cs	(revision 9102)
@@ -0,0 +1,901 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions; 
+
+
+
+namespace ILNumerics {
+    public partial class ILMath {
+
+
+        /// <summary>
+        /// Determine if matrix A is a lower triangular matrix
+        /// </summary>
+        /// <param name="A">Matrix of numeric inner type</param>
+        /// <returns>true if A is a lower triangular matrix, false otherwise</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A was not a matrix or if A was null</exception>
+        public static bool istrilow(ILInArray<double> A) {
+            if (object.Equals(A, null))
+                throw new ILArgumentException("istrilow: A must not be null!");
+            using (ILScope.Enter(A)) {
+                if (A.IsScalar) { return true; }
+                if (A.IsEmpty) { return false; }
+                if (!A.IsMatrix)
+                    throw new ILArgumentException("istrilow: A must be a matrix!");
+                int n = A.Size[1];
+                for (int c = 1; c < n; c++) {
+                    for (int r = 0; r < c; r++) {
+                        if (A.GetValue(r, c) !=  0.0) return false;
+                    }
+                }
+                return true;
+            }
+        }
+        
+        /// <summary>
+        /// Determine if matrix A is upper triangular matrix
+        /// </summary>
+        /// <param name="A">Matrix or scalar A of numeric inner type</param>
+        /// <returns>true if A is a upper triangular matrix, false otherwise</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A was not a matrix or if A was null</exception>
+        public static bool istriup(ILInArray<double> A) {
+            if (object.Equals(A, null))
+                throw new ILArgumentException("istriup: A must not be null!");
+            using (ILScope.Enter(A)) {
+                if (A.IsScalar) { return true; }
+                if (A.IsEmpty) { return false; }
+                if (!A.IsMatrix)
+                    throw new ILArgumentException("istriup: A must be matrix or scalar!");
+                int m = A.Size[0];
+                int n = A.Size[1];
+                for (int c = 0; c < n; c++) {
+                    for (int r = c + 1; r < m; r++) {
+                        if (A.GetValue(r, c) !=  0.0) return false;
+                    }
+                }
+                return true;
+            }
+        }
+        /// <summary>
+        /// Determine if matrix A is lower Hessenberg matrix 
+        /// </summary>
+        /// <param name="A">Matrix or scalar A of numeric inner type</param>
+        /// <returns>true if A is a lower Hessenberg matrix, false otherwise</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A was null</exception>
+        public static bool ishesslow(ILInArray<double> A) {
+            if (object.Equals(A, null))
+                throw new ILArgumentException("ishesslow: A must not be null!");
+            using (ILScope.Enter(A)) {
+                if (A.IsScalar) { return true; }
+                if (A.IsEmpty) { return false; }
+                if (!A.IsMatrix) return false;
+                int m = A.Size[0];
+                int n = A.Size[1];
+                if (m != n) return false;
+                for (int c = 2; c < n; c++) {
+                    for (int r = 0; r < c - 1; r++) {
+                        if (A.GetValue(r, c) !=  0.0) return false;
+                    }
+                }
+                return true;
+            }
+        }
+        /// <summary>
+        /// Determine if matrix A is upper Hessenberg matrix 
+        /// </summary>
+        /// <param name="A">Matrix or scalar A of numeric inner type</param>
+        /// <returns>true if A is a upper Hessenberg matrix, false otherwise</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A was null</exception>
+        public static bool ishessup(ILInArray<double> A) {
+            if (object.Equals(A, null))
+                throw new ILArgumentException("ishessup: A must not be null!");
+            using (ILScope.Enter(A)) {
+                if (A.IsScalar) { return true; }
+                if (A.IsEmpty) { return false; }
+                if (!A.IsMatrix) return false;
+                int n = A.Size[1];
+                if (n != A.Size[0]) return false;
+                for (int c = 0; c < n - 2; c++) {
+                    for (int r = c + 2; r < n; r++) {
+                        if (A.GetValue(r, c) !=  0.0) return false;
+                    }
+                }
+                return true;
+            }
+        }
+        /// <summary>
+        /// Determine if matrix A is Hermitian matrix 
+        /// </summary>
+        /// <param name="A">Matrix or scalar A of numeric inner type</param>
+        /// <returns>true if A is a Hermitian matrix, false otherwise</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A was null</exception>
+        public static bool ishermitian(ILInArray<double> A) {
+            if (object.Equals(A,null))
+                throw new ILArgumentException("ishessup: A must not be null!"); 
+            using (ILScope.Enter(A)) {
+                if (A.IsScalar) { return true; }
+                if (A.IsEmpty) { return false; }
+                if (!A.IsMatrix) return false;
+                int n = A.Size[1];
+                if (n != A.Size[0]) return false;
+                for (int c = 0; c < n; c++) {
+                    
+                    //
+                    for (int r = c + 1; r < n; r++) {
+                        
+                        if (A.GetValue(r, c) != A.GetValue(c, r)) return false;
+                    }
+                }
+                return true;
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// Determine if matrix A is a lower triangular matrix
+        /// </summary>
+        /// <param name="A">Matrix of numeric inner type</param>
+        /// <returns>true if A is a lower triangular matrix, false otherwise</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A was not a matrix or if A was null</exception>
+        public static bool istrilow(ILInArray<fcomplex> A) {
+            if (object.Equals(A, null))
+                throw new ILArgumentException("istrilow: A must not be null!");
+            using (ILScope.Enter(A)) {
+                if (A.IsScalar) { return true; }
+                if (A.IsEmpty) { return false; }
+                if (!A.IsMatrix)
+                    throw new ILArgumentException("istrilow: A must be a matrix!");
+                int n = A.Size[1];
+                for (int c = 1; c < n; c++) {
+                    for (int r = 0; r < c; r++) {
+                        if (A.GetValue(r, c) !=  0.0) return false;
+                    }
+                }
+                return true;
+            }
+        }
+        
+        /// <summary>
+        /// Determine if matrix A is upper triangular matrix
+        /// </summary>
+        /// <param name="A">Matrix or scalar A of numeric inner type</param>
+        /// <returns>true if A is a upper triangular matrix, false otherwise</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A was not a matrix or if A was null</exception>
+        public static bool istriup(ILInArray<fcomplex> A) {
+            if (object.Equals(A, null))
+                throw new ILArgumentException("istriup: A must not be null!");
+            using (ILScope.Enter(A)) {
+                if (A.IsScalar) { return true; }
+                if (A.IsEmpty) { return false; }
+                if (!A.IsMatrix)
+                    throw new ILArgumentException("istriup: A must be matrix or scalar!");
+                int m = A.Size[0];
+                int n = A.Size[1];
+                for (int c = 0; c < n; c++) {
+                    for (int r = c + 1; r < m; r++) {
+                        if (A.GetValue(r, c) !=  0.0) return false;
+                    }
+                }
+                return true;
+            }
+        }
+        /// <summary>
+        /// Determine if matrix A is lower Hessenberg matrix 
+        /// </summary>
+        /// <param name="A">Matrix or scalar A of numeric inner type</param>
+        /// <returns>true if A is a lower Hessenberg matrix, false otherwise</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A was null</exception>
+        public static bool ishesslow(ILInArray<fcomplex> A) {
+            if (object.Equals(A, null))
+                throw new ILArgumentException("ishesslow: A must not be null!");
+            using (ILScope.Enter(A)) {
+                if (A.IsScalar) { return true; }
+                if (A.IsEmpty) { return false; }
+                if (!A.IsMatrix) return false;
+                int m = A.Size[0];
+                int n = A.Size[1];
+                if (m != n) return false;
+                for (int c = 2; c < n; c++) {
+                    for (int r = 0; r < c - 1; r++) {
+                        if (A.GetValue(r, c) !=  0.0) return false;
+                    }
+                }
+                return true;
+            }
+        }
+        /// <summary>
+        /// Determine if matrix A is upper Hessenberg matrix 
+        /// </summary>
+        /// <param name="A">Matrix or scalar A of numeric inner type</param>
+        /// <returns>true if A is a upper Hessenberg matrix, false otherwise</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A was null</exception>
+        public static bool ishessup(ILInArray<fcomplex> A) {
+            if (object.Equals(A, null))
+                throw new ILArgumentException("ishessup: A must not be null!");
+            using (ILScope.Enter(A)) {
+                if (A.IsScalar) { return true; }
+                if (A.IsEmpty) { return false; }
+                if (!A.IsMatrix) return false;
+                int n = A.Size[1];
+                if (n != A.Size[0]) return false;
+                for (int c = 0; c < n - 2; c++) {
+                    for (int r = c + 2; r < n; r++) {
+                        if (A.GetValue(r, c) !=  0.0) return false;
+                    }
+                }
+                return true;
+            }
+        }
+        /// <summary>
+        /// Determine if matrix A is Hermitian matrix 
+        /// </summary>
+        /// <param name="A">Matrix or scalar A of numeric inner type</param>
+        /// <returns>true if A is a Hermitian matrix, false otherwise</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A was null</exception>
+        public static bool ishermitian(ILInArray<fcomplex> A) {
+            if (object.Equals(A,null))
+                throw new ILArgumentException("ishessup: A must not be null!"); 
+            using (ILScope.Enter(A)) {
+                if (A.IsScalar) { return true; }
+                if (A.IsEmpty) { return false; }
+                if (!A.IsMatrix) return false;
+                int n = A.Size[1];
+                if (n != A.Size[0]) return false;
+                for (int c = 0; c < n; c++) {
+                   
+                    if (A.GetValue(c,c).imag != 0.0f) return false; 
+                    for (int r = c + 1; r < n; r++) {
+                        fcomplex val1 = A.GetValue(r,c); fcomplex val2 = A.GetValue(c,r); if (val1.real != val2.real || val1.imag + val2.imag != 0.0f) return false;
+                    }
+                }
+                return true;
+            }
+        }
+        /// <summary>
+        /// Determine if matrix A is a lower triangular matrix
+        /// </summary>
+        /// <param name="A">Matrix of numeric inner type</param>
+        /// <returns>true if A is a lower triangular matrix, false otherwise</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A was not a matrix or if A was null</exception>
+        public static bool istrilow(ILInArray<complex> A) {
+            if (object.Equals(A, null))
+                throw new ILArgumentException("istrilow: A must not be null!");
+            using (ILScope.Enter(A)) {
+                if (A.IsScalar) { return true; }
+                if (A.IsEmpty) { return false; }
+                if (!A.IsMatrix)
+                    throw new ILArgumentException("istrilow: A must be a matrix!");
+                int n = A.Size[1];
+                for (int c = 1; c < n; c++) {
+                    for (int r = 0; r < c; r++) {
+                        if (A.GetValue(r, c) !=  0.0) return false;
+                    }
+                }
+                return true;
+            }
+        }
+        
+        /// <summary>
+        /// Determine if matrix A is upper triangular matrix
+        /// </summary>
+        /// <param name="A">Matrix or scalar A of numeric inner type</param>
+        /// <returns>true if A is a upper triangular matrix, false otherwise</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A was not a matrix or if A was null</exception>
+        public static bool istriup(ILInArray<complex> A) {
+            if (object.Equals(A, null))
+                throw new ILArgumentException("istriup: A must not be null!");
+            using (ILScope.Enter(A)) {
+                if (A.IsScalar) { return true; }
+                if (A.IsEmpty) { return false; }
+                if (!A.IsMatrix)
+                    throw new ILArgumentException("istriup: A must be matrix or scalar!");
+                int m = A.Size[0];
+                int n = A.Size[1];
+                for (int c = 0; c < n; c++) {
+                    for (int r = c + 1; r < m; r++) {
+                        if (A.GetValue(r, c) !=  0.0) return false;
+                    }
+                }
+                return true;
+            }
+        }
+        /// <summary>
+        /// Determine if matrix A is lower Hessenberg matrix 
+        /// </summary>
+        /// <param name="A">Matrix or scalar A of numeric inner type</param>
+        /// <returns>true if A is a lower Hessenberg matrix, false otherwise</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A was null</exception>
+        public static bool ishesslow(ILInArray<complex> A) {
+            if (object.Equals(A, null))
+                throw new ILArgumentException("ishesslow: A must not be null!");
+            using (ILScope.Enter(A)) {
+                if (A.IsScalar) { return true; }
+                if (A.IsEmpty) { return false; }
+                if (!A.IsMatrix) return false;
+                int m = A.Size[0];
+                int n = A.Size[1];
+                if (m != n) return false;
+                for (int c = 2; c < n; c++) {
+                    for (int r = 0; r < c - 1; r++) {
+                        if (A.GetValue(r, c) !=  0.0) return false;
+                    }
+                }
+                return true;
+            }
+        }
+        /// <summary>
+        /// Determine if matrix A is upper Hessenberg matrix 
+        /// </summary>
+        /// <param name="A">Matrix or scalar A of numeric inner type</param>
+        /// <returns>true if A is a upper Hessenberg matrix, false otherwise</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A was null</exception>
+        public static bool ishessup(ILInArray<complex> A) {
+            if (object.Equals(A, null))
+                throw new ILArgumentException("ishessup: A must not be null!");
+            using (ILScope.Enter(A)) {
+                if (A.IsScalar) { return true; }
+                if (A.IsEmpty) { return false; }
+                if (!A.IsMatrix) return false;
+                int n = A.Size[1];
+                if (n != A.Size[0]) return false;
+                for (int c = 0; c < n - 2; c++) {
+                    for (int r = c + 2; r < n; r++) {
+                        if (A.GetValue(r, c) !=  0.0) return false;
+                    }
+                }
+                return true;
+            }
+        }
+        /// <summary>
+        /// Determine if matrix A is Hermitian matrix 
+        /// </summary>
+        /// <param name="A">Matrix or scalar A of numeric inner type</param>
+        /// <returns>true if A is a Hermitian matrix, false otherwise</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A was null</exception>
+        public static bool ishermitian(ILInArray<complex> A) {
+            if (object.Equals(A,null))
+                throw new ILArgumentException("ishessup: A must not be null!"); 
+            using (ILScope.Enter(A)) {
+                if (A.IsScalar) { return true; }
+                if (A.IsEmpty) { return false; }
+                if (!A.IsMatrix) return false;
+                int n = A.Size[1];
+                if (n != A.Size[0]) return false;
+                for (int c = 0; c < n; c++) {
+                   
+                    if (A.GetValue(c,c).imag != 0.0) return false;
+                    for (int r = c + 1; r < n; r++) {
+                        complex val1 = A.GetValue(r,c); complex val2 = A.GetValue(c,r); if (val1.real != val2.real || val1.imag + val2.imag != 0.0) return false;
+                    }
+                }
+                return true;
+            }
+        }
+        /// <summary>
+        /// Determine if matrix A is a lower triangular matrix
+        /// </summary>
+        /// <param name="A">Matrix of numeric inner type</param>
+        /// <returns>true if A is a lower triangular matrix, false otherwise</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A was not a matrix or if A was null</exception>
+        public static bool istrilow(ILInArray<byte> A) {
+            if (object.Equals(A, null))
+                throw new ILArgumentException("istrilow: A must not be null!");
+            using (ILScope.Enter(A)) {
+                if (A.IsScalar) { return true; }
+                if (A.IsEmpty) { return false; }
+                if (!A.IsMatrix)
+                    throw new ILArgumentException("istrilow: A must be a matrix!");
+                int n = A.Size[1];
+                for (int c = 1; c < n; c++) {
+                    for (int r = 0; r < c; r++) {
+                        if (A.GetValue(r, c) !=  0.0) return false;
+                    }
+                }
+                return true;
+            }
+        }
+        
+        /// <summary>
+        /// Determine if matrix A is upper triangular matrix
+        /// </summary>
+        /// <param name="A">Matrix or scalar A of numeric inner type</param>
+        /// <returns>true if A is a upper triangular matrix, false otherwise</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A was not a matrix or if A was null</exception>
+        public static bool istriup(ILInArray<byte> A) {
+            if (object.Equals(A, null))
+                throw new ILArgumentException("istriup: A must not be null!");
+            using (ILScope.Enter(A)) {
+                if (A.IsScalar) { return true; }
+                if (A.IsEmpty) { return false; }
+                if (!A.IsMatrix)
+                    throw new ILArgumentException("istriup: A must be matrix or scalar!");
+                int m = A.Size[0];
+                int n = A.Size[1];
+                for (int c = 0; c < n; c++) {
+                    for (int r = c + 1; r < m; r++) {
+                        if (A.GetValue(r, c) !=  0.0) return false;
+                    }
+                }
+                return true;
+            }
+        }
+        /// <summary>
+        /// Determine if matrix A is lower Hessenberg matrix 
+        /// </summary>
+        /// <param name="A">Matrix or scalar A of numeric inner type</param>
+        /// <returns>true if A is a lower Hessenberg matrix, false otherwise</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A was null</exception>
+        public static bool ishesslow(ILInArray<byte> A) {
+            if (object.Equals(A, null))
+                throw new ILArgumentException("ishesslow: A must not be null!");
+            using (ILScope.Enter(A)) {
+                if (A.IsScalar) { return true; }
+                if (A.IsEmpty) { return false; }
+                if (!A.IsMatrix) return false;
+                int m = A.Size[0];
+                int n = A.Size[1];
+                if (m != n) return false;
+                for (int c = 2; c < n; c++) {
+                    for (int r = 0; r < c - 1; r++) {
+                        if (A.GetValue(r, c) !=  0.0) return false;
+                    }
+                }
+                return true;
+            }
+        }
+        /// <summary>
+        /// Determine if matrix A is upper Hessenberg matrix 
+        /// </summary>
+        /// <param name="A">Matrix or scalar A of numeric inner type</param>
+        /// <returns>true if A is a upper Hessenberg matrix, false otherwise</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A was null</exception>
+        public static bool ishessup(ILInArray<byte> A) {
+            if (object.Equals(A, null))
+                throw new ILArgumentException("ishessup: A must not be null!");
+            using (ILScope.Enter(A)) {
+                if (A.IsScalar) { return true; }
+                if (A.IsEmpty) { return false; }
+                if (!A.IsMatrix) return false;
+                int n = A.Size[1];
+                if (n != A.Size[0]) return false;
+                for (int c = 0; c < n - 2; c++) {
+                    for (int r = c + 2; r < n; r++) {
+                        if (A.GetValue(r, c) !=  0.0) return false;
+                    }
+                }
+                return true;
+            }
+        }
+        /// <summary>
+        /// Determine if matrix A is Hermitian matrix 
+        /// </summary>
+        /// <param name="A">Matrix or scalar A of numeric inner type</param>
+        /// <returns>true if A is a Hermitian matrix, false otherwise</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A was null</exception>
+        public static bool ishermitian(ILInArray<byte> A) {
+            if (object.Equals(A,null))
+                throw new ILArgumentException("ishessup: A must not be null!"); 
+            using (ILScope.Enter(A)) {
+                if (A.IsScalar) { return true; }
+                if (A.IsEmpty) { return false; }
+                if (!A.IsMatrix) return false;
+                int n = A.Size[1];
+                if (n != A.Size[0]) return false;
+                for (int c = 0; c < n; c++) {
+                   
+                    
+                    for (int r = c + 1; r < n; r++) {
+                        if (A.GetValue(r,c) != A.GetValue(c,r)) return false; 
+                    }
+                }
+                return true;
+            }
+        }
+        /// <summary>
+        /// Determine if matrix A is a lower triangular matrix
+        /// </summary>
+        /// <param name="A">Matrix of numeric inner type</param>
+        /// <returns>true if A is a lower triangular matrix, false otherwise</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A was not a matrix or if A was null</exception>
+        public static bool istrilow(ILInArray<Int64> A) {
+            if (object.Equals(A, null))
+                throw new ILArgumentException("istrilow: A must not be null!");
+            using (ILScope.Enter(A)) {
+                if (A.IsScalar) { return true; }
+                if (A.IsEmpty) { return false; }
+                if (!A.IsMatrix)
+                    throw new ILArgumentException("istrilow: A must be a matrix!");
+                int n = A.Size[1];
+                for (int c = 1; c < n; c++) {
+                    for (int r = 0; r < c; r++) {
+                        if (A.GetValue(r, c) !=  0.0) return false;
+                    }
+                }
+                return true;
+            }
+        }
+        
+        /// <summary>
+        /// Determine if matrix A is upper triangular matrix
+        /// </summary>
+        /// <param name="A">Matrix or scalar A of numeric inner type</param>
+        /// <returns>true if A is a upper triangular matrix, false otherwise</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A was not a matrix or if A was null</exception>
+        public static bool istriup(ILInArray<Int64> A) {
+            if (object.Equals(A, null))
+                throw new ILArgumentException("istriup: A must not be null!");
+            using (ILScope.Enter(A)) {
+                if (A.IsScalar) { return true; }
+                if (A.IsEmpty) { return false; }
+                if (!A.IsMatrix)
+                    throw new ILArgumentException("istriup: A must be matrix or scalar!");
+                int m = A.Size[0];
+                int n = A.Size[1];
+                for (int c = 0; c < n; c++) {
+                    for (int r = c + 1; r < m; r++) {
+                        if (A.GetValue(r, c) !=  0.0) return false;
+                    }
+                }
+                return true;
+            }
+        }
+        /// <summary>
+        /// Determine if matrix A is lower Hessenberg matrix 
+        /// </summary>
+        /// <param name="A">Matrix or scalar A of numeric inner type</param>
+        /// <returns>true if A is a lower Hessenberg matrix, false otherwise</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A was null</exception>
+        public static bool ishesslow(ILInArray<Int64> A) {
+            if (object.Equals(A, null))
+                throw new ILArgumentException("ishesslow: A must not be null!");
+            using (ILScope.Enter(A)) {
+                if (A.IsScalar) { return true; }
+                if (A.IsEmpty) { return false; }
+                if (!A.IsMatrix) return false;
+                int m = A.Size[0];
+                int n = A.Size[1];
+                if (m != n) return false;
+                for (int c = 2; c < n; c++) {
+                    for (int r = 0; r < c - 1; r++) {
+                        if (A.GetValue(r, c) !=  0.0) return false;
+                    }
+                }
+                return true;
+            }
+        }
+        /// <summary>
+        /// Determine if matrix A is upper Hessenberg matrix 
+        /// </summary>
+        /// <param name="A">Matrix or scalar A of numeric inner type</param>
+        /// <returns>true if A is a upper Hessenberg matrix, false otherwise</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A was null</exception>
+        public static bool ishessup(ILInArray<Int64> A) {
+            if (object.Equals(A, null))
+                throw new ILArgumentException("ishessup: A must not be null!");
+            using (ILScope.Enter(A)) {
+                if (A.IsScalar) { return true; }
+                if (A.IsEmpty) { return false; }
+                if (!A.IsMatrix) return false;
+                int n = A.Size[1];
+                if (n != A.Size[0]) return false;
+                for (int c = 0; c < n - 2; c++) {
+                    for (int r = c + 2; r < n; r++) {
+                        if (A.GetValue(r, c) !=  0.0) return false;
+                    }
+                }
+                return true;
+            }
+        }
+        /// <summary>
+        /// Determine if matrix A is Hermitian matrix 
+        /// </summary>
+        /// <param name="A">Matrix or scalar A of numeric inner type</param>
+        /// <returns>true if A is a Hermitian matrix, false otherwise</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A was null</exception>
+        public static bool ishermitian(ILInArray<Int64> A) {
+            if (object.Equals(A,null))
+                throw new ILArgumentException("ishessup: A must not be null!"); 
+            using (ILScope.Enter(A)) {
+                if (A.IsScalar) { return true; }
+                if (A.IsEmpty) { return false; }
+                if (!A.IsMatrix) return false;
+                int n = A.Size[1];
+                if (n != A.Size[0]) return false;
+                for (int c = 0; c < n; c++) {
+                   
+                    
+                    for (int r = c + 1; r < n; r++) {
+                        if (A.GetValue(r,c) != A.GetValue(c,r)) return false; 
+                    }
+                }
+                return true;
+            }
+        }
+        /// <summary>
+        /// Determine if matrix A is a lower triangular matrix
+        /// </summary>
+        /// <param name="A">Matrix of numeric inner type</param>
+        /// <returns>true if A is a lower triangular matrix, false otherwise</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A was not a matrix or if A was null</exception>
+        public static bool istrilow(ILInArray<Int32> A) {
+            if (object.Equals(A, null))
+                throw new ILArgumentException("istrilow: A must not be null!");
+            using (ILScope.Enter(A)) {
+                if (A.IsScalar) { return true; }
+                if (A.IsEmpty) { return false; }
+                if (!A.IsMatrix)
+                    throw new ILArgumentException("istrilow: A must be a matrix!");
+                int n = A.Size[1];
+                for (int c = 1; c < n; c++) {
+                    for (int r = 0; r < c; r++) {
+                        if (A.GetValue(r, c) !=  0.0) return false;
+                    }
+                }
+                return true;
+            }
+        }
+        
+        /// <summary>
+        /// Determine if matrix A is upper triangular matrix
+        /// </summary>
+        /// <param name="A">Matrix or scalar A of numeric inner type</param>
+        /// <returns>true if A is a upper triangular matrix, false otherwise</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A was not a matrix or if A was null</exception>
+        public static bool istriup(ILInArray<Int32> A) {
+            if (object.Equals(A, null))
+                throw new ILArgumentException("istriup: A must not be null!");
+            using (ILScope.Enter(A)) {
+                if (A.IsScalar) { return true; }
+                if (A.IsEmpty) { return false; }
+                if (!A.IsMatrix)
+                    throw new ILArgumentException("istriup: A must be matrix or scalar!");
+                int m = A.Size[0];
+                int n = A.Size[1];
+                for (int c = 0; c < n; c++) {
+                    for (int r = c + 1; r < m; r++) {
+                        if (A.GetValue(r, c) !=  0.0) return false;
+                    }
+                }
+                return true;
+            }
+        }
+        /// <summary>
+        /// Determine if matrix A is lower Hessenberg matrix 
+        /// </summary>
+        /// <param name="A">Matrix or scalar A of numeric inner type</param>
+        /// <returns>true if A is a lower Hessenberg matrix, false otherwise</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A was null</exception>
+        public static bool ishesslow(ILInArray<Int32> A) {
+            if (object.Equals(A, null))
+                throw new ILArgumentException("ishesslow: A must not be null!");
+            using (ILScope.Enter(A)) {
+                if (A.IsScalar) { return true; }
+                if (A.IsEmpty) { return false; }
+                if (!A.IsMatrix) return false;
+                int m = A.Size[0];
+                int n = A.Size[1];
+                if (m != n) return false;
+                for (int c = 2; c < n; c++) {
+                    for (int r = 0; r < c - 1; r++) {
+                        if (A.GetValue(r, c) !=  0.0) return false;
+                    }
+                }
+                return true;
+            }
+        }
+        /// <summary>
+        /// Determine if matrix A is upper Hessenberg matrix 
+        /// </summary>
+        /// <param name="A">Matrix or scalar A of numeric inner type</param>
+        /// <returns>true if A is a upper Hessenberg matrix, false otherwise</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A was null</exception>
+        public static bool ishessup(ILInArray<Int32> A) {
+            if (object.Equals(A, null))
+                throw new ILArgumentException("ishessup: A must not be null!");
+            using (ILScope.Enter(A)) {
+                if (A.IsScalar) { return true; }
+                if (A.IsEmpty) { return false; }
+                if (!A.IsMatrix) return false;
+                int n = A.Size[1];
+                if (n != A.Size[0]) return false;
+                for (int c = 0; c < n - 2; c++) {
+                    for (int r = c + 2; r < n; r++) {
+                        if (A.GetValue(r, c) !=  0.0) return false;
+                    }
+                }
+                return true;
+            }
+        }
+        /// <summary>
+        /// Determine if matrix A is Hermitian matrix 
+        /// </summary>
+        /// <param name="A">Matrix or scalar A of numeric inner type</param>
+        /// <returns>true if A is a Hermitian matrix, false otherwise</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A was null</exception>
+        public static bool ishermitian(ILInArray<Int32> A) {
+            if (object.Equals(A,null))
+                throw new ILArgumentException("ishessup: A must not be null!"); 
+            using (ILScope.Enter(A)) {
+                if (A.IsScalar) { return true; }
+                if (A.IsEmpty) { return false; }
+                if (!A.IsMatrix) return false;
+                int n = A.Size[1];
+                if (n != A.Size[0]) return false;
+                for (int c = 0; c < n; c++) {
+                   
+                    
+                    for (int r = c + 1; r < n; r++) {
+                        if (A.GetValue(r,c) != A.GetValue(c,r)) return false; 
+                    }
+                }
+                return true;
+            }
+        }
+        /// <summary>
+        /// Determine if matrix A is a lower triangular matrix
+        /// </summary>
+        /// <param name="A">Matrix of numeric inner type</param>
+        /// <returns>true if A is a lower triangular matrix, false otherwise</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A was not a matrix or if A was null</exception>
+        public static bool istrilow(ILInArray<float> A) {
+            if (object.Equals(A, null))
+                throw new ILArgumentException("istrilow: A must not be null!");
+            using (ILScope.Enter(A)) {
+                if (A.IsScalar) { return true; }
+                if (A.IsEmpty) { return false; }
+                if (!A.IsMatrix)
+                    throw new ILArgumentException("istrilow: A must be a matrix!");
+                int n = A.Size[1];
+                for (int c = 1; c < n; c++) {
+                    for (int r = 0; r < c; r++) {
+                        if (A.GetValue(r, c) !=  0.0) return false;
+                    }
+                }
+                return true;
+            }
+        }
+        
+        /// <summary>
+        /// Determine if matrix A is upper triangular matrix
+        /// </summary>
+        /// <param name="A">Matrix or scalar A of numeric inner type</param>
+        /// <returns>true if A is a upper triangular matrix, false otherwise</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A was not a matrix or if A was null</exception>
+        public static bool istriup(ILInArray<float> A) {
+            if (object.Equals(A, null))
+                throw new ILArgumentException("istriup: A must not be null!");
+            using (ILScope.Enter(A)) {
+                if (A.IsScalar) { return true; }
+                if (A.IsEmpty) { return false; }
+                if (!A.IsMatrix)
+                    throw new ILArgumentException("istriup: A must be matrix or scalar!");
+                int m = A.Size[0];
+                int n = A.Size[1];
+                for (int c = 0; c < n; c++) {
+                    for (int r = c + 1; r < m; r++) {
+                        if (A.GetValue(r, c) !=  0.0) return false;
+                    }
+                }
+                return true;
+            }
+        }
+        /// <summary>
+        /// Determine if matrix A is lower Hessenberg matrix 
+        /// </summary>
+        /// <param name="A">Matrix or scalar A of numeric inner type</param>
+        /// <returns>true if A is a lower Hessenberg matrix, false otherwise</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A was null</exception>
+        public static bool ishesslow(ILInArray<float> A) {
+            if (object.Equals(A, null))
+                throw new ILArgumentException("ishesslow: A must not be null!");
+            using (ILScope.Enter(A)) {
+                if (A.IsScalar) { return true; }
+                if (A.IsEmpty) { return false; }
+                if (!A.IsMatrix) return false;
+                int m = A.Size[0];
+                int n = A.Size[1];
+                if (m != n) return false;
+                for (int c = 2; c < n; c++) {
+                    for (int r = 0; r < c - 1; r++) {
+                        if (A.GetValue(r, c) !=  0.0) return false;
+                    }
+                }
+                return true;
+            }
+        }
+        /// <summary>
+        /// Determine if matrix A is upper Hessenberg matrix 
+        /// </summary>
+        /// <param name="A">Matrix or scalar A of numeric inner type</param>
+        /// <returns>true if A is a upper Hessenberg matrix, false otherwise</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A was null</exception>
+        public static bool ishessup(ILInArray<float> A) {
+            if (object.Equals(A, null))
+                throw new ILArgumentException("ishessup: A must not be null!");
+            using (ILScope.Enter(A)) {
+                if (A.IsScalar) { return true; }
+                if (A.IsEmpty) { return false; }
+                if (!A.IsMatrix) return false;
+                int n = A.Size[1];
+                if (n != A.Size[0]) return false;
+                for (int c = 0; c < n - 2; c++) {
+                    for (int r = c + 2; r < n; r++) {
+                        if (A.GetValue(r, c) !=  0.0) return false;
+                    }
+                }
+                return true;
+            }
+        }
+        /// <summary>
+        /// Determine if matrix A is Hermitian matrix 
+        /// </summary>
+        /// <param name="A">Matrix or scalar A of numeric inner type</param>
+        /// <returns>true if A is a Hermitian matrix, false otherwise</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A was null</exception>
+        public static bool ishermitian(ILInArray<float> A) {
+            if (object.Equals(A,null))
+                throw new ILArgumentException("ishessup: A must not be null!"); 
+            using (ILScope.Enter(A)) {
+                if (A.IsScalar) { return true; }
+                if (A.IsEmpty) { return false; }
+                if (!A.IsMatrix) return false;
+                int n = A.Size[1];
+                if (n != A.Size[0]) return false;
+                for (int c = 0; c < n; c++) {
+                   
+                    
+                    for (int r = c + 1; r < n; r++) {
+                        if (A.GetValue(r,c) != A.GetValue(c,r)) return false; 
+                    }
+                }
+                return true;
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/maxall.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/maxall.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/maxall.cs	(revision 9102)
@@ -0,0 +1,226 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+#pragma warning disable 
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions; 
+
+
+namespace ILNumerics {
+
+    public partial class ILMath {
+
+
+        /// <summary>
+        /// Maximum for all elements of A
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns><para>Scalar maximum of all elements for A</para>
+        /// <para>If A is empty, an empty array will be returned.</para></returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If A was null.</exception>
+        /// <seealso cref="ILNumerics.ILMath.max"/>
+        public static ILRetArray<double> maxall(ILInArray<double> A) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A, null))
+                    throw new ILArgumentException("input argument must not be null");
+                if (A.IsEmpty) {
+                    return empty<double>(ILSize.Empty00);
+                }
+                
+                double retVal =  double.MinValue;
+                unsafe {
+                    fixed ( double* inArrStart = A.GetArrayForRead()) {
+                        
+                        double* inArrWalk = inArrStart;
+                        
+                        double* inArrEnd = inArrStart + A.Size.NumberOfElements;
+                        while (inArrWalk < inArrEnd) {
+                            if (retVal < *inArrWalk)
+                                retVal = *inArrWalk;
+                            inArrWalk++;
+                        }
+                    }
+                }
+                return array<double>(retVal, 1, 1);
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// Maximum for all elements of A
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns><para>Scalar maximum of all elements for A</para>
+        /// <para>If A is empty, an empty array will be returned.</para></returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If A was null.</exception>
+        /// <seealso cref="ILNumerics.ILMath.max"/>
+        public static ILRetArray<Int64> maxall(ILInArray<Int64> A) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A, null))
+                    throw new ILArgumentException("input argument must not be null");
+                if (A.IsEmpty) {
+                    return empty<Int64>(ILSize.Empty00);
+                }
+               
+                Int64 retVal =  Int64.MinValue;
+                unsafe {
+                    fixed ( Int64* inArrStart = A.GetArrayForRead()) {
+                       
+                        Int64* inArrWalk = inArrStart;
+                       
+                        Int64* inArrEnd = inArrStart + A.Size.NumberOfElements;
+                        while (inArrWalk < inArrEnd) {
+                            if (retVal < *inArrWalk)
+                                retVal = *inArrWalk;
+                            inArrWalk++;
+                        }
+                    }
+                }
+                return array<Int64>(retVal, 1, 1);
+            }
+        }
+        /// <summary>
+        /// Maximum for all elements of A
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns><para>Scalar maximum of all elements for A</para>
+        /// <para>If A is empty, an empty array will be returned.</para></returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If A was null.</exception>
+        /// <seealso cref="ILNumerics.ILMath.max"/>
+        public static ILRetArray<Int32> maxall(ILInArray<Int32> A) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A, null))
+                    throw new ILArgumentException("input argument must not be null");
+                if (A.IsEmpty) {
+                    return empty<Int32>(ILSize.Empty00);
+                }
+               
+                Int32 retVal =  Int32.MinValue;
+                unsafe {
+                    fixed ( Int32* inArrStart = A.GetArrayForRead()) {
+                       
+                        Int32* inArrWalk = inArrStart;
+                       
+                        Int32* inArrEnd = inArrStart + A.Size.NumberOfElements;
+                        while (inArrWalk < inArrEnd) {
+                            if (retVal < *inArrWalk)
+                                retVal = *inArrWalk;
+                            inArrWalk++;
+                        }
+                    }
+                }
+                return array<Int32>(retVal, 1, 1);
+            }
+        }
+        /// <summary>
+        /// Maximum for all elements of A
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns><para>Scalar maximum of all elements for A</para>
+        /// <para>If A is empty, an empty array will be returned.</para></returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If A was null.</exception>
+        /// <seealso cref="ILNumerics.ILMath.max"/>
+        public static ILRetArray<byte> maxall(ILInArray<byte> A) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A, null))
+                    throw new ILArgumentException("input argument must not be null");
+                if (A.IsEmpty) {
+                    return empty<byte>(ILSize.Empty00);
+                }
+               
+                byte retVal =  byte.MinValue;
+                unsafe {
+                    fixed ( byte* inArrStart = A.GetArrayForRead()) {
+                       
+                        byte* inArrWalk = inArrStart;
+                       
+                        byte* inArrEnd = inArrStart + A.Size.NumberOfElements;
+                        while (inArrWalk < inArrEnd) {
+                            if (retVal < *inArrWalk)
+                                retVal = *inArrWalk;
+                            inArrWalk++;
+                        }
+                    }
+                }
+                return array<byte>(retVal, 1, 1);
+            }
+        }
+        /// <summary>
+        /// Maximum for all elements of A
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns><para>Scalar maximum of all elements for A</para>
+        /// <para>If A is empty, an empty array will be returned.</para></returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If A was null.</exception>
+        /// <seealso cref="ILNumerics.ILMath.max"/>
+        public static ILRetArray<float> maxall(ILInArray<float> A) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A, null))
+                    throw new ILArgumentException("input argument must not be null");
+                if (A.IsEmpty) {
+                    return empty<float>(ILSize.Empty00);
+                }
+               
+                float retVal =  float.MinValue;
+                unsafe {
+                    fixed ( float* inArrStart = A.GetArrayForRead()) {
+                       
+                        float* inArrWalk = inArrStart;
+                       
+                        float* inArrEnd = inArrStart + A.Size.NumberOfElements;
+                        while (inArrWalk < inArrEnd) {
+                            if (retVal < *inArrWalk)
+                                retVal = *inArrWalk;
+                            inArrWalk++;
+                        }
+                    }
+                }
+                return array<float>(retVal, 1, 1);
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/mean.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/mean.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/mean.cs	(revision 9102)
@@ -0,0 +1,177 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions;
+
+
+
+namespace ILNumerics  {
+	public partial class ILMath {
+
+        /// <summary>
+        /// Mean of array along specified dimension
+        /// </summary>
+        /// <param name="A">Input Array</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns>Mean of elements along specified or first non singleton dimension</returns>
+        /// <remarks>The return array has the same shape as A, but the specified or first non singleton dimension is reduced 
+        /// to length 1. If A is scalar, an scalar array will be returned. On empty input, the output will be empty.</remarks>
+        public static ILRetArray< double> mean( ILInArray< double> A, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (dim < 0)
+                    dim = 0;
+                return sum(A, dim) / ( double)A.Size[dim];
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// Mean of array along specified dimension
+        /// </summary>
+        /// <param name="A">Input Array</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns>Mean of elements along specified or first non singleton dimension</returns>
+        /// <remarks>The return array has the same shape as A, but the specified or first non singleton dimension is reduced 
+        /// to length 1. If A is scalar, an scalar array will be returned. On empty input, the output will be empty.</remarks>
+        public static ILRetArray< Int64> mean( ILInArray< Int64> A, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (dim < 0)
+                    dim = 0;
+                return sum(A, dim) / ( Int64)A.Size[dim];
+            }
+        }
+        /// <summary>
+        /// Mean of array along specified dimension
+        /// </summary>
+        /// <param name="A">Input Array</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns>Mean of elements along specified or first non singleton dimension</returns>
+        /// <remarks>The return array has the same shape as A, but the specified or first non singleton dimension is reduced 
+        /// to length 1. If A is scalar, an scalar array will be returned. On empty input, the output will be empty.</remarks>
+        public static ILRetArray< Int32> mean( ILInArray< Int32> A, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (dim < 0)
+                    dim = 0;
+                return sum(A, dim) / ( Int32)A.Size[dim];
+            }
+        }
+        /// <summary>
+        /// Mean of array along specified dimension
+        /// </summary>
+        /// <param name="A">Input Array</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns>Mean of elements along specified or first non singleton dimension</returns>
+        /// <remarks>The return array has the same shape as A, but the specified or first non singleton dimension is reduced 
+        /// to length 1. If A is scalar, an scalar array will be returned. On empty input, the output will be empty.</remarks>
+        public static ILRetArray< byte> mean( ILInArray< byte> A, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (dim < 0)
+                    dim = 0;
+                return sum(A, dim) / ( byte)A.Size[dim];
+            }
+        }
+        /// <summary>
+        /// Mean of array along specified dimension
+        /// </summary>
+        /// <param name="A">Input Array</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns>Mean of elements along specified or first non singleton dimension</returns>
+        /// <remarks>The return array has the same shape as A, but the specified or first non singleton dimension is reduced 
+        /// to length 1. If A is scalar, an scalar array will be returned. On empty input, the output will be empty.</remarks>
+        public static ILRetArray< fcomplex> mean( ILInArray< fcomplex> A, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (dim < 0)
+                    dim = 0;
+                return sum(A, dim) / ( fcomplex)A.Size[dim];
+            }
+        }
+        /// <summary>
+        /// Mean of array along specified dimension
+        /// </summary>
+        /// <param name="A">Input Array</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns>Mean of elements along specified or first non singleton dimension</returns>
+        /// <remarks>The return array has the same shape as A, but the specified or first non singleton dimension is reduced 
+        /// to length 1. If A is scalar, an scalar array will be returned. On empty input, the output will be empty.</remarks>
+        public static ILRetArray< float> mean( ILInArray< float> A, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (dim < 0)
+                    dim = 0;
+                return sum(A, dim) / ( float)A.Size[dim];
+            }
+        }
+        /// <summary>
+        /// Mean of array along specified dimension
+        /// </summary>
+        /// <param name="A">Input Array</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns>Mean of elements along specified or first non singleton dimension</returns>
+        /// <remarks>The return array has the same shape as A, but the specified or first non singleton dimension is reduced 
+        /// to length 1. If A is scalar, an scalar array will be returned. On empty input, the output will be empty.</remarks>
+        public static ILRetArray< complex> mean( ILInArray< complex> A, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (dim < 0)
+                    dim = 0;
+                return sum(A, dim) / ( complex)A.Size[dim];
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+   }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/meshgrid.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/meshgrid.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/meshgrid.cs	(revision 9102)
@@ -0,0 +1,269 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions; 
+
+
+namespace ILNumerics {
+
+    public partial class ILMath {
+
+        /// <summary>
+        /// Create two matrices for evaluation and visualization of 2 dimensional functions
+        /// </summary>
+        /// <param name="X">Vector of x values</param>
+        /// <param name="Y">Vector of y values</param>
+        /// <param name="outY">[Output, Optional]: if on entry outY is not null, on return it will hold the values for the Y dimension</param>
+        /// <returns>X values matrix along the values of the X input array. Corresponding values for Y are returned in outY</returns>
+        /// <remarks>The matrices returned can be utilize to evaluate and visualize functions of 2 variables X and Y.</remarks>
+        public static ILRetArray< double > meshgrid(ILInArray< double > X, ILInArray< double > Y
+                                                                  , ILOutArray< double > outY = null)
+        {
+            using (ILScope.Enter(X,Y)) {
+                if (!X.IsVector || !Y.IsVector)
+                {
+                    throw new ILArgumentException("inputs must be vectors");
+                }
+                if (!X.IsRowVector) X = X.T; 
+                if (!Y.IsColumnVector) Y = Y.T; 
+                ILArray< double > ret = repmat(X,Y.Length,1);
+                if (!isnull(outY)) 
+                    outY.a = repmat(Y,1,X.Length);
+                return ret;
+            }
+        }
+
+        /// <summary>
+        /// Create 3d arrays for evaluation and visualization of 3 dimensional functions
+        /// </summary>
+        /// <param name="X">Vector of x values</param>
+        /// <param name="Y">Vector of y values</param>
+        /// <param name="Z">Vector of z values</param>
+        /// <param name="outY">[Output, Optional] If on entry outY is not null, on return it will hold the values for the y dimension</param>
+        /// <param name="outZ">[Output, Optional] If on entry outZ is not null, on return it will hold the values for the z dimension</param>
+        /// <returns>X value array along the values of the X input vector, arrays for y and z dimensions are returned in outY and outZ respectively</returns>
+        /// <remarks>The arrays returned can be used to evaluate and visualize functions of 3 variables X, Y and Z.</remarks>
+        public static ILRetArray< double > meshgrid(ILInArray< double > X, ILInArray< double > Y, ILInArray< double > Z
+                                                                ,ILOutArray< double > outY = null, ILOutArray< double > outZ = null)
+        {
+            using (ILScope.Enter()) {
+                if (!X.IsVector || !Y.IsVector || !Z.IsVector)
+                {
+                    throw new ILArgumentException("inputs must be vectors");
+                }
+                if (!X.IsRowVector) X = X.T; 
+                if (!Y.IsColumnVector) Y = Y.T;  
+                Z = Z[full].Reshape(new ILSize(1,1,Z.Size.NumberOfElements)); 
+
+                ILArray< double > ret = repmat(X,Y.Length,1,Z.Length);
+                if (!isnull(outY)) outY.a = repmat(Y,1,X.Length,Z.Length);
+                if (!isnull(outZ)) outZ.a = repmat(Z, Y.Length, X.Length, 1);
+                return ret;
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// Create two matrices for evaluation and visualization of 2 dimensional functions
+        /// </summary>
+        /// <param name="X">Vector of x values</param>
+        /// <param name="Y">Vector of y values</param>
+        /// <param name="outY">[Output, Optional]: if on entry outY is not null, on return it will hold the values for the Y dimension</param>
+        /// <returns>X values matrix along the values of the X input array. Corresponding values for Y are returned in outY</returns>
+        /// <remarks>The matrices returned can be utilize to evaluate and visualize functions of 2 variables X and Y.</remarks>
+        public static ILRetArray< Int64 > meshgrid(ILInArray< Int64 > X, ILInArray< Int64 > Y
+                                                                  , ILOutArray< Int64 > outY = null)
+        {
+            using (ILScope.Enter(X,Y)) {
+                if (!X.IsVector || !Y.IsVector)
+                {
+                    throw new ILArgumentException("inputs must be vectors");
+                }
+                if (!X.IsRowVector) X = X.T; 
+                if (!Y.IsColumnVector) Y = Y.T; 
+                ILArray< Int64 > ret = repmat(X,Y.Length,1);
+                if (!isnull(outY)) 
+                    outY.a = repmat(Y,1,X.Length);
+                return ret;
+            }
+        }
+
+        /// <summary>
+        /// Create 3d arrays for evaluation and visualization of 3 dimensional functions
+        /// </summary>
+        /// <param name="X">Vector of x values</param>
+        /// <param name="Y">Vector of y values</param>
+        /// <param name="Z">Vector of z values</param>
+        /// <param name="outY">[Output, Optional] If on entry outY is not null, on return it will hold the values for the y dimension</param>
+        /// <param name="outZ">[Output, Optional] If on entry outZ is not null, on return it will hold the values for the z dimension</param>
+        /// <returns>X value array along the values of the X input vector, arrays for y and z dimensions are returned in outY and outZ respectively</returns>
+        /// <remarks>The arrays returned can be used to evaluate and visualize functions of 3 variables X, Y and Z.</remarks>
+        public static ILRetArray< Int64 > meshgrid(ILInArray< Int64 > X, ILInArray< Int64 > Y, ILInArray< Int64 > Z
+                                                                ,ILOutArray< Int64 > outY = null, ILOutArray< Int64 > outZ = null)
+        {
+            using (ILScope.Enter()) {
+                if (!X.IsVector || !Y.IsVector || !Z.IsVector)
+                {
+                    throw new ILArgumentException("inputs must be vectors");
+                }
+                if (!X.IsRowVector) X = X.T; 
+                if (!Y.IsColumnVector) Y = Y.T;  
+                Z = Z[full].Reshape(new ILSize(1,1,Z.Size.NumberOfElements)); 
+
+                ILArray< Int64 > ret = repmat(X,Y.Length,1,Z.Length);
+                if (!isnull(outY)) outY.a = repmat(Y,1,X.Length,Z.Length);
+                if (!isnull(outZ)) outZ.a = repmat(Z, Y.Length, X.Length, 1);
+                return ret;
+            }
+        }
+        /// <summary>
+        /// Create two matrices for evaluation and visualization of 2 dimensional functions
+        /// </summary>
+        /// <param name="X">Vector of x values</param>
+        /// <param name="Y">Vector of y values</param>
+        /// <param name="outY">[Output, Optional]: if on entry outY is not null, on return it will hold the values for the Y dimension</param>
+        /// <returns>X values matrix along the values of the X input array. Corresponding values for Y are returned in outY</returns>
+        /// <remarks>The matrices returned can be utilize to evaluate and visualize functions of 2 variables X and Y.</remarks>
+        public static ILRetArray< Int32 > meshgrid(ILInArray< Int32 > X, ILInArray< Int32 > Y
+                                                                  , ILOutArray< Int32 > outY = null)
+        {
+            using (ILScope.Enter(X,Y)) {
+                if (!X.IsVector || !Y.IsVector)
+                {
+                    throw new ILArgumentException("inputs must be vectors");
+                }
+                if (!X.IsRowVector) X = X.T; 
+                if (!Y.IsColumnVector) Y = Y.T; 
+                ILArray< Int32 > ret = repmat(X,Y.Length,1);
+                if (!isnull(outY)) 
+                    outY.a = repmat(Y,1,X.Length);
+                return ret;
+            }
+        }
+
+        /// <summary>
+        /// Create 3d arrays for evaluation and visualization of 3 dimensional functions
+        /// </summary>
+        /// <param name="X">Vector of x values</param>
+        /// <param name="Y">Vector of y values</param>
+        /// <param name="Z">Vector of z values</param>
+        /// <param name="outY">[Output, Optional] If on entry outY is not null, on return it will hold the values for the y dimension</param>
+        /// <param name="outZ">[Output, Optional] If on entry outZ is not null, on return it will hold the values for the z dimension</param>
+        /// <returns>X value array along the values of the X input vector, arrays for y and z dimensions are returned in outY and outZ respectively</returns>
+        /// <remarks>The arrays returned can be used to evaluate and visualize functions of 3 variables X, Y and Z.</remarks>
+        public static ILRetArray< Int32 > meshgrid(ILInArray< Int32 > X, ILInArray< Int32 > Y, ILInArray< Int32 > Z
+                                                                ,ILOutArray< Int32 > outY = null, ILOutArray< Int32 > outZ = null)
+        {
+            using (ILScope.Enter()) {
+                if (!X.IsVector || !Y.IsVector || !Z.IsVector)
+                {
+                    throw new ILArgumentException("inputs must be vectors");
+                }
+                if (!X.IsRowVector) X = X.T; 
+                if (!Y.IsColumnVector) Y = Y.T;  
+                Z = Z[full].Reshape(new ILSize(1,1,Z.Size.NumberOfElements)); 
+
+                ILArray< Int32 > ret = repmat(X,Y.Length,1,Z.Length);
+                if (!isnull(outY)) outY.a = repmat(Y,1,X.Length,Z.Length);
+                if (!isnull(outZ)) outZ.a = repmat(Z, Y.Length, X.Length, 1);
+                return ret;
+            }
+        }
+        /// <summary>
+        /// Create two matrices for evaluation and visualization of 2 dimensional functions
+        /// </summary>
+        /// <param name="X">Vector of x values</param>
+        /// <param name="Y">Vector of y values</param>
+        /// <param name="outY">[Output, Optional]: if on entry outY is not null, on return it will hold the values for the Y dimension</param>
+        /// <returns>X values matrix along the values of the X input array. Corresponding values for Y are returned in outY</returns>
+        /// <remarks>The matrices returned can be utilize to evaluate and visualize functions of 2 variables X and Y.</remarks>
+        public static ILRetArray< float > meshgrid(ILInArray< float > X, ILInArray< float > Y
+                                                                  , ILOutArray< float > outY = null)
+        {
+            using (ILScope.Enter(X,Y)) {
+                if (!X.IsVector || !Y.IsVector)
+                {
+                    throw new ILArgumentException("inputs must be vectors");
+                }
+                if (!X.IsRowVector) X = X.T; 
+                if (!Y.IsColumnVector) Y = Y.T; 
+                ILArray< float > ret = repmat(X,Y.Length,1);
+                if (!isnull(outY)) 
+                    outY.a = repmat(Y,1,X.Length);
+                return ret;
+            }
+        }
+
+        /// <summary>
+        /// Create 3d arrays for evaluation and visualization of 3 dimensional functions
+        /// </summary>
+        /// <param name="X">Vector of x values</param>
+        /// <param name="Y">Vector of y values</param>
+        /// <param name="Z">Vector of z values</param>
+        /// <param name="outY">[Output, Optional] If on entry outY is not null, on return it will hold the values for the y dimension</param>
+        /// <param name="outZ">[Output, Optional] If on entry outZ is not null, on return it will hold the values for the z dimension</param>
+        /// <returns>X value array along the values of the X input vector, arrays for y and z dimensions are returned in outY and outZ respectively</returns>
+        /// <remarks>The arrays returned can be used to evaluate and visualize functions of 3 variables X, Y and Z.</remarks>
+        public static ILRetArray< float > meshgrid(ILInArray< float > X, ILInArray< float > Y, ILInArray< float > Z
+                                                                ,ILOutArray< float > outY = null, ILOutArray< float > outZ = null)
+        {
+            using (ILScope.Enter()) {
+                if (!X.IsVector || !Y.IsVector || !Z.IsVector)
+                {
+                    throw new ILArgumentException("inputs must be vectors");
+                }
+                if (!X.IsRowVector) X = X.T; 
+                if (!Y.IsColumnVector) Y = Y.T;  
+                Z = Z[full].Reshape(new ILSize(1,1,Z.Size.NumberOfElements)); 
+
+                ILArray< float > ret = repmat(X,Y.Length,1,Z.Length);
+                if (!isnull(outY)) outY.a = repmat(Y,1,X.Length,Z.Length);
+                if (!isnull(outZ)) outZ.a = repmat(Z, Y.Length, X.Length, 1);
+                return ret;
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+   }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/minall.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/minall.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/minall.cs	(revision 9102)
@@ -0,0 +1,212 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions; 
+
+namespace ILNumerics  {
+    public partial class ILMath {
+
+        /// <summary>
+        /// Minimum of all elements of array A
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns><para>Scalar minimum of all elements of A.</para>
+        /// <para>If A is empty, an empty array will be returned.</para></returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If A was null.</exception>
+        /// <seealso cref="ILNumerics.ILMath.min(ILInArray{double},ILOutArray{double},int)"/>
+        public static ILRetArray<double> minall(ILInArray<double> A ) {
+            if (object.Equals(A, null))
+                throw new ILArgumentException("input argument must not be null");
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    return empty<double>(ILSize.Empty00);
+                }
+                
+                double retVal = double.MaxValue;
+                unsafe {
+                    fixed (double* inArrStart = A.GetArrayForRead()) {
+                          double* inArrWalk = inArrStart;
+                         double* inArrEnd = inArrStart + A.Size.NumberOfElements;
+                        while (inArrWalk < inArrEnd) {
+                            if (retVal > *inArrWalk)
+                                retVal = *inArrWalk;
+                            inArrWalk++;
+                        }
+                    }
+                }
+                return array<double>(retVal , 1, 1);
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// Minimum of all elements of array A
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns><para>Scalar minimum of all elements of A.</para>
+        /// <para>If A is empty, an empty array will be returned.</para></returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If A was null.</exception>
+        /// <seealso cref="ILNumerics.ILMath.min(ILInArray{double},ILOutArray{double},int)"/>
+        public static ILRetArray<Int64> minall(ILInArray<Int64> A ) {
+            if (object.Equals(A, null))
+                throw new ILArgumentException("input argument must not be null");
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    return empty<Int64>(ILSize.Empty00);
+                }
+               
+                Int64 retVal = Int64.MaxValue;
+                unsafe {
+                    fixed (Int64* inArrStart = A.GetArrayForRead()) {
+                         Int64* inArrWalk = inArrStart;
+                        Int64* inArrEnd = inArrStart + A.Size.NumberOfElements;
+                        while (inArrWalk < inArrEnd) {
+                            if (retVal > *inArrWalk)
+                                retVal = *inArrWalk;
+                            inArrWalk++;
+                        }
+                    }
+                }
+                return array<Int64>(retVal , 1, 1);
+            }
+        }
+        /// <summary>
+        /// Minimum of all elements of array A
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns><para>Scalar minimum of all elements of A.</para>
+        /// <para>If A is empty, an empty array will be returned.</para></returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If A was null.</exception>
+        /// <seealso cref="ILNumerics.ILMath.min(ILInArray{double},ILOutArray{double},int)"/>
+        public static ILRetArray<Int32> minall(ILInArray<Int32> A ) {
+            if (object.Equals(A, null))
+                throw new ILArgumentException("input argument must not be null");
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    return empty<Int32>(ILSize.Empty00);
+                }
+               
+                Int32 retVal = Int32.MaxValue;
+                unsafe {
+                    fixed (Int32* inArrStart = A.GetArrayForRead()) {
+                         Int32* inArrWalk = inArrStart;
+                        Int32* inArrEnd = inArrStart + A.Size.NumberOfElements;
+                        while (inArrWalk < inArrEnd) {
+                            if (retVal > *inArrWalk)
+                                retVal = *inArrWalk;
+                            inArrWalk++;
+                        }
+                    }
+                }
+                return array<Int32>(retVal , 1, 1);
+            }
+        }
+        /// <summary>
+        /// Minimum of all elements of array A
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns><para>Scalar minimum of all elements of A.</para>
+        /// <para>If A is empty, an empty array will be returned.</para></returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If A was null.</exception>
+        /// <seealso cref="ILNumerics.ILMath.min(ILInArray{double},ILOutArray{double},int)"/>
+        public static ILRetArray<byte> minall(ILInArray<byte> A ) {
+            if (object.Equals(A, null))
+                throw new ILArgumentException("input argument must not be null");
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    return empty<byte>(ILSize.Empty00);
+                }
+               
+                byte retVal = byte.MaxValue;
+                unsafe {
+                    fixed (byte* inArrStart = A.GetArrayForRead()) {
+                         byte* inArrWalk = inArrStart;
+                        byte* inArrEnd = inArrStart + A.Size.NumberOfElements;
+                        while (inArrWalk < inArrEnd) {
+                            if (retVal > *inArrWalk)
+                                retVal = *inArrWalk;
+                            inArrWalk++;
+                        }
+                    }
+                }
+                return array<byte>(retVal , 1, 1);
+            }
+        }
+        /// <summary>
+        /// Minimum of all elements of array A
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns><para>Scalar minimum of all elements of A.</para>
+        /// <para>If A is empty, an empty array will be returned.</para></returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If A was null.</exception>
+        /// <seealso cref="ILNumerics.ILMath.min(ILInArray{double},ILOutArray{double},int)"/>
+        public static ILRetArray<float> minall(ILInArray<float> A ) {
+            if (object.Equals(A, null))
+                throw new ILArgumentException("input argument must not be null");
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    return empty<float>(ILSize.Empty00);
+                }
+               
+                float retVal = float.MaxValue;
+                unsafe {
+                    fixed (float* inArrStart = A.GetArrayForRead()) {
+                         float* inArrWalk = inArrStart;
+                        float* inArrEnd = inArrStart + A.Size.NumberOfElements;
+                        while (inArrWalk < inArrEnd) {
+                            if (retVal > *inArrWalk)
+                                retVal = *inArrWalk;
+                            inArrWalk++;
+                        }
+                    }
+                }
+                return array<float>(retVal , 1, 1);
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/mod.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/mod.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/mod.cs	(revision 9102)
@@ -0,0 +1,3662 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using ILNumerics;
+using ILNumerics.Misc;
+using ILNumerics.Storage;
+using ILNumerics.Native;
+using ILNumerics.Exceptions;
+
+
+
+namespace ILNumerics {
+
+    public partial class ILMath {
+
+
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>Modulus of array elements</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>New array with result of elementwise modulus operation</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<Int64>  mod(ILInArray<Int64> A, ILInArray<Int64> B) {
+            using (ILScope.Enter(A,B)) {
+                int outLen; 
+                BinOpItMode mode; 
+                Int64 [] retArr;
+                Int64 [] arrA = A.GetArrayForRead();
+                Int64[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size; 
+                    if (B.IsScalar) {
+                       
+                        return new  ILRetArray<Int64> (new  Int64 [1]{ saturateInt64 (A.GetValue(0)  % (double) B.GetValue(0))}, A.Size);
+                    } else if (B.IsEmpty) {
+                        return  ILRetArray<Int64>.empty(outDims); 
+                    } else {
+                        outLen = outDims.NumberOfElements; 
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< Int64 > (outLen);
+                            mode = BinOpItMode.SAN; 
+                        } else {
+                            mode = BinOpItMode.SAI; 
+                        }
+                    }
+                } else {
+                    outDims = A.Size; 
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return  ILRetArray<Int64>.empty(A.Size);  
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< Int64 > (outLen);
+                            mode = BinOpItMode.ASN; 
+                        } else {
+                            mode = BinOpItMode.ASI; 
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  modEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (A.TryGetStorage4InplaceOp(out retArr)) 
+                            mode  = BinOpItMode.AAIA; 
+                        else if (B.TryGetStorage4InplaceOp(out retArr)) 
+                            mode = BinOpItMode.AAIB; 
+                        else {
+                            retArr = ILMemoryPool.Pool.New< Int64 > (outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<Int64> retStorage = new ILDenseStorage<Int64>(retArr, outDims);
+                int i = 0, workerCount = 1; 
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    Int64* cp = (Int64*)range.Item5 + range.Item1;
+                    Int64 scalar;
+                    int j = range.Item2; 
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           Int64* bp = ((Int64*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                                cp[0] =  saturateInt64 (cp[0]  % (double) bp[0]);
+                                cp[1] =  saturateInt64 (cp[1]  % (double) bp[1]);
+                                cp[2] =  saturateInt64 (cp[2]  % (double) bp[2]);
+                                cp[3] =  saturateInt64 (cp[3]  % (double) bp[3]);
+                                cp[4] =  saturateInt64 (cp[4]  % (double) bp[4]);
+                                cp[5] =  saturateInt64 (cp[5]  % (double) bp[5]);
+                                cp[6] =  saturateInt64 (cp[6]  % (double) bp[6]);
+                                cp[7] =  saturateInt64 (cp[7]  % (double) bp[7]);
+                                cp[8] =  saturateInt64 (cp[8]  % (double) bp[8]);
+                                cp[9] =  saturateInt64 (cp[9]  % (double) bp[9]);
+                                cp[10] =  saturateInt64 (cp[10]  % (double) bp[10]);
+                                cp[11] =  saturateInt64 (cp[11]  % (double) bp[11]);
+                                cp[12] =  saturateInt64 (cp[12]  % (double) bp[12]);
+                                cp[13] =  saturateInt64 (cp[13]  % (double) bp[13]);
+                                cp[14] =  saturateInt64 (cp[14]  % (double) bp[14]);
+                                cp[15] =  saturateInt64 (cp[15]  % (double) bp[15]);
+                                cp[16] =  saturateInt64 (cp[16]  % (double) bp[16]);
+                                cp[17] =  saturateInt64 (cp[17]  % (double) bp[17]);
+                                cp[18] =  saturateInt64 (cp[18]  % (double) bp[18]);
+                                cp[19] =  saturateInt64 (cp[19]  % (double) bp[19]);
+                                cp[20] =  saturateInt64 (cp[20]  % (double) bp[20]);
+                                cp += 21; bp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt64 (*cp  % (double) *bp);
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           Int64* ap = ((Int64*)range.Item3 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt64 (ap[0]  % (double) cp[0]);
+                                cp[1] =  saturateInt64 (ap[1]  % (double) cp[1]);
+                                cp[2] =  saturateInt64 (ap[2]  % (double) cp[2]);
+                                cp[3] =  saturateInt64 (ap[3]  % (double) cp[3]);
+                                cp[4] =  saturateInt64 (ap[4]  % (double) cp[4]);
+                                cp[5] =  saturateInt64 (ap[5]  % (double) cp[5]);
+                                cp[6] =  saturateInt64 (ap[6]  % (double) cp[6]);
+                                cp[7] =  saturateInt64 (ap[7]  % (double) cp[7]);
+                                cp[8] =  saturateInt64 (ap[8]  % (double) cp[8]);
+                                cp[9] =  saturateInt64 (ap[9]  % (double) cp[9]);
+                                cp[10] =  saturateInt64 (ap[10]  % (double) cp[10]);
+                                cp[11] =  saturateInt64 (ap[11]  % (double) cp[11]);
+                                cp[12] =  saturateInt64 (ap[12]  % (double) cp[12]);
+                                cp[13] =  saturateInt64 (ap[13]  % (double) cp[13]);
+                                cp[14] =  saturateInt64 (ap[14]  % (double) cp[14]);
+                                cp[15] =  saturateInt64 (ap[15]  % (double) cp[15]);
+                                cp[16] =  saturateInt64 (ap[16]  % (double) cp[16]);
+                                cp[17] =  saturateInt64 (ap[17]  % (double) cp[17]);
+                                cp[18] =  saturateInt64 (ap[18]  % (double) cp[18]);
+                                cp[19] =  saturateInt64 (ap[19]  % (double) cp[19]);
+                                cp[20] =  saturateInt64 (ap[20]  % (double) cp[20]);
+                                ap += 21; cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt64 (*ap  % (double) *cp);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((Int64*)range.Item3 + range.Item1);
+                            bp = ((Int64*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt64 (ap[0]  % (double) bp[0]);
+                                cp[1] =  saturateInt64 (ap[1]  % (double) bp[1]);
+                                cp[2] =  saturateInt64 (ap[2]  % (double) bp[2]);
+                                cp[3] =  saturateInt64 (ap[3]  % (double) bp[3]);
+                                cp[4] =  saturateInt64 (ap[4]  % (double) bp[4]);
+                                cp[5] =  saturateInt64 (ap[5]  % (double) bp[5]);
+                                cp[6] =  saturateInt64 (ap[6]  % (double) bp[6]);
+                                cp[7] =  saturateInt64 (ap[7]  % (double) bp[7]);
+                                cp[8] =  saturateInt64 (ap[8]  % (double) bp[8]);
+                                cp[9] =  saturateInt64 (ap[9]  % (double) bp[9]);
+                                cp[10] =  saturateInt64 (ap[10]  % (double) bp[10]);
+                                cp[11] =  saturateInt64 (ap[11]  % (double) bp[11]);
+                                cp[12] =  saturateInt64 (ap[12]  % (double) bp[12]);
+                                cp[13] =  saturateInt64 (ap[13]  % (double) bp[13]);
+                                cp[14] =  saturateInt64 (ap[14]  % (double) bp[14]);
+                                cp[15] =  saturateInt64 (ap[15]  % (double) bp[15]);
+                                cp[16] =  saturateInt64 (ap[16]  % (double) bp[16]);
+                                cp[17] =  saturateInt64 (ap[17]  % (double) bp[17]);
+                                cp[18] =  saturateInt64 (ap[18]  % (double) bp[18]);
+                                cp[19] =  saturateInt64 (ap[19]  % (double) bp[19]);
+                                cp[20] =  saturateInt64 (ap[20]  % (double) bp[20]);
+                                ap+=21; bp+=21; cp+=21; j-=21;
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt64 (*ap  % (double) *bp);
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((Int64*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt64 (cp[0]  % (double) scalar);
+                                cp[1] =  saturateInt64 (cp[1]  % (double) scalar);
+                                cp[2] =  saturateInt64 (cp[2]  % (double) scalar);
+                                cp[3] =  saturateInt64 (cp[3]  % (double) scalar);
+                                cp[4] =  saturateInt64 (cp[4]  % (double) scalar);
+                                cp[5] =  saturateInt64 (cp[5]  % (double) scalar);
+                                cp[6] =  saturateInt64 (cp[6]  % (double) scalar);
+                                cp[7] =  saturateInt64 (cp[7]  % (double) scalar);
+                                cp[8] =  saturateInt64 (cp[8]  % (double) scalar);
+                                cp[9] =  saturateInt64 (cp[9]  % (double) scalar);
+                                cp[10] =  saturateInt64 (cp[10]  % (double) scalar);
+                                cp[11] =  saturateInt64 (cp[11]  % (double) scalar);
+                                cp[12] =  saturateInt64 (cp[12]  % (double) scalar);
+                                cp[13] =  saturateInt64 (cp[13]  % (double) scalar);
+                                cp[14] =  saturateInt64 (cp[14]  % (double) scalar);
+                                cp[15] =  saturateInt64 (cp[15]  % (double) scalar);
+                                cp[16] =  saturateInt64 (cp[16]  % (double) scalar);
+                                cp[17] =  saturateInt64 (cp[17]  % (double) scalar);
+                                cp[18] =  saturateInt64 (cp[18]  % (double) scalar);
+                                cp[19] =  saturateInt64 (cp[19]  % (double) scalar);
+                                cp[20] =  saturateInt64 (cp[20]  % (double) scalar);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt64 (*cp  % (double) scalar);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((Int64*)range.Item3 + range.Item1);
+                            scalar = *((Int64*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt64 (ap[0]  % (double) scalar);
+                                cp[1] =  saturateInt64 (ap[1]  % (double) scalar);
+                                cp[2] =  saturateInt64 (ap[2]  % (double) scalar);
+                                cp[3] =  saturateInt64 (ap[3]  % (double) scalar);
+                                cp[4] =  saturateInt64 (ap[4]  % (double) scalar);
+                                cp[5] =  saturateInt64 (ap[5]  % (double) scalar);
+                                cp[6] =  saturateInt64 (ap[6]  % (double) scalar);
+                                cp[7] =  saturateInt64 (ap[7]  % (double) scalar);
+                                cp[8] =  saturateInt64 (ap[8]  % (double) scalar);
+                                cp[9] =  saturateInt64 (ap[9]  % (double) scalar);
+                                cp[10] =  saturateInt64 (ap[10]  % (double) scalar);
+                                cp[11] =  saturateInt64 (ap[11]  % (double) scalar);
+                                cp[12] =  saturateInt64 (ap[12]  % (double) scalar);
+                                cp[13] =  saturateInt64 (ap[13]  % (double) scalar);
+                                cp[14] =  saturateInt64 (ap[14]  % (double) scalar);
+                                cp[15] =  saturateInt64 (ap[15]  % (double) scalar);
+                                cp[16] =  saturateInt64 (ap[16]  % (double) scalar);
+                                cp[17] =  saturateInt64 (ap[17]  % (double) scalar);
+                                cp[18] =  saturateInt64 (ap[18]  % (double) scalar);
+                                cp[19] =  saturateInt64 (ap[19]  % (double) scalar);
+                                cp[20] =  saturateInt64 (ap[20]  % (double) scalar);
+                                ap+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt64 (*ap  % (double) scalar);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((Int64*)range.Item3);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt64 (scalar  % (double) cp[0]);
+                                cp[1] =  saturateInt64 (scalar  % (double) cp[1]);
+                                cp[2] =  saturateInt64 (scalar  % (double) cp[2]);
+                                cp[3] =  saturateInt64 (scalar  % (double) cp[3]);
+                                cp[4] =  saturateInt64 (scalar  % (double) cp[4]);
+                                cp[5] =  saturateInt64 (scalar  % (double) cp[5]);
+                                cp[6] =  saturateInt64 (scalar  % (double) cp[6]);
+                                cp[7] =  saturateInt64 (scalar  % (double) cp[7]);
+                                cp[8] =  saturateInt64 (scalar  % (double) cp[8]);
+                                cp[9] =  saturateInt64 (scalar  % (double) cp[9]);
+                                cp[10] =  saturateInt64 (scalar  % (double) cp[10]);
+                                cp[11] =  saturateInt64 (scalar  % (double) cp[11]);
+                                cp[12] =  saturateInt64 (scalar  % (double) cp[12]);
+                                cp[13] =  saturateInt64 (scalar  % (double) cp[13]);
+                                cp[14] =  saturateInt64 (scalar  % (double) cp[14]);
+                                cp[15] =  saturateInt64 (scalar  % (double) cp[15]);
+                                cp[16] =  saturateInt64 (scalar  % (double) cp[16]);
+                                cp[17] =  saturateInt64 (scalar  % (double) cp[17]);
+                                cp[18] =  saturateInt64 (scalar  % (double) cp[18]);
+                                cp[19] =  saturateInt64 (scalar  % (double) cp[19]);
+                                cp[20] =  saturateInt64 (scalar  % (double) cp[20]);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt64 (scalar  % (double) *cp);
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((Int64*)range.Item3);
+                            bp = ((Int64*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt64 (scalar  % (double) bp[0]);
+                                cp[1] =  saturateInt64 (scalar  % (double) bp[1]);
+                                cp[2] =  saturateInt64 (scalar  % (double) bp[2]);
+                                cp[3] =  saturateInt64 (scalar  % (double) bp[3]);
+                                cp[4] =  saturateInt64 (scalar  % (double) bp[4]);
+                                cp[5] =  saturateInt64 (scalar  % (double) bp[5]);
+                                cp[6] =  saturateInt64 (scalar  % (double) bp[6]);
+                                cp[7] =  saturateInt64 (scalar  % (double) bp[7]);
+                                cp[8] =  saturateInt64 (scalar  % (double) bp[8]);
+                                cp[9] =  saturateInt64 (scalar  % (double) bp[9]);
+                                cp[10] =  saturateInt64 (scalar  % (double) bp[10]);
+                                cp[11] =  saturateInt64 (scalar  % (double) bp[11]);
+                                cp[12] =  saturateInt64 (scalar  % (double) bp[12]);
+                                cp[13] =  saturateInt64 (scalar  % (double) bp[13]);
+                                cp[14] =  saturateInt64 (scalar  % (double) bp[14]);
+                                cp[15] =  saturateInt64 (scalar  % (double) bp[15]);
+                                cp[16] =  saturateInt64 (scalar  % (double) bp[16]);
+                                cp[17] =  saturateInt64 (scalar  % (double) bp[17]);
+                                cp[18] =  saturateInt64 (scalar  % (double) bp[18]);
+                                cp[19] =  saturateInt64 (scalar  % (double) bp[19]);
+                                cp[20] =  saturateInt64 (scalar  % (double) bp[20]);
+                                bp+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt64 (scalar  % (double) *bp);
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work 
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                
+                fixed ( Int64* arrAP = arrA)
+                fixed ( Int64* arrBP = arrB)
+                fixed ( Int64* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range 
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new  ILRetArray< Int64>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<Int64>  modEx(ILInArray<Int64> A, ILInArray<Int64> B) {
+            //using (ILScope.Enter(A, B)) { we cannot start a new scope here, since this would prevent A and B to be used implace if applicable
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<Int64>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<Int64>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<Int64>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                dim = -(dim - 1);  // 0 -> 1, 1 -> 0
+                #endregion
+
+                #region parameter preparation
+               
+                Int64[] retArr;
+               
+                Int64[] arrA = A.GetArrayForRead();
+               
+                Int64[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int workItemMultiplierLenA;
+                int workItemMultiplierLenB;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<Int64>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    workItemMultiplierLenB = outDims[0]; 
+                    workItemMultiplierLenA = dim;  // 0 for column, 1 for row vector
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<Int64>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    workItemMultiplierLenB = dim;  // 0 for column, 1 for row vector
+                    workItemMultiplierLenA = outDims[0]; 
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one singleton dimension in either A or B");
+                }
+                int itLen = outDims[0]; // (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<Int64> retStorage = new ILDenseStorage<Int64>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    Int64* ap;
+                   
+                    Int64* bp;
+                   
+                    Int64* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            if (dim == 0) {
+                                bp = (Int64*)range.Item3;
+                                cp = (Int64*)range.Item4; 
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (Int64*)range.Item2;
+                                    int l = itLen; 
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt64 (ap[0]  % (double) bp[0]);
+                                        cp[1] =  saturateInt64 (ap[1]  % (double) bp[1]);
+                                        cp[2] =  saturateInt64 (ap[2]  % (double) bp[2]);
+                                        cp[3] =  saturateInt64 (ap[3]  % (double) bp[3]);
+                                        cp[4] =  saturateInt64 (ap[4]  % (double) bp[4]);
+                                        cp[5] =  saturateInt64 (ap[5]  % (double) bp[5]);
+                                        cp[6] =  saturateInt64 (ap[6]  % (double) bp[6]);
+                                        cp[7] =  saturateInt64 (ap[7]  % (double) bp[7]);
+                                        cp[8] =  saturateInt64 (ap[8]  % (double) bp[8]);
+                                        cp[9] =  saturateInt64 (ap[9]  % (double) bp[9]);
+                                        cp[10] =  saturateInt64 (ap[10]  % (double) bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =  saturateInt64 (*ap++  % (double) *bp++);
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                ap = (Int64*)range.Item2;
+                                bp = (Int64*)range.Item3;
+                                cp = (Int64*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   Int64 val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt64 (val  % (double) bp[0]);
+                                        cp[1] =  saturateInt64 (val  % (double) bp[1]);
+                                        cp[2] =  saturateInt64 (val  % (double) bp[2]);
+                                        cp[3] =  saturateInt64 (val  % (double) bp[3]);
+                                        cp[4] =  saturateInt64 (val  % (double) bp[4]);
+                                        cp[5] =  saturateInt64 (val  % (double) bp[5]);
+                                        cp[6] =  saturateInt64 (val  % (double) bp[6]);
+                                        cp[7] =  saturateInt64 (val  % (double) bp[7]);
+                                        cp[8] =  saturateInt64 (val  % (double) bp[8]);
+                                        cp[9] =  saturateInt64 (val  % (double) bp[9]);
+                                        cp[10] =  saturateInt64 (val  % (double) bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11; 
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =  saturateInt64 (val  % (double) *bp++);
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            if (dim == 0) {
+                                cp = (Int64*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (Int64*)range.Item2;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt64 (ap[0]  % (double) cp[0]);
+                                        cp[1] =  saturateInt64 (ap[1]  % (double) cp[1]);
+                                        cp[2] =  saturateInt64 (ap[2]  % (double) cp[2]);
+                                        cp[3] =  saturateInt64 (ap[3]  % (double) cp[3]);
+                                        cp[4] =  saturateInt64 (ap[4]  % (double) cp[4]);
+                                        cp[5] =  saturateInt64 (ap[5]  % (double) cp[5]);
+                                        cp[6] =  saturateInt64 (ap[6]  % (double) cp[6]);
+                                        cp[7] =  saturateInt64 (ap[7]  % (double) cp[7]);
+                                        cp[8] =  saturateInt64 (ap[8]  % (double) cp[8]);
+                                        cp[9] =  saturateInt64 (ap[9]  % (double) cp[9]);
+                                        cp[10] =  saturateInt64 (ap[10]  % (double) cp[10]);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt64 (*ap++  % (double) *cp);
+                                        cp++; 
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                cp = (Int64*)range.Item4;
+                                ap = (Int64*)range.Item2;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    Int64 val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt64 (val  % (double) cp[0]);
+                                        cp[1] =  saturateInt64 (val  % (double) cp[1]);
+                                        cp[2] =  saturateInt64 (val  % (double) cp[2]);
+                                        cp[3] =  saturateInt64 (val  % (double) cp[3]);
+                                        cp[4] =  saturateInt64 (val  % (double) cp[4]);
+                                        cp[5] =  saturateInt64 (val  % (double) cp[5]);
+                                        cp[6] =  saturateInt64 (val  % (double) cp[6]);
+                                        cp[7] =  saturateInt64 (val  % (double) cp[7]);
+                                        cp[8] =  saturateInt64 (val  % (double) cp[8]);
+                                        cp[9] =  saturateInt64 (val  % (double) cp[9]);
+                                        cp[10] =  saturateInt64 (val  % (double) cp[10]);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt64 (val  % (double) *cp);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            if (dim == 0) {
+                                ap = (Int64*)range.Item2;
+                                cp = (Int64*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (Int64*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt64 (ap[0]  % (double) bp[0]);
+                                        cp[1] =  saturateInt64 (ap[1]  % (double) bp[1]);
+                                        cp[2] =  saturateInt64 (ap[2]  % (double) bp[2]);
+                                        cp[3] =  saturateInt64 (ap[3]  % (double) bp[3]);
+                                        cp[4] =  saturateInt64 (ap[4]  % (double) bp[4]);
+                                        cp[5] =  saturateInt64 (ap[5]  % (double) bp[5]);
+                                        cp[6] =  saturateInt64 (ap[6]  % (double) bp[6]);
+                                        cp[7] =  saturateInt64 (ap[7]  % (double) bp[7]);
+                                        cp[8] =  saturateInt64 (ap[8]  % (double) bp[8]);
+                                        cp[9] =  saturateInt64 (ap[9]  % (double) bp[9]);
+                                        cp[10] =  saturateInt64 (ap[10]  % (double) bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt64 (*ap  % (double) *bp);
+                                        ap++;
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                ap = (Int64*)range.Item2;
+                                bp = (Int64*)range.Item3;
+                                cp = (Int64*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   Int64 val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt64 (ap[0]  % (double) val);
+                                        cp[1] =  saturateInt64 (ap[1]  % (double) val);
+                                        cp[2] =  saturateInt64 (ap[2]  % (double) val);
+                                        cp[3] =  saturateInt64 (ap[3]  % (double) val);
+                                        cp[4] =  saturateInt64 (ap[4]  % (double) val);
+                                        cp[5] =  saturateInt64 (ap[5]  % (double) val);
+                                        cp[6] =  saturateInt64 (ap[6]  % (double) val);
+                                        cp[7] =  saturateInt64 (ap[7]  % (double) val);
+                                        cp[8] =  saturateInt64 (ap[8]  % (double) val);
+                                        cp[9] =  saturateInt64 (ap[9]  % (double) val);
+                                        cp[10] =  saturateInt64 (ap[10]  % (double) val);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt64 (*ap  % (double) val);
+                                        ap++;
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            if (dim == 0) {
+                                cp = (Int64*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (Int64*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt64 (cp[0]  % (double) bp[0]);
+                                        cp[1] =  saturateInt64 (cp[1]  % (double) bp[1]);
+                                        cp[2] =  saturateInt64 (cp[2]  % (double) bp[2]);
+                                        cp[3] =  saturateInt64 (cp[3]  % (double) bp[3]);
+                                        cp[4] =  saturateInt64 (cp[4]  % (double) bp[4]);
+                                        cp[5] =  saturateInt64 (cp[5]  % (double) bp[5]);
+                                        cp[6] =  saturateInt64 (cp[6]  % (double) bp[6]);
+                                        cp[7] =  saturateInt64 (cp[7]  % (double) bp[7]);
+                                        cp[8] =  saturateInt64 (cp[8]  % (double) bp[8]);
+                                        cp[9] =  saturateInt64 (cp[9]  % (double) bp[9]);
+                                        cp[10] =  saturateInt64 (cp[10]  % (double) bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt64 (*cp  % (double) *bp);
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                bp = (Int64*)range.Item3;
+                                cp = (Int64*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    Int64 val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt64 (cp[0]  % (double) val);
+                                        cp[1] =  saturateInt64 (cp[1]  % (double) val);
+                                        cp[2] =  saturateInt64 (cp[2]  % (double) val);
+                                        cp[3] =  saturateInt64 (cp[3]  % (double) val);
+                                        cp[4] =  saturateInt64 (cp[4]  % (double) val);
+                                        cp[5] =  saturateInt64 (cp[5]  % (double) val);
+                                        cp[6] =  saturateInt64 (cp[6]  % (double) val);
+                                        cp[7] =  saturateInt64 (cp[7]  % (double) val);
+                                        cp[8] =  saturateInt64 (cp[8]  % (double) val);
+                                        cp[9] =  saturateInt64 (cp[9]  % (double) val);
+                                        cp[10] =  saturateInt64 (cp[10]  % (double) val);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l --> 0) {
+                                        *cp =  saturateInt64 (*cp  % (double) val);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outDims.NumberOfElements >= Settings.s_minParallelElement1Count
+                    && outDims[1] > 1) {
+                        if (outDims[1] > workItemCount) {
+                        workItemLength = outDims[1] / workItemCount;
+                    } else {
+                        workItemLength = outDims[1] / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outDims[1];
+                    workItemCount = 1;
+                }
+
+                fixed ( Int64* arrAP = arrA)
+                fixed ( Int64* arrBP = arrB)
+                fixed ( Int64* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, IntPtr, IntPtr, IntPtr> range = new Tuple<int, IntPtr, IntPtr, IntPtr>
+                               (workItemLength
+                               , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                               , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                               , (IntPtr)(retArrP + i * outDims[0] * workItemLength)); 
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, IntPtr, IntPtr, IntPtr>
+                                (outDims[1] - i * workItemLength
+                                , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                                , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                                , (IntPtr)(retArrP + i * outDims[0] * workItemLength)));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<Int64>(retStorage);
+            //}  // no scopes here! it disables implace operations
+        }
+
+        /// <summary>Modulus of array elements</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>New array with result of elementwise modulus operation</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<Int32>  mod(ILInArray<Int32> A, ILInArray<Int32> B) {
+            using (ILScope.Enter(A,B)) {
+                int outLen; 
+                BinOpItMode mode; 
+                Int32 [] retArr;
+                Int32 [] arrA = A.GetArrayForRead();
+                Int32[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size; 
+                    if (B.IsScalar) {
+                       
+                        return new  ILRetArray<Int32> (new  Int32 [1]{ saturateInt32 (A.GetValue(0)  % (double) B.GetValue(0))}, A.Size);
+                    } else if (B.IsEmpty) {
+                        return  ILRetArray<Int32>.empty(outDims); 
+                    } else {
+                        outLen = outDims.NumberOfElements; 
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< Int32 > (outLen);
+                            mode = BinOpItMode.SAN; 
+                        } else {
+                            mode = BinOpItMode.SAI; 
+                        }
+                    }
+                } else {
+                    outDims = A.Size; 
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return  ILRetArray<Int32>.empty(A.Size);  
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< Int32 > (outLen);
+                            mode = BinOpItMode.ASN; 
+                        } else {
+                            mode = BinOpItMode.ASI; 
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  modEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (A.TryGetStorage4InplaceOp(out retArr)) 
+                            mode  = BinOpItMode.AAIA; 
+                        else if (B.TryGetStorage4InplaceOp(out retArr)) 
+                            mode = BinOpItMode.AAIB; 
+                        else {
+                            retArr = ILMemoryPool.Pool.New< Int32 > (outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<Int32> retStorage = new ILDenseStorage<Int32>(retArr, outDims);
+                int i = 0, workerCount = 1; 
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    Int32* cp = (Int32*)range.Item5 + range.Item1;
+                    Int32 scalar;
+                    int j = range.Item2; 
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           Int32* bp = ((Int32*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                                cp[0] =  saturateInt32 (cp[0]  % (double) bp[0]);
+                                cp[1] =  saturateInt32 (cp[1]  % (double) bp[1]);
+                                cp[2] =  saturateInt32 (cp[2]  % (double) bp[2]);
+                                cp[3] =  saturateInt32 (cp[3]  % (double) bp[3]);
+                                cp[4] =  saturateInt32 (cp[4]  % (double) bp[4]);
+                                cp[5] =  saturateInt32 (cp[5]  % (double) bp[5]);
+                                cp[6] =  saturateInt32 (cp[6]  % (double) bp[6]);
+                                cp[7] =  saturateInt32 (cp[7]  % (double) bp[7]);
+                                cp[8] =  saturateInt32 (cp[8]  % (double) bp[8]);
+                                cp[9] =  saturateInt32 (cp[9]  % (double) bp[9]);
+                                cp[10] =  saturateInt32 (cp[10]  % (double) bp[10]);
+                                cp[11] =  saturateInt32 (cp[11]  % (double) bp[11]);
+                                cp[12] =  saturateInt32 (cp[12]  % (double) bp[12]);
+                                cp[13] =  saturateInt32 (cp[13]  % (double) bp[13]);
+                                cp[14] =  saturateInt32 (cp[14]  % (double) bp[14]);
+                                cp[15] =  saturateInt32 (cp[15]  % (double) bp[15]);
+                                cp[16] =  saturateInt32 (cp[16]  % (double) bp[16]);
+                                cp[17] =  saturateInt32 (cp[17]  % (double) bp[17]);
+                                cp[18] =  saturateInt32 (cp[18]  % (double) bp[18]);
+                                cp[19] =  saturateInt32 (cp[19]  % (double) bp[19]);
+                                cp[20] =  saturateInt32 (cp[20]  % (double) bp[20]);
+                                cp += 21; bp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt32 (*cp  % (double) *bp);
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           Int32* ap = ((Int32*)range.Item3 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt32 (ap[0]  % (double) cp[0]);
+                                cp[1] =  saturateInt32 (ap[1]  % (double) cp[1]);
+                                cp[2] =  saturateInt32 (ap[2]  % (double) cp[2]);
+                                cp[3] =  saturateInt32 (ap[3]  % (double) cp[3]);
+                                cp[4] =  saturateInt32 (ap[4]  % (double) cp[4]);
+                                cp[5] =  saturateInt32 (ap[5]  % (double) cp[5]);
+                                cp[6] =  saturateInt32 (ap[6]  % (double) cp[6]);
+                                cp[7] =  saturateInt32 (ap[7]  % (double) cp[7]);
+                                cp[8] =  saturateInt32 (ap[8]  % (double) cp[8]);
+                                cp[9] =  saturateInt32 (ap[9]  % (double) cp[9]);
+                                cp[10] =  saturateInt32 (ap[10]  % (double) cp[10]);
+                                cp[11] =  saturateInt32 (ap[11]  % (double) cp[11]);
+                                cp[12] =  saturateInt32 (ap[12]  % (double) cp[12]);
+                                cp[13] =  saturateInt32 (ap[13]  % (double) cp[13]);
+                                cp[14] =  saturateInt32 (ap[14]  % (double) cp[14]);
+                                cp[15] =  saturateInt32 (ap[15]  % (double) cp[15]);
+                                cp[16] =  saturateInt32 (ap[16]  % (double) cp[16]);
+                                cp[17] =  saturateInt32 (ap[17]  % (double) cp[17]);
+                                cp[18] =  saturateInt32 (ap[18]  % (double) cp[18]);
+                                cp[19] =  saturateInt32 (ap[19]  % (double) cp[19]);
+                                cp[20] =  saturateInt32 (ap[20]  % (double) cp[20]);
+                                ap += 21; cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt32 (*ap  % (double) *cp);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((Int32*)range.Item3 + range.Item1);
+                            bp = ((Int32*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt32 (ap[0]  % (double) bp[0]);
+                                cp[1] =  saturateInt32 (ap[1]  % (double) bp[1]);
+                                cp[2] =  saturateInt32 (ap[2]  % (double) bp[2]);
+                                cp[3] =  saturateInt32 (ap[3]  % (double) bp[3]);
+                                cp[4] =  saturateInt32 (ap[4]  % (double) bp[4]);
+                                cp[5] =  saturateInt32 (ap[5]  % (double) bp[5]);
+                                cp[6] =  saturateInt32 (ap[6]  % (double) bp[6]);
+                                cp[7] =  saturateInt32 (ap[7]  % (double) bp[7]);
+                                cp[8] =  saturateInt32 (ap[8]  % (double) bp[8]);
+                                cp[9] =  saturateInt32 (ap[9]  % (double) bp[9]);
+                                cp[10] =  saturateInt32 (ap[10]  % (double) bp[10]);
+                                cp[11] =  saturateInt32 (ap[11]  % (double) bp[11]);
+                                cp[12] =  saturateInt32 (ap[12]  % (double) bp[12]);
+                                cp[13] =  saturateInt32 (ap[13]  % (double) bp[13]);
+                                cp[14] =  saturateInt32 (ap[14]  % (double) bp[14]);
+                                cp[15] =  saturateInt32 (ap[15]  % (double) bp[15]);
+                                cp[16] =  saturateInt32 (ap[16]  % (double) bp[16]);
+                                cp[17] =  saturateInt32 (ap[17]  % (double) bp[17]);
+                                cp[18] =  saturateInt32 (ap[18]  % (double) bp[18]);
+                                cp[19] =  saturateInt32 (ap[19]  % (double) bp[19]);
+                                cp[20] =  saturateInt32 (ap[20]  % (double) bp[20]);
+                                ap+=21; bp+=21; cp+=21; j-=21;
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt32 (*ap  % (double) *bp);
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((Int32*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt32 (cp[0]  % (double) scalar);
+                                cp[1] =  saturateInt32 (cp[1]  % (double) scalar);
+                                cp[2] =  saturateInt32 (cp[2]  % (double) scalar);
+                                cp[3] =  saturateInt32 (cp[3]  % (double) scalar);
+                                cp[4] =  saturateInt32 (cp[4]  % (double) scalar);
+                                cp[5] =  saturateInt32 (cp[5]  % (double) scalar);
+                                cp[6] =  saturateInt32 (cp[6]  % (double) scalar);
+                                cp[7] =  saturateInt32 (cp[7]  % (double) scalar);
+                                cp[8] =  saturateInt32 (cp[8]  % (double) scalar);
+                                cp[9] =  saturateInt32 (cp[9]  % (double) scalar);
+                                cp[10] =  saturateInt32 (cp[10]  % (double) scalar);
+                                cp[11] =  saturateInt32 (cp[11]  % (double) scalar);
+                                cp[12] =  saturateInt32 (cp[12]  % (double) scalar);
+                                cp[13] =  saturateInt32 (cp[13]  % (double) scalar);
+                                cp[14] =  saturateInt32 (cp[14]  % (double) scalar);
+                                cp[15] =  saturateInt32 (cp[15]  % (double) scalar);
+                                cp[16] =  saturateInt32 (cp[16]  % (double) scalar);
+                                cp[17] =  saturateInt32 (cp[17]  % (double) scalar);
+                                cp[18] =  saturateInt32 (cp[18]  % (double) scalar);
+                                cp[19] =  saturateInt32 (cp[19]  % (double) scalar);
+                                cp[20] =  saturateInt32 (cp[20]  % (double) scalar);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt32 (*cp  % (double) scalar);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((Int32*)range.Item3 + range.Item1);
+                            scalar = *((Int32*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt32 (ap[0]  % (double) scalar);
+                                cp[1] =  saturateInt32 (ap[1]  % (double) scalar);
+                                cp[2] =  saturateInt32 (ap[2]  % (double) scalar);
+                                cp[3] =  saturateInt32 (ap[3]  % (double) scalar);
+                                cp[4] =  saturateInt32 (ap[4]  % (double) scalar);
+                                cp[5] =  saturateInt32 (ap[5]  % (double) scalar);
+                                cp[6] =  saturateInt32 (ap[6]  % (double) scalar);
+                                cp[7] =  saturateInt32 (ap[7]  % (double) scalar);
+                                cp[8] =  saturateInt32 (ap[8]  % (double) scalar);
+                                cp[9] =  saturateInt32 (ap[9]  % (double) scalar);
+                                cp[10] =  saturateInt32 (ap[10]  % (double) scalar);
+                                cp[11] =  saturateInt32 (ap[11]  % (double) scalar);
+                                cp[12] =  saturateInt32 (ap[12]  % (double) scalar);
+                                cp[13] =  saturateInt32 (ap[13]  % (double) scalar);
+                                cp[14] =  saturateInt32 (ap[14]  % (double) scalar);
+                                cp[15] =  saturateInt32 (ap[15]  % (double) scalar);
+                                cp[16] =  saturateInt32 (ap[16]  % (double) scalar);
+                                cp[17] =  saturateInt32 (ap[17]  % (double) scalar);
+                                cp[18] =  saturateInt32 (ap[18]  % (double) scalar);
+                                cp[19] =  saturateInt32 (ap[19]  % (double) scalar);
+                                cp[20] =  saturateInt32 (ap[20]  % (double) scalar);
+                                ap+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt32 (*ap  % (double) scalar);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((Int32*)range.Item3);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt32 (scalar  % (double) cp[0]);
+                                cp[1] =  saturateInt32 (scalar  % (double) cp[1]);
+                                cp[2] =  saturateInt32 (scalar  % (double) cp[2]);
+                                cp[3] =  saturateInt32 (scalar  % (double) cp[3]);
+                                cp[4] =  saturateInt32 (scalar  % (double) cp[4]);
+                                cp[5] =  saturateInt32 (scalar  % (double) cp[5]);
+                                cp[6] =  saturateInt32 (scalar  % (double) cp[6]);
+                                cp[7] =  saturateInt32 (scalar  % (double) cp[7]);
+                                cp[8] =  saturateInt32 (scalar  % (double) cp[8]);
+                                cp[9] =  saturateInt32 (scalar  % (double) cp[9]);
+                                cp[10] =  saturateInt32 (scalar  % (double) cp[10]);
+                                cp[11] =  saturateInt32 (scalar  % (double) cp[11]);
+                                cp[12] =  saturateInt32 (scalar  % (double) cp[12]);
+                                cp[13] =  saturateInt32 (scalar  % (double) cp[13]);
+                                cp[14] =  saturateInt32 (scalar  % (double) cp[14]);
+                                cp[15] =  saturateInt32 (scalar  % (double) cp[15]);
+                                cp[16] =  saturateInt32 (scalar  % (double) cp[16]);
+                                cp[17] =  saturateInt32 (scalar  % (double) cp[17]);
+                                cp[18] =  saturateInt32 (scalar  % (double) cp[18]);
+                                cp[19] =  saturateInt32 (scalar  % (double) cp[19]);
+                                cp[20] =  saturateInt32 (scalar  % (double) cp[20]);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt32 (scalar  % (double) *cp);
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((Int32*)range.Item3);
+                            bp = ((Int32*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt32 (scalar  % (double) bp[0]);
+                                cp[1] =  saturateInt32 (scalar  % (double) bp[1]);
+                                cp[2] =  saturateInt32 (scalar  % (double) bp[2]);
+                                cp[3] =  saturateInt32 (scalar  % (double) bp[3]);
+                                cp[4] =  saturateInt32 (scalar  % (double) bp[4]);
+                                cp[5] =  saturateInt32 (scalar  % (double) bp[5]);
+                                cp[6] =  saturateInt32 (scalar  % (double) bp[6]);
+                                cp[7] =  saturateInt32 (scalar  % (double) bp[7]);
+                                cp[8] =  saturateInt32 (scalar  % (double) bp[8]);
+                                cp[9] =  saturateInt32 (scalar  % (double) bp[9]);
+                                cp[10] =  saturateInt32 (scalar  % (double) bp[10]);
+                                cp[11] =  saturateInt32 (scalar  % (double) bp[11]);
+                                cp[12] =  saturateInt32 (scalar  % (double) bp[12]);
+                                cp[13] =  saturateInt32 (scalar  % (double) bp[13]);
+                                cp[14] =  saturateInt32 (scalar  % (double) bp[14]);
+                                cp[15] =  saturateInt32 (scalar  % (double) bp[15]);
+                                cp[16] =  saturateInt32 (scalar  % (double) bp[16]);
+                                cp[17] =  saturateInt32 (scalar  % (double) bp[17]);
+                                cp[18] =  saturateInt32 (scalar  % (double) bp[18]);
+                                cp[19] =  saturateInt32 (scalar  % (double) bp[19]);
+                                cp[20] =  saturateInt32 (scalar  % (double) bp[20]);
+                                bp+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt32 (scalar  % (double) *bp);
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work 
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                
+                fixed ( Int32* arrAP = arrA)
+                fixed ( Int32* arrBP = arrB)
+                fixed ( Int32* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range 
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new  ILRetArray< Int32>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<Int32>  modEx(ILInArray<Int32> A, ILInArray<Int32> B) {
+            //using (ILScope.Enter(A, B)) { we cannot start a new scope here, since this would prevent A and B to be used implace if applicable
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<Int32>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<Int32>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<Int32>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                dim = -(dim - 1);  // 0 -> 1, 1 -> 0
+                #endregion
+
+                #region parameter preparation
+               
+                Int32[] retArr;
+               
+                Int32[] arrA = A.GetArrayForRead();
+               
+                Int32[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int workItemMultiplierLenA;
+                int workItemMultiplierLenB;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<Int32>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    workItemMultiplierLenB = outDims[0]; 
+                    workItemMultiplierLenA = dim;  // 0 for column, 1 for row vector
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<Int32>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    workItemMultiplierLenB = dim;  // 0 for column, 1 for row vector
+                    workItemMultiplierLenA = outDims[0]; 
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one singleton dimension in either A or B");
+                }
+                int itLen = outDims[0]; // (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<Int32> retStorage = new ILDenseStorage<Int32>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    Int32* ap;
+                   
+                    Int32* bp;
+                   
+                    Int32* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            if (dim == 0) {
+                                bp = (Int32*)range.Item3;
+                                cp = (Int32*)range.Item4; 
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (Int32*)range.Item2;
+                                    int l = itLen; 
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt32 (ap[0]  % (double) bp[0]);
+                                        cp[1] =  saturateInt32 (ap[1]  % (double) bp[1]);
+                                        cp[2] =  saturateInt32 (ap[2]  % (double) bp[2]);
+                                        cp[3] =  saturateInt32 (ap[3]  % (double) bp[3]);
+                                        cp[4] =  saturateInt32 (ap[4]  % (double) bp[4]);
+                                        cp[5] =  saturateInt32 (ap[5]  % (double) bp[5]);
+                                        cp[6] =  saturateInt32 (ap[6]  % (double) bp[6]);
+                                        cp[7] =  saturateInt32 (ap[7]  % (double) bp[7]);
+                                        cp[8] =  saturateInt32 (ap[8]  % (double) bp[8]);
+                                        cp[9] =  saturateInt32 (ap[9]  % (double) bp[9]);
+                                        cp[10] =  saturateInt32 (ap[10]  % (double) bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =  saturateInt32 (*ap++  % (double) *bp++);
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                ap = (Int32*)range.Item2;
+                                bp = (Int32*)range.Item3;
+                                cp = (Int32*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   Int32 val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt32 (val  % (double) bp[0]);
+                                        cp[1] =  saturateInt32 (val  % (double) bp[1]);
+                                        cp[2] =  saturateInt32 (val  % (double) bp[2]);
+                                        cp[3] =  saturateInt32 (val  % (double) bp[3]);
+                                        cp[4] =  saturateInt32 (val  % (double) bp[4]);
+                                        cp[5] =  saturateInt32 (val  % (double) bp[5]);
+                                        cp[6] =  saturateInt32 (val  % (double) bp[6]);
+                                        cp[7] =  saturateInt32 (val  % (double) bp[7]);
+                                        cp[8] =  saturateInt32 (val  % (double) bp[8]);
+                                        cp[9] =  saturateInt32 (val  % (double) bp[9]);
+                                        cp[10] =  saturateInt32 (val  % (double) bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11; 
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =  saturateInt32 (val  % (double) *bp++);
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            if (dim == 0) {
+                                cp = (Int32*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (Int32*)range.Item2;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt32 (ap[0]  % (double) cp[0]);
+                                        cp[1] =  saturateInt32 (ap[1]  % (double) cp[1]);
+                                        cp[2] =  saturateInt32 (ap[2]  % (double) cp[2]);
+                                        cp[3] =  saturateInt32 (ap[3]  % (double) cp[3]);
+                                        cp[4] =  saturateInt32 (ap[4]  % (double) cp[4]);
+                                        cp[5] =  saturateInt32 (ap[5]  % (double) cp[5]);
+                                        cp[6] =  saturateInt32 (ap[6]  % (double) cp[6]);
+                                        cp[7] =  saturateInt32 (ap[7]  % (double) cp[7]);
+                                        cp[8] =  saturateInt32 (ap[8]  % (double) cp[8]);
+                                        cp[9] =  saturateInt32 (ap[9]  % (double) cp[9]);
+                                        cp[10] =  saturateInt32 (ap[10]  % (double) cp[10]);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt32 (*ap++  % (double) *cp);
+                                        cp++; 
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                cp = (Int32*)range.Item4;
+                                ap = (Int32*)range.Item2;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    Int32 val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt32 (val  % (double) cp[0]);
+                                        cp[1] =  saturateInt32 (val  % (double) cp[1]);
+                                        cp[2] =  saturateInt32 (val  % (double) cp[2]);
+                                        cp[3] =  saturateInt32 (val  % (double) cp[3]);
+                                        cp[4] =  saturateInt32 (val  % (double) cp[4]);
+                                        cp[5] =  saturateInt32 (val  % (double) cp[5]);
+                                        cp[6] =  saturateInt32 (val  % (double) cp[6]);
+                                        cp[7] =  saturateInt32 (val  % (double) cp[7]);
+                                        cp[8] =  saturateInt32 (val  % (double) cp[8]);
+                                        cp[9] =  saturateInt32 (val  % (double) cp[9]);
+                                        cp[10] =  saturateInt32 (val  % (double) cp[10]);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt32 (val  % (double) *cp);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            if (dim == 0) {
+                                ap = (Int32*)range.Item2;
+                                cp = (Int32*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (Int32*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt32 (ap[0]  % (double) bp[0]);
+                                        cp[1] =  saturateInt32 (ap[1]  % (double) bp[1]);
+                                        cp[2] =  saturateInt32 (ap[2]  % (double) bp[2]);
+                                        cp[3] =  saturateInt32 (ap[3]  % (double) bp[3]);
+                                        cp[4] =  saturateInt32 (ap[4]  % (double) bp[4]);
+                                        cp[5] =  saturateInt32 (ap[5]  % (double) bp[5]);
+                                        cp[6] =  saturateInt32 (ap[6]  % (double) bp[6]);
+                                        cp[7] =  saturateInt32 (ap[7]  % (double) bp[7]);
+                                        cp[8] =  saturateInt32 (ap[8]  % (double) bp[8]);
+                                        cp[9] =  saturateInt32 (ap[9]  % (double) bp[9]);
+                                        cp[10] =  saturateInt32 (ap[10]  % (double) bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt32 (*ap  % (double) *bp);
+                                        ap++;
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                ap = (Int32*)range.Item2;
+                                bp = (Int32*)range.Item3;
+                                cp = (Int32*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   Int32 val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt32 (ap[0]  % (double) val);
+                                        cp[1] =  saturateInt32 (ap[1]  % (double) val);
+                                        cp[2] =  saturateInt32 (ap[2]  % (double) val);
+                                        cp[3] =  saturateInt32 (ap[3]  % (double) val);
+                                        cp[4] =  saturateInt32 (ap[4]  % (double) val);
+                                        cp[5] =  saturateInt32 (ap[5]  % (double) val);
+                                        cp[6] =  saturateInt32 (ap[6]  % (double) val);
+                                        cp[7] =  saturateInt32 (ap[7]  % (double) val);
+                                        cp[8] =  saturateInt32 (ap[8]  % (double) val);
+                                        cp[9] =  saturateInt32 (ap[9]  % (double) val);
+                                        cp[10] =  saturateInt32 (ap[10]  % (double) val);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt32 (*ap  % (double) val);
+                                        ap++;
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            if (dim == 0) {
+                                cp = (Int32*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (Int32*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt32 (cp[0]  % (double) bp[0]);
+                                        cp[1] =  saturateInt32 (cp[1]  % (double) bp[1]);
+                                        cp[2] =  saturateInt32 (cp[2]  % (double) bp[2]);
+                                        cp[3] =  saturateInt32 (cp[3]  % (double) bp[3]);
+                                        cp[4] =  saturateInt32 (cp[4]  % (double) bp[4]);
+                                        cp[5] =  saturateInt32 (cp[5]  % (double) bp[5]);
+                                        cp[6] =  saturateInt32 (cp[6]  % (double) bp[6]);
+                                        cp[7] =  saturateInt32 (cp[7]  % (double) bp[7]);
+                                        cp[8] =  saturateInt32 (cp[8]  % (double) bp[8]);
+                                        cp[9] =  saturateInt32 (cp[9]  % (double) bp[9]);
+                                        cp[10] =  saturateInt32 (cp[10]  % (double) bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt32 (*cp  % (double) *bp);
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                bp = (Int32*)range.Item3;
+                                cp = (Int32*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    Int32 val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt32 (cp[0]  % (double) val);
+                                        cp[1] =  saturateInt32 (cp[1]  % (double) val);
+                                        cp[2] =  saturateInt32 (cp[2]  % (double) val);
+                                        cp[3] =  saturateInt32 (cp[3]  % (double) val);
+                                        cp[4] =  saturateInt32 (cp[4]  % (double) val);
+                                        cp[5] =  saturateInt32 (cp[5]  % (double) val);
+                                        cp[6] =  saturateInt32 (cp[6]  % (double) val);
+                                        cp[7] =  saturateInt32 (cp[7]  % (double) val);
+                                        cp[8] =  saturateInt32 (cp[8]  % (double) val);
+                                        cp[9] =  saturateInt32 (cp[9]  % (double) val);
+                                        cp[10] =  saturateInt32 (cp[10]  % (double) val);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l --> 0) {
+                                        *cp =  saturateInt32 (*cp  % (double) val);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outDims.NumberOfElements >= Settings.s_minParallelElement1Count
+                    && outDims[1] > 1) {
+                        if (outDims[1] > workItemCount) {
+                        workItemLength = outDims[1] / workItemCount;
+                    } else {
+                        workItemLength = outDims[1] / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outDims[1];
+                    workItemCount = 1;
+                }
+
+                fixed ( Int32* arrAP = arrA)
+                fixed ( Int32* arrBP = arrB)
+                fixed ( Int32* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, IntPtr, IntPtr, IntPtr> range = new Tuple<int, IntPtr, IntPtr, IntPtr>
+                               (workItemLength
+                               , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                               , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                               , (IntPtr)(retArrP + i * outDims[0] * workItemLength)); 
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, IntPtr, IntPtr, IntPtr>
+                                (outDims[1] - i * workItemLength
+                                , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                                , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                                , (IntPtr)(retArrP + i * outDims[0] * workItemLength)));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<Int32>(retStorage);
+            //}  // no scopes here! it disables implace operations
+        }
+
+        /// <summary>Modulus of array elements</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>New array with result of elementwise modulus operation</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<float>  mod(ILInArray<float> A, ILInArray<float> B) {
+            using (ILScope.Enter(A,B)) {
+                int outLen; 
+                BinOpItMode mode; 
+                float [] retArr;
+                float [] arrA = A.GetArrayForRead();
+                float[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size; 
+                    if (B.IsScalar) {
+                       
+                        return new  ILRetArray<float> (new  float [1]{  (A.GetValue(0)  % B.GetValue(0))}, A.Size);
+                    } else if (B.IsEmpty) {
+                        return  ILRetArray<float>.empty(outDims); 
+                    } else {
+                        outLen = outDims.NumberOfElements; 
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< float > (outLen);
+                            mode = BinOpItMode.SAN; 
+                        } else {
+                            mode = BinOpItMode.SAI; 
+                        }
+                    }
+                } else {
+                    outDims = A.Size; 
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return  ILRetArray<float>.empty(A.Size);  
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< float > (outLen);
+                            mode = BinOpItMode.ASN; 
+                        } else {
+                            mode = BinOpItMode.ASI; 
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  modEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (A.TryGetStorage4InplaceOp(out retArr)) 
+                            mode  = BinOpItMode.AAIA; 
+                        else if (B.TryGetStorage4InplaceOp(out retArr)) 
+                            mode = BinOpItMode.AAIB; 
+                        else {
+                            retArr = ILMemoryPool.Pool.New< float > (outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<float> retStorage = new ILDenseStorage<float>(retArr, outDims);
+                int i = 0, workerCount = 1; 
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    float* cp = (float*)range.Item5 + range.Item1;
+                    float scalar;
+                    int j = range.Item2; 
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           float* bp = ((float*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                                cp[0] =   (cp[0]  % bp[0]);
+                                cp[1] =   (cp[1]  % bp[1]);
+                                cp[2] =   (cp[2]  % bp[2]);
+                                cp[3] =   (cp[3]  % bp[3]);
+                                cp[4] =   (cp[4]  % bp[4]);
+                                cp[5] =   (cp[5]  % bp[5]);
+                                cp[6] =   (cp[6]  % bp[6]);
+                                cp[7] =   (cp[7]  % bp[7]);
+                                cp[8] =   (cp[8]  % bp[8]);
+                                cp[9] =   (cp[9]  % bp[9]);
+                                cp[10] =   (cp[10]  % bp[10]);
+                                cp[11] =   (cp[11]  % bp[11]);
+                                cp[12] =   (cp[12]  % bp[12]);
+                                cp[13] =   (cp[13]  % bp[13]);
+                                cp[14] =   (cp[14]  % bp[14]);
+                                cp[15] =   (cp[15]  % bp[15]);
+                                cp[16] =   (cp[16]  % bp[16]);
+                                cp[17] =   (cp[17]  % bp[17]);
+                                cp[18] =   (cp[18]  % bp[18]);
+                                cp[19] =   (cp[19]  % bp[19]);
+                                cp[20] =   (cp[20]  % bp[20]);
+                                cp += 21; bp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*cp  % *bp);
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           float* ap = ((float*)range.Item3 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  % cp[0]);
+                                cp[1] =   (ap[1]  % cp[1]);
+                                cp[2] =   (ap[2]  % cp[2]);
+                                cp[3] =   (ap[3]  % cp[3]);
+                                cp[4] =   (ap[4]  % cp[4]);
+                                cp[5] =   (ap[5]  % cp[5]);
+                                cp[6] =   (ap[6]  % cp[6]);
+                                cp[7] =   (ap[7]  % cp[7]);
+                                cp[8] =   (ap[8]  % cp[8]);
+                                cp[9] =   (ap[9]  % cp[9]);
+                                cp[10] =   (ap[10]  % cp[10]);
+                                cp[11] =   (ap[11]  % cp[11]);
+                                cp[12] =   (ap[12]  % cp[12]);
+                                cp[13] =   (ap[13]  % cp[13]);
+                                cp[14] =   (ap[14]  % cp[14]);
+                                cp[15] =   (ap[15]  % cp[15]);
+                                cp[16] =   (ap[16]  % cp[16]);
+                                cp[17] =   (ap[17]  % cp[17]);
+                                cp[18] =   (ap[18]  % cp[18]);
+                                cp[19] =   (ap[19]  % cp[19]);
+                                cp[20] =   (ap[20]  % cp[20]);
+                                ap += 21; cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  % *cp);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((float*)range.Item3 + range.Item1);
+                            bp = ((float*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  % bp[0]);
+                                cp[1] =   (ap[1]  % bp[1]);
+                                cp[2] =   (ap[2]  % bp[2]);
+                                cp[3] =   (ap[3]  % bp[3]);
+                                cp[4] =   (ap[4]  % bp[4]);
+                                cp[5] =   (ap[5]  % bp[5]);
+                                cp[6] =   (ap[6]  % bp[6]);
+                                cp[7] =   (ap[7]  % bp[7]);
+                                cp[8] =   (ap[8]  % bp[8]);
+                                cp[9] =   (ap[9]  % bp[9]);
+                                cp[10] =   (ap[10]  % bp[10]);
+                                cp[11] =   (ap[11]  % bp[11]);
+                                cp[12] =   (ap[12]  % bp[12]);
+                                cp[13] =   (ap[13]  % bp[13]);
+                                cp[14] =   (ap[14]  % bp[14]);
+                                cp[15] =   (ap[15]  % bp[15]);
+                                cp[16] =   (ap[16]  % bp[16]);
+                                cp[17] =   (ap[17]  % bp[17]);
+                                cp[18] =   (ap[18]  % bp[18]);
+                                cp[19] =   (ap[19]  % bp[19]);
+                                cp[20] =   (ap[20]  % bp[20]);
+                                ap+=21; bp+=21; cp+=21; j-=21;
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  % *bp);
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((float*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =   (cp[0]  % scalar);
+                                cp[1] =   (cp[1]  % scalar);
+                                cp[2] =   (cp[2]  % scalar);
+                                cp[3] =   (cp[3]  % scalar);
+                                cp[4] =   (cp[4]  % scalar);
+                                cp[5] =   (cp[5]  % scalar);
+                                cp[6] =   (cp[6]  % scalar);
+                                cp[7] =   (cp[7]  % scalar);
+                                cp[8] =   (cp[8]  % scalar);
+                                cp[9] =   (cp[9]  % scalar);
+                                cp[10] =   (cp[10]  % scalar);
+                                cp[11] =   (cp[11]  % scalar);
+                                cp[12] =   (cp[12]  % scalar);
+                                cp[13] =   (cp[13]  % scalar);
+                                cp[14] =   (cp[14]  % scalar);
+                                cp[15] =   (cp[15]  % scalar);
+                                cp[16] =   (cp[16]  % scalar);
+                                cp[17] =   (cp[17]  % scalar);
+                                cp[18] =   (cp[18]  % scalar);
+                                cp[19] =   (cp[19]  % scalar);
+                                cp[20] =   (cp[20]  % scalar);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*cp  % scalar);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((float*)range.Item3 + range.Item1);
+                            scalar = *((float*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  % scalar);
+                                cp[1] =   (ap[1]  % scalar);
+                                cp[2] =   (ap[2]  % scalar);
+                                cp[3] =   (ap[3]  % scalar);
+                                cp[4] =   (ap[4]  % scalar);
+                                cp[5] =   (ap[5]  % scalar);
+                                cp[6] =   (ap[6]  % scalar);
+                                cp[7] =   (ap[7]  % scalar);
+                                cp[8] =   (ap[8]  % scalar);
+                                cp[9] =   (ap[9]  % scalar);
+                                cp[10] =   (ap[10]  % scalar);
+                                cp[11] =   (ap[11]  % scalar);
+                                cp[12] =   (ap[12]  % scalar);
+                                cp[13] =   (ap[13]  % scalar);
+                                cp[14] =   (ap[14]  % scalar);
+                                cp[15] =   (ap[15]  % scalar);
+                                cp[16] =   (ap[16]  % scalar);
+                                cp[17] =   (ap[17]  % scalar);
+                                cp[18] =   (ap[18]  % scalar);
+                                cp[19] =   (ap[19]  % scalar);
+                                cp[20] =   (ap[20]  % scalar);
+                                ap+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  % scalar);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((float*)range.Item3);
+                            while (j > 20) {
+                               
+                                cp[0] =   (scalar  % cp[0]);
+                                cp[1] =   (scalar  % cp[1]);
+                                cp[2] =   (scalar  % cp[2]);
+                                cp[3] =   (scalar  % cp[3]);
+                                cp[4] =   (scalar  % cp[4]);
+                                cp[5] =   (scalar  % cp[5]);
+                                cp[6] =   (scalar  % cp[6]);
+                                cp[7] =   (scalar  % cp[7]);
+                                cp[8] =   (scalar  % cp[8]);
+                                cp[9] =   (scalar  % cp[9]);
+                                cp[10] =   (scalar  % cp[10]);
+                                cp[11] =   (scalar  % cp[11]);
+                                cp[12] =   (scalar  % cp[12]);
+                                cp[13] =   (scalar  % cp[13]);
+                                cp[14] =   (scalar  % cp[14]);
+                                cp[15] =   (scalar  % cp[15]);
+                                cp[16] =   (scalar  % cp[16]);
+                                cp[17] =   (scalar  % cp[17]);
+                                cp[18] =   (scalar  % cp[18]);
+                                cp[19] =   (scalar  % cp[19]);
+                                cp[20] =   (scalar  % cp[20]);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (scalar  % *cp);
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((float*)range.Item3);
+                            bp = ((float*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (scalar  % bp[0]);
+                                cp[1] =   (scalar  % bp[1]);
+                                cp[2] =   (scalar  % bp[2]);
+                                cp[3] =   (scalar  % bp[3]);
+                                cp[4] =   (scalar  % bp[4]);
+                                cp[5] =   (scalar  % bp[5]);
+                                cp[6] =   (scalar  % bp[6]);
+                                cp[7] =   (scalar  % bp[7]);
+                                cp[8] =   (scalar  % bp[8]);
+                                cp[9] =   (scalar  % bp[9]);
+                                cp[10] =   (scalar  % bp[10]);
+                                cp[11] =   (scalar  % bp[11]);
+                                cp[12] =   (scalar  % bp[12]);
+                                cp[13] =   (scalar  % bp[13]);
+                                cp[14] =   (scalar  % bp[14]);
+                                cp[15] =   (scalar  % bp[15]);
+                                cp[16] =   (scalar  % bp[16]);
+                                cp[17] =   (scalar  % bp[17]);
+                                cp[18] =   (scalar  % bp[18]);
+                                cp[19] =   (scalar  % bp[19]);
+                                cp[20] =   (scalar  % bp[20]);
+                                bp+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (scalar  % *bp);
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work 
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                
+                fixed ( float* arrAP = arrA)
+                fixed ( float* arrBP = arrB)
+                fixed ( float* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range 
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new  ILRetArray< float>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<float>  modEx(ILInArray<float> A, ILInArray<float> B) {
+            //using (ILScope.Enter(A, B)) { we cannot start a new scope here, since this would prevent A and B to be used implace if applicable
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<float>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<float>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<float>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                dim = -(dim - 1);  // 0 -> 1, 1 -> 0
+                #endregion
+
+                #region parameter preparation
+               
+                float[] retArr;
+               
+                float[] arrA = A.GetArrayForRead();
+               
+                float[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int workItemMultiplierLenA;
+                int workItemMultiplierLenB;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<float>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    workItemMultiplierLenB = outDims[0]; 
+                    workItemMultiplierLenA = dim;  // 0 for column, 1 for row vector
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<float>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    workItemMultiplierLenB = dim;  // 0 for column, 1 for row vector
+                    workItemMultiplierLenA = outDims[0]; 
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one singleton dimension in either A or B");
+                }
+                int itLen = outDims[0]; // (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<float> retStorage = new ILDenseStorage<float>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    float* ap;
+                   
+                    float* bp;
+                   
+                    float* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            if (dim == 0) {
+                                bp = (float*)range.Item3;
+                                cp = (float*)range.Item4; 
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (float*)range.Item2;
+                                    int l = itLen; 
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  % bp[0]);
+                                        cp[1] =   (ap[1]  % bp[1]);
+                                        cp[2] =   (ap[2]  % bp[2]);
+                                        cp[3] =   (ap[3]  % bp[3]);
+                                        cp[4] =   (ap[4]  % bp[4]);
+                                        cp[5] =   (ap[5]  % bp[5]);
+                                        cp[6] =   (ap[6]  % bp[6]);
+                                        cp[7] =   (ap[7]  % bp[7]);
+                                        cp[8] =   (ap[8]  % bp[8]);
+                                        cp[9] =   (ap[9]  % bp[9]);
+                                        cp[10] =   (ap[10]  % bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =   (*ap++  % *bp++);
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                ap = (float*)range.Item2;
+                                bp = (float*)range.Item3;
+                                cp = (float*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   float val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (val  % bp[0]);
+                                        cp[1] =   (val  % bp[1]);
+                                        cp[2] =   (val  % bp[2]);
+                                        cp[3] =   (val  % bp[3]);
+                                        cp[4] =   (val  % bp[4]);
+                                        cp[5] =   (val  % bp[5]);
+                                        cp[6] =   (val  % bp[6]);
+                                        cp[7] =   (val  % bp[7]);
+                                        cp[8] =   (val  % bp[8]);
+                                        cp[9] =   (val  % bp[9]);
+                                        cp[10] =   (val  % bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11; 
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =   (val  % *bp++);
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            if (dim == 0) {
+                                cp = (float*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (float*)range.Item2;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  % cp[0]);
+                                        cp[1] =   (ap[1]  % cp[1]);
+                                        cp[2] =   (ap[2]  % cp[2]);
+                                        cp[3] =   (ap[3]  % cp[3]);
+                                        cp[4] =   (ap[4]  % cp[4]);
+                                        cp[5] =   (ap[5]  % cp[5]);
+                                        cp[6] =   (ap[6]  % cp[6]);
+                                        cp[7] =   (ap[7]  % cp[7]);
+                                        cp[8] =   (ap[8]  % cp[8]);
+                                        cp[9] =   (ap[9]  % cp[9]);
+                                        cp[10] =   (ap[10]  % cp[10]);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap++  % *cp);
+                                        cp++; 
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                cp = (float*)range.Item4;
+                                ap = (float*)range.Item2;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    float val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (val  % cp[0]);
+                                        cp[1] =   (val  % cp[1]);
+                                        cp[2] =   (val  % cp[2]);
+                                        cp[3] =   (val  % cp[3]);
+                                        cp[4] =   (val  % cp[4]);
+                                        cp[5] =   (val  % cp[5]);
+                                        cp[6] =   (val  % cp[6]);
+                                        cp[7] =   (val  % cp[7]);
+                                        cp[8] =   (val  % cp[8]);
+                                        cp[9] =   (val  % cp[9]);
+                                        cp[10] =   (val  % cp[10]);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (val  % *cp);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            if (dim == 0) {
+                                ap = (float*)range.Item2;
+                                cp = (float*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (float*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  % bp[0]);
+                                        cp[1] =   (ap[1]  % bp[1]);
+                                        cp[2] =   (ap[2]  % bp[2]);
+                                        cp[3] =   (ap[3]  % bp[3]);
+                                        cp[4] =   (ap[4]  % bp[4]);
+                                        cp[5] =   (ap[5]  % bp[5]);
+                                        cp[6] =   (ap[6]  % bp[6]);
+                                        cp[7] =   (ap[7]  % bp[7]);
+                                        cp[8] =   (ap[8]  % bp[8]);
+                                        cp[9] =   (ap[9]  % bp[9]);
+                                        cp[10] =   (ap[10]  % bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap  % *bp);
+                                        ap++;
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                ap = (float*)range.Item2;
+                                bp = (float*)range.Item3;
+                                cp = (float*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   float val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  % val);
+                                        cp[1] =   (ap[1]  % val);
+                                        cp[2] =   (ap[2]  % val);
+                                        cp[3] =   (ap[3]  % val);
+                                        cp[4] =   (ap[4]  % val);
+                                        cp[5] =   (ap[5]  % val);
+                                        cp[6] =   (ap[6]  % val);
+                                        cp[7] =   (ap[7]  % val);
+                                        cp[8] =   (ap[8]  % val);
+                                        cp[9] =   (ap[9]  % val);
+                                        cp[10] =   (ap[10]  % val);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap  % val);
+                                        ap++;
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            if (dim == 0) {
+                                cp = (float*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (float*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (cp[0]  % bp[0]);
+                                        cp[1] =   (cp[1]  % bp[1]);
+                                        cp[2] =   (cp[2]  % bp[2]);
+                                        cp[3] =   (cp[3]  % bp[3]);
+                                        cp[4] =   (cp[4]  % bp[4]);
+                                        cp[5] =   (cp[5]  % bp[5]);
+                                        cp[6] =   (cp[6]  % bp[6]);
+                                        cp[7] =   (cp[7]  % bp[7]);
+                                        cp[8] =   (cp[8]  % bp[8]);
+                                        cp[9] =   (cp[9]  % bp[9]);
+                                        cp[10] =   (cp[10]  % bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*cp  % *bp);
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                bp = (float*)range.Item3;
+                                cp = (float*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    float val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (cp[0]  % val);
+                                        cp[1] =   (cp[1]  % val);
+                                        cp[2] =   (cp[2]  % val);
+                                        cp[3] =   (cp[3]  % val);
+                                        cp[4] =   (cp[4]  % val);
+                                        cp[5] =   (cp[5]  % val);
+                                        cp[6] =   (cp[6]  % val);
+                                        cp[7] =   (cp[7]  % val);
+                                        cp[8] =   (cp[8]  % val);
+                                        cp[9] =   (cp[9]  % val);
+                                        cp[10] =   (cp[10]  % val);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l --> 0) {
+                                        *cp =   (*cp  % val);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outDims.NumberOfElements >= Settings.s_minParallelElement1Count
+                    && outDims[1] > 1) {
+                        if (outDims[1] > workItemCount) {
+                        workItemLength = outDims[1] / workItemCount;
+                    } else {
+                        workItemLength = outDims[1] / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outDims[1];
+                    workItemCount = 1;
+                }
+
+                fixed ( float* arrAP = arrA)
+                fixed ( float* arrBP = arrB)
+                fixed ( float* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, IntPtr, IntPtr, IntPtr> range = new Tuple<int, IntPtr, IntPtr, IntPtr>
+                               (workItemLength
+                               , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                               , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                               , (IntPtr)(retArrP + i * outDims[0] * workItemLength)); 
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, IntPtr, IntPtr, IntPtr>
+                                (outDims[1] - i * workItemLength
+                                , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                                , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                                , (IntPtr)(retArrP + i * outDims[0] * workItemLength)));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<float>(retStorage);
+            //}  // no scopes here! it disables implace operations
+        }
+
+        /// <summary>Modulus of array elements</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>New array with result of elementwise modulus operation</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<byte>  mod(ILInArray<byte> A, ILInArray<byte> B) {
+            using (ILScope.Enter(A,B)) {
+                int outLen; 
+                BinOpItMode mode; 
+                byte [] retArr;
+                byte [] arrA = A.GetArrayForRead();
+                byte[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size; 
+                    if (B.IsScalar) {
+                       
+                        return new  ILRetArray<byte> (new  byte [1]{ saturateByte (A.GetValue(0)  % (double) B.GetValue(0))}, A.Size);
+                    } else if (B.IsEmpty) {
+                        return  ILRetArray<byte>.empty(outDims); 
+                    } else {
+                        outLen = outDims.NumberOfElements; 
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< byte > (outLen);
+                            mode = BinOpItMode.SAN; 
+                        } else {
+                            mode = BinOpItMode.SAI; 
+                        }
+                    }
+                } else {
+                    outDims = A.Size; 
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return  ILRetArray<byte>.empty(A.Size);  
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< byte > (outLen);
+                            mode = BinOpItMode.ASN; 
+                        } else {
+                            mode = BinOpItMode.ASI; 
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  modEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (A.TryGetStorage4InplaceOp(out retArr)) 
+                            mode  = BinOpItMode.AAIA; 
+                        else if (B.TryGetStorage4InplaceOp(out retArr)) 
+                            mode = BinOpItMode.AAIB; 
+                        else {
+                            retArr = ILMemoryPool.Pool.New< byte > (outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<byte> retStorage = new ILDenseStorage<byte>(retArr, outDims);
+                int i = 0, workerCount = 1; 
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cp = (byte*)range.Item5 + range.Item1;
+                    byte scalar;
+                    int j = range.Item2; 
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           byte* bp = ((byte*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                                cp[0] =  saturateByte (cp[0]  % (double) bp[0]);
+                                cp[1] =  saturateByte (cp[1]  % (double) bp[1]);
+                                cp[2] =  saturateByte (cp[2]  % (double) bp[2]);
+                                cp[3] =  saturateByte (cp[3]  % (double) bp[3]);
+                                cp[4] =  saturateByte (cp[4]  % (double) bp[4]);
+                                cp[5] =  saturateByte (cp[5]  % (double) bp[5]);
+                                cp[6] =  saturateByte (cp[6]  % (double) bp[6]);
+                                cp[7] =  saturateByte (cp[7]  % (double) bp[7]);
+                                cp[8] =  saturateByte (cp[8]  % (double) bp[8]);
+                                cp[9] =  saturateByte (cp[9]  % (double) bp[9]);
+                                cp[10] =  saturateByte (cp[10]  % (double) bp[10]);
+                                cp[11] =  saturateByte (cp[11]  % (double) bp[11]);
+                                cp[12] =  saturateByte (cp[12]  % (double) bp[12]);
+                                cp[13] =  saturateByte (cp[13]  % (double) bp[13]);
+                                cp[14] =  saturateByte (cp[14]  % (double) bp[14]);
+                                cp[15] =  saturateByte (cp[15]  % (double) bp[15]);
+                                cp[16] =  saturateByte (cp[16]  % (double) bp[16]);
+                                cp[17] =  saturateByte (cp[17]  % (double) bp[17]);
+                                cp[18] =  saturateByte (cp[18]  % (double) bp[18]);
+                                cp[19] =  saturateByte (cp[19]  % (double) bp[19]);
+                                cp[20] =  saturateByte (cp[20]  % (double) bp[20]);
+                                cp += 21; bp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateByte (*cp  % (double) *bp);
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           byte* ap = ((byte*)range.Item3 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateByte (ap[0]  % (double) cp[0]);
+                                cp[1] =  saturateByte (ap[1]  % (double) cp[1]);
+                                cp[2] =  saturateByte (ap[2]  % (double) cp[2]);
+                                cp[3] =  saturateByte (ap[3]  % (double) cp[3]);
+                                cp[4] =  saturateByte (ap[4]  % (double) cp[4]);
+                                cp[5] =  saturateByte (ap[5]  % (double) cp[5]);
+                                cp[6] =  saturateByte (ap[6]  % (double) cp[6]);
+                                cp[7] =  saturateByte (ap[7]  % (double) cp[7]);
+                                cp[8] =  saturateByte (ap[8]  % (double) cp[8]);
+                                cp[9] =  saturateByte (ap[9]  % (double) cp[9]);
+                                cp[10] =  saturateByte (ap[10]  % (double) cp[10]);
+                                cp[11] =  saturateByte (ap[11]  % (double) cp[11]);
+                                cp[12] =  saturateByte (ap[12]  % (double) cp[12]);
+                                cp[13] =  saturateByte (ap[13]  % (double) cp[13]);
+                                cp[14] =  saturateByte (ap[14]  % (double) cp[14]);
+                                cp[15] =  saturateByte (ap[15]  % (double) cp[15]);
+                                cp[16] =  saturateByte (ap[16]  % (double) cp[16]);
+                                cp[17] =  saturateByte (ap[17]  % (double) cp[17]);
+                                cp[18] =  saturateByte (ap[18]  % (double) cp[18]);
+                                cp[19] =  saturateByte (ap[19]  % (double) cp[19]);
+                                cp[20] =  saturateByte (ap[20]  % (double) cp[20]);
+                                ap += 21; cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateByte (*ap  % (double) *cp);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((byte*)range.Item3 + range.Item1);
+                            bp = ((byte*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateByte (ap[0]  % (double) bp[0]);
+                                cp[1] =  saturateByte (ap[1]  % (double) bp[1]);
+                                cp[2] =  saturateByte (ap[2]  % (double) bp[2]);
+                                cp[3] =  saturateByte (ap[3]  % (double) bp[3]);
+                                cp[4] =  saturateByte (ap[4]  % (double) bp[4]);
+                                cp[5] =  saturateByte (ap[5]  % (double) bp[5]);
+                                cp[6] =  saturateByte (ap[6]  % (double) bp[6]);
+                                cp[7] =  saturateByte (ap[7]  % (double) bp[7]);
+                                cp[8] =  saturateByte (ap[8]  % (double) bp[8]);
+                                cp[9] =  saturateByte (ap[9]  % (double) bp[9]);
+                                cp[10] =  saturateByte (ap[10]  % (double) bp[10]);
+                                cp[11] =  saturateByte (ap[11]  % (double) bp[11]);
+                                cp[12] =  saturateByte (ap[12]  % (double) bp[12]);
+                                cp[13] =  saturateByte (ap[13]  % (double) bp[13]);
+                                cp[14] =  saturateByte (ap[14]  % (double) bp[14]);
+                                cp[15] =  saturateByte (ap[15]  % (double) bp[15]);
+                                cp[16] =  saturateByte (ap[16]  % (double) bp[16]);
+                                cp[17] =  saturateByte (ap[17]  % (double) bp[17]);
+                                cp[18] =  saturateByte (ap[18]  % (double) bp[18]);
+                                cp[19] =  saturateByte (ap[19]  % (double) bp[19]);
+                                cp[20] =  saturateByte (ap[20]  % (double) bp[20]);
+                                ap+=21; bp+=21; cp+=21; j-=21;
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateByte (*ap  % (double) *bp);
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((byte*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateByte (cp[0]  % (double) scalar);
+                                cp[1] =  saturateByte (cp[1]  % (double) scalar);
+                                cp[2] =  saturateByte (cp[2]  % (double) scalar);
+                                cp[3] =  saturateByte (cp[3]  % (double) scalar);
+                                cp[4] =  saturateByte (cp[4]  % (double) scalar);
+                                cp[5] =  saturateByte (cp[5]  % (double) scalar);
+                                cp[6] =  saturateByte (cp[6]  % (double) scalar);
+                                cp[7] =  saturateByte (cp[7]  % (double) scalar);
+                                cp[8] =  saturateByte (cp[8]  % (double) scalar);
+                                cp[9] =  saturateByte (cp[9]  % (double) scalar);
+                                cp[10] =  saturateByte (cp[10]  % (double) scalar);
+                                cp[11] =  saturateByte (cp[11]  % (double) scalar);
+                                cp[12] =  saturateByte (cp[12]  % (double) scalar);
+                                cp[13] =  saturateByte (cp[13]  % (double) scalar);
+                                cp[14] =  saturateByte (cp[14]  % (double) scalar);
+                                cp[15] =  saturateByte (cp[15]  % (double) scalar);
+                                cp[16] =  saturateByte (cp[16]  % (double) scalar);
+                                cp[17] =  saturateByte (cp[17]  % (double) scalar);
+                                cp[18] =  saturateByte (cp[18]  % (double) scalar);
+                                cp[19] =  saturateByte (cp[19]  % (double) scalar);
+                                cp[20] =  saturateByte (cp[20]  % (double) scalar);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateByte (*cp  % (double) scalar);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((byte*)range.Item3 + range.Item1);
+                            scalar = *((byte*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateByte (ap[0]  % (double) scalar);
+                                cp[1] =  saturateByte (ap[1]  % (double) scalar);
+                                cp[2] =  saturateByte (ap[2]  % (double) scalar);
+                                cp[3] =  saturateByte (ap[3]  % (double) scalar);
+                                cp[4] =  saturateByte (ap[4]  % (double) scalar);
+                                cp[5] =  saturateByte (ap[5]  % (double) scalar);
+                                cp[6] =  saturateByte (ap[6]  % (double) scalar);
+                                cp[7] =  saturateByte (ap[7]  % (double) scalar);
+                                cp[8] =  saturateByte (ap[8]  % (double) scalar);
+                                cp[9] =  saturateByte (ap[9]  % (double) scalar);
+                                cp[10] =  saturateByte (ap[10]  % (double) scalar);
+                                cp[11] =  saturateByte (ap[11]  % (double) scalar);
+                                cp[12] =  saturateByte (ap[12]  % (double) scalar);
+                                cp[13] =  saturateByte (ap[13]  % (double) scalar);
+                                cp[14] =  saturateByte (ap[14]  % (double) scalar);
+                                cp[15] =  saturateByte (ap[15]  % (double) scalar);
+                                cp[16] =  saturateByte (ap[16]  % (double) scalar);
+                                cp[17] =  saturateByte (ap[17]  % (double) scalar);
+                                cp[18] =  saturateByte (ap[18]  % (double) scalar);
+                                cp[19] =  saturateByte (ap[19]  % (double) scalar);
+                                cp[20] =  saturateByte (ap[20]  % (double) scalar);
+                                ap+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateByte (*ap  % (double) scalar);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((byte*)range.Item3);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateByte (scalar  % (double) cp[0]);
+                                cp[1] =  saturateByte (scalar  % (double) cp[1]);
+                                cp[2] =  saturateByte (scalar  % (double) cp[2]);
+                                cp[3] =  saturateByte (scalar  % (double) cp[3]);
+                                cp[4] =  saturateByte (scalar  % (double) cp[4]);
+                                cp[5] =  saturateByte (scalar  % (double) cp[5]);
+                                cp[6] =  saturateByte (scalar  % (double) cp[6]);
+                                cp[7] =  saturateByte (scalar  % (double) cp[7]);
+                                cp[8] =  saturateByte (scalar  % (double) cp[8]);
+                                cp[9] =  saturateByte (scalar  % (double) cp[9]);
+                                cp[10] =  saturateByte (scalar  % (double) cp[10]);
+                                cp[11] =  saturateByte (scalar  % (double) cp[11]);
+                                cp[12] =  saturateByte (scalar  % (double) cp[12]);
+                                cp[13] =  saturateByte (scalar  % (double) cp[13]);
+                                cp[14] =  saturateByte (scalar  % (double) cp[14]);
+                                cp[15] =  saturateByte (scalar  % (double) cp[15]);
+                                cp[16] =  saturateByte (scalar  % (double) cp[16]);
+                                cp[17] =  saturateByte (scalar  % (double) cp[17]);
+                                cp[18] =  saturateByte (scalar  % (double) cp[18]);
+                                cp[19] =  saturateByte (scalar  % (double) cp[19]);
+                                cp[20] =  saturateByte (scalar  % (double) cp[20]);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateByte (scalar  % (double) *cp);
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((byte*)range.Item3);
+                            bp = ((byte*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateByte (scalar  % (double) bp[0]);
+                                cp[1] =  saturateByte (scalar  % (double) bp[1]);
+                                cp[2] =  saturateByte (scalar  % (double) bp[2]);
+                                cp[3] =  saturateByte (scalar  % (double) bp[3]);
+                                cp[4] =  saturateByte (scalar  % (double) bp[4]);
+                                cp[5] =  saturateByte (scalar  % (double) bp[5]);
+                                cp[6] =  saturateByte (scalar  % (double) bp[6]);
+                                cp[7] =  saturateByte (scalar  % (double) bp[7]);
+                                cp[8] =  saturateByte (scalar  % (double) bp[8]);
+                                cp[9] =  saturateByte (scalar  % (double) bp[9]);
+                                cp[10] =  saturateByte (scalar  % (double) bp[10]);
+                                cp[11] =  saturateByte (scalar  % (double) bp[11]);
+                                cp[12] =  saturateByte (scalar  % (double) bp[12]);
+                                cp[13] =  saturateByte (scalar  % (double) bp[13]);
+                                cp[14] =  saturateByte (scalar  % (double) bp[14]);
+                                cp[15] =  saturateByte (scalar  % (double) bp[15]);
+                                cp[16] =  saturateByte (scalar  % (double) bp[16]);
+                                cp[17] =  saturateByte (scalar  % (double) bp[17]);
+                                cp[18] =  saturateByte (scalar  % (double) bp[18]);
+                                cp[19] =  saturateByte (scalar  % (double) bp[19]);
+                                cp[20] =  saturateByte (scalar  % (double) bp[20]);
+                                bp+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateByte (scalar  % (double) *bp);
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work 
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                
+                fixed ( byte* arrAP = arrA)
+                fixed ( byte* arrBP = arrB)
+                fixed ( byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range 
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new  ILRetArray< byte>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<byte>  modEx(ILInArray<byte> A, ILInArray<byte> B) {
+            //using (ILScope.Enter(A, B)) { we cannot start a new scope here, since this would prevent A and B to be used implace if applicable
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<byte>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<byte>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<byte>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                dim = -(dim - 1);  // 0 -> 1, 1 -> 0
+                #endregion
+
+                #region parameter preparation
+               
+                byte[] retArr;
+               
+                byte[] arrA = A.GetArrayForRead();
+               
+                byte[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int workItemMultiplierLenA;
+                int workItemMultiplierLenB;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    workItemMultiplierLenB = outDims[0]; 
+                    workItemMultiplierLenA = dim;  // 0 for column, 1 for row vector
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    workItemMultiplierLenB = dim;  // 0 for column, 1 for row vector
+                    workItemMultiplierLenA = outDims[0]; 
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one singleton dimension in either A or B");
+                }
+                int itLen = outDims[0]; // (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<byte> retStorage = new ILDenseStorage<byte>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    byte* ap;
+                   
+                    byte* bp;
+                   
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            if (dim == 0) {
+                                bp = (byte*)range.Item3;
+                                cp = (byte*)range.Item4; 
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (byte*)range.Item2;
+                                    int l = itLen; 
+                                    while (l > 10) {
+                                        cp[0] =  saturateByte (ap[0]  % (double) bp[0]);
+                                        cp[1] =  saturateByte (ap[1]  % (double) bp[1]);
+                                        cp[2] =  saturateByte (ap[2]  % (double) bp[2]);
+                                        cp[3] =  saturateByte (ap[3]  % (double) bp[3]);
+                                        cp[4] =  saturateByte (ap[4]  % (double) bp[4]);
+                                        cp[5] =  saturateByte (ap[5]  % (double) bp[5]);
+                                        cp[6] =  saturateByte (ap[6]  % (double) bp[6]);
+                                        cp[7] =  saturateByte (ap[7]  % (double) bp[7]);
+                                        cp[8] =  saturateByte (ap[8]  % (double) bp[8]);
+                                        cp[9] =  saturateByte (ap[9]  % (double) bp[9]);
+                                        cp[10] =  saturateByte (ap[10]  % (double) bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =  saturateByte (*ap++  % (double) *bp++);
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                ap = (byte*)range.Item2;
+                                bp = (byte*)range.Item3;
+                                cp = (byte*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   byte val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateByte (val  % (double) bp[0]);
+                                        cp[1] =  saturateByte (val  % (double) bp[1]);
+                                        cp[2] =  saturateByte (val  % (double) bp[2]);
+                                        cp[3] =  saturateByte (val  % (double) bp[3]);
+                                        cp[4] =  saturateByte (val  % (double) bp[4]);
+                                        cp[5] =  saturateByte (val  % (double) bp[5]);
+                                        cp[6] =  saturateByte (val  % (double) bp[6]);
+                                        cp[7] =  saturateByte (val  % (double) bp[7]);
+                                        cp[8] =  saturateByte (val  % (double) bp[8]);
+                                        cp[9] =  saturateByte (val  % (double) bp[9]);
+                                        cp[10] =  saturateByte (val  % (double) bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11; 
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =  saturateByte (val  % (double) *bp++);
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            if (dim == 0) {
+                                cp = (byte*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (byte*)range.Item2;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateByte (ap[0]  % (double) cp[0]);
+                                        cp[1] =  saturateByte (ap[1]  % (double) cp[1]);
+                                        cp[2] =  saturateByte (ap[2]  % (double) cp[2]);
+                                        cp[3] =  saturateByte (ap[3]  % (double) cp[3]);
+                                        cp[4] =  saturateByte (ap[4]  % (double) cp[4]);
+                                        cp[5] =  saturateByte (ap[5]  % (double) cp[5]);
+                                        cp[6] =  saturateByte (ap[6]  % (double) cp[6]);
+                                        cp[7] =  saturateByte (ap[7]  % (double) cp[7]);
+                                        cp[8] =  saturateByte (ap[8]  % (double) cp[8]);
+                                        cp[9] =  saturateByte (ap[9]  % (double) cp[9]);
+                                        cp[10] =  saturateByte (ap[10]  % (double) cp[10]);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateByte (*ap++  % (double) *cp);
+                                        cp++; 
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                cp = (byte*)range.Item4;
+                                ap = (byte*)range.Item2;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    byte val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateByte (val  % (double) cp[0]);
+                                        cp[1] =  saturateByte (val  % (double) cp[1]);
+                                        cp[2] =  saturateByte (val  % (double) cp[2]);
+                                        cp[3] =  saturateByte (val  % (double) cp[3]);
+                                        cp[4] =  saturateByte (val  % (double) cp[4]);
+                                        cp[5] =  saturateByte (val  % (double) cp[5]);
+                                        cp[6] =  saturateByte (val  % (double) cp[6]);
+                                        cp[7] =  saturateByte (val  % (double) cp[7]);
+                                        cp[8] =  saturateByte (val  % (double) cp[8]);
+                                        cp[9] =  saturateByte (val  % (double) cp[9]);
+                                        cp[10] =  saturateByte (val  % (double) cp[10]);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateByte (val  % (double) *cp);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            if (dim == 0) {
+                                ap = (byte*)range.Item2;
+                                cp = (byte*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (byte*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateByte (ap[0]  % (double) bp[0]);
+                                        cp[1] =  saturateByte (ap[1]  % (double) bp[1]);
+                                        cp[2] =  saturateByte (ap[2]  % (double) bp[2]);
+                                        cp[3] =  saturateByte (ap[3]  % (double) bp[3]);
+                                        cp[4] =  saturateByte (ap[4]  % (double) bp[4]);
+                                        cp[5] =  saturateByte (ap[5]  % (double) bp[5]);
+                                        cp[6] =  saturateByte (ap[6]  % (double) bp[6]);
+                                        cp[7] =  saturateByte (ap[7]  % (double) bp[7]);
+                                        cp[8] =  saturateByte (ap[8]  % (double) bp[8]);
+                                        cp[9] =  saturateByte (ap[9]  % (double) bp[9]);
+                                        cp[10] =  saturateByte (ap[10]  % (double) bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateByte (*ap  % (double) *bp);
+                                        ap++;
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                ap = (byte*)range.Item2;
+                                bp = (byte*)range.Item3;
+                                cp = (byte*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   byte val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateByte (ap[0]  % (double) val);
+                                        cp[1] =  saturateByte (ap[1]  % (double) val);
+                                        cp[2] =  saturateByte (ap[2]  % (double) val);
+                                        cp[3] =  saturateByte (ap[3]  % (double) val);
+                                        cp[4] =  saturateByte (ap[4]  % (double) val);
+                                        cp[5] =  saturateByte (ap[5]  % (double) val);
+                                        cp[6] =  saturateByte (ap[6]  % (double) val);
+                                        cp[7] =  saturateByte (ap[7]  % (double) val);
+                                        cp[8] =  saturateByte (ap[8]  % (double) val);
+                                        cp[9] =  saturateByte (ap[9]  % (double) val);
+                                        cp[10] =  saturateByte (ap[10]  % (double) val);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateByte (*ap  % (double) val);
+                                        ap++;
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            if (dim == 0) {
+                                cp = (byte*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (byte*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateByte (cp[0]  % (double) bp[0]);
+                                        cp[1] =  saturateByte (cp[1]  % (double) bp[1]);
+                                        cp[2] =  saturateByte (cp[2]  % (double) bp[2]);
+                                        cp[3] =  saturateByte (cp[3]  % (double) bp[3]);
+                                        cp[4] =  saturateByte (cp[4]  % (double) bp[4]);
+                                        cp[5] =  saturateByte (cp[5]  % (double) bp[5]);
+                                        cp[6] =  saturateByte (cp[6]  % (double) bp[6]);
+                                        cp[7] =  saturateByte (cp[7]  % (double) bp[7]);
+                                        cp[8] =  saturateByte (cp[8]  % (double) bp[8]);
+                                        cp[9] =  saturateByte (cp[9]  % (double) bp[9]);
+                                        cp[10] =  saturateByte (cp[10]  % (double) bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateByte (*cp  % (double) *bp);
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                bp = (byte*)range.Item3;
+                                cp = (byte*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    byte val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateByte (cp[0]  % (double) val);
+                                        cp[1] =  saturateByte (cp[1]  % (double) val);
+                                        cp[2] =  saturateByte (cp[2]  % (double) val);
+                                        cp[3] =  saturateByte (cp[3]  % (double) val);
+                                        cp[4] =  saturateByte (cp[4]  % (double) val);
+                                        cp[5] =  saturateByte (cp[5]  % (double) val);
+                                        cp[6] =  saturateByte (cp[6]  % (double) val);
+                                        cp[7] =  saturateByte (cp[7]  % (double) val);
+                                        cp[8] =  saturateByte (cp[8]  % (double) val);
+                                        cp[9] =  saturateByte (cp[9]  % (double) val);
+                                        cp[10] =  saturateByte (cp[10]  % (double) val);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l --> 0) {
+                                        *cp =  saturateByte (*cp  % (double) val);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outDims.NumberOfElements >= Settings.s_minParallelElement1Count
+                    && outDims[1] > 1) {
+                        if (outDims[1] > workItemCount) {
+                        workItemLength = outDims[1] / workItemCount;
+                    } else {
+                        workItemLength = outDims[1] / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outDims[1];
+                    workItemCount = 1;
+                }
+
+                fixed ( byte* arrAP = arrA)
+                fixed ( byte* arrBP = arrB)
+                fixed ( byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, IntPtr, IntPtr, IntPtr> range = new Tuple<int, IntPtr, IntPtr, IntPtr>
+                               (workItemLength
+                               , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                               , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                               , (IntPtr)(retArrP + i * outDims[0] * workItemLength)); 
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, IntPtr, IntPtr, IntPtr>
+                                (outDims[1] - i * workItemLength
+                                , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                                , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                                , (IntPtr)(retArrP + i * outDims[0] * workItemLength)));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<byte>(retStorage);
+            //}  // no scopes here! it disables implace operations
+        }
+
+        /// <summary>Modulus of array elements</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>New array with result of elementwise modulus operation</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<double>  mod(ILInArray<double> A, ILInArray<double> B) {
+            using (ILScope.Enter(A,B)) {
+                int outLen; 
+                BinOpItMode mode; 
+                double [] retArr;
+                double [] arrA = A.GetArrayForRead();
+                double[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size; 
+                    if (B.IsScalar) {
+                       
+                        return new  ILRetArray<double> (new  double [1]{  (A.GetValue(0)  % B.GetValue(0))}, A.Size);
+                    } else if (B.IsEmpty) {
+                        return  ILRetArray<double>.empty(outDims); 
+                    } else {
+                        outLen = outDims.NumberOfElements; 
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< double > (outLen);
+                            mode = BinOpItMode.SAN; 
+                        } else {
+                            mode = BinOpItMode.SAI; 
+                        }
+                    }
+                } else {
+                    outDims = A.Size; 
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return  ILRetArray<double>.empty(A.Size);  
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< double > (outLen);
+                            mode = BinOpItMode.ASN; 
+                        } else {
+                            mode = BinOpItMode.ASI; 
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  modEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (A.TryGetStorage4InplaceOp(out retArr)) 
+                            mode  = BinOpItMode.AAIA; 
+                        else if (B.TryGetStorage4InplaceOp(out retArr)) 
+                            mode = BinOpItMode.AAIB; 
+                        else {
+                            retArr = ILMemoryPool.Pool.New< double > (outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<double> retStorage = new ILDenseStorage<double>(retArr, outDims);
+                int i = 0, workerCount = 1; 
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    double* cp = (double*)range.Item5 + range.Item1;
+                    double scalar;
+                    int j = range.Item2; 
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           double* bp = ((double*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                                cp[0] =   (cp[0]  % bp[0]);
+                                cp[1] =   (cp[1]  % bp[1]);
+                                cp[2] =   (cp[2]  % bp[2]);
+                                cp[3] =   (cp[3]  % bp[3]);
+                                cp[4] =   (cp[4]  % bp[4]);
+                                cp[5] =   (cp[5]  % bp[5]);
+                                cp[6] =   (cp[6]  % bp[6]);
+                                cp[7] =   (cp[7]  % bp[7]);
+                                cp[8] =   (cp[8]  % bp[8]);
+                                cp[9] =   (cp[9]  % bp[9]);
+                                cp[10] =   (cp[10]  % bp[10]);
+                                cp[11] =   (cp[11]  % bp[11]);
+                                cp[12] =   (cp[12]  % bp[12]);
+                                cp[13] =   (cp[13]  % bp[13]);
+                                cp[14] =   (cp[14]  % bp[14]);
+                                cp[15] =   (cp[15]  % bp[15]);
+                                cp[16] =   (cp[16]  % bp[16]);
+                                cp[17] =   (cp[17]  % bp[17]);
+                                cp[18] =   (cp[18]  % bp[18]);
+                                cp[19] =   (cp[19]  % bp[19]);
+                                cp[20] =   (cp[20]  % bp[20]);
+                                cp += 21; bp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*cp  % *bp);
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           double* ap = ((double*)range.Item3 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  % cp[0]);
+                                cp[1] =   (ap[1]  % cp[1]);
+                                cp[2] =   (ap[2]  % cp[2]);
+                                cp[3] =   (ap[3]  % cp[3]);
+                                cp[4] =   (ap[4]  % cp[4]);
+                                cp[5] =   (ap[5]  % cp[5]);
+                                cp[6] =   (ap[6]  % cp[6]);
+                                cp[7] =   (ap[7]  % cp[7]);
+                                cp[8] =   (ap[8]  % cp[8]);
+                                cp[9] =   (ap[9]  % cp[9]);
+                                cp[10] =   (ap[10]  % cp[10]);
+                                cp[11] =   (ap[11]  % cp[11]);
+                                cp[12] =   (ap[12]  % cp[12]);
+                                cp[13] =   (ap[13]  % cp[13]);
+                                cp[14] =   (ap[14]  % cp[14]);
+                                cp[15] =   (ap[15]  % cp[15]);
+                                cp[16] =   (ap[16]  % cp[16]);
+                                cp[17] =   (ap[17]  % cp[17]);
+                                cp[18] =   (ap[18]  % cp[18]);
+                                cp[19] =   (ap[19]  % cp[19]);
+                                cp[20] =   (ap[20]  % cp[20]);
+                                ap += 21; cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  % *cp);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((double*)range.Item3 + range.Item1);
+                            bp = ((double*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  % bp[0]);
+                                cp[1] =   (ap[1]  % bp[1]);
+                                cp[2] =   (ap[2]  % bp[2]);
+                                cp[3] =   (ap[3]  % bp[3]);
+                                cp[4] =   (ap[4]  % bp[4]);
+                                cp[5] =   (ap[5]  % bp[5]);
+                                cp[6] =   (ap[6]  % bp[6]);
+                                cp[7] =   (ap[7]  % bp[7]);
+                                cp[8] =   (ap[8]  % bp[8]);
+                                cp[9] =   (ap[9]  % bp[9]);
+                                cp[10] =   (ap[10]  % bp[10]);
+                                cp[11] =   (ap[11]  % bp[11]);
+                                cp[12] =   (ap[12]  % bp[12]);
+                                cp[13] =   (ap[13]  % bp[13]);
+                                cp[14] =   (ap[14]  % bp[14]);
+                                cp[15] =   (ap[15]  % bp[15]);
+                                cp[16] =   (ap[16]  % bp[16]);
+                                cp[17] =   (ap[17]  % bp[17]);
+                                cp[18] =   (ap[18]  % bp[18]);
+                                cp[19] =   (ap[19]  % bp[19]);
+                                cp[20] =   (ap[20]  % bp[20]);
+                                ap+=21; bp+=21; cp+=21; j-=21;
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  % *bp);
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((double*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =   (cp[0]  % scalar);
+                                cp[1] =   (cp[1]  % scalar);
+                                cp[2] =   (cp[2]  % scalar);
+                                cp[3] =   (cp[3]  % scalar);
+                                cp[4] =   (cp[4]  % scalar);
+                                cp[5] =   (cp[5]  % scalar);
+                                cp[6] =   (cp[6]  % scalar);
+                                cp[7] =   (cp[7]  % scalar);
+                                cp[8] =   (cp[8]  % scalar);
+                                cp[9] =   (cp[9]  % scalar);
+                                cp[10] =   (cp[10]  % scalar);
+                                cp[11] =   (cp[11]  % scalar);
+                                cp[12] =   (cp[12]  % scalar);
+                                cp[13] =   (cp[13]  % scalar);
+                                cp[14] =   (cp[14]  % scalar);
+                                cp[15] =   (cp[15]  % scalar);
+                                cp[16] =   (cp[16]  % scalar);
+                                cp[17] =   (cp[17]  % scalar);
+                                cp[18] =   (cp[18]  % scalar);
+                                cp[19] =   (cp[19]  % scalar);
+                                cp[20] =   (cp[20]  % scalar);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*cp  % scalar);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((double*)range.Item3 + range.Item1);
+                            scalar = *((double*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =   (ap[0]  % scalar);
+                                cp[1] =   (ap[1]  % scalar);
+                                cp[2] =   (ap[2]  % scalar);
+                                cp[3] =   (ap[3]  % scalar);
+                                cp[4] =   (ap[4]  % scalar);
+                                cp[5] =   (ap[5]  % scalar);
+                                cp[6] =   (ap[6]  % scalar);
+                                cp[7] =   (ap[7]  % scalar);
+                                cp[8] =   (ap[8]  % scalar);
+                                cp[9] =   (ap[9]  % scalar);
+                                cp[10] =   (ap[10]  % scalar);
+                                cp[11] =   (ap[11]  % scalar);
+                                cp[12] =   (ap[12]  % scalar);
+                                cp[13] =   (ap[13]  % scalar);
+                                cp[14] =   (ap[14]  % scalar);
+                                cp[15] =   (ap[15]  % scalar);
+                                cp[16] =   (ap[16]  % scalar);
+                                cp[17] =   (ap[17]  % scalar);
+                                cp[18] =   (ap[18]  % scalar);
+                                cp[19] =   (ap[19]  % scalar);
+                                cp[20] =   (ap[20]  % scalar);
+                                ap+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (*ap  % scalar);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((double*)range.Item3);
+                            while (j > 20) {
+                               
+                                cp[0] =   (scalar  % cp[0]);
+                                cp[1] =   (scalar  % cp[1]);
+                                cp[2] =   (scalar  % cp[2]);
+                                cp[3] =   (scalar  % cp[3]);
+                                cp[4] =   (scalar  % cp[4]);
+                                cp[5] =   (scalar  % cp[5]);
+                                cp[6] =   (scalar  % cp[6]);
+                                cp[7] =   (scalar  % cp[7]);
+                                cp[8] =   (scalar  % cp[8]);
+                                cp[9] =   (scalar  % cp[9]);
+                                cp[10] =   (scalar  % cp[10]);
+                                cp[11] =   (scalar  % cp[11]);
+                                cp[12] =   (scalar  % cp[12]);
+                                cp[13] =   (scalar  % cp[13]);
+                                cp[14] =   (scalar  % cp[14]);
+                                cp[15] =   (scalar  % cp[15]);
+                                cp[16] =   (scalar  % cp[16]);
+                                cp[17] =   (scalar  % cp[17]);
+                                cp[18] =   (scalar  % cp[18]);
+                                cp[19] =   (scalar  % cp[19]);
+                                cp[20] =   (scalar  % cp[20]);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (scalar  % *cp);
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((double*)range.Item3);
+                            bp = ((double*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =   (scalar  % bp[0]);
+                                cp[1] =   (scalar  % bp[1]);
+                                cp[2] =   (scalar  % bp[2]);
+                                cp[3] =   (scalar  % bp[3]);
+                                cp[4] =   (scalar  % bp[4]);
+                                cp[5] =   (scalar  % bp[5]);
+                                cp[6] =   (scalar  % bp[6]);
+                                cp[7] =   (scalar  % bp[7]);
+                                cp[8] =   (scalar  % bp[8]);
+                                cp[9] =   (scalar  % bp[9]);
+                                cp[10] =   (scalar  % bp[10]);
+                                cp[11] =   (scalar  % bp[11]);
+                                cp[12] =   (scalar  % bp[12]);
+                                cp[13] =   (scalar  % bp[13]);
+                                cp[14] =   (scalar  % bp[14]);
+                                cp[15] =   (scalar  % bp[15]);
+                                cp[16] =   (scalar  % bp[16]);
+                                cp[17] =   (scalar  % bp[17]);
+                                cp[18] =   (scalar  % bp[18]);
+                                cp[19] =   (scalar  % bp[19]);
+                                cp[20] =   (scalar  % bp[20]);
+                                bp+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =   (scalar  % *bp);
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work 
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                
+                fixed ( double* arrAP = arrA)
+                fixed ( double* arrBP = arrB)
+                fixed ( double* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range 
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new  ILRetArray< double>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<double>  modEx(ILInArray<double> A, ILInArray<double> B) {
+            //using (ILScope.Enter(A, B)) { we cannot start a new scope here, since this would prevent A and B to be used implace if applicable
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<double>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<double>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<double>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                dim = -(dim - 1);  // 0 -> 1, 1 -> 0
+                #endregion
+
+                #region parameter preparation
+               
+                double[] retArr;
+               
+                double[] arrA = A.GetArrayForRead();
+               
+                double[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int workItemMultiplierLenA;
+                int workItemMultiplierLenB;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<double>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    workItemMultiplierLenB = outDims[0]; 
+                    workItemMultiplierLenA = dim;  // 0 for column, 1 for row vector
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<double>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    workItemMultiplierLenB = dim;  // 0 for column, 1 for row vector
+                    workItemMultiplierLenA = outDims[0]; 
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one singleton dimension in either A or B");
+                }
+                int itLen = outDims[0]; // (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<double> retStorage = new ILDenseStorage<double>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    double* ap;
+                   
+                    double* bp;
+                   
+                    double* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            if (dim == 0) {
+                                bp = (double*)range.Item3;
+                                cp = (double*)range.Item4; 
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (double*)range.Item2;
+                                    int l = itLen; 
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  % bp[0]);
+                                        cp[1] =   (ap[1]  % bp[1]);
+                                        cp[2] =   (ap[2]  % bp[2]);
+                                        cp[3] =   (ap[3]  % bp[3]);
+                                        cp[4] =   (ap[4]  % bp[4]);
+                                        cp[5] =   (ap[5]  % bp[5]);
+                                        cp[6] =   (ap[6]  % bp[6]);
+                                        cp[7] =   (ap[7]  % bp[7]);
+                                        cp[8] =   (ap[8]  % bp[8]);
+                                        cp[9] =   (ap[9]  % bp[9]);
+                                        cp[10] =   (ap[10]  % bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =   (*ap++  % *bp++);
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                ap = (double*)range.Item2;
+                                bp = (double*)range.Item3;
+                                cp = (double*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   double val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (val  % bp[0]);
+                                        cp[1] =   (val  % bp[1]);
+                                        cp[2] =   (val  % bp[2]);
+                                        cp[3] =   (val  % bp[3]);
+                                        cp[4] =   (val  % bp[4]);
+                                        cp[5] =   (val  % bp[5]);
+                                        cp[6] =   (val  % bp[6]);
+                                        cp[7] =   (val  % bp[7]);
+                                        cp[8] =   (val  % bp[8]);
+                                        cp[9] =   (val  % bp[9]);
+                                        cp[10] =   (val  % bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11; 
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =   (val  % *bp++);
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            if (dim == 0) {
+                                cp = (double*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (double*)range.Item2;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  % cp[0]);
+                                        cp[1] =   (ap[1]  % cp[1]);
+                                        cp[2] =   (ap[2]  % cp[2]);
+                                        cp[3] =   (ap[3]  % cp[3]);
+                                        cp[4] =   (ap[4]  % cp[4]);
+                                        cp[5] =   (ap[5]  % cp[5]);
+                                        cp[6] =   (ap[6]  % cp[6]);
+                                        cp[7] =   (ap[7]  % cp[7]);
+                                        cp[8] =   (ap[8]  % cp[8]);
+                                        cp[9] =   (ap[9]  % cp[9]);
+                                        cp[10] =   (ap[10]  % cp[10]);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap++  % *cp);
+                                        cp++; 
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                cp = (double*)range.Item4;
+                                ap = (double*)range.Item2;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    double val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (val  % cp[0]);
+                                        cp[1] =   (val  % cp[1]);
+                                        cp[2] =   (val  % cp[2]);
+                                        cp[3] =   (val  % cp[3]);
+                                        cp[4] =   (val  % cp[4]);
+                                        cp[5] =   (val  % cp[5]);
+                                        cp[6] =   (val  % cp[6]);
+                                        cp[7] =   (val  % cp[7]);
+                                        cp[8] =   (val  % cp[8]);
+                                        cp[9] =   (val  % cp[9]);
+                                        cp[10] =   (val  % cp[10]);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (val  % *cp);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            if (dim == 0) {
+                                ap = (double*)range.Item2;
+                                cp = (double*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (double*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  % bp[0]);
+                                        cp[1] =   (ap[1]  % bp[1]);
+                                        cp[2] =   (ap[2]  % bp[2]);
+                                        cp[3] =   (ap[3]  % bp[3]);
+                                        cp[4] =   (ap[4]  % bp[4]);
+                                        cp[5] =   (ap[5]  % bp[5]);
+                                        cp[6] =   (ap[6]  % bp[6]);
+                                        cp[7] =   (ap[7]  % bp[7]);
+                                        cp[8] =   (ap[8]  % bp[8]);
+                                        cp[9] =   (ap[9]  % bp[9]);
+                                        cp[10] =   (ap[10]  % bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap  % *bp);
+                                        ap++;
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                ap = (double*)range.Item2;
+                                bp = (double*)range.Item3;
+                                cp = (double*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   double val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (ap[0]  % val);
+                                        cp[1] =   (ap[1]  % val);
+                                        cp[2] =   (ap[2]  % val);
+                                        cp[3] =   (ap[3]  % val);
+                                        cp[4] =   (ap[4]  % val);
+                                        cp[5] =   (ap[5]  % val);
+                                        cp[6] =   (ap[6]  % val);
+                                        cp[7] =   (ap[7]  % val);
+                                        cp[8] =   (ap[8]  % val);
+                                        cp[9] =   (ap[9]  % val);
+                                        cp[10] =   (ap[10]  % val);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*ap  % val);
+                                        ap++;
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            if (dim == 0) {
+                                cp = (double*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (double*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (cp[0]  % bp[0]);
+                                        cp[1] =   (cp[1]  % bp[1]);
+                                        cp[2] =   (cp[2]  % bp[2]);
+                                        cp[3] =   (cp[3]  % bp[3]);
+                                        cp[4] =   (cp[4]  % bp[4]);
+                                        cp[5] =   (cp[5]  % bp[5]);
+                                        cp[6] =   (cp[6]  % bp[6]);
+                                        cp[7] =   (cp[7]  % bp[7]);
+                                        cp[8] =   (cp[8]  % bp[8]);
+                                        cp[9] =   (cp[9]  % bp[9]);
+                                        cp[10] =   (cp[10]  % bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =   (*cp  % *bp);
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                bp = (double*)range.Item3;
+                                cp = (double*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    double val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =   (cp[0]  % val);
+                                        cp[1] =   (cp[1]  % val);
+                                        cp[2] =   (cp[2]  % val);
+                                        cp[3] =   (cp[3]  % val);
+                                        cp[4] =   (cp[4]  % val);
+                                        cp[5] =   (cp[5]  % val);
+                                        cp[6] =   (cp[6]  % val);
+                                        cp[7] =   (cp[7]  % val);
+                                        cp[8] =   (cp[8]  % val);
+                                        cp[9] =   (cp[9]  % val);
+                                        cp[10] =   (cp[10]  % val);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l --> 0) {
+                                        *cp =   (*cp  % val);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outDims.NumberOfElements >= Settings.s_minParallelElement1Count
+                    && outDims[1] > 1) {
+                        if (outDims[1] > workItemCount) {
+                        workItemLength = outDims[1] / workItemCount;
+                    } else {
+                        workItemLength = outDims[1] / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outDims[1];
+                    workItemCount = 1;
+                }
+
+                fixed ( double* arrAP = arrA)
+                fixed ( double* arrBP = arrB)
+                fixed ( double* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, IntPtr, IntPtr, IntPtr> range = new Tuple<int, IntPtr, IntPtr, IntPtr>
+                               (workItemLength
+                               , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                               , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                               , (IntPtr)(retArrP + i * outDims[0] * workItemLength)); 
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, IntPtr, IntPtr, IntPtr>
+                                (outDims[1] - i * workItemLength
+                                , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                                , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                                , (IntPtr)(retArrP + i * outDims[0] * workItemLength)));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<double>(retStorage);
+            //}  // no scopes here! it disables implace operations
+        }
+
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/multiply.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/multiply.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/multiply.cs	(revision 9102)
@@ -0,0 +1,416 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.InteropServices; 
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Native;
+using ILNumerics.Exceptions;
+
+
+
+namespace ILNumerics {
+
+	public partial class ILMath {
+
+        private static readonly uint ALIGN = 1024 * 4;
+        [DllImport("matmulttestASM.dll", SetLastError = false, CallingConvention = CallingConvention.Cdecl, ExactSpelling= true, EntryPoint = "?inner_k_loop@@YAXHHHHHHHPAN0000HH@Z")]
+        unsafe static extern void inner_k_loop(int m, int n, int k, int kc, int mc, int mr, int nr,
+                                            IntPtr pAArr, IntPtr pBArr, IntPtr pCArr, IntPtr pBpack, IntPtr pApack,
+                                            int n_start, int n_end);
+        internal struct MatMultArguments {
+            public IntPtr pArr;
+            public IntPtr pBrr;
+            public IntPtr pCrr;
+            public IntPtr pAPack;
+            public IntPtr pBPack;
+            public int m_start;
+            public int m_end;
+            public int n_start;
+            public int n_end; 
+        }
+
+
+        /// <summary>
+        /// Multiplicate an arbitrary number of matrices from left to right
+        /// </summary>
+        /// <param name="matrices">Input matrices </param>
+        /// <returns>Result of matrix multiplication for all matrices</returns>
+        public static ILRetArray< double> multiply(params ILInArray< double>[] matrices) {
+            if (matrices == null || matrices.Length < 2) 
+                throw new ILArgumentException("the number of matching parameters for multiply must be at least 2"); 
+            using (ILScope.Enter(matrices)) {
+                ILArray< double> ret = multiply(matrices[0], matrices[1]); 
+                for (int i = 2; i < matrices.Length; i++) {
+                    ret.a = multiply(ret, matrices[i]); 
+                }
+                return ret; 
+            }
+        }
+
+        /// <summary>
+        /// General matrix multiply this array
+        /// </summary>
+        /// <param name="A">Input matrix A</param>
+        /// <param name="B">Input matrix B</param>
+        /// <returns>Matrix with result of matrix multiplication</returns>
+        /// <remarks>Both arrays must be matrices with matching dimension length. Therefore the number of rows 
+        /// of B must equal the number of columns of A. An ILArgumentSizeException will be thrown otherwise. 
+        /// The multiplication will be carried out inside optimized BLAS libraries if availiable. If not it 
+        /// will be done in managed code. 
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentSizeException">If at least one arrays is not a matrix</exception>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If the size of both matrices do not match</exception>
+        public static ILRetArray< double > multiply(ILInArray< double > A, ILInArray< double > B) {
+            using (ILScope.Enter(A,B)) {
+                ILArray< double> ret = null;
+                //if (A.Dimensions.NumberOfDimensions != 2
+                //    || B.Dimensions.NumberOfDimensions != 2)
+                //    throw new ILArgumentSizeException("input arguments must be matrices");
+                if (A.Size[1] != B.Size[0])
+                    throw new ILDimensionMismatchException("inner matrix dimensions must match");
+                
+                double[] retArr = null;
+                if (A.Size.NumberOfElements > ILAtlasMinimumElementSize ||
+                    B.Size.NumberOfElements > ILAtlasMinimumElementSize) {
+                    // do BLAS GEMM 
+                    ret = zeros< double>(new ILSize(A.Size[0], B.Size[1]));  // todo: change to use uninitialized memory!
+                    retArr = ret.GetArrayForWrite();
+                    unsafe {
+                        fixed ( double* ptrC = retArr)
+                        fixed ( double* pA = A.GetArrayForRead())
+                        fixed ( double* pB = B.GetArrayForRead()) {
+                            
+                            Lapack.dgemm(TRANS_NONE, TRANS_NONE,
+                                A.Size[0], B.Size[1],
+                                A.Size[1], ( double)1.0,
+                                (IntPtr)pA, A.Size[0],
+                                (IntPtr)pB, B.Size[0], ( double)1.0,
+                                retArr, ret.Size[0]);
+                        }
+                    }
+                } else {
+                    // do GEMM by hand 
+                    retArr = new  double[A.Size[0] * B.Size[1]];
+                    ret = array< double>(retArr, A.Size[0], B.Size[1]);
+                    unsafe {
+                        int in2Len1 = B.Size[1];
+                        int in1Len0 = A.Size[0];
+                        int in1Len1 = A.Size[1];
+                        fixed ( double* ptrC = retArr) {
+                            
+                            double* pC = ptrC;
+                            for (int c = 0; c < in2Len1; c++) {
+                                for (int r = 0; r < in1Len0; r++) {
+                                    for (int n = 0; n < in1Len1; n++) {
+                                        *pC += A.GetValue(r, n) * B.GetValue(n, c);
+                                    }
+                                    pC++;
+                                }
+                            }
+                        }
+                    }
+                }
+                return ret;
+            }
+        }
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// Multiplicate an arbitrary number of matrices from left to right
+        /// </summary>
+        /// <param name="matrices">Input matrices </param>
+        /// <returns>Result of matrix multiplication for all matrices</returns>
+        public static ILRetArray< float> multiply(params ILInArray< float>[] matrices) {
+            if (matrices == null || matrices.Length < 2) 
+                throw new ILArgumentException("the number of matching parameters for multiply must be at least 2"); 
+            using (ILScope.Enter(matrices)) {
+                ILArray< float> ret = multiply(matrices[0], matrices[1]); 
+                for (int i = 2; i < matrices.Length; i++) {
+                    ret.a = multiply(ret, matrices[i]); 
+                }
+                return ret; 
+            }
+        }
+
+        /// <summary>
+        /// General matrix multiply this array
+        /// </summary>
+        /// <param name="A">Input matrix A</param>
+        /// <param name="B">Input matrix B</param>
+        /// <returns>Matrix with result of matrix multiplication</returns>
+        /// <remarks>Both arrays must be matrices with matching dimension length. Therefore the number of rows 
+        /// of B must equal the number of columns of A. An ILArgumentSizeException will be thrown otherwise. 
+        /// The multiplication will be carried out inside optimized BLAS libraries if availiable. If not it 
+        /// will be done in managed code. 
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentSizeException">If at least one arrays is not a matrix</exception>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If the size of both matrices do not match</exception>
+        public static ILRetArray< float > multiply(ILInArray< float > A, ILInArray< float > B) {
+            using (ILScope.Enter(A,B)) {
+                ILArray< float> ret = null;
+                //if (A.Dimensions.NumberOfDimensions != 2
+                //    || B.Dimensions.NumberOfDimensions != 2)
+                //    throw new ILArgumentSizeException("input arguments must be matrices");
+                if (A.Size[1] != B.Size[0])
+                    throw new ILDimensionMismatchException("inner matrix dimensions must match");
+               
+                float[] retArr = null;
+                if (A.Size.NumberOfElements > ILAtlasMinimumElementSize ||
+                    B.Size.NumberOfElements > ILAtlasMinimumElementSize) {
+                    // do BLAS GEMM 
+                    ret = zeros< float>(new ILSize(A.Size[0], B.Size[1]));  // todo: change to use uninitialized memory!
+                    retArr = ret.GetArrayForWrite();
+                    unsafe {
+                        fixed ( float* ptrC = retArr)
+                        fixed ( float* pA = A.GetArrayForRead())
+                        fixed ( float* pB = B.GetArrayForRead()) {
+                           
+                            Lapack.sgemm(TRANS_NONE, TRANS_NONE,
+                                A.Size[0], B.Size[1],
+                                A.Size[1], ( float)1.0,
+                                (IntPtr)pA, A.Size[0],
+                                (IntPtr)pB, B.Size[0], ( float)1.0,
+                                retArr, ret.Size[0]);
+                        }
+                    }
+                } else {
+                    // do GEMM by hand 
+                    retArr = new  float[A.Size[0] * B.Size[1]];
+                    ret = array< float>(retArr, A.Size[0], B.Size[1]);
+                    unsafe {
+                        int in2Len1 = B.Size[1];
+                        int in1Len0 = A.Size[0];
+                        int in1Len1 = A.Size[1];
+                        fixed ( float* ptrC = retArr) {
+                           
+                            float* pC = ptrC;
+                            for (int c = 0; c < in2Len1; c++) {
+                                for (int r = 0; r < in1Len0; r++) {
+                                    for (int n = 0; n < in1Len1; n++) {
+                                        *pC += A.GetValue(r, n) * B.GetValue(n, c);
+                                    }
+                                    pC++;
+                                }
+                            }
+                        }
+                    }
+                }
+                return ret;
+            }
+        }
+
+        /// <summary>
+        /// Multiplicate an arbitrary number of matrices from left to right
+        /// </summary>
+        /// <param name="matrices">Input matrices </param>
+        /// <returns>Result of matrix multiplication for all matrices</returns>
+        public static ILRetArray< fcomplex> multiply(params ILInArray< fcomplex>[] matrices) {
+            if (matrices == null || matrices.Length < 2) 
+                throw new ILArgumentException("the number of matching parameters for multiply must be at least 2"); 
+            using (ILScope.Enter(matrices)) {
+                ILArray< fcomplex> ret = multiply(matrices[0], matrices[1]); 
+                for (int i = 2; i < matrices.Length; i++) {
+                    ret.a = multiply(ret, matrices[i]); 
+                }
+                return ret; 
+            }
+        }
+
+        /// <summary>
+        /// General matrix multiply this array
+        /// </summary>
+        /// <param name="A">Input matrix A</param>
+        /// <param name="B">Input matrix B</param>
+        /// <returns>Matrix with result of matrix multiplication</returns>
+        /// <remarks>Both arrays must be matrices with matching dimension length. Therefore the number of rows 
+        /// of B must equal the number of columns of A. An ILArgumentSizeException will be thrown otherwise. 
+        /// The multiplication will be carried out inside optimized BLAS libraries if availiable. If not it 
+        /// will be done in managed code. 
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentSizeException">If at least one arrays is not a matrix</exception>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If the size of both matrices do not match</exception>
+        public static ILRetArray< fcomplex > multiply(ILInArray< fcomplex > A, ILInArray< fcomplex > B) {
+            using (ILScope.Enter(A,B)) {
+                ILArray< fcomplex> ret = null;
+                //if (A.Dimensions.NumberOfDimensions != 2
+                //    || B.Dimensions.NumberOfDimensions != 2)
+                //    throw new ILArgumentSizeException("input arguments must be matrices");
+                if (A.Size[1] != B.Size[0])
+                    throw new ILDimensionMismatchException("inner matrix dimensions must match");
+               
+                fcomplex[] retArr = null;
+                if (A.Size.NumberOfElements > ILAtlasMinimumElementSize ||
+                    B.Size.NumberOfElements > ILAtlasMinimumElementSize) {
+                    // do BLAS GEMM 
+                    ret = zeros< fcomplex>(new ILSize(A.Size[0], B.Size[1]));  // todo: change to use uninitialized memory!
+                    retArr = ret.GetArrayForWrite();
+                    unsafe {
+                        fixed ( fcomplex* ptrC = retArr)
+                        fixed ( fcomplex* pA = A.GetArrayForRead())
+                        fixed ( fcomplex* pB = B.GetArrayForRead()) {
+                           
+                            Lapack.cgemm(TRANS_NONE, TRANS_NONE,
+                                A.Size[0], B.Size[1],
+                                A.Size[1], ( fcomplex)1.0,
+                                (IntPtr)pA, A.Size[0],
+                                (IntPtr)pB, B.Size[0], ( fcomplex)1.0,
+                                retArr, ret.Size[0]);
+                        }
+                    }
+                } else {
+                    // do GEMM by hand 
+                    retArr = new  fcomplex[A.Size[0] * B.Size[1]];
+                    ret = array< fcomplex>(retArr, A.Size[0], B.Size[1]);
+                    unsafe {
+                        int in2Len1 = B.Size[1];
+                        int in1Len0 = A.Size[0];
+                        int in1Len1 = A.Size[1];
+                        fixed ( fcomplex* ptrC = retArr) {
+                           
+                            fcomplex* pC = ptrC;
+                            for (int c = 0; c < in2Len1; c++) {
+                                for (int r = 0; r < in1Len0; r++) {
+                                    for (int n = 0; n < in1Len1; n++) {
+                                        *pC += A.GetValue(r, n) * B.GetValue(n, c);
+                                    }
+                                    pC++;
+                                }
+                            }
+                        }
+                    }
+                }
+                return ret;
+            }
+        }
+
+        /// <summary>
+        /// Multiplicate an arbitrary number of matrices from left to right
+        /// </summary>
+        /// <param name="matrices">Input matrices </param>
+        /// <returns>Result of matrix multiplication for all matrices</returns>
+        public static ILRetArray< complex> multiply(params ILInArray< complex>[] matrices) {
+            if (matrices == null || matrices.Length < 2) 
+                throw new ILArgumentException("the number of matching parameters for multiply must be at least 2"); 
+            using (ILScope.Enter(matrices)) {
+                ILArray< complex> ret = multiply(matrices[0], matrices[1]); 
+                for (int i = 2; i < matrices.Length; i++) {
+                    ret.a = multiply(ret, matrices[i]); 
+                }
+                return ret; 
+            }
+        }
+
+        /// <summary>
+        /// General matrix multiply this array
+        /// </summary>
+        /// <param name="A">Input matrix A</param>
+        /// <param name="B">Input matrix B</param>
+        /// <returns>Matrix with result of matrix multiplication</returns>
+        /// <remarks>Both arrays must be matrices with matching dimension length. Therefore the number of rows 
+        /// of B must equal the number of columns of A. An ILArgumentSizeException will be thrown otherwise. 
+        /// The multiplication will be carried out inside optimized BLAS libraries if availiable. If not it 
+        /// will be done in managed code. 
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentSizeException">If at least one arrays is not a matrix</exception>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If the size of both matrices do not match</exception>
+        public static ILRetArray< complex > multiply(ILInArray< complex > A, ILInArray< complex > B) {
+            using (ILScope.Enter(A,B)) {
+                ILArray< complex> ret = null;
+                //if (A.Dimensions.NumberOfDimensions != 2
+                //    || B.Dimensions.NumberOfDimensions != 2)
+                //    throw new ILArgumentSizeException("input arguments must be matrices");
+                if (A.Size[1] != B.Size[0])
+                    throw new ILDimensionMismatchException("inner matrix dimensions must match");
+               
+                complex[] retArr = null;
+                if (A.Size.NumberOfElements > ILAtlasMinimumElementSize ||
+                    B.Size.NumberOfElements > ILAtlasMinimumElementSize) {
+                    // do BLAS GEMM 
+                    ret = zeros< complex>(new ILSize(A.Size[0], B.Size[1]));  // todo: change to use uninitialized memory!
+                    retArr = ret.GetArrayForWrite();
+                    unsafe {
+                        fixed ( complex* ptrC = retArr)
+                        fixed ( complex* pA = A.GetArrayForRead())
+                        fixed ( complex* pB = B.GetArrayForRead()) {
+                           
+                            Lapack.zgemm(TRANS_NONE, TRANS_NONE,
+                                A.Size[0], B.Size[1],
+                                A.Size[1], ( complex)1.0,
+                                (IntPtr)pA, A.Size[0],
+                                (IntPtr)pB, B.Size[0], ( complex)1.0,
+                                retArr, ret.Size[0]);
+                        }
+                    }
+                } else {
+                    // do GEMM by hand 
+                    retArr = new  complex[A.Size[0] * B.Size[1]];
+                    ret = array< complex>(retArr, A.Size[0], B.Size[1]);
+                    unsafe {
+                        int in2Len1 = B.Size[1];
+                        int in1Len0 = A.Size[0];
+                        int in1Len1 = A.Size[1];
+                        fixed ( complex* ptrC = retArr) {
+                           
+                            complex* pC = ptrC;
+                            for (int c = 0; c < in2Len1; c++) {
+                                for (int r = 0; r < in1Len0; r++) {
+                                    for (int n = 0; n < in1Len1; n++) {
+                                        *pC += A.GetValue(r, n) * B.GetValue(n, c);
+                                    }
+                                    pC++;
+                                }
+                            }
+                        }
+                    }
+                }
+                return ret;
+            }
+        }
+
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/mvnpdf.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/mvnpdf.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/mvnpdf.cs	(revision 9102)
@@ -0,0 +1,129 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics;
+using ILNumerics.Exceptions;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+
+
+
+namespace ILNumerics {
+
+    public partial class ILMath {
+
+        /// <summary>
+        /// Probability density function for a multivariate normal random distribution
+        /// </summary>
+        /// <param name="A">Matrix of points in columns, where the probability density function is to be evaluated</param>
+        /// <param name="mu">[Optional] Centers, size d x 1, if 'null': zeros are attempted, default: null</param>
+        /// <param name="sigma">Covariance matrix, must be positive definite, size d x d or vector of lenght d</param>
+        /// <returns>Random numbers as taken from the multivariate random probability distribution given by mu and sigma</returns>
+        public static ILRetArray<double> mvnpdf(ILInArray<double> A, ILInArray<double> mu = null, ILInArray<double> sigma = null) {
+            using (ILScope.Enter(mu, sigma)) {
+                if (isnull(A)) {
+                    throw new ILArgumentException("input parameter 'samples' may not be null");
+                }
+                int d = A.S[0], n = A.S[1];
+                if (A.IsEmpty) {
+                    if (d > 0)
+                        return empty<double>(A.S); 
+                    else {
+                        return empty<double>(ILSize.Empty00); 
+                    }
+                }
+                // early exit, trivial case 
+                if (isnullorempty(mu) && isnullorempty(sigma)) {
+                    return 1 / (pow(sqrt(2 * pi), d)) * exp(-0.5f * (diag(multiply(A.T, A))));
+                }
+                ILArray<double> muLoc = mu; 
+                if (isnullorempty(mu)) {
+                    muLoc.a = zeros<double>(d,1);      
+                }
+                ILArray<double> sigmaLoc = sigma; 
+                if (isnullorempty(sigma)) {
+                    sigmaLoc.a = eye<double>(d,d);      
+                }
+                ILArray<double> sampMinMu = A - muLoc;
+                return 1 / (pow(sqrt(2 * pi), d) * det(sigmaLoc)) * exp(-0.5 * (diag(multiply(sampMinMu.T, eye(d, d) / sigmaLoc, sampMinMu))));
+            }
+        }
+
+        /// <summary>
+        /// Probability density function for a multivariate normal random distribution
+        /// </summary>
+        /// <param name="A">Matrix of points in columns, where the probability density function is to be evaluated</param>
+        /// <param name="mu">[Optional] Centers, size d x 1, if 'null': zeros are attempted, default: null</param>
+        /// <param name="sigma">Covariance matrix, must be positive definite, size d x d or vector of lenght d</param>
+        /// <returns>Random numbers as taken from the multivariate random probability distribution given by mu and sigma</returns>
+        public static ILRetArray<float> mvnpdf(ILInArray<float> A, ILInArray<float> mu = null, ILInArray<float> sigma = null) {
+            using (ILScope.Enter(mu, sigma)) {
+                if (isnull(A)) {
+                    throw new ILArgumentException("input parameter 'samples' may not be null");
+                }
+                int d = A.S[0], n = A.S[1];
+                if (A.IsEmpty) {
+                    if (d > 0)
+                        return empty<float>(A.S); 
+                    else {
+                        return empty<float>(ILSize.Empty00); 
+                    }
+                }
+                // early exit, trivial case 
+                if (isnullorempty(mu) && isnullorempty(sigma)) {
+                    return 1 / tosingle(pow(sqrt(2 * pi), d)) * exp(-0.5f * (diag(multiply(A.T, A))));
+                }
+                ILArray<float> muLoc = mu; 
+                if (isnullorempty(mu)) {
+                    muLoc.a = zeros<float>(d,1);      
+                }
+                ILArray<float> sigmaLoc = sigma; 
+                if (isnullorempty(sigma)) {
+                    sigmaLoc.a = eye<float>(d,d);      
+                }
+                ILArray<float> sampMinMu = A - muLoc;
+                return 1f / tosingle(pow(sqrt(2 * pi), d)) * det(sigmaLoc) * exp(-0.5f * (diag(multiply(sampMinMu.T, eye<float>(d, d) / sigmaLoc, sampMinMu))));
+            }
+        }
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/mvnrnd.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/mvnrnd.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/mvnrnd.cs	(revision 9102)
@@ -0,0 +1,268 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics;
+using ILNumerics.Exceptions;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+
+
+
+namespace ILNumerics {
+
+    public partial class ILMath {
+
+        private static ILArrayCache s_mvnrndcache = ILCacheManager.Manager.GetCache();
+
+        /// <summary>
+        /// Choose samples from a multivariate random distribution
+        /// </summary>
+        /// <returns>n random numbers as taken from the multivariate random probability distribution with zero mean and unity covariance</returns>
+        /// <remarks><para>This is an alias for <see cref="M:ILNumerics.ILMath.randn(params int[])"/>. If n was not specified, a single random number is generated.</para>
+        /// <para>The samples are returned as row vector of size 1 x n.</para></remarks>
+        public static ILRetArray<double> mvnrnd(int n = -1) {
+            if (n >= 0)
+                return randn(1,n); 
+            return randn(1,1);  
+        }
+
+        /// <summary>
+        /// Choose one sample from a multivariate random distribution
+        /// </summary>
+        /// <returns>Single random number, taken from the multivariate random probability distribution with zero mean and unity covariance</returns>
+        /// <remarks><para>This is an alias for <see cref="M:ILNumerics.ILMath.randn(params int[])"/>. A single (scalar) random number is generated.</para></remarks>
+        public static ILRetArray<double> mvnrnd() {
+            return randn(1, 1); 
+        }
+
+
+
+        /// <summary>
+        /// choose samples from a multivariate random distribution  
+        /// </summary>
+        /// <param name="inMu">[optional] centers, size d x n; if d x 1 is given, optional parameter <paramref name="n"/> is used to replicate mu accordingly, if null, the values will be genereated with a center of zero</param>
+        /// <param name="inSigma">[optional] covariance matrix, must be positive definite, size d x d or vector of lenght d, if null (not set), unitiy matrix is expected</param>
+        /// <param name="n">[optional] number of samples to generate, per default (-1) the number of columns of <paramref name="mu"/> defines that number</param>
+        /// <param name="sigmaIsSquaredCov">[optional] if false: safe the effort of finding the square root of <paramref name="sigma"/> parameter; default: true</param>
+        /// <returns>random numbers as taken from the multivariate random probability distribution given by mu and sigma</returns>
+        /// <remarks><para>In order to safe the step of finding the root of sigma, the following options exist: 
+        /// <list type="bullet">
+        /// <item>Provide only the diagonal of a (virtual) diagonal matrix to <paramref name="sigma"/>.</item>
+        /// <item>Compute the root manually, give it to sigma and set <paramref name="sigmaIsSquaredCov"/> to false.</item>
+        /// </list></para>
+        /// <para>In case <paramref name="sigmaIsSquaredCov"/> set to 'false' and <paramref name="sigma"/> is given, 
+        /// the root is computed via cholesky factorization. The result of the last root finding process is cached and reused for 
+        /// subsequent requests with the same set of <paramref name="n"/> and <paramref name="sigma"/> parameters.</para></remarks>
+        public static ILRetArray<double> mvnrnd(ILInArray<double> inMu = null, ILInArray<double> inSigma = null,
+                                                       int n = -1, bool sigmaIsSquaredCov = true) {
+            using (ILScope.Enter(inMu, inSigma)) {
+
+                // early exit, trivial case 
+                if (isnullorempty(inMu) && isnullorempty(inSigma)) {
+                    return  /*dummy*/ (randn(1, Math.Max(n, 0)));
+                }
+                ILArray<double> mu = check(inMu, Default: empty< double>());
+                ILArray<double> sigma = check(inSigma, Default: empty<double>()); 
+
+                // determine output size
+                n = Math.Max(Math.Max(mu.S[1], sigma.S[2]), n);
+                int d = Math.Max(Math.Max(mu.S[0], sigma.S[0]), sigma.S[1]);
+                ILArray<double> ret = empty<double>();
+
+                if (mu.IsEmpty)
+                    mu = zeros<double>(d, 1);
+                if (mu.IsRowVector)
+                    mu = mu.T;
+                if (sigma.IsEmpty)
+                    sigma = ones<double>(d, 1);
+                if (sigma.IsRowVector)
+                    sigma = sigma.T;
+
+                if (mu.IsVector && mu.Length != d) {
+                    throw new ILArgumentException("mu must be empty or have the same dimensionality as sigma");
+                } else if (mu.S[1] > 1 && (mu.S[0] != d || mu.S[1] != n)) {
+                    throw new ILArgumentException("mu must be empty, vector d x 1 or matrix d x n, d = dimensionality of sigma");
+                }
+                ILArray<double> sigmaLoc = sigma;
+                // main
+                if (sigma.IsVector && sigma.Length == d) {
+                    // we dont cach vector sigmas
+                    if (any(sigmaLoc < 0)) {
+                        throw new ILArgumentException("all diagonal elements of sigma must be >= 0"); 
+                    }
+                    sigmaLoc.a = sqrt(sigmaLoc);
+                    ret.a =  /*dummy*/ (randn(d, n)) * sigmaLoc + mu;
+
+                } else if ((sigma.IsMatrix || sigma.S[2] == n) && sigma.S[0] == d && sigma.S[1] == d) {
+                    if (sigmaIsSquaredCov && !s_mvnrndcache.TryGetArray<double>(sigmaLoc, n, sigma)) {
+                        for (int i = sigmaLoc.S[2]; i --> 0; ) {
+                            sigmaLoc[full, full, i] = chol(sigmaLoc[full, full, i]); 
+                        }
+                        s_mvnrndcache.Cache<double>(sigmaLoc, n, sigma);
+                    }
+                    ret.a  = zeros<double>(d,n);
+                    bool sigmaIsMatrix = sigmaLoc.S[2] <= 1; 
+                    if (mu.IsVector) {
+                        for (int i = 0; i < n; i++) {
+                            using (ILScope.Enter()) {
+                                if (sigmaIsMatrix)
+                                    ret[full, i] = multiply( /*dummy*/ (randn(1, d)), sigmaLoc).T + mu;
+                                else
+                                    ret[full, i] = multiply( /*dummy*/ (randn(1, d)), sigmaLoc[full, full, i]).T + mu;
+                            }
+                        }
+                    } else {
+                        for (int i = 0; i < n; i++) {
+                            using (ILScope.Enter()) {
+                                if (sigmaIsMatrix)
+                                    ret[full, i] = multiply( /*dummy*/ (randn(1, d)), sigmaLoc).T + mu[full, i];
+                                else
+                                    ret[full, i] = multiply( /*dummy*/ (randn(1, d)), sigmaLoc[full, full, i]).T + mu[full, i];
+
+                            }
+                        }
+                    }
+                } else {
+                    throw new ILArgumentException("invalid size of sigma, check the documentation for valid options");
+                }
+                return ret; 
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+
+        /// <summary>
+        /// choose samples from a multivariate random distribution  
+        /// </summary>
+        /// <param name="inMu">[optional] centers, size d x n; if d x 1 is given, optional parameter <paramref name="n"/> is used to replicate mu accordingly, if null, the values will be genereated with a center of zero</param>
+        /// <param name="inSigma">[optional] covariance matrix, must be positive definite, size d x d or vector of lenght d, if null (not set), unitiy matrix is expected</param>
+        /// <param name="n">[optional] number of samples to generate, per default (-1) the number of columns of <paramref name="mu"/> defines that number</param>
+        /// <param name="sigmaIsSquaredCov">[optional] if false: safe the effort of finding the square root of <paramref name="sigma"/> parameter; default: true</param>
+        /// <returns>random numbers as taken from the multivariate random probability distribution given by mu and sigma</returns>
+        /// <remarks><para>In order to safe the step of finding the root of sigma, the following options exist: 
+        /// <list type="bullet">
+        /// <item>Provide only the diagonal of a (virtual) diagonal matrix to <paramref name="sigma"/>.</item>
+        /// <item>Compute the root manually, give it to sigma and set <paramref name="sigmaIsSquaredCov"/> to false.</item>
+        /// </list></para>
+        /// <para>In case <paramref name="sigmaIsSquaredCov"/> set to 'false' and <paramref name="sigma"/> is given, 
+        /// the root is computed via cholesky factorization. The result of the last root finding process is cached and reused for 
+        /// subsequent requests with the same set of <paramref name="n"/> and <paramref name="sigma"/> parameters.</para></remarks>
+        public static ILRetArray<float> mvnrnd(ILInArray<float> inMu = null, ILInArray<float> inSigma = null,
+                                                       int n = -1, bool sigmaIsSquaredCov = true) {
+            using (ILScope.Enter(inMu, inSigma)) {
+
+                // early exit, trivial case 
+                if (isnullorempty(inMu) && isnullorempty(inSigma)) {
+                    return  tosingle (randn(1, Math.Max(n, 0)));
+                }
+                ILArray<float> mu = check(inMu, Default: empty< float>());
+                ILArray<float> sigma = check(inSigma, Default: empty<float>()); 
+
+                // determine output size
+                n = Math.Max(Math.Max(mu.S[1], sigma.S[2]), n);
+                int d = Math.Max(Math.Max(mu.S[0], sigma.S[0]), sigma.S[1]);
+                ILArray<float> ret = empty<float>();
+
+                if (mu.IsEmpty)
+                    mu = zeros<float>(d, 1);
+                if (mu.IsRowVector)
+                    mu = mu.T;
+                if (sigma.IsEmpty)
+                    sigma = ones<float>(d, 1);
+                if (sigma.IsRowVector)
+                    sigma = sigma.T;
+
+                if (mu.IsVector && mu.Length != d) {
+                    throw new ILArgumentException("mu must be empty or have the same dimensionality as sigma");
+                } else if (mu.S[1] > 1 && (mu.S[0] != d || mu.S[1] != n)) {
+                    throw new ILArgumentException("mu must be empty, vector d x 1 or matrix d x n, d = dimensionality of sigma");
+                }
+                ILArray<float> sigmaLoc = sigma;
+                // main
+                if (sigma.IsVector && sigma.Length == d) {
+                    // we dont cach vector sigmas
+                    if (any(sigmaLoc < 0)) {
+                        throw new ILArgumentException("all diagonal elements of sigma must be >= 0"); 
+                    }
+                    sigmaLoc.a = sqrt(sigmaLoc);
+                    ret.a =  tosingle (randn(d, n)) * sigmaLoc + mu;
+
+                } else if ((sigma.IsMatrix || sigma.S[2] == n) && sigma.S[0] == d && sigma.S[1] == d) {
+                    if (sigmaIsSquaredCov && !s_mvnrndcache.TryGetArray<float>(sigmaLoc, n, sigma)) {
+                        for (int i = sigmaLoc.S[2]; i --> 0; ) {
+                            sigmaLoc[full, full, i] = chol(sigmaLoc[full, full, i]); 
+                        }
+                        s_mvnrndcache.Cache<float>(sigmaLoc, n, sigma);
+                    }
+                    ret.a  = zeros<float>(d,n);
+                    bool sigmaIsMatrix = sigmaLoc.S[2] <= 1; 
+                    if (mu.IsVector) {
+                        for (int i = 0; i < n; i++) {
+                            using (ILScope.Enter()) {
+                                if (sigmaIsMatrix)
+                                    ret[full, i] = multiply( tosingle (randn(1, d)), sigmaLoc).T + mu;
+                                else
+                                    ret[full, i] = multiply( tosingle (randn(1, d)), sigmaLoc[full, full, i]).T + mu;
+                            }
+                        }
+                    } else {
+                        for (int i = 0; i < n; i++) {
+                            using (ILScope.Enter()) {
+                                if (sigmaIsMatrix)
+                                    ret[full, i] = multiply( tosingle (randn(1, d)), sigmaLoc).T + mu[full, i];
+                                else
+                                    ret[full, i] = multiply( tosingle (randn(1, d)), sigmaLoc[full, full, i]).T + mu[full, i];
+
+                            }
+                        }
+                    }
+                } else {
+                    throw new ILArgumentException("invalid size of sigma, check the documentation for valid options");
+                }
+                return ret; 
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+   }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/neq.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/neq.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/neq.cs	(revision 9102)
@@ -0,0 +1,2016 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.InteropServices; 
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Native;
+using ILNumerics.Exceptions;
+
+
+
+namespace ILNumerics {
+
+	public partial class ILMath {
+
+
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>Elementwise logical 'not equal' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array having '1' for elements in A not equal to corresponding elements in B, '0' else</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  neq(ILInArray<Int64> A, ILInArray<Int64> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                Int64[] arrA = A.GetArrayForRead();
+               
+                Int64[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                       
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0)  != B.GetValue(0)) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  neqEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    Int64 scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            Int64* ap = ((Int64*)range.Item3 + range.Item1);
+                            Int64* bp = ((Int64*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  != *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((Int64*)range.Item3 + range.Item1);
+                            scalar = *((Int64*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  != scalar) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((Int64*)range.Item3);
+                            bp = ((Int64*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (scalar  != *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (Int64* arrAP = arrA)
+                fixed (Int64* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  neqEx(ILInArray<Int64> A, ILInArray<Int64> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                Int64[] arrA = A.GetArrayForRead();
+               
+                Int64[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    Int64* ap;
+                   
+                    Int64* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (Int64*)range.Item3;
+                                bp = (Int64*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  != *bp) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (Int64*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (Int64*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  != *bp) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( Int64* arrAP = arrA)
+                fixed ( Int64* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'not equal' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array having '1' for elements in A not equal to corresponding elements in B, '0' else</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  neq(ILInArray<Int32> A, ILInArray<Int32> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                Int32[] arrA = A.GetArrayForRead();
+               
+                Int32[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                       
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0)  != B.GetValue(0)) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  neqEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    Int32 scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            Int32* ap = ((Int32*)range.Item3 + range.Item1);
+                            Int32* bp = ((Int32*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  != *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((Int32*)range.Item3 + range.Item1);
+                            scalar = *((Int32*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  != scalar) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((Int32*)range.Item3);
+                            bp = ((Int32*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (scalar  != *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (Int32* arrAP = arrA)
+                fixed (Int32* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  neqEx(ILInArray<Int32> A, ILInArray<Int32> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                Int32[] arrA = A.GetArrayForRead();
+               
+                Int32[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    Int32* ap;
+                   
+                    Int32* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (Int32*)range.Item3;
+                                bp = (Int32*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  != *bp) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (Int32*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (Int32*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  != *bp) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( Int32* arrAP = arrA)
+                fixed ( Int32* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'not equal' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array having '1' for elements in A not equal to corresponding elements in B, '0' else</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  neq(ILInArray<float> A, ILInArray<float> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                float[] arrA = A.GetArrayForRead();
+               
+                float[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                       
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0)  != B.GetValue(0)) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  neqEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    float scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            float* ap = ((float*)range.Item3 + range.Item1);
+                            float* bp = ((float*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  != *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((float*)range.Item3 + range.Item1);
+                            scalar = *((float*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  != scalar) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((float*)range.Item3);
+                            bp = ((float*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (scalar  != *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (float* arrAP = arrA)
+                fixed (float* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  neqEx(ILInArray<float> A, ILInArray<float> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                float[] arrA = A.GetArrayForRead();
+               
+                float[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    float* ap;
+                   
+                    float* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (float*)range.Item3;
+                                bp = (float*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  != *bp) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (float*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (float*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  != *bp) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( float* arrAP = arrA)
+                fixed ( float* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'not equal' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array having '1' for elements in A not equal to corresponding elements in B, '0' else</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  neq(ILInArray<fcomplex> A, ILInArray<fcomplex> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                fcomplex[] arrA = A.GetArrayForRead();
+               
+                fcomplex[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                       
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0)  != B.GetValue(0)) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  neqEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    fcomplex scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            fcomplex* ap = ((fcomplex*)range.Item3 + range.Item1);
+                            fcomplex* bp = ((fcomplex*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  != *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((fcomplex*)range.Item3 + range.Item1);
+                            scalar = *((fcomplex*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  != scalar) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((fcomplex*)range.Item3);
+                            bp = ((fcomplex*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (scalar  != *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (fcomplex* arrAP = arrA)
+                fixed (fcomplex* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  neqEx(ILInArray<fcomplex> A, ILInArray<fcomplex> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                fcomplex[] arrA = A.GetArrayForRead();
+               
+                fcomplex[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    fcomplex* ap;
+                   
+                    fcomplex* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (fcomplex*)range.Item3;
+                                bp = (fcomplex*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  != *bp) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (fcomplex*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (fcomplex*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  != *bp) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( fcomplex* arrAP = arrA)
+                fixed ( fcomplex* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'not equal' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array having '1' for elements in A not equal to corresponding elements in B, '0' else</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  neq(ILInArray<complex> A, ILInArray<complex> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                complex[] arrA = A.GetArrayForRead();
+               
+                complex[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                       
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0)  != B.GetValue(0)) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  neqEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    complex scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            complex* ap = ((complex*)range.Item3 + range.Item1);
+                            complex* bp = ((complex*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  != *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((complex*)range.Item3 + range.Item1);
+                            scalar = *((complex*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  != scalar) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((complex*)range.Item3);
+                            bp = ((complex*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (scalar  != *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (complex* arrAP = arrA)
+                fixed (complex* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  neqEx(ILInArray<complex> A, ILInArray<complex> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                complex[] arrA = A.GetArrayForRead();
+               
+                complex[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    complex* ap;
+                   
+                    complex* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (complex*)range.Item3;
+                                bp = (complex*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  != *bp) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (complex*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (complex*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  != *bp) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( complex* arrAP = arrA)
+                fixed ( complex* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'not equal' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array having '1' for elements in A not equal to corresponding elements in B, '0' else</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  neq(ILInArray<byte> A, ILInArray<byte> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                byte[] arrA = A.GetArrayForRead();
+               
+                byte[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                       
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0)  != B.GetValue(0)) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  neqEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    byte scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            byte* ap = ((byte*)range.Item3 + range.Item1);
+                            byte* bp = ((byte*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  != *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((byte*)range.Item3 + range.Item1);
+                            scalar = *((byte*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  != scalar) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((byte*)range.Item3);
+                            bp = ((byte*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (scalar  != *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (byte* arrAP = arrA)
+                fixed (byte* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  neqEx(ILInArray<byte> A, ILInArray<byte> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                byte[] arrA = A.GetArrayForRead();
+               
+                byte[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    byte* ap;
+                   
+                    byte* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (byte*)range.Item3;
+                                bp = (byte*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  != *bp) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (byte*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (byte*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  != *bp) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( byte* arrAP = arrA)
+                fixed ( byte* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'not equal' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array having '1' for elements in A not equal to corresponding elements in B, '0' else</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  neq(ILInArray<double> A, ILInArray<double> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                double[] arrA = A.GetArrayForRead();
+               
+                double[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                       
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0)  != B.GetValue(0)) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  neqEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    double scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            double* ap = ((double*)range.Item3 + range.Item1);
+                            double* bp = ((double*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  != *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((double*)range.Item3 + range.Item1);
+                            scalar = *((double*)range.Item4);
+                            while (cp < cLast) {
+                               
+                                *cp = (*ap  != scalar) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((double*)range.Item3);
+                            bp = ((double*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                               
+                                *cp = (scalar  != *bp) ? (byte)1 : (byte)0; 
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (double* arrAP = arrA)
+                fixed (double* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  neqEx(ILInArray<double> A, ILInArray<double> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                double[] arrA = A.GetArrayForRead();
+               
+                double[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    double* ap;
+                   
+                    double* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (double*)range.Item3;
+                                bp = (double*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  != *bp) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (double*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (double*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                   
+                                    *cp = (*ap  != *bp) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( double* arrAP = arrA)
+                fixed ( double* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// Elementwise logical 'not equal' operator
+        /// </summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array having '1' for elements in A not equal elements in B, '0' else</returns>
+        /// <remarks><para>On empty input - empty array will be returned.</para>
+        /// <para>A and / or B may be scalar. The scalar value will operate on all elements of the other arrays in this case.</para>
+        /// <para>If neither of A or B is scalar or empty, the dimensions of both arrays must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">if neither of A or B is scalar and the size of both arrays does not match</exception>
+        public static ILRetLogical neq (ILInArray<String> A, ILInArray<String> B) {
+            if (object.Equals(A,null)) 
+                throw new ILArgumentException("input argurment A must not be null!");
+            if (object.Equals(B,null)) 
+                throw new ILArgumentException("input argurment B must not be null!");
+            if (!A.Size.IsSameShape(B.Size)) 
+                throw new ILArgumentException("input arrays must have the same size"); 
+            if (A.IsEmpty || B.IsEmpty)
+                return new ILRetLogical(ILSize.Empty00); 
+            ILRetLogical ret = null; 
+            string scalarValue; 
+            ILSize retDim = null; 
+            byte[] retArr = null; 
+            if (A.IsScalar) {
+                if (B.IsScalar) {
+                    retDim = new ILSize(1,1); 
+                    ret = new ILRetLogical(new byte[1]{(A.GetValue(0) != B.GetValue(0))?(byte)1:(byte)0},1,1); 
+                } else {
+                    retDim = B.Size; 
+                    int len = B.Size.NumberOfElements; 
+                    retArr = new byte[len]; 
+                    scalarValue = A.GetValue(0); 
+                    for (int i = 0; i < len; i++) {
+                        if (scalarValue != B.GetValue(i)) {
+                            retArr[i] = 1; 
+                        }
+                    }
+                }
+            } else {
+                retDim = A.Size; 
+                if (B.IsScalar) {
+                    int len = A.Size.NumberOfElements; 
+                    retArr = new byte[len]; 
+                    scalarValue = B.GetValue(0); 
+                    for (int i = 0; i < len; i++) {
+                        if (scalarValue != A.GetValue(i))
+                            retArr[i] = 1; 
+                    }
+                } else {
+                    if (!A.Size.IsSameSize(B.Size))
+                        throw new ILDimensionMismatchException("neq: size of arrays must match!");
+                    int len = A.Size.NumberOfElements; 
+                    retArr = new byte[len]; 
+                    for (int i = 0; i < len; i++) {
+                        if (A.GetValue(i) != B.GetValue(i))
+                            retArr[i] = 1; 
+                    }
+                }
+            }
+            return new ILRetLogical(retArr,retDim); 
+        }
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/new.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/new.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/new.cs	(revision 9102)
@@ -0,0 +1,117 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace ILNumerics {
+    public partial class ILMath {
+        /// <summary>
+        /// Request System.Array <typeparamref name="T"/>[] from ILNumerics Memory Pool
+        /// </summary>
+        /// <typeparam name="T">the element type</typeparam>
+        /// <param name="length"><b>minimal</b> length of the array returned</param>
+        /// <returns>A system array of element type <typeparamref name="T"/> and minimal length <paramref name="length"/>.</returns>
+        /// <remarks>
+        /// <para>This function fetches a System.Array from the collection of available arrays with matching properties which are currently held in the ILNumerics Memory Pool. 
+        /// This simplifies usage scenarios where the user must handle System.Arrays in computational loops and still wants to profit from the ILNumerics memory management.</para>
+        /// <para>The array returned is fetched from the collection of available arrays in the pool. If no matching array was found, a new array is requested from the managed heap.</para>
+        /// <para>The user is reponsible to return the array to the pool once finished using it. The <see cref="ILNumerics.ILMath.free{T}"/> method should be used for returning an array.</para>
+        /// <para>Keep in mind, the array returned may be <b>longer</b> as requested! Therefore, in order to reference its elements use the <paramref name="length"/> parameter rather than the System.Array.Length property.</para>
+        /// <example>A system array is needed inside a computational loop. The loop calls a native function repeatedly which requests a working array. The System.Array is requested from the pool and returned to the pool after usage.
+        /// <code>
+        ///[System.Runtime.InteropServices.DllImport("myDLL")]
+        ///private static extern void MyDllFunc(double[] a, int lenA, double[] b, double[] work, int lenWork);
+        ///
+        ///public static ILRetArray<double> MyFunc(ILInArray<double> A) {
+        ///    using (ILScope.Enter(A)) {
+        ///        // myDllFunc needs storage for the result
+        ///        ILArray<double> ret = zeros(A.Size);
+        ///        ILArray<double> tmpRow = zeros(1, A.S[1]);
+        ///
+        ///        // myDllFunc needs a working storage:
+        ///        double[] work = New<double>(A.S[1]);
+        ///        // for all rows of A use the same working array
+        ///        for (int i = 0; i < A.S[0]; i++) {
+        ///            using (ILScope.Enter()) {
+        ///                ILArray<double> ARow = A[i, full];
+        ///                MyDllFunc(ARow.GetArrayForRead(), A.Length, tmpRow.GetArrayForWrite(), work, A.Length);
+        ///                ret[i, full] = tmpRow;
+        ///            }
+        ///        }
+        ///        // return the System.Array to the pool 
+        ///        free(work);
+        ///        return ret;
+        ///    }
+        ///}
+        /// </code>
+        /// However, in most situations, the handling of system.arrays directly can be circumvented. The same goal as in the example could be archieved as follows: 
+        /// <code>        
+        /// public static ILRetArray<double> MyFunc(ILInArray<double> A) {
+        ///using (ILScope.Enter(A)) {
+        ///    // myDllFunc needs storage for the result
+        ///    ILArray<double> ret = zeros(A.Size);
+        ///    ILArray<double> tmpRow = zeros(1, A.S[1]);
+        ///    // myDllFunc needs a working storage. We us a regular ILNumerics array 
+        ///    // which we dont have to free afterwards. 
+        ///    ILArray<double> work = zeros(tmpRow.S); 
+        ///
+        ///    // for all rows of A use the same working array
+        ///    for (int i = 0; i < A.S[0]; i++) {
+        ///        using (ILScope.Enter()) {
+        ///            ILArray<double> ARow = A[i, full];
+        ///            MyDllFunc(ARow.GetArrayForRead(), A.Length, tmpRow.GetArrayForWrite(), work.GetArrayForWrite(), A.Length);
+        ///            ret[i, full] = tmpRow;
+        ///        }
+        ///    }
+        ///    // returning the working storage is not needed here...
+        ///
+        ///    return ret;
+        ///}
+        ///}</code>
+        /// Both examples archieve a 100% memory efficiency by completely reusing the memory needed within the function. 
+        /// </example>
+        /// </remarks>
+        public static T[] New<T>(int length) {
+            return ILMemoryPool.Pool.New<T>(length); 
+        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/ones.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/ones.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/ones.cs	(revision 9102)
@@ -0,0 +1,175 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.InteropServices; 
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Native;
+using ILNumerics.Exceptions;
+
+namespace ILNumerics {
+
+	public partial class ILMath {
+
+        /// <summary>
+        /// Create new double array, set initial values to 1
+        /// </summary>
+        /// <returns>array</returns>
+        public static ILRetArray<double> ones(params int[] dimensions) {
+            return (ILRetArray<double>)ones(NumericType.Double, new ILSize(dimensions));
+        }
+        /// <summary>
+        /// Create array initialized with all elements set to one
+        /// </summary>
+        /// <param name="type">Numeric type specification. One value out of the types listed in the <see cred="ILNumerics.NumericType"/>
+        /// enum.</param>
+        /// <param name="size">Size descriptor</param>
+        /// <returns>Array of inner type corresponding to <paramref name="type"/> argument.</returns>
+        /// <remarks>The array returned must be casted to the appropriate actual type afterwards and assigned to a concrete array! Caution: 
+        /// This overload is provided for compatibility reasons only! Use <see cref="ones{T}(ILSize)"/> instead.
+        /// <para>
+        /// <list type="number"> 
+        /// <listheader>The following types are supported: </listheader>
+        /// <item>Double</item>
+        /// <item>Single</item>
+        /// <item>Complex</item>
+        /// <item>FComplex</item>
+        /// <item>Byte</item>
+        /// <item>Int32</item>
+        /// <item>Int64</item>
+        /// </list>
+        /// </para>
+        /// </remarks>
+        public static ILBaseArray ones(NumericType type, ILSize size) {
+            switch (type) {
+                case NumericType.Double:
+                    return array<double>(1.0, size);
+                case NumericType.Single:
+                    return array<float>(1f, size);
+                case NumericType.Complex:
+                    return array<complex>(new complex(1, 0), size);
+                case NumericType.FComplex:
+                    return array<fcomplex>(new fcomplex(1f, 0f), size);
+                case NumericType.Byte:
+                    return array<byte>(1, size);
+                case NumericType.Int32:
+                    return array<int>(1, size).T;
+                case NumericType.Int64:
+                    return array<long>(1, size);
+            }
+            return null;
+        }
+        /// <summary>
+        /// Create array initialized with all elements set to one
+        /// </summary>
+        /// <typeparam name="T">Numeric type specification.</typeparam>
+        /// <param name="size">Size descriptor</param>
+        /// <returns>Array of inner type corresponding to the given type.</returns>
+        ///  <remarks>The array returned may be casted to the appropriate actual type afterwards. 
+        /// <para>
+        /// <list type="number"> 
+        /// <listheader>The following types are supported: </listheader>
+        /// <item>Double</item>
+        /// <item>Single</item>
+        /// <item>complex</item>
+        /// <item>fcomplex</item>
+        /// <item>Byte</item>
+        /// <item>Int32</item>
+        /// <item>Int64</item>
+        /// </list>
+        /// </para>
+        /// </remarks>
+        public static ILRetArray<T> ones<T>(params int[] size) {
+            return ones<T>(new ILSize(size)); 
+        }
+        /// <summary>
+        /// Create array initialized with all elements set to one
+        /// </summary>
+        /// <typeparam name="T">Numeric type specification.</typeparam>
+        /// <param name="size">Size descriptor</param>
+        /// <returns>Array of inner type corresponding to the given type.</returns>
+        ///  <remarks>The array returned may be casted to the appropriate actual type afterwards. 
+        /// <para>
+        /// <list type="number"> 
+        /// <listheader>The following types are supported: </listheader>
+        /// <item>Double</item>
+        /// <item>Single</item>
+        /// <item>complex</item>
+        /// <item>fcomplex</item>
+        /// <item>Byte</item>
+        /// <item>Int32</item>
+        /// <item>Int64</item>
+        /// </list>
+        /// </para>
+        /// </remarks>
+        public static ILRetArray<T> ones<T>(ILSize size) {
+            using (ILScope.Enter()) {
+                if (typeof(T) == typeof(double)) {
+                    return (ILRetArray<T>)(object)array<double>(1.0, size);
+                } else if (typeof(T) == typeof(float)) {
+                    return (ILRetArray<T>)(object)array<float>(1f, size);
+                } else if (typeof(T) == typeof(int)) {
+                    return (ILRetArray<T>)(object)array<int>(1, size);
+                } else if (typeof(T) == typeof(long)) {
+                    return (ILRetArray<T>)(object)array<long>(1, size);
+                } else if (typeof(T) == typeof(complex)) {
+                    return (ILRetArray<T>)(object)array<complex>(new complex(1, 0), size);
+                } else if (typeof(T) == typeof(fcomplex)) {
+                    return (ILRetArray<T>)(object)array<fcomplex>(new fcomplex(1f, 0f), size);
+                } else if (typeof(T) == typeof(byte)) {
+                    return (ILRetArray<T>)(object)array<byte>(1, size);
+                } else if (typeof(T) == typeof(short)) {
+                    return (ILRetArray<T>)(object)array<short>(1, size);
+                }
+                return null;
+            }
+        }
+        /// <summary>
+        /// Create new double array, set initial values to 1
+        /// </summary>
+        /// <returns>Array</returns>
+        public static ILRetArray<double> ones(ILSize dimensions) {
+            return (ILRetArray<double>)ones(NumericType.Double, dimensions);
+        }
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/or.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/or.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/or.cs	(revision 9102)
@@ -0,0 +1,1912 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.InteropServices;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Native;
+using ILNumerics.Exceptions;
+
+
+
+namespace ILNumerics {
+
+    public partial class ILMath {
+
+
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>Elementwise logical 'or' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array with the elementwise result of logical 'or' for all elements in A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  or(ILInArray<Int64> A, ILInArray<Int64> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                Int64[] arrA = A.GetArrayForRead();
+               
+                Int64[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0) != 0 || B.GetValue(0) != 0) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  orEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    Int64 scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            Int64* ap = ((Int64*)range.Item3 + range.Item1);
+                            Int64* bp = ((Int64*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                                *cp = (*ap != 0 || *bp != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((Int64*)range.Item3 + range.Item1);
+                            scalar = *((Int64*)range.Item4);
+                            while (cp < cLast) {
+                                *cp = (scalar != 0 || *ap != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((Int64*)range.Item3);
+                            bp = ((Int64*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                                *cp = (scalar != 0 || *bp != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (Int64* arrAP = arrA)
+                fixed (Int64* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  orEx(ILInArray<Int64> A, ILInArray<Int64> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                Int64[] arrA = A.GetArrayForRead();
+               
+                Int64[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    Int64* ap;
+                   
+                    Int64* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (Int64*)range.Item3;
+                                bp = (Int64*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap != 0 || *bp != 0) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (Int64*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (Int64*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap != 0 || *bp != 0) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( Int64* arrAP = arrA)
+                fixed ( Int64* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'or' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array with the elementwise result of logical 'or' for all elements in A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  or(ILInArray<Int32> A, ILInArray<Int32> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                Int32[] arrA = A.GetArrayForRead();
+               
+                Int32[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0) != 0 || B.GetValue(0) != 0) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  orEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    Int32 scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            Int32* ap = ((Int32*)range.Item3 + range.Item1);
+                            Int32* bp = ((Int32*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                                *cp = (*ap != 0 || *bp != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((Int32*)range.Item3 + range.Item1);
+                            scalar = *((Int32*)range.Item4);
+                            while (cp < cLast) {
+                                *cp = (scalar != 0 || *ap != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((Int32*)range.Item3);
+                            bp = ((Int32*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                                *cp = (scalar != 0 || *bp != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (Int32* arrAP = arrA)
+                fixed (Int32* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  orEx(ILInArray<Int32> A, ILInArray<Int32> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                Int32[] arrA = A.GetArrayForRead();
+               
+                Int32[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    Int32* ap;
+                   
+                    Int32* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (Int32*)range.Item3;
+                                bp = (Int32*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap != 0 || *bp != 0) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (Int32*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (Int32*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap != 0 || *bp != 0) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( Int32* arrAP = arrA)
+                fixed ( Int32* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'or' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array with the elementwise result of logical 'or' for all elements in A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  or(ILInArray<float> A, ILInArray<float> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                float[] arrA = A.GetArrayForRead();
+               
+                float[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0) != 0 || B.GetValue(0) != 0) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  orEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    float scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            float* ap = ((float*)range.Item3 + range.Item1);
+                            float* bp = ((float*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                                *cp = (*ap != 0 || *bp != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((float*)range.Item3 + range.Item1);
+                            scalar = *((float*)range.Item4);
+                            while (cp < cLast) {
+                                *cp = (scalar != 0 || *ap != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((float*)range.Item3);
+                            bp = ((float*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                                *cp = (scalar != 0 || *bp != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (float* arrAP = arrA)
+                fixed (float* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  orEx(ILInArray<float> A, ILInArray<float> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                float[] arrA = A.GetArrayForRead();
+               
+                float[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    float* ap;
+                   
+                    float* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (float*)range.Item3;
+                                bp = (float*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap != 0 || *bp != 0) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (float*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (float*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap != 0 || *bp != 0) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( float* arrAP = arrA)
+                fixed ( float* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'or' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array with the elementwise result of logical 'or' for all elements in A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  or(ILInArray<fcomplex> A, ILInArray<fcomplex> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                fcomplex[] arrA = A.GetArrayForRead();
+               
+                fcomplex[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0) != 0 || B.GetValue(0) != 0) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  orEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    fcomplex scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            fcomplex* ap = ((fcomplex*)range.Item3 + range.Item1);
+                            fcomplex* bp = ((fcomplex*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                                *cp = (*ap != 0 || *bp != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((fcomplex*)range.Item3 + range.Item1);
+                            scalar = *((fcomplex*)range.Item4);
+                            while (cp < cLast) {
+                                *cp = (scalar != 0 || *ap != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((fcomplex*)range.Item3);
+                            bp = ((fcomplex*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                                *cp = (scalar != 0 || *bp != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (fcomplex* arrAP = arrA)
+                fixed (fcomplex* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  orEx(ILInArray<fcomplex> A, ILInArray<fcomplex> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                fcomplex[] arrA = A.GetArrayForRead();
+               
+                fcomplex[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    fcomplex* ap;
+                   
+                    fcomplex* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (fcomplex*)range.Item3;
+                                bp = (fcomplex*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap != 0 || *bp != 0) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (fcomplex*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (fcomplex*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap != 0 || *bp != 0) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( fcomplex* arrAP = arrA)
+                fixed ( fcomplex* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'or' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array with the elementwise result of logical 'or' for all elements in A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  or(ILInArray<complex> A, ILInArray<complex> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                complex[] arrA = A.GetArrayForRead();
+               
+                complex[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0) != 0 || B.GetValue(0) != 0) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  orEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    complex scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            complex* ap = ((complex*)range.Item3 + range.Item1);
+                            complex* bp = ((complex*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                                *cp = (*ap != 0 || *bp != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((complex*)range.Item3 + range.Item1);
+                            scalar = *((complex*)range.Item4);
+                            while (cp < cLast) {
+                                *cp = (scalar != 0 || *ap != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((complex*)range.Item3);
+                            bp = ((complex*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                                *cp = (scalar != 0 || *bp != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (complex* arrAP = arrA)
+                fixed (complex* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  orEx(ILInArray<complex> A, ILInArray<complex> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                complex[] arrA = A.GetArrayForRead();
+               
+                complex[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    complex* ap;
+                   
+                    complex* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (complex*)range.Item3;
+                                bp = (complex*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap != 0 || *bp != 0) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (complex*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (complex*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap != 0 || *bp != 0) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( complex* arrAP = arrA)
+                fixed ( complex* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'or' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array with the elementwise result of logical 'or' for all elements in A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  or(ILInArray<byte> A, ILInArray<byte> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                byte[] arrA = A.GetArrayForRead();
+               
+                byte[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0) != 0 || B.GetValue(0) != 0) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  orEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    byte scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            byte* ap = ((byte*)range.Item3 + range.Item1);
+                            byte* bp = ((byte*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                                *cp = (*ap != 0 || *bp != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((byte*)range.Item3 + range.Item1);
+                            scalar = *((byte*)range.Item4);
+                            while (cp < cLast) {
+                                *cp = (scalar != 0 || *ap != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((byte*)range.Item3);
+                            bp = ((byte*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                                *cp = (scalar != 0 || *bp != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (byte* arrAP = arrA)
+                fixed (byte* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  orEx(ILInArray<byte> A, ILInArray<byte> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                byte[] arrA = A.GetArrayForRead();
+               
+                byte[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    byte* ap;
+                   
+                    byte* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (byte*)range.Item3;
+                                bp = (byte*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap != 0 || *bp != 0) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (byte*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (byte*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap != 0 || *bp != 0) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( byte* arrAP = arrA)
+                fixed ( byte* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'or' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array with the elementwise result of logical 'or' for all elements in A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  or(ILInArray<double> A, ILInArray<double> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                double[] arrA = A.GetArrayForRead();
+               
+                double[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0) != 0 || B.GetValue(0) != 0) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  orEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    double scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            double* ap = ((double*)range.Item3 + range.Item1);
+                            double* bp = ((double*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                                *cp = (*ap != 0 || *bp != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((double*)range.Item3 + range.Item1);
+                            scalar = *((double*)range.Item4);
+                            while (cp < cLast) {
+                                *cp = (scalar != 0 || *ap != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((double*)range.Item3);
+                            bp = ((double*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                                *cp = (scalar != 0 || *bp != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (double* arrAP = arrA)
+                fixed (double* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  orEx(ILInArray<double> A, ILInArray<double> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                double[] arrA = A.GetArrayForRead();
+               
+                double[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    double* ap;
+                   
+                    double* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (double*)range.Item3;
+                                bp = (double*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap != 0 || *bp != 0) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (double*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (double*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap != 0 || *bp != 0) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( double* arrAP = arrA)
+                fixed ( double* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/pinv.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/pinv.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/pinv.cs	(revision 9102)
@@ -0,0 +1,494 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions;
+using ILNumerics;
+
+namespace ILNumerics  {
+
+    public partial class ILMath {
+
+
+
+
+        /// <summary>
+        /// Pseudo - inverse of input argument M
+        /// </summary>
+        /// <param name="M">Input matrix M</param>
+        /// <returns>Pseudo inverse of input matrix M</returns>
+        /// <remarks>The function returns the pseudo inverse (Moore-Penrose pseudoinverse)
+        /// of input matrix M. The return value will be of the same size as 
+        /// the transposed of M. it will satisfy the following conditions: 
+        /// <list type="bullet">
+        /// <item>M * pinv(M) * M  = M </item>
+        /// <item>pinv(M) * M * pinv(M) = pinv(M)</item>
+        /// <item>pinv(M) * M is hermitian</item>
+        /// <item>M * pinv(M) is hermitian</item>
+        /// </list>
+        /// pinv uses Lapack's function svd internally. Any singular values less than 
+        /// the default tolerance will be set to zero. As tolerance the following equation is used: \\
+        /// tol = length(M) * norm(M) * Double.epsilon \\
+        /// with 
+        /// <list type="bullet">
+        /// <item>length(M) - the longest dimension of M</item>
+        /// <item>norm(M) being the largest singular value of M, </item>
+        /// <item>Double.epsilon - the smallest number greater than zero</item>
+        /// </list>
+        /// You may use a overloaded function to define an alternative tolerance. 
+        /// </remarks>
+        /// <seealso cref="ILNumerics.ILMath.pinv(ILInArray{double}, double)"/>
+        public static ILRetArray< double > pinv(ILInArray< double > M) {
+            return pinv(M, -1); 
+        }
+        /// <summary>
+        /// Pseudo inverse of input matrix M
+        /// </summary>
+        /// <param name="M">Input matrix M</param>
+        /// <param name="tolerance">Tolerance, see remarks (default = -1; use default tolerance)</param>
+        /// <returns>Pseudo inverse of M</returns>
+        /// <remarks>The function returns the pseudo inverse (Moore-Penrose pseudoinverse)
+        /// of input matrix M. The return value will be of the same size as 
+        /// the transposed of M. it will satisfy the following conditions: 
+        /// <list type="bullet">
+        /// <item>M * pinv(M) * M  = M </item>
+        /// <item>pinv(M) * M * pinv(M) = pinv(M)</item>
+        /// <item>pinv(M) * M is hermitian</item>
+        /// <item>M * pinv(M) is hermitian</item>
+        /// </list>
+        /// pinv uses LAPACK's function svd internally. Any singular values less than 
+        /// tolerance will be set to zero. If tolerance is less than zero, the following equation 
+        /// is used as default: \\
+        /// tol = length(M) * norm(M) * Double.epsilon \\
+        /// with 
+        /// <list type="bullet">
+        /// <item>length(M) - the longest dimension of M</item>
+        /// <item>norm(M) being the largest singular value of M, </item>
+        /// <item>Double.epsilon - the smallest constructable double precision number greater than zero</item>
+        /// </list>
+        /// </remarks>
+        public static ILRetArray< double > pinv(ILInArray< double > M,  double tolerance) {
+            using (ILScope.Enter(M)) {
+                // let svd check the dimensions! 
+                //if (M.Dimensions.NumberOfDimensions > 2)
+                //   throw new ILDimensionMismatchException("pinv: ...");
+
+                // in order to use the cheap packed version of svd, the matrix must be m x n with m > n! 
+                if (M.Size[0] < M.Size[1]) {
+                    
+                    return pinv(M.T, tolerance).T;
+                }
+                if (M.IsScalar)
+                    return  1.0 / M;
+
+                ILArray< double> U = empty< double>(ILSize.Empty00);
+                ILArray< double> V = empty< double>(ILSize.Empty00);
+                ILArray< double> S = svd(M, U, V, true, false);
+
+                int m = M.Size[0];
+                int n = M.Size[1];
+
+                ILArray< double> s;
+                switch (m) {
+                    case 0:
+                        s = zeros< double>(ILSize.Scalar1_1);
+                        break;
+                    case 1:
+                        s = S[0];
+                        break;
+                    default:
+                        s = diag< double>(S);
+                        break;
+                }
+                if (tolerance < 0) {
+                    tolerance = ( double)(M.Size.Longest * max(s).GetValue(0) *  MachineParameterDouble.eps);
+                }
+                // sum vector elements: s is dense vector returned from svd
+                int count = (int)sum(s > ( double)tolerance);
+
+                ILArray< double> Ret = empty< double>(ILSize.Empty00);
+                if (count == 0)
+                    S.a = zeros< double>(new ILSize(n, m));
+                else {
+                    ILArray< double> OneVec = array< double>( 1.0, count, 1);
+
+                    S.a = diag(divide(OneVec, s[r(0,count - 1)]));
+                    
+                    U.a = U[full,r(0,count-1)].T;
+                    
+                    Ret.a = multiply(multiply(V[full,r(0,count - 1)], S), U);
+                }
+                return Ret;
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+
+
+        /// <summary>
+        /// Pseudo - inverse of input argument M
+        /// </summary>
+        /// <param name="M">Input matrix M</param>
+        /// <returns>Pseudo inverse of input matrix M</returns>
+        /// <remarks>The function returns the pseudo inverse (Moore-Penrose pseudoinverse)
+        /// of input matrix M. The return value will be of the same size as 
+        /// the transposed of M. it will satisfy the following conditions: 
+        /// <list type="bullet">
+        /// <item>M * pinv(M) * M  = M </item>
+        /// <item>pinv(M) * M * pinv(M) = pinv(M)</item>
+        /// <item>pinv(M) * M is hermitian</item>
+        /// <item>M * pinv(M) is hermitian</item>
+        /// </list>
+        /// pinv uses Lapack's function svd internally. Any singular values less than 
+        /// the default tolerance will be set to zero. As tolerance the following equation is used: \\
+        /// tol = length(M) * norm(M) * Double.epsilon \\
+        /// with 
+        /// <list type="bullet">
+        /// <item>length(M) - the longest dimension of M</item>
+        /// <item>norm(M) being the largest singular value of M, </item>
+        /// <item>Double.epsilon - the smallest number greater than zero</item>
+        /// </list>
+        /// You may use a overloaded function to define an alternative tolerance. 
+        /// </remarks>
+        /// <seealso cref="ILNumerics.ILMath.pinv(ILInArray{double}, double)"/>
+        public static ILRetArray< float > pinv(ILInArray< float > M) {
+            return pinv(M, -1); 
+        }
+        /// <summary>
+        /// Pseudo inverse of input matrix M
+        /// </summary>
+        /// <param name="M">Input matrix M</param>
+        /// <param name="tolerance">Tolerance, see remarks (default = -1; use default tolerance)</param>
+        /// <returns>Pseudo inverse of M</returns>
+        /// <remarks>The function returns the pseudo inverse (Moore-Penrose pseudoinverse)
+        /// of input matrix M. The return value will be of the same size as 
+        /// the transposed of M. it will satisfy the following conditions: 
+        /// <list type="bullet">
+        /// <item>M * pinv(M) * M  = M </item>
+        /// <item>pinv(M) * M * pinv(M) = pinv(M)</item>
+        /// <item>pinv(M) * M is hermitian</item>
+        /// <item>M * pinv(M) is hermitian</item>
+        /// </list>
+        /// pinv uses LAPACK's function svd internally. Any singular values less than 
+        /// tolerance will be set to zero. If tolerance is less than zero, the following equation 
+        /// is used as default: \\
+        /// tol = length(M) * norm(M) * Double.epsilon \\
+        /// with 
+        /// <list type="bullet">
+        /// <item>length(M) - the longest dimension of M</item>
+        /// <item>norm(M) being the largest singular value of M, </item>
+        /// <item>Double.epsilon - the smallest constructable double precision number greater than zero</item>
+        /// </list>
+        /// </remarks>
+        public static ILRetArray< float > pinv(ILInArray< float > M,  float tolerance) {
+            using (ILScope.Enter(M)) {
+                // let svd check the dimensions! 
+                //if (M.Dimensions.NumberOfDimensions > 2)
+                //   throw new ILDimensionMismatchException("pinv: ...");
+
+                // in order to use the cheap packed version of svd, the matrix must be m x n with m > n! 
+                if (M.Size[0] < M.Size[1]) {
+                    return pinv(M.T, tolerance).T;
+                }
+                if (M.IsScalar)
+                    return  1 / M;
+
+                ILArray< float> U = empty< float>(ILSize.Empty00);
+                ILArray< float> V = empty< float>(ILSize.Empty00);
+                ILArray< float> S = svd(M, U, V, true, false);
+
+                int m = M.Size[0];
+                int n = M.Size[1];
+
+                ILArray< float> s;
+                switch (m) {
+                    case 0:
+                        s = zeros< float>(ILSize.Scalar1_1);
+                        break;
+                    case 1:
+                        s = S[0];
+                        break;
+                    default:
+                        s = diag< float>(S);
+                        break;
+                }
+                if (tolerance < 0) {
+                    tolerance = ( float)(M.Size.Longest * max(s).GetValue(0) *  ILMath.MachineParameterSingle.eps);
+                }
+                // sum vector elements: s is dense vector returned from svd
+                int count = (int)sum(s > ( float)tolerance);
+
+                ILArray< float> Ret = empty< float>(ILSize.Empty00);
+                if (count == 0)
+                    S.a = zeros< float>(new ILSize(n, m));
+                else {
+                    ILArray< float> OneVec = array< float>( 1.0f, count, 1);
+
+                    S.a = diag(divide(OneVec, s[r(0,count - 1)]));
+                    U = U[":;0:" + (count - 1)].T;
+                    Ret = multiply(multiply(V[":;0:" + (count - 1)], S), U);
+                }
+                return Ret;
+            }
+        }
+
+
+        /// <summary>
+        /// Pseudo - inverse of input argument M
+        /// </summary>
+        /// <param name="M">Input matrix M</param>
+        /// <returns>Pseudo inverse of input matrix M</returns>
+        /// <remarks>The function returns the pseudo inverse (Moore-Penrose pseudoinverse)
+        /// of input matrix M. The return value will be of the same size as 
+        /// the transposed of M. it will satisfy the following conditions: 
+        /// <list type="bullet">
+        /// <item>M * pinv(M) * M  = M </item>
+        /// <item>pinv(M) * M * pinv(M) = pinv(M)</item>
+        /// <item>pinv(M) * M is hermitian</item>
+        /// <item>M * pinv(M) is hermitian</item>
+        /// </list>
+        /// pinv uses Lapack's function svd internally. Any singular values less than 
+        /// the default tolerance will be set to zero. As tolerance the following equation is used: \\
+        /// tol = length(M) * norm(M) * Double.epsilon \\
+        /// with 
+        /// <list type="bullet">
+        /// <item>length(M) - the longest dimension of M</item>
+        /// <item>norm(M) being the largest singular value of M, </item>
+        /// <item>Double.epsilon - the smallest number greater than zero</item>
+        /// </list>
+        /// You may use a overloaded function to define an alternative tolerance. 
+        /// </remarks>
+        /// <seealso cref="ILNumerics.ILMath.pinv(ILInArray{double}, double)"/>
+        public static ILRetArray< fcomplex > pinv(ILInArray< fcomplex > M) {
+            return pinv(M, -1); 
+        }
+        /// <summary>
+        /// Pseudo inverse of input matrix M
+        /// </summary>
+        /// <param name="M">Input matrix M</param>
+        /// <param name="tolerance">Tolerance, see remarks (default = -1; use default tolerance)</param>
+        /// <returns>Pseudo inverse of M</returns>
+        /// <remarks>The function returns the pseudo inverse (Moore-Penrose pseudoinverse)
+        /// of input matrix M. The return value will be of the same size as 
+        /// the transposed of M. it will satisfy the following conditions: 
+        /// <list type="bullet">
+        /// <item>M * pinv(M) * M  = M </item>
+        /// <item>pinv(M) * M * pinv(M) = pinv(M)</item>
+        /// <item>pinv(M) * M is hermitian</item>
+        /// <item>M * pinv(M) is hermitian</item>
+        /// </list>
+        /// pinv uses LAPACK's function svd internally. Any singular values less than 
+        /// tolerance will be set to zero. If tolerance is less than zero, the following equation 
+        /// is used as default: \\
+        /// tol = length(M) * norm(M) * Double.epsilon \\
+        /// with 
+        /// <list type="bullet">
+        /// <item>length(M) - the longest dimension of M</item>
+        /// <item>norm(M) being the largest singular value of M, </item>
+        /// <item>Double.epsilon - the smallest constructable double precision number greater than zero</item>
+        /// </list>
+        /// </remarks>
+        public static ILRetArray< fcomplex > pinv(ILInArray< fcomplex > M,  fcomplex tolerance) {
+            using (ILScope.Enter(M)) {
+                // let svd check the dimensions! 
+                //if (M.Dimensions.NumberOfDimensions > 2)
+                //   throw new ILDimensionMismatchException("pinv: ...");
+
+                // in order to use the cheap packed version of svd, the matrix must be m x n with m > n! 
+                if (M.Size[0] < M.Size[1]) {
+                    return conj(pinv(conj(M.T), tolerance)).T;
+                }
+                if (M.IsScalar)
+                    return  new fcomplex(1f,0f) / M;
+
+                ILArray< fcomplex> U = empty< fcomplex>(ILSize.Empty00);
+                ILArray< fcomplex> V = empty< fcomplex>(ILSize.Empty00);
+                ILArray< float> S = svd(M, U, V, true, false);
+
+                int m = M.Size[0];
+                int n = M.Size[1];
+
+                ILArray< float> s;
+                switch (m) {
+                    case 0:
+                        s = zeros< float>(ILSize.Scalar1_1);
+                        break;
+                    case 1:
+                        s = S[0];
+                        break;
+                    default:
+                        s = diag< float>(S);
+                        break;
+                }
+                if (tolerance < 0) {
+                    tolerance = ( fcomplex)(M.Size.Longest * max(s).GetValue(0) *  ILMath.MachineParameterSingle.eps);
+                }
+                // sum vector elements: s is dense vector returned from svd
+                int count = (int)sum(s > ( float)tolerance);
+
+                ILArray< fcomplex> Ret = empty< fcomplex>(ILSize.Empty00);
+                if (count == 0)
+                    S.a = zeros< float>(new ILSize(n, m));
+                else {
+                    ILArray< float> OneVec = array< float>( 1.0f, count, 1);
+
+                    S.a = diag(divide(OneVec, s[r(0,count - 1)]));
+                    U = conj(U[":;0:" + (count - 1)].T);
+                    Ret = multiply(multiply(V[":;0:" + (count - 1)], real2fcomplex(S)), U);
+                }
+                return Ret;
+            }
+        }
+
+
+        /// <summary>
+        /// Pseudo - inverse of input argument M
+        /// </summary>
+        /// <param name="M">Input matrix M</param>
+        /// <returns>Pseudo inverse of input matrix M</returns>
+        /// <remarks>The function returns the pseudo inverse (Moore-Penrose pseudoinverse)
+        /// of input matrix M. The return value will be of the same size as 
+        /// the transposed of M. it will satisfy the following conditions: 
+        /// <list type="bullet">
+        /// <item>M * pinv(M) * M  = M </item>
+        /// <item>pinv(M) * M * pinv(M) = pinv(M)</item>
+        /// <item>pinv(M) * M is hermitian</item>
+        /// <item>M * pinv(M) is hermitian</item>
+        /// </list>
+        /// pinv uses Lapack's function svd internally. Any singular values less than 
+        /// the default tolerance will be set to zero. As tolerance the following equation is used: \\
+        /// tol = length(M) * norm(M) * Double.epsilon \\
+        /// with 
+        /// <list type="bullet">
+        /// <item>length(M) - the longest dimension of M</item>
+        /// <item>norm(M) being the largest singular value of M, </item>
+        /// <item>Double.epsilon - the smallest number greater than zero</item>
+        /// </list>
+        /// You may use a overloaded function to define an alternative tolerance. 
+        /// </remarks>
+        /// <seealso cref="ILNumerics.ILMath.pinv(ILInArray{double}, double)"/>
+        public static ILRetArray< complex > pinv(ILInArray< complex > M) {
+            return pinv(M, -1); 
+        }
+        /// <summary>
+        /// Pseudo inverse of input matrix M
+        /// </summary>
+        /// <param name="M">Input matrix M</param>
+        /// <param name="tolerance">Tolerance, see remarks (default = -1; use default tolerance)</param>
+        /// <returns>Pseudo inverse of M</returns>
+        /// <remarks>The function returns the pseudo inverse (Moore-Penrose pseudoinverse)
+        /// of input matrix M. The return value will be of the same size as 
+        /// the transposed of M. it will satisfy the following conditions: 
+        /// <list type="bullet">
+        /// <item>M * pinv(M) * M  = M </item>
+        /// <item>pinv(M) * M * pinv(M) = pinv(M)</item>
+        /// <item>pinv(M) * M is hermitian</item>
+        /// <item>M * pinv(M) is hermitian</item>
+        /// </list>
+        /// pinv uses LAPACK's function svd internally. Any singular values less than 
+        /// tolerance will be set to zero. If tolerance is less than zero, the following equation 
+        /// is used as default: \\
+        /// tol = length(M) * norm(M) * Double.epsilon \\
+        /// with 
+        /// <list type="bullet">
+        /// <item>length(M) - the longest dimension of M</item>
+        /// <item>norm(M) being the largest singular value of M, </item>
+        /// <item>Double.epsilon - the smallest constructable double precision number greater than zero</item>
+        /// </list>
+        /// </remarks>
+        public static ILRetArray< complex > pinv(ILInArray< complex > M,  complex tolerance) {
+            using (ILScope.Enter(M)) {
+                // let svd check the dimensions! 
+                //if (M.Dimensions.NumberOfDimensions > 2)
+                //   throw new ILDimensionMismatchException("pinv: ...");
+
+                // in order to use the cheap packed version of svd, the matrix must be m x n with m > n! 
+                if (M.Size[0] < M.Size[1]) {
+                    return conj(pinv(conj(M.T), tolerance)).T;
+                }
+                if (M.IsScalar)
+                    return  new complex(1,0) / M;
+
+                ILArray< complex> U = empty< complex>(ILSize.Empty00);
+                ILArray< complex> V = empty< complex>(ILSize.Empty00);
+                ILArray< double> S = svd(M, U, V, true, false);
+
+                int m = M.Size[0];
+                int n = M.Size[1];
+
+                ILArray< double> s;
+                switch (m) {
+                    case 0:
+                        s = zeros< double>(ILSize.Scalar1_1);
+                        break;
+                    case 1:
+                        s = S[0];
+                        break;
+                    default:
+                        s = diag< double>(S);
+                        break;
+                }
+                if (tolerance < 0) {
+                    tolerance = ( complex)(M.Size.Longest * max(s).GetValue(0) *  ILMath.MachineParameterDouble.eps);
+                }
+                // sum vector elements: s is dense vector returned from svd
+                int count = (int)sum(s > ( double)tolerance);
+
+                ILArray< complex> Ret = empty< complex>(ILSize.Empty00);
+                if (count == 0)
+                    S.a = zeros< double>(new ILSize(n, m));
+                else {
+                    ILArray< double> OneVec = array< double>( 1.0, count, 1);
+
+                    S.a = diag(divide(OneVec, s[r(0,count - 1)]));
+                    U = conj(U[":;0:" + (count - 1)].T);
+                    Ret = multiply(multiply(V[":;0:" + (count - 1)], real2complex(S)), U);
+                }
+                return Ret;
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+   }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/pol2cart.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/pol2cart.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/pol2cart.cs	(revision 9102)
@@ -0,0 +1,93 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace ILNumerics {
+
+    public partial class ILMath {
+        /// <summary>
+        /// Transform polar/ cylindrical coordinates into scalar coordinates
+        /// </summary>
+        /// <param name="theta">Angle to x axis</param>
+        /// <param name="radius">Radius from z axis</param>
+        /// <param name="Z">Height</param>
+        /// <param name="outY">If on entry not null, the Y components are returned in outY</param>
+        /// <param name="outZ">If on entry not null, the Z components are returned in outZ</param>
+        /// <returns>X component, Y and Z are returned as out parameter if requested</returns>
+        /// <remarks>Theta, radius and Z must be of the same size or either one may be scalar. 
+        /// Scalar coordinate arrays returned are of the same size then the input arrays.</remarks>
+        public static ILRetArray<double> pol2cart(ILInArray<double> theta, ILInArray<double> radius, ILInArray<double> Z
+                                                   ,ILOutArray<double> outY, ILOutArray<double> outZ) {
+            using (ILScope.Enter(theta, radius, Z)) {
+                if (!object.Equals(outY,null))
+                    outY.a = radius * sin(theta); 
+                if (!object.Equals(outZ,null))
+                    outZ.a = Z.C; 
+                return radius * cos(theta); 
+            }
+        }
+
+        /// <summary>
+        /// Transform polar/ cylindrical coordinates into scalar coordinates
+        /// </summary>
+        /// <param name="theta">Angle to x axis</param>
+        /// <param name="radius">Radius from z axis</param>
+        /// <param name="Z">Height</param>
+        /// <param name="outY">If on entry not null, the Y components are returned in outY</param>
+        /// <param name="outZ">If on entry not null, the Z components are returned in outZ</param>
+        /// <returns>X component, Y and Z are returned as out parameter if requested</returns>
+        /// <remarks>Theta, radius and Z must be of the same size or either one may be scalar. 
+        /// Scalar coordinate arrays returned are of the same size then the input arrays.</remarks>
+        public static ILRetArray<float> pol2cart( ILInArray<float> theta, ILInArray<float> radius, ILInArray<float> Z
+                                                   , ILOutArray<float> outY, ILOutArray<float> outZ) {
+            using (ILScope.Enter(theta, radius, Z)) {
+                if (!object.Equals(outY, null))
+                    outY.a = radius * sin(theta);
+                if (!object.Equals(outZ, null))
+                    outZ.a = Z.C;
+                return radius * cos(theta);
+            }
+        }
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/pow.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/pow.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/pow.cs	(revision 9102)
@@ -0,0 +1,5111 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using ILNumerics;
+using ILNumerics.Misc;
+using ILNumerics.Storage;
+using ILNumerics.Native;
+using ILNumerics.Exceptions;
+
+
+namespace ILNumerics {
+
+    public partial class ILMath {
+
+        private static byte saturateBytePow( byte a, byte b ) {
+            return saturateByte(Math.Pow(a, b));
+        }
+        private static int saturateInt32Pow( int a, int b ) {
+            return saturateInt32(Math.Pow(a, b));
+        }
+        private static long saturateInt64Pow( long a, long b ) {
+            return saturateInt64(Math.Pow(a, b));
+        }
+       
+
+        
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>Power elements</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Array with elementwise result of A <sup>B</sup></returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<Int64>  pow(ILInArray<Int64> A, ILInArray<Int64> B) {
+            using (ILScope.Enter(A,B)) {
+                int outLen; 
+                BinOpItMode mode; 
+                Int64 [] retArr;
+                Int64 [] arrA = A.GetArrayForRead();
+                Int64[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size; 
+                    if (B.IsScalar) {
+                       
+                        return new  ILRetArray<Int64> (new  Int64 [1]{ saturateInt64Pow (A.GetValue(0)  , B.GetValue(0))}, A.Size);
+                    } else if (B.IsEmpty) {
+                        return  ILRetArray<Int64>.empty(outDims); 
+                    } else {
+                        outLen = outDims.NumberOfElements; 
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< Int64 > (outLen);
+                            mode = BinOpItMode.SAN; 
+                        } else {
+                            mode = BinOpItMode.SAI; 
+                        }
+                    }
+                } else {
+                    outDims = A.Size; 
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return  ILRetArray<Int64>.empty(A.Size);  
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< Int64 > (outLen);
+                            mode = BinOpItMode.ASN; 
+                        } else {
+                            mode = BinOpItMode.ASI; 
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  powEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (A.TryGetStorage4InplaceOp(out retArr)) 
+                            mode  = BinOpItMode.AAIA; 
+                        else if (B.TryGetStorage4InplaceOp(out retArr)) 
+                            mode = BinOpItMode.AAIB; 
+                        else {
+                            retArr = ILMemoryPool.Pool.New< Int64 > (outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<Int64> retStorage = new ILDenseStorage<Int64>(retArr, outDims);
+                int i = 0, workerCount = 1; 
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    Int64* cp = (Int64*)range.Item5 + range.Item1;
+                    Int64 scalar;
+                    int j = range.Item2; 
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           Int64* bp = ((Int64*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                                cp[0] =  saturateInt64Pow (cp[0]  , bp[0]);
+                                cp[1] =  saturateInt64Pow (cp[1]  , bp[1]);
+                                cp[2] =  saturateInt64Pow (cp[2]  , bp[2]);
+                                cp[3] =  saturateInt64Pow (cp[3]  , bp[3]);
+                                cp[4] =  saturateInt64Pow (cp[4]  , bp[4]);
+                                cp[5] =  saturateInt64Pow (cp[5]  , bp[5]);
+                                cp[6] =  saturateInt64Pow (cp[6]  , bp[6]);
+                                cp[7] =  saturateInt64Pow (cp[7]  , bp[7]);
+                                cp[8] =  saturateInt64Pow (cp[8]  , bp[8]);
+                                cp[9] =  saturateInt64Pow (cp[9]  , bp[9]);
+                                cp[10] =  saturateInt64Pow (cp[10]  , bp[10]);
+                                cp[11] =  saturateInt64Pow (cp[11]  , bp[11]);
+                                cp[12] =  saturateInt64Pow (cp[12]  , bp[12]);
+                                cp[13] =  saturateInt64Pow (cp[13]  , bp[13]);
+                                cp[14] =  saturateInt64Pow (cp[14]  , bp[14]);
+                                cp[15] =  saturateInt64Pow (cp[15]  , bp[15]);
+                                cp[16] =  saturateInt64Pow (cp[16]  , bp[16]);
+                                cp[17] =  saturateInt64Pow (cp[17]  , bp[17]);
+                                cp[18] =  saturateInt64Pow (cp[18]  , bp[18]);
+                                cp[19] =  saturateInt64Pow (cp[19]  , bp[19]);
+                                cp[20] =  saturateInt64Pow (cp[20]  , bp[20]);
+                                cp += 21; bp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt64Pow (*cp  , *bp);
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           Int64* ap = ((Int64*)range.Item3 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt64Pow (ap[0]  , cp[0]);
+                                cp[1] =  saturateInt64Pow (ap[1]  , cp[1]);
+                                cp[2] =  saturateInt64Pow (ap[2]  , cp[2]);
+                                cp[3] =  saturateInt64Pow (ap[3]  , cp[3]);
+                                cp[4] =  saturateInt64Pow (ap[4]  , cp[4]);
+                                cp[5] =  saturateInt64Pow (ap[5]  , cp[5]);
+                                cp[6] =  saturateInt64Pow (ap[6]  , cp[6]);
+                                cp[7] =  saturateInt64Pow (ap[7]  , cp[7]);
+                                cp[8] =  saturateInt64Pow (ap[8]  , cp[8]);
+                                cp[9] =  saturateInt64Pow (ap[9]  , cp[9]);
+                                cp[10] =  saturateInt64Pow (ap[10]  , cp[10]);
+                                cp[11] =  saturateInt64Pow (ap[11]  , cp[11]);
+                                cp[12] =  saturateInt64Pow (ap[12]  , cp[12]);
+                                cp[13] =  saturateInt64Pow (ap[13]  , cp[13]);
+                                cp[14] =  saturateInt64Pow (ap[14]  , cp[14]);
+                                cp[15] =  saturateInt64Pow (ap[15]  , cp[15]);
+                                cp[16] =  saturateInt64Pow (ap[16]  , cp[16]);
+                                cp[17] =  saturateInt64Pow (ap[17]  , cp[17]);
+                                cp[18] =  saturateInt64Pow (ap[18]  , cp[18]);
+                                cp[19] =  saturateInt64Pow (ap[19]  , cp[19]);
+                                cp[20] =  saturateInt64Pow (ap[20]  , cp[20]);
+                                ap += 21; cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt64Pow (*ap  , *cp);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((Int64*)range.Item3 + range.Item1);
+                            bp = ((Int64*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt64Pow (ap[0]  , bp[0]);
+                                cp[1] =  saturateInt64Pow (ap[1]  , bp[1]);
+                                cp[2] =  saturateInt64Pow (ap[2]  , bp[2]);
+                                cp[3] =  saturateInt64Pow (ap[3]  , bp[3]);
+                                cp[4] =  saturateInt64Pow (ap[4]  , bp[4]);
+                                cp[5] =  saturateInt64Pow (ap[5]  , bp[5]);
+                                cp[6] =  saturateInt64Pow (ap[6]  , bp[6]);
+                                cp[7] =  saturateInt64Pow (ap[7]  , bp[7]);
+                                cp[8] =  saturateInt64Pow (ap[8]  , bp[8]);
+                                cp[9] =  saturateInt64Pow (ap[9]  , bp[9]);
+                                cp[10] =  saturateInt64Pow (ap[10]  , bp[10]);
+                                cp[11] =  saturateInt64Pow (ap[11]  , bp[11]);
+                                cp[12] =  saturateInt64Pow (ap[12]  , bp[12]);
+                                cp[13] =  saturateInt64Pow (ap[13]  , bp[13]);
+                                cp[14] =  saturateInt64Pow (ap[14]  , bp[14]);
+                                cp[15] =  saturateInt64Pow (ap[15]  , bp[15]);
+                                cp[16] =  saturateInt64Pow (ap[16]  , bp[16]);
+                                cp[17] =  saturateInt64Pow (ap[17]  , bp[17]);
+                                cp[18] =  saturateInt64Pow (ap[18]  , bp[18]);
+                                cp[19] =  saturateInt64Pow (ap[19]  , bp[19]);
+                                cp[20] =  saturateInt64Pow (ap[20]  , bp[20]);
+                                ap+=21; bp+=21; cp+=21; j-=21;
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt64Pow (*ap  , *bp);
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((Int64*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt64Pow (cp[0]  , scalar);
+                                cp[1] =  saturateInt64Pow (cp[1]  , scalar);
+                                cp[2] =  saturateInt64Pow (cp[2]  , scalar);
+                                cp[3] =  saturateInt64Pow (cp[3]  , scalar);
+                                cp[4] =  saturateInt64Pow (cp[4]  , scalar);
+                                cp[5] =  saturateInt64Pow (cp[5]  , scalar);
+                                cp[6] =  saturateInt64Pow (cp[6]  , scalar);
+                                cp[7] =  saturateInt64Pow (cp[7]  , scalar);
+                                cp[8] =  saturateInt64Pow (cp[8]  , scalar);
+                                cp[9] =  saturateInt64Pow (cp[9]  , scalar);
+                                cp[10] =  saturateInt64Pow (cp[10]  , scalar);
+                                cp[11] =  saturateInt64Pow (cp[11]  , scalar);
+                                cp[12] =  saturateInt64Pow (cp[12]  , scalar);
+                                cp[13] =  saturateInt64Pow (cp[13]  , scalar);
+                                cp[14] =  saturateInt64Pow (cp[14]  , scalar);
+                                cp[15] =  saturateInt64Pow (cp[15]  , scalar);
+                                cp[16] =  saturateInt64Pow (cp[16]  , scalar);
+                                cp[17] =  saturateInt64Pow (cp[17]  , scalar);
+                                cp[18] =  saturateInt64Pow (cp[18]  , scalar);
+                                cp[19] =  saturateInt64Pow (cp[19]  , scalar);
+                                cp[20] =  saturateInt64Pow (cp[20]  , scalar);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt64Pow (*cp  , scalar);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((Int64*)range.Item3 + range.Item1);
+                            scalar = *((Int64*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt64Pow (ap[0]  , scalar);
+                                cp[1] =  saturateInt64Pow (ap[1]  , scalar);
+                                cp[2] =  saturateInt64Pow (ap[2]  , scalar);
+                                cp[3] =  saturateInt64Pow (ap[3]  , scalar);
+                                cp[4] =  saturateInt64Pow (ap[4]  , scalar);
+                                cp[5] =  saturateInt64Pow (ap[5]  , scalar);
+                                cp[6] =  saturateInt64Pow (ap[6]  , scalar);
+                                cp[7] =  saturateInt64Pow (ap[7]  , scalar);
+                                cp[8] =  saturateInt64Pow (ap[8]  , scalar);
+                                cp[9] =  saturateInt64Pow (ap[9]  , scalar);
+                                cp[10] =  saturateInt64Pow (ap[10]  , scalar);
+                                cp[11] =  saturateInt64Pow (ap[11]  , scalar);
+                                cp[12] =  saturateInt64Pow (ap[12]  , scalar);
+                                cp[13] =  saturateInt64Pow (ap[13]  , scalar);
+                                cp[14] =  saturateInt64Pow (ap[14]  , scalar);
+                                cp[15] =  saturateInt64Pow (ap[15]  , scalar);
+                                cp[16] =  saturateInt64Pow (ap[16]  , scalar);
+                                cp[17] =  saturateInt64Pow (ap[17]  , scalar);
+                                cp[18] =  saturateInt64Pow (ap[18]  , scalar);
+                                cp[19] =  saturateInt64Pow (ap[19]  , scalar);
+                                cp[20] =  saturateInt64Pow (ap[20]  , scalar);
+                                ap+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt64Pow (*ap  , scalar);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((Int64*)range.Item3);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt64Pow (scalar  , cp[0]);
+                                cp[1] =  saturateInt64Pow (scalar  , cp[1]);
+                                cp[2] =  saturateInt64Pow (scalar  , cp[2]);
+                                cp[3] =  saturateInt64Pow (scalar  , cp[3]);
+                                cp[4] =  saturateInt64Pow (scalar  , cp[4]);
+                                cp[5] =  saturateInt64Pow (scalar  , cp[5]);
+                                cp[6] =  saturateInt64Pow (scalar  , cp[6]);
+                                cp[7] =  saturateInt64Pow (scalar  , cp[7]);
+                                cp[8] =  saturateInt64Pow (scalar  , cp[8]);
+                                cp[9] =  saturateInt64Pow (scalar  , cp[9]);
+                                cp[10] =  saturateInt64Pow (scalar  , cp[10]);
+                                cp[11] =  saturateInt64Pow (scalar  , cp[11]);
+                                cp[12] =  saturateInt64Pow (scalar  , cp[12]);
+                                cp[13] =  saturateInt64Pow (scalar  , cp[13]);
+                                cp[14] =  saturateInt64Pow (scalar  , cp[14]);
+                                cp[15] =  saturateInt64Pow (scalar  , cp[15]);
+                                cp[16] =  saturateInt64Pow (scalar  , cp[16]);
+                                cp[17] =  saturateInt64Pow (scalar  , cp[17]);
+                                cp[18] =  saturateInt64Pow (scalar  , cp[18]);
+                                cp[19] =  saturateInt64Pow (scalar  , cp[19]);
+                                cp[20] =  saturateInt64Pow (scalar  , cp[20]);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt64Pow (scalar  , *cp);
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((Int64*)range.Item3);
+                            bp = ((Int64*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt64Pow (scalar  , bp[0]);
+                                cp[1] =  saturateInt64Pow (scalar  , bp[1]);
+                                cp[2] =  saturateInt64Pow (scalar  , bp[2]);
+                                cp[3] =  saturateInt64Pow (scalar  , bp[3]);
+                                cp[4] =  saturateInt64Pow (scalar  , bp[4]);
+                                cp[5] =  saturateInt64Pow (scalar  , bp[5]);
+                                cp[6] =  saturateInt64Pow (scalar  , bp[6]);
+                                cp[7] =  saturateInt64Pow (scalar  , bp[7]);
+                                cp[8] =  saturateInt64Pow (scalar  , bp[8]);
+                                cp[9] =  saturateInt64Pow (scalar  , bp[9]);
+                                cp[10] =  saturateInt64Pow (scalar  , bp[10]);
+                                cp[11] =  saturateInt64Pow (scalar  , bp[11]);
+                                cp[12] =  saturateInt64Pow (scalar  , bp[12]);
+                                cp[13] =  saturateInt64Pow (scalar  , bp[13]);
+                                cp[14] =  saturateInt64Pow (scalar  , bp[14]);
+                                cp[15] =  saturateInt64Pow (scalar  , bp[15]);
+                                cp[16] =  saturateInt64Pow (scalar  , bp[16]);
+                                cp[17] =  saturateInt64Pow (scalar  , bp[17]);
+                                cp[18] =  saturateInt64Pow (scalar  , bp[18]);
+                                cp[19] =  saturateInt64Pow (scalar  , bp[19]);
+                                cp[20] =  saturateInt64Pow (scalar  , bp[20]);
+                                bp+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt64Pow (scalar  , *bp);
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work 
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                
+                fixed ( Int64* arrAP = arrA)
+                fixed ( Int64* arrBP = arrB)
+                fixed ( Int64* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range 
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new  ILRetArray< Int64>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<Int64>  powEx(ILInArray<Int64> A, ILInArray<Int64> B) {
+            //using (ILScope.Enter(A, B)) { we cannot start a new scope here, since this would prevent A and B to be used implace if applicable
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<Int64>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<Int64>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<Int64>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                dim = -(dim - 1);  // 0 -> 1, 1 -> 0
+                #endregion
+
+                #region parameter preparation
+               
+                Int64[] retArr;
+               
+                Int64[] arrA = A.GetArrayForRead();
+               
+                Int64[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int workItemMultiplierLenA;
+                int workItemMultiplierLenB;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<Int64>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    workItemMultiplierLenB = outDims[0]; 
+                    workItemMultiplierLenA = dim;  // 0 for column, 1 for row vector
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<Int64>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    workItemMultiplierLenB = dim;  // 0 for column, 1 for row vector
+                    workItemMultiplierLenA = outDims[0]; 
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one singleton dimension in either A or B");
+                }
+                int itLen = outDims[0]; // (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<Int64> retStorage = new ILDenseStorage<Int64>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    Int64* ap;
+                   
+                    Int64* bp;
+                   
+                    Int64* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            if (dim == 0) {
+                                bp = (Int64*)range.Item3;
+                                cp = (Int64*)range.Item4; 
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (Int64*)range.Item2;
+                                    int l = itLen; 
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt64Pow (ap[0]  , bp[0]);
+                                        cp[1] =  saturateInt64Pow (ap[1]  , bp[1]);
+                                        cp[2] =  saturateInt64Pow (ap[2]  , bp[2]);
+                                        cp[3] =  saturateInt64Pow (ap[3]  , bp[3]);
+                                        cp[4] =  saturateInt64Pow (ap[4]  , bp[4]);
+                                        cp[5] =  saturateInt64Pow (ap[5]  , bp[5]);
+                                        cp[6] =  saturateInt64Pow (ap[6]  , bp[6]);
+                                        cp[7] =  saturateInt64Pow (ap[7]  , bp[7]);
+                                        cp[8] =  saturateInt64Pow (ap[8]  , bp[8]);
+                                        cp[9] =  saturateInt64Pow (ap[9]  , bp[9]);
+                                        cp[10] =  saturateInt64Pow (ap[10]  , bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =  saturateInt64Pow (*ap++  , *bp++);
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                ap = (Int64*)range.Item2;
+                                bp = (Int64*)range.Item3;
+                                cp = (Int64*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   Int64 val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt64Pow (val  , bp[0]);
+                                        cp[1] =  saturateInt64Pow (val  , bp[1]);
+                                        cp[2] =  saturateInt64Pow (val  , bp[2]);
+                                        cp[3] =  saturateInt64Pow (val  , bp[3]);
+                                        cp[4] =  saturateInt64Pow (val  , bp[4]);
+                                        cp[5] =  saturateInt64Pow (val  , bp[5]);
+                                        cp[6] =  saturateInt64Pow (val  , bp[6]);
+                                        cp[7] =  saturateInt64Pow (val  , bp[7]);
+                                        cp[8] =  saturateInt64Pow (val  , bp[8]);
+                                        cp[9] =  saturateInt64Pow (val  , bp[9]);
+                                        cp[10] =  saturateInt64Pow (val  , bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11; 
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =  saturateInt64Pow (val  , *bp++);
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            if (dim == 0) {
+                                cp = (Int64*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (Int64*)range.Item2;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt64Pow (ap[0]  , cp[0]);
+                                        cp[1] =  saturateInt64Pow (ap[1]  , cp[1]);
+                                        cp[2] =  saturateInt64Pow (ap[2]  , cp[2]);
+                                        cp[3] =  saturateInt64Pow (ap[3]  , cp[3]);
+                                        cp[4] =  saturateInt64Pow (ap[4]  , cp[4]);
+                                        cp[5] =  saturateInt64Pow (ap[5]  , cp[5]);
+                                        cp[6] =  saturateInt64Pow (ap[6]  , cp[6]);
+                                        cp[7] =  saturateInt64Pow (ap[7]  , cp[7]);
+                                        cp[8] =  saturateInt64Pow (ap[8]  , cp[8]);
+                                        cp[9] =  saturateInt64Pow (ap[9]  , cp[9]);
+                                        cp[10] =  saturateInt64Pow (ap[10]  , cp[10]);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt64Pow (*ap++  , *cp);
+                                        cp++; 
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                cp = (Int64*)range.Item4;
+                                ap = (Int64*)range.Item2;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    Int64 val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt64Pow (val  , cp[0]);
+                                        cp[1] =  saturateInt64Pow (val  , cp[1]);
+                                        cp[2] =  saturateInt64Pow (val  , cp[2]);
+                                        cp[3] =  saturateInt64Pow (val  , cp[3]);
+                                        cp[4] =  saturateInt64Pow (val  , cp[4]);
+                                        cp[5] =  saturateInt64Pow (val  , cp[5]);
+                                        cp[6] =  saturateInt64Pow (val  , cp[6]);
+                                        cp[7] =  saturateInt64Pow (val  , cp[7]);
+                                        cp[8] =  saturateInt64Pow (val  , cp[8]);
+                                        cp[9] =  saturateInt64Pow (val  , cp[9]);
+                                        cp[10] =  saturateInt64Pow (val  , cp[10]);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt64Pow (val  , *cp);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            if (dim == 0) {
+                                ap = (Int64*)range.Item2;
+                                cp = (Int64*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (Int64*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt64Pow (ap[0]  , bp[0]);
+                                        cp[1] =  saturateInt64Pow (ap[1]  , bp[1]);
+                                        cp[2] =  saturateInt64Pow (ap[2]  , bp[2]);
+                                        cp[3] =  saturateInt64Pow (ap[3]  , bp[3]);
+                                        cp[4] =  saturateInt64Pow (ap[4]  , bp[4]);
+                                        cp[5] =  saturateInt64Pow (ap[5]  , bp[5]);
+                                        cp[6] =  saturateInt64Pow (ap[6]  , bp[6]);
+                                        cp[7] =  saturateInt64Pow (ap[7]  , bp[7]);
+                                        cp[8] =  saturateInt64Pow (ap[8]  , bp[8]);
+                                        cp[9] =  saturateInt64Pow (ap[9]  , bp[9]);
+                                        cp[10] =  saturateInt64Pow (ap[10]  , bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt64Pow (*ap  , *bp);
+                                        ap++;
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                ap = (Int64*)range.Item2;
+                                bp = (Int64*)range.Item3;
+                                cp = (Int64*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   Int64 val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt64Pow (ap[0]  , val);
+                                        cp[1] =  saturateInt64Pow (ap[1]  , val);
+                                        cp[2] =  saturateInt64Pow (ap[2]  , val);
+                                        cp[3] =  saturateInt64Pow (ap[3]  , val);
+                                        cp[4] =  saturateInt64Pow (ap[4]  , val);
+                                        cp[5] =  saturateInt64Pow (ap[5]  , val);
+                                        cp[6] =  saturateInt64Pow (ap[6]  , val);
+                                        cp[7] =  saturateInt64Pow (ap[7]  , val);
+                                        cp[8] =  saturateInt64Pow (ap[8]  , val);
+                                        cp[9] =  saturateInt64Pow (ap[9]  , val);
+                                        cp[10] =  saturateInt64Pow (ap[10]  , val);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt64Pow (*ap  , val);
+                                        ap++;
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            if (dim == 0) {
+                                cp = (Int64*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (Int64*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt64Pow (cp[0]  , bp[0]);
+                                        cp[1] =  saturateInt64Pow (cp[1]  , bp[1]);
+                                        cp[2] =  saturateInt64Pow (cp[2]  , bp[2]);
+                                        cp[3] =  saturateInt64Pow (cp[3]  , bp[3]);
+                                        cp[4] =  saturateInt64Pow (cp[4]  , bp[4]);
+                                        cp[5] =  saturateInt64Pow (cp[5]  , bp[5]);
+                                        cp[6] =  saturateInt64Pow (cp[6]  , bp[6]);
+                                        cp[7] =  saturateInt64Pow (cp[7]  , bp[7]);
+                                        cp[8] =  saturateInt64Pow (cp[8]  , bp[8]);
+                                        cp[9] =  saturateInt64Pow (cp[9]  , bp[9]);
+                                        cp[10] =  saturateInt64Pow (cp[10]  , bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt64Pow (*cp  , *bp);
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                bp = (Int64*)range.Item3;
+                                cp = (Int64*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    Int64 val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt64Pow (cp[0]  , val);
+                                        cp[1] =  saturateInt64Pow (cp[1]  , val);
+                                        cp[2] =  saturateInt64Pow (cp[2]  , val);
+                                        cp[3] =  saturateInt64Pow (cp[3]  , val);
+                                        cp[4] =  saturateInt64Pow (cp[4]  , val);
+                                        cp[5] =  saturateInt64Pow (cp[5]  , val);
+                                        cp[6] =  saturateInt64Pow (cp[6]  , val);
+                                        cp[7] =  saturateInt64Pow (cp[7]  , val);
+                                        cp[8] =  saturateInt64Pow (cp[8]  , val);
+                                        cp[9] =  saturateInt64Pow (cp[9]  , val);
+                                        cp[10] =  saturateInt64Pow (cp[10]  , val);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l --> 0) {
+                                        *cp =  saturateInt64Pow (*cp  , val);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outDims.NumberOfElements >= Settings.s_minParallelElement1Count
+                    && outDims[1] > 1) {
+                        if (outDims[1] > workItemCount) {
+                        workItemLength = outDims[1] / workItemCount;
+                    } else {
+                        workItemLength = outDims[1] / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outDims[1];
+                    workItemCount = 1;
+                }
+
+                fixed ( Int64* arrAP = arrA)
+                fixed ( Int64* arrBP = arrB)
+                fixed ( Int64* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, IntPtr, IntPtr, IntPtr> range = new Tuple<int, IntPtr, IntPtr, IntPtr>
+                               (workItemLength
+                               , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                               , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                               , (IntPtr)(retArrP + i * outDims[0] * workItemLength)); 
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, IntPtr, IntPtr, IntPtr>
+                                (outDims[1] - i * workItemLength
+                                , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                                , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                                , (IntPtr)(retArrP + i * outDims[0] * workItemLength)));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<Int64>(retStorage);
+            //}  // no scopes here! it disables implace operations
+        }
+
+        /// <summary>Power elements</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Array with elementwise result of A <sup>B</sup></returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<Int32>  pow(ILInArray<Int32> A, ILInArray<Int32> B) {
+            using (ILScope.Enter(A,B)) {
+                int outLen; 
+                BinOpItMode mode; 
+                Int32 [] retArr;
+                Int32 [] arrA = A.GetArrayForRead();
+                Int32[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size; 
+                    if (B.IsScalar) {
+                       
+                        return new  ILRetArray<Int32> (new  Int32 [1]{ saturateInt32Pow (A.GetValue(0)  , B.GetValue(0))}, A.Size);
+                    } else if (B.IsEmpty) {
+                        return  ILRetArray<Int32>.empty(outDims); 
+                    } else {
+                        outLen = outDims.NumberOfElements; 
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< Int32 > (outLen);
+                            mode = BinOpItMode.SAN; 
+                        } else {
+                            mode = BinOpItMode.SAI; 
+                        }
+                    }
+                } else {
+                    outDims = A.Size; 
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return  ILRetArray<Int32>.empty(A.Size);  
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< Int32 > (outLen);
+                            mode = BinOpItMode.ASN; 
+                        } else {
+                            mode = BinOpItMode.ASI; 
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  powEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (A.TryGetStorage4InplaceOp(out retArr)) 
+                            mode  = BinOpItMode.AAIA; 
+                        else if (B.TryGetStorage4InplaceOp(out retArr)) 
+                            mode = BinOpItMode.AAIB; 
+                        else {
+                            retArr = ILMemoryPool.Pool.New< Int32 > (outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<Int32> retStorage = new ILDenseStorage<Int32>(retArr, outDims);
+                int i = 0, workerCount = 1; 
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    Int32* cp = (Int32*)range.Item5 + range.Item1;
+                    Int32 scalar;
+                    int j = range.Item2; 
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           Int32* bp = ((Int32*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                                cp[0] =  saturateInt32Pow (cp[0]  , bp[0]);
+                                cp[1] =  saturateInt32Pow (cp[1]  , bp[1]);
+                                cp[2] =  saturateInt32Pow (cp[2]  , bp[2]);
+                                cp[3] =  saturateInt32Pow (cp[3]  , bp[3]);
+                                cp[4] =  saturateInt32Pow (cp[4]  , bp[4]);
+                                cp[5] =  saturateInt32Pow (cp[5]  , bp[5]);
+                                cp[6] =  saturateInt32Pow (cp[6]  , bp[6]);
+                                cp[7] =  saturateInt32Pow (cp[7]  , bp[7]);
+                                cp[8] =  saturateInt32Pow (cp[8]  , bp[8]);
+                                cp[9] =  saturateInt32Pow (cp[9]  , bp[9]);
+                                cp[10] =  saturateInt32Pow (cp[10]  , bp[10]);
+                                cp[11] =  saturateInt32Pow (cp[11]  , bp[11]);
+                                cp[12] =  saturateInt32Pow (cp[12]  , bp[12]);
+                                cp[13] =  saturateInt32Pow (cp[13]  , bp[13]);
+                                cp[14] =  saturateInt32Pow (cp[14]  , bp[14]);
+                                cp[15] =  saturateInt32Pow (cp[15]  , bp[15]);
+                                cp[16] =  saturateInt32Pow (cp[16]  , bp[16]);
+                                cp[17] =  saturateInt32Pow (cp[17]  , bp[17]);
+                                cp[18] =  saturateInt32Pow (cp[18]  , bp[18]);
+                                cp[19] =  saturateInt32Pow (cp[19]  , bp[19]);
+                                cp[20] =  saturateInt32Pow (cp[20]  , bp[20]);
+                                cp += 21; bp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt32Pow (*cp  , *bp);
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           Int32* ap = ((Int32*)range.Item3 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt32Pow (ap[0]  , cp[0]);
+                                cp[1] =  saturateInt32Pow (ap[1]  , cp[1]);
+                                cp[2] =  saturateInt32Pow (ap[2]  , cp[2]);
+                                cp[3] =  saturateInt32Pow (ap[3]  , cp[3]);
+                                cp[4] =  saturateInt32Pow (ap[4]  , cp[4]);
+                                cp[5] =  saturateInt32Pow (ap[5]  , cp[5]);
+                                cp[6] =  saturateInt32Pow (ap[6]  , cp[6]);
+                                cp[7] =  saturateInt32Pow (ap[7]  , cp[7]);
+                                cp[8] =  saturateInt32Pow (ap[8]  , cp[8]);
+                                cp[9] =  saturateInt32Pow (ap[9]  , cp[9]);
+                                cp[10] =  saturateInt32Pow (ap[10]  , cp[10]);
+                                cp[11] =  saturateInt32Pow (ap[11]  , cp[11]);
+                                cp[12] =  saturateInt32Pow (ap[12]  , cp[12]);
+                                cp[13] =  saturateInt32Pow (ap[13]  , cp[13]);
+                                cp[14] =  saturateInt32Pow (ap[14]  , cp[14]);
+                                cp[15] =  saturateInt32Pow (ap[15]  , cp[15]);
+                                cp[16] =  saturateInt32Pow (ap[16]  , cp[16]);
+                                cp[17] =  saturateInt32Pow (ap[17]  , cp[17]);
+                                cp[18] =  saturateInt32Pow (ap[18]  , cp[18]);
+                                cp[19] =  saturateInt32Pow (ap[19]  , cp[19]);
+                                cp[20] =  saturateInt32Pow (ap[20]  , cp[20]);
+                                ap += 21; cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt32Pow (*ap  , *cp);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((Int32*)range.Item3 + range.Item1);
+                            bp = ((Int32*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt32Pow (ap[0]  , bp[0]);
+                                cp[1] =  saturateInt32Pow (ap[1]  , bp[1]);
+                                cp[2] =  saturateInt32Pow (ap[2]  , bp[2]);
+                                cp[3] =  saturateInt32Pow (ap[3]  , bp[3]);
+                                cp[4] =  saturateInt32Pow (ap[4]  , bp[4]);
+                                cp[5] =  saturateInt32Pow (ap[5]  , bp[5]);
+                                cp[6] =  saturateInt32Pow (ap[6]  , bp[6]);
+                                cp[7] =  saturateInt32Pow (ap[7]  , bp[7]);
+                                cp[8] =  saturateInt32Pow (ap[8]  , bp[8]);
+                                cp[9] =  saturateInt32Pow (ap[9]  , bp[9]);
+                                cp[10] =  saturateInt32Pow (ap[10]  , bp[10]);
+                                cp[11] =  saturateInt32Pow (ap[11]  , bp[11]);
+                                cp[12] =  saturateInt32Pow (ap[12]  , bp[12]);
+                                cp[13] =  saturateInt32Pow (ap[13]  , bp[13]);
+                                cp[14] =  saturateInt32Pow (ap[14]  , bp[14]);
+                                cp[15] =  saturateInt32Pow (ap[15]  , bp[15]);
+                                cp[16] =  saturateInt32Pow (ap[16]  , bp[16]);
+                                cp[17] =  saturateInt32Pow (ap[17]  , bp[17]);
+                                cp[18] =  saturateInt32Pow (ap[18]  , bp[18]);
+                                cp[19] =  saturateInt32Pow (ap[19]  , bp[19]);
+                                cp[20] =  saturateInt32Pow (ap[20]  , bp[20]);
+                                ap+=21; bp+=21; cp+=21; j-=21;
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt32Pow (*ap  , *bp);
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((Int32*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt32Pow (cp[0]  , scalar);
+                                cp[1] =  saturateInt32Pow (cp[1]  , scalar);
+                                cp[2] =  saturateInt32Pow (cp[2]  , scalar);
+                                cp[3] =  saturateInt32Pow (cp[3]  , scalar);
+                                cp[4] =  saturateInt32Pow (cp[4]  , scalar);
+                                cp[5] =  saturateInt32Pow (cp[5]  , scalar);
+                                cp[6] =  saturateInt32Pow (cp[6]  , scalar);
+                                cp[7] =  saturateInt32Pow (cp[7]  , scalar);
+                                cp[8] =  saturateInt32Pow (cp[8]  , scalar);
+                                cp[9] =  saturateInt32Pow (cp[9]  , scalar);
+                                cp[10] =  saturateInt32Pow (cp[10]  , scalar);
+                                cp[11] =  saturateInt32Pow (cp[11]  , scalar);
+                                cp[12] =  saturateInt32Pow (cp[12]  , scalar);
+                                cp[13] =  saturateInt32Pow (cp[13]  , scalar);
+                                cp[14] =  saturateInt32Pow (cp[14]  , scalar);
+                                cp[15] =  saturateInt32Pow (cp[15]  , scalar);
+                                cp[16] =  saturateInt32Pow (cp[16]  , scalar);
+                                cp[17] =  saturateInt32Pow (cp[17]  , scalar);
+                                cp[18] =  saturateInt32Pow (cp[18]  , scalar);
+                                cp[19] =  saturateInt32Pow (cp[19]  , scalar);
+                                cp[20] =  saturateInt32Pow (cp[20]  , scalar);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt32Pow (*cp  , scalar);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((Int32*)range.Item3 + range.Item1);
+                            scalar = *((Int32*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt32Pow (ap[0]  , scalar);
+                                cp[1] =  saturateInt32Pow (ap[1]  , scalar);
+                                cp[2] =  saturateInt32Pow (ap[2]  , scalar);
+                                cp[3] =  saturateInt32Pow (ap[3]  , scalar);
+                                cp[4] =  saturateInt32Pow (ap[4]  , scalar);
+                                cp[5] =  saturateInt32Pow (ap[5]  , scalar);
+                                cp[6] =  saturateInt32Pow (ap[6]  , scalar);
+                                cp[7] =  saturateInt32Pow (ap[7]  , scalar);
+                                cp[8] =  saturateInt32Pow (ap[8]  , scalar);
+                                cp[9] =  saturateInt32Pow (ap[9]  , scalar);
+                                cp[10] =  saturateInt32Pow (ap[10]  , scalar);
+                                cp[11] =  saturateInt32Pow (ap[11]  , scalar);
+                                cp[12] =  saturateInt32Pow (ap[12]  , scalar);
+                                cp[13] =  saturateInt32Pow (ap[13]  , scalar);
+                                cp[14] =  saturateInt32Pow (ap[14]  , scalar);
+                                cp[15] =  saturateInt32Pow (ap[15]  , scalar);
+                                cp[16] =  saturateInt32Pow (ap[16]  , scalar);
+                                cp[17] =  saturateInt32Pow (ap[17]  , scalar);
+                                cp[18] =  saturateInt32Pow (ap[18]  , scalar);
+                                cp[19] =  saturateInt32Pow (ap[19]  , scalar);
+                                cp[20] =  saturateInt32Pow (ap[20]  , scalar);
+                                ap+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt32Pow (*ap  , scalar);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((Int32*)range.Item3);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt32Pow (scalar  , cp[0]);
+                                cp[1] =  saturateInt32Pow (scalar  , cp[1]);
+                                cp[2] =  saturateInt32Pow (scalar  , cp[2]);
+                                cp[3] =  saturateInt32Pow (scalar  , cp[3]);
+                                cp[4] =  saturateInt32Pow (scalar  , cp[4]);
+                                cp[5] =  saturateInt32Pow (scalar  , cp[5]);
+                                cp[6] =  saturateInt32Pow (scalar  , cp[6]);
+                                cp[7] =  saturateInt32Pow (scalar  , cp[7]);
+                                cp[8] =  saturateInt32Pow (scalar  , cp[8]);
+                                cp[9] =  saturateInt32Pow (scalar  , cp[9]);
+                                cp[10] =  saturateInt32Pow (scalar  , cp[10]);
+                                cp[11] =  saturateInt32Pow (scalar  , cp[11]);
+                                cp[12] =  saturateInt32Pow (scalar  , cp[12]);
+                                cp[13] =  saturateInt32Pow (scalar  , cp[13]);
+                                cp[14] =  saturateInt32Pow (scalar  , cp[14]);
+                                cp[15] =  saturateInt32Pow (scalar  , cp[15]);
+                                cp[16] =  saturateInt32Pow (scalar  , cp[16]);
+                                cp[17] =  saturateInt32Pow (scalar  , cp[17]);
+                                cp[18] =  saturateInt32Pow (scalar  , cp[18]);
+                                cp[19] =  saturateInt32Pow (scalar  , cp[19]);
+                                cp[20] =  saturateInt32Pow (scalar  , cp[20]);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt32Pow (scalar  , *cp);
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((Int32*)range.Item3);
+                            bp = ((Int32*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateInt32Pow (scalar  , bp[0]);
+                                cp[1] =  saturateInt32Pow (scalar  , bp[1]);
+                                cp[2] =  saturateInt32Pow (scalar  , bp[2]);
+                                cp[3] =  saturateInt32Pow (scalar  , bp[3]);
+                                cp[4] =  saturateInt32Pow (scalar  , bp[4]);
+                                cp[5] =  saturateInt32Pow (scalar  , bp[5]);
+                                cp[6] =  saturateInt32Pow (scalar  , bp[6]);
+                                cp[7] =  saturateInt32Pow (scalar  , bp[7]);
+                                cp[8] =  saturateInt32Pow (scalar  , bp[8]);
+                                cp[9] =  saturateInt32Pow (scalar  , bp[9]);
+                                cp[10] =  saturateInt32Pow (scalar  , bp[10]);
+                                cp[11] =  saturateInt32Pow (scalar  , bp[11]);
+                                cp[12] =  saturateInt32Pow (scalar  , bp[12]);
+                                cp[13] =  saturateInt32Pow (scalar  , bp[13]);
+                                cp[14] =  saturateInt32Pow (scalar  , bp[14]);
+                                cp[15] =  saturateInt32Pow (scalar  , bp[15]);
+                                cp[16] =  saturateInt32Pow (scalar  , bp[16]);
+                                cp[17] =  saturateInt32Pow (scalar  , bp[17]);
+                                cp[18] =  saturateInt32Pow (scalar  , bp[18]);
+                                cp[19] =  saturateInt32Pow (scalar  , bp[19]);
+                                cp[20] =  saturateInt32Pow (scalar  , bp[20]);
+                                bp+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateInt32Pow (scalar  , *bp);
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work 
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                
+                fixed ( Int32* arrAP = arrA)
+                fixed ( Int32* arrBP = arrB)
+                fixed ( Int32* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range 
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new  ILRetArray< Int32>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<Int32>  powEx(ILInArray<Int32> A, ILInArray<Int32> B) {
+            //using (ILScope.Enter(A, B)) { we cannot start a new scope here, since this would prevent A and B to be used implace if applicable
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<Int32>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<Int32>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<Int32>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                dim = -(dim - 1);  // 0 -> 1, 1 -> 0
+                #endregion
+
+                #region parameter preparation
+               
+                Int32[] retArr;
+               
+                Int32[] arrA = A.GetArrayForRead();
+               
+                Int32[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int workItemMultiplierLenA;
+                int workItemMultiplierLenB;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<Int32>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    workItemMultiplierLenB = outDims[0]; 
+                    workItemMultiplierLenA = dim;  // 0 for column, 1 for row vector
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<Int32>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    workItemMultiplierLenB = dim;  // 0 for column, 1 for row vector
+                    workItemMultiplierLenA = outDims[0]; 
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one singleton dimension in either A or B");
+                }
+                int itLen = outDims[0]; // (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<Int32> retStorage = new ILDenseStorage<Int32>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    Int32* ap;
+                   
+                    Int32* bp;
+                   
+                    Int32* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            if (dim == 0) {
+                                bp = (Int32*)range.Item3;
+                                cp = (Int32*)range.Item4; 
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (Int32*)range.Item2;
+                                    int l = itLen; 
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt32Pow (ap[0]  , bp[0]);
+                                        cp[1] =  saturateInt32Pow (ap[1]  , bp[1]);
+                                        cp[2] =  saturateInt32Pow (ap[2]  , bp[2]);
+                                        cp[3] =  saturateInt32Pow (ap[3]  , bp[3]);
+                                        cp[4] =  saturateInt32Pow (ap[4]  , bp[4]);
+                                        cp[5] =  saturateInt32Pow (ap[5]  , bp[5]);
+                                        cp[6] =  saturateInt32Pow (ap[6]  , bp[6]);
+                                        cp[7] =  saturateInt32Pow (ap[7]  , bp[7]);
+                                        cp[8] =  saturateInt32Pow (ap[8]  , bp[8]);
+                                        cp[9] =  saturateInt32Pow (ap[9]  , bp[9]);
+                                        cp[10] =  saturateInt32Pow (ap[10]  , bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =  saturateInt32Pow (*ap++  , *bp++);
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                ap = (Int32*)range.Item2;
+                                bp = (Int32*)range.Item3;
+                                cp = (Int32*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   Int32 val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt32Pow (val  , bp[0]);
+                                        cp[1] =  saturateInt32Pow (val  , bp[1]);
+                                        cp[2] =  saturateInt32Pow (val  , bp[2]);
+                                        cp[3] =  saturateInt32Pow (val  , bp[3]);
+                                        cp[4] =  saturateInt32Pow (val  , bp[4]);
+                                        cp[5] =  saturateInt32Pow (val  , bp[5]);
+                                        cp[6] =  saturateInt32Pow (val  , bp[6]);
+                                        cp[7] =  saturateInt32Pow (val  , bp[7]);
+                                        cp[8] =  saturateInt32Pow (val  , bp[8]);
+                                        cp[9] =  saturateInt32Pow (val  , bp[9]);
+                                        cp[10] =  saturateInt32Pow (val  , bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11; 
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =  saturateInt32Pow (val  , *bp++);
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            if (dim == 0) {
+                                cp = (Int32*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (Int32*)range.Item2;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt32Pow (ap[0]  , cp[0]);
+                                        cp[1] =  saturateInt32Pow (ap[1]  , cp[1]);
+                                        cp[2] =  saturateInt32Pow (ap[2]  , cp[2]);
+                                        cp[3] =  saturateInt32Pow (ap[3]  , cp[3]);
+                                        cp[4] =  saturateInt32Pow (ap[4]  , cp[4]);
+                                        cp[5] =  saturateInt32Pow (ap[5]  , cp[5]);
+                                        cp[6] =  saturateInt32Pow (ap[6]  , cp[6]);
+                                        cp[7] =  saturateInt32Pow (ap[7]  , cp[7]);
+                                        cp[8] =  saturateInt32Pow (ap[8]  , cp[8]);
+                                        cp[9] =  saturateInt32Pow (ap[9]  , cp[9]);
+                                        cp[10] =  saturateInt32Pow (ap[10]  , cp[10]);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt32Pow (*ap++  , *cp);
+                                        cp++; 
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                cp = (Int32*)range.Item4;
+                                ap = (Int32*)range.Item2;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    Int32 val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt32Pow (val  , cp[0]);
+                                        cp[1] =  saturateInt32Pow (val  , cp[1]);
+                                        cp[2] =  saturateInt32Pow (val  , cp[2]);
+                                        cp[3] =  saturateInt32Pow (val  , cp[3]);
+                                        cp[4] =  saturateInt32Pow (val  , cp[4]);
+                                        cp[5] =  saturateInt32Pow (val  , cp[5]);
+                                        cp[6] =  saturateInt32Pow (val  , cp[6]);
+                                        cp[7] =  saturateInt32Pow (val  , cp[7]);
+                                        cp[8] =  saturateInt32Pow (val  , cp[8]);
+                                        cp[9] =  saturateInt32Pow (val  , cp[9]);
+                                        cp[10] =  saturateInt32Pow (val  , cp[10]);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt32Pow (val  , *cp);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            if (dim == 0) {
+                                ap = (Int32*)range.Item2;
+                                cp = (Int32*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (Int32*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt32Pow (ap[0]  , bp[0]);
+                                        cp[1] =  saturateInt32Pow (ap[1]  , bp[1]);
+                                        cp[2] =  saturateInt32Pow (ap[2]  , bp[2]);
+                                        cp[3] =  saturateInt32Pow (ap[3]  , bp[3]);
+                                        cp[4] =  saturateInt32Pow (ap[4]  , bp[4]);
+                                        cp[5] =  saturateInt32Pow (ap[5]  , bp[5]);
+                                        cp[6] =  saturateInt32Pow (ap[6]  , bp[6]);
+                                        cp[7] =  saturateInt32Pow (ap[7]  , bp[7]);
+                                        cp[8] =  saturateInt32Pow (ap[8]  , bp[8]);
+                                        cp[9] =  saturateInt32Pow (ap[9]  , bp[9]);
+                                        cp[10] =  saturateInt32Pow (ap[10]  , bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt32Pow (*ap  , *bp);
+                                        ap++;
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                ap = (Int32*)range.Item2;
+                                bp = (Int32*)range.Item3;
+                                cp = (Int32*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   Int32 val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt32Pow (ap[0]  , val);
+                                        cp[1] =  saturateInt32Pow (ap[1]  , val);
+                                        cp[2] =  saturateInt32Pow (ap[2]  , val);
+                                        cp[3] =  saturateInt32Pow (ap[3]  , val);
+                                        cp[4] =  saturateInt32Pow (ap[4]  , val);
+                                        cp[5] =  saturateInt32Pow (ap[5]  , val);
+                                        cp[6] =  saturateInt32Pow (ap[6]  , val);
+                                        cp[7] =  saturateInt32Pow (ap[7]  , val);
+                                        cp[8] =  saturateInt32Pow (ap[8]  , val);
+                                        cp[9] =  saturateInt32Pow (ap[9]  , val);
+                                        cp[10] =  saturateInt32Pow (ap[10]  , val);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt32Pow (*ap  , val);
+                                        ap++;
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            if (dim == 0) {
+                                cp = (Int32*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (Int32*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt32Pow (cp[0]  , bp[0]);
+                                        cp[1] =  saturateInt32Pow (cp[1]  , bp[1]);
+                                        cp[2] =  saturateInt32Pow (cp[2]  , bp[2]);
+                                        cp[3] =  saturateInt32Pow (cp[3]  , bp[3]);
+                                        cp[4] =  saturateInt32Pow (cp[4]  , bp[4]);
+                                        cp[5] =  saturateInt32Pow (cp[5]  , bp[5]);
+                                        cp[6] =  saturateInt32Pow (cp[6]  , bp[6]);
+                                        cp[7] =  saturateInt32Pow (cp[7]  , bp[7]);
+                                        cp[8] =  saturateInt32Pow (cp[8]  , bp[8]);
+                                        cp[9] =  saturateInt32Pow (cp[9]  , bp[9]);
+                                        cp[10] =  saturateInt32Pow (cp[10]  , bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateInt32Pow (*cp  , *bp);
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                bp = (Int32*)range.Item3;
+                                cp = (Int32*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    Int32 val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateInt32Pow (cp[0]  , val);
+                                        cp[1] =  saturateInt32Pow (cp[1]  , val);
+                                        cp[2] =  saturateInt32Pow (cp[2]  , val);
+                                        cp[3] =  saturateInt32Pow (cp[3]  , val);
+                                        cp[4] =  saturateInt32Pow (cp[4]  , val);
+                                        cp[5] =  saturateInt32Pow (cp[5]  , val);
+                                        cp[6] =  saturateInt32Pow (cp[6]  , val);
+                                        cp[7] =  saturateInt32Pow (cp[7]  , val);
+                                        cp[8] =  saturateInt32Pow (cp[8]  , val);
+                                        cp[9] =  saturateInt32Pow (cp[9]  , val);
+                                        cp[10] =  saturateInt32Pow (cp[10]  , val);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l --> 0) {
+                                        *cp =  saturateInt32Pow (*cp  , val);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outDims.NumberOfElements >= Settings.s_minParallelElement1Count
+                    && outDims[1] > 1) {
+                        if (outDims[1] > workItemCount) {
+                        workItemLength = outDims[1] / workItemCount;
+                    } else {
+                        workItemLength = outDims[1] / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outDims[1];
+                    workItemCount = 1;
+                }
+
+                fixed ( Int32* arrAP = arrA)
+                fixed ( Int32* arrBP = arrB)
+                fixed ( Int32* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, IntPtr, IntPtr, IntPtr> range = new Tuple<int, IntPtr, IntPtr, IntPtr>
+                               (workItemLength
+                               , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                               , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                               , (IntPtr)(retArrP + i * outDims[0] * workItemLength)); 
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, IntPtr, IntPtr, IntPtr>
+                                (outDims[1] - i * workItemLength
+                                , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                                , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                                , (IntPtr)(retArrP + i * outDims[0] * workItemLength)));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<Int32>(retStorage);
+            //}  // no scopes here! it disables implace operations
+        }
+
+        /// <summary>Power elements</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Array with elementwise result of A <sup>B</sup></returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<float>  pow(ILInArray<float> A, ILInArray<float> B) {
+            using (ILScope.Enter(A,B)) {
+                int outLen; 
+                BinOpItMode mode; 
+                float [] retArr;
+                float [] arrA = A.GetArrayForRead();
+                float[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size; 
+                    if (B.IsScalar) {
+                       
+                        return new  ILRetArray<float> (new  float [1]{ (float)Math.Pow (A.GetValue(0)  , B.GetValue(0))}, A.Size);
+                    } else if (B.IsEmpty) {
+                        return  ILRetArray<float>.empty(outDims); 
+                    } else {
+                        outLen = outDims.NumberOfElements; 
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< float > (outLen);
+                            mode = BinOpItMode.SAN; 
+                        } else {
+                            mode = BinOpItMode.SAI; 
+                        }
+                    }
+                } else {
+                    outDims = A.Size; 
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return  ILRetArray<float>.empty(A.Size);  
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< float > (outLen);
+                            mode = BinOpItMode.ASN; 
+                        } else {
+                            mode = BinOpItMode.ASI; 
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  powEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (A.TryGetStorage4InplaceOp(out retArr)) 
+                            mode  = BinOpItMode.AAIA; 
+                        else if (B.TryGetStorage4InplaceOp(out retArr)) 
+                            mode = BinOpItMode.AAIB; 
+                        else {
+                            retArr = ILMemoryPool.Pool.New< float > (outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<float> retStorage = new ILDenseStorage<float>(retArr, outDims);
+                int i = 0, workerCount = 1; 
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    float* cp = (float*)range.Item5 + range.Item1;
+                    float scalar;
+                    int j = range.Item2; 
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           float* bp = ((float*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                                cp[0] =  (float)Math.Pow (cp[0]  , bp[0]);
+                                cp[1] =  (float)Math.Pow (cp[1]  , bp[1]);
+                                cp[2] =  (float)Math.Pow (cp[2]  , bp[2]);
+                                cp[3] =  (float)Math.Pow (cp[3]  , bp[3]);
+                                cp[4] =  (float)Math.Pow (cp[4]  , bp[4]);
+                                cp[5] =  (float)Math.Pow (cp[5]  , bp[5]);
+                                cp[6] =  (float)Math.Pow (cp[6]  , bp[6]);
+                                cp[7] =  (float)Math.Pow (cp[7]  , bp[7]);
+                                cp[8] =  (float)Math.Pow (cp[8]  , bp[8]);
+                                cp[9] =  (float)Math.Pow (cp[9]  , bp[9]);
+                                cp[10] =  (float)Math.Pow (cp[10]  , bp[10]);
+                                cp[11] =  (float)Math.Pow (cp[11]  , bp[11]);
+                                cp[12] =  (float)Math.Pow (cp[12]  , bp[12]);
+                                cp[13] =  (float)Math.Pow (cp[13]  , bp[13]);
+                                cp[14] =  (float)Math.Pow (cp[14]  , bp[14]);
+                                cp[15] =  (float)Math.Pow (cp[15]  , bp[15]);
+                                cp[16] =  (float)Math.Pow (cp[16]  , bp[16]);
+                                cp[17] =  (float)Math.Pow (cp[17]  , bp[17]);
+                                cp[18] =  (float)Math.Pow (cp[18]  , bp[18]);
+                                cp[19] =  (float)Math.Pow (cp[19]  , bp[19]);
+                                cp[20] =  (float)Math.Pow (cp[20]  , bp[20]);
+                                cp += 21; bp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  (float)Math.Pow (*cp  , *bp);
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           float* ap = ((float*)range.Item3 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  (float)Math.Pow (ap[0]  , cp[0]);
+                                cp[1] =  (float)Math.Pow (ap[1]  , cp[1]);
+                                cp[2] =  (float)Math.Pow (ap[2]  , cp[2]);
+                                cp[3] =  (float)Math.Pow (ap[3]  , cp[3]);
+                                cp[4] =  (float)Math.Pow (ap[4]  , cp[4]);
+                                cp[5] =  (float)Math.Pow (ap[5]  , cp[5]);
+                                cp[6] =  (float)Math.Pow (ap[6]  , cp[6]);
+                                cp[7] =  (float)Math.Pow (ap[7]  , cp[7]);
+                                cp[8] =  (float)Math.Pow (ap[8]  , cp[8]);
+                                cp[9] =  (float)Math.Pow (ap[9]  , cp[9]);
+                                cp[10] =  (float)Math.Pow (ap[10]  , cp[10]);
+                                cp[11] =  (float)Math.Pow (ap[11]  , cp[11]);
+                                cp[12] =  (float)Math.Pow (ap[12]  , cp[12]);
+                                cp[13] =  (float)Math.Pow (ap[13]  , cp[13]);
+                                cp[14] =  (float)Math.Pow (ap[14]  , cp[14]);
+                                cp[15] =  (float)Math.Pow (ap[15]  , cp[15]);
+                                cp[16] =  (float)Math.Pow (ap[16]  , cp[16]);
+                                cp[17] =  (float)Math.Pow (ap[17]  , cp[17]);
+                                cp[18] =  (float)Math.Pow (ap[18]  , cp[18]);
+                                cp[19] =  (float)Math.Pow (ap[19]  , cp[19]);
+                                cp[20] =  (float)Math.Pow (ap[20]  , cp[20]);
+                                ap += 21; cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  (float)Math.Pow (*ap  , *cp);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((float*)range.Item3 + range.Item1);
+                            bp = ((float*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  (float)Math.Pow (ap[0]  , bp[0]);
+                                cp[1] =  (float)Math.Pow (ap[1]  , bp[1]);
+                                cp[2] =  (float)Math.Pow (ap[2]  , bp[2]);
+                                cp[3] =  (float)Math.Pow (ap[3]  , bp[3]);
+                                cp[4] =  (float)Math.Pow (ap[4]  , bp[4]);
+                                cp[5] =  (float)Math.Pow (ap[5]  , bp[5]);
+                                cp[6] =  (float)Math.Pow (ap[6]  , bp[6]);
+                                cp[7] =  (float)Math.Pow (ap[7]  , bp[7]);
+                                cp[8] =  (float)Math.Pow (ap[8]  , bp[8]);
+                                cp[9] =  (float)Math.Pow (ap[9]  , bp[9]);
+                                cp[10] =  (float)Math.Pow (ap[10]  , bp[10]);
+                                cp[11] =  (float)Math.Pow (ap[11]  , bp[11]);
+                                cp[12] =  (float)Math.Pow (ap[12]  , bp[12]);
+                                cp[13] =  (float)Math.Pow (ap[13]  , bp[13]);
+                                cp[14] =  (float)Math.Pow (ap[14]  , bp[14]);
+                                cp[15] =  (float)Math.Pow (ap[15]  , bp[15]);
+                                cp[16] =  (float)Math.Pow (ap[16]  , bp[16]);
+                                cp[17] =  (float)Math.Pow (ap[17]  , bp[17]);
+                                cp[18] =  (float)Math.Pow (ap[18]  , bp[18]);
+                                cp[19] =  (float)Math.Pow (ap[19]  , bp[19]);
+                                cp[20] =  (float)Math.Pow (ap[20]  , bp[20]);
+                                ap+=21; bp+=21; cp+=21; j-=21;
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  (float)Math.Pow (*ap  , *bp);
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((float*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =  (float)Math.Pow (cp[0]  , scalar);
+                                cp[1] =  (float)Math.Pow (cp[1]  , scalar);
+                                cp[2] =  (float)Math.Pow (cp[2]  , scalar);
+                                cp[3] =  (float)Math.Pow (cp[3]  , scalar);
+                                cp[4] =  (float)Math.Pow (cp[4]  , scalar);
+                                cp[5] =  (float)Math.Pow (cp[5]  , scalar);
+                                cp[6] =  (float)Math.Pow (cp[6]  , scalar);
+                                cp[7] =  (float)Math.Pow (cp[7]  , scalar);
+                                cp[8] =  (float)Math.Pow (cp[8]  , scalar);
+                                cp[9] =  (float)Math.Pow (cp[9]  , scalar);
+                                cp[10] =  (float)Math.Pow (cp[10]  , scalar);
+                                cp[11] =  (float)Math.Pow (cp[11]  , scalar);
+                                cp[12] =  (float)Math.Pow (cp[12]  , scalar);
+                                cp[13] =  (float)Math.Pow (cp[13]  , scalar);
+                                cp[14] =  (float)Math.Pow (cp[14]  , scalar);
+                                cp[15] =  (float)Math.Pow (cp[15]  , scalar);
+                                cp[16] =  (float)Math.Pow (cp[16]  , scalar);
+                                cp[17] =  (float)Math.Pow (cp[17]  , scalar);
+                                cp[18] =  (float)Math.Pow (cp[18]  , scalar);
+                                cp[19] =  (float)Math.Pow (cp[19]  , scalar);
+                                cp[20] =  (float)Math.Pow (cp[20]  , scalar);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  (float)Math.Pow (*cp  , scalar);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((float*)range.Item3 + range.Item1);
+                            scalar = *((float*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =  (float)Math.Pow (ap[0]  , scalar);
+                                cp[1] =  (float)Math.Pow (ap[1]  , scalar);
+                                cp[2] =  (float)Math.Pow (ap[2]  , scalar);
+                                cp[3] =  (float)Math.Pow (ap[3]  , scalar);
+                                cp[4] =  (float)Math.Pow (ap[4]  , scalar);
+                                cp[5] =  (float)Math.Pow (ap[5]  , scalar);
+                                cp[6] =  (float)Math.Pow (ap[6]  , scalar);
+                                cp[7] =  (float)Math.Pow (ap[7]  , scalar);
+                                cp[8] =  (float)Math.Pow (ap[8]  , scalar);
+                                cp[9] =  (float)Math.Pow (ap[9]  , scalar);
+                                cp[10] =  (float)Math.Pow (ap[10]  , scalar);
+                                cp[11] =  (float)Math.Pow (ap[11]  , scalar);
+                                cp[12] =  (float)Math.Pow (ap[12]  , scalar);
+                                cp[13] =  (float)Math.Pow (ap[13]  , scalar);
+                                cp[14] =  (float)Math.Pow (ap[14]  , scalar);
+                                cp[15] =  (float)Math.Pow (ap[15]  , scalar);
+                                cp[16] =  (float)Math.Pow (ap[16]  , scalar);
+                                cp[17] =  (float)Math.Pow (ap[17]  , scalar);
+                                cp[18] =  (float)Math.Pow (ap[18]  , scalar);
+                                cp[19] =  (float)Math.Pow (ap[19]  , scalar);
+                                cp[20] =  (float)Math.Pow (ap[20]  , scalar);
+                                ap+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  (float)Math.Pow (*ap  , scalar);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((float*)range.Item3);
+                            while (j > 20) {
+                               
+                                cp[0] =  (float)Math.Pow (scalar  , cp[0]);
+                                cp[1] =  (float)Math.Pow (scalar  , cp[1]);
+                                cp[2] =  (float)Math.Pow (scalar  , cp[2]);
+                                cp[3] =  (float)Math.Pow (scalar  , cp[3]);
+                                cp[4] =  (float)Math.Pow (scalar  , cp[4]);
+                                cp[5] =  (float)Math.Pow (scalar  , cp[5]);
+                                cp[6] =  (float)Math.Pow (scalar  , cp[6]);
+                                cp[7] =  (float)Math.Pow (scalar  , cp[7]);
+                                cp[8] =  (float)Math.Pow (scalar  , cp[8]);
+                                cp[9] =  (float)Math.Pow (scalar  , cp[9]);
+                                cp[10] =  (float)Math.Pow (scalar  , cp[10]);
+                                cp[11] =  (float)Math.Pow (scalar  , cp[11]);
+                                cp[12] =  (float)Math.Pow (scalar  , cp[12]);
+                                cp[13] =  (float)Math.Pow (scalar  , cp[13]);
+                                cp[14] =  (float)Math.Pow (scalar  , cp[14]);
+                                cp[15] =  (float)Math.Pow (scalar  , cp[15]);
+                                cp[16] =  (float)Math.Pow (scalar  , cp[16]);
+                                cp[17] =  (float)Math.Pow (scalar  , cp[17]);
+                                cp[18] =  (float)Math.Pow (scalar  , cp[18]);
+                                cp[19] =  (float)Math.Pow (scalar  , cp[19]);
+                                cp[20] =  (float)Math.Pow (scalar  , cp[20]);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  (float)Math.Pow (scalar  , *cp);
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((float*)range.Item3);
+                            bp = ((float*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  (float)Math.Pow (scalar  , bp[0]);
+                                cp[1] =  (float)Math.Pow (scalar  , bp[1]);
+                                cp[2] =  (float)Math.Pow (scalar  , bp[2]);
+                                cp[3] =  (float)Math.Pow (scalar  , bp[3]);
+                                cp[4] =  (float)Math.Pow (scalar  , bp[4]);
+                                cp[5] =  (float)Math.Pow (scalar  , bp[5]);
+                                cp[6] =  (float)Math.Pow (scalar  , bp[6]);
+                                cp[7] =  (float)Math.Pow (scalar  , bp[7]);
+                                cp[8] =  (float)Math.Pow (scalar  , bp[8]);
+                                cp[9] =  (float)Math.Pow (scalar  , bp[9]);
+                                cp[10] =  (float)Math.Pow (scalar  , bp[10]);
+                                cp[11] =  (float)Math.Pow (scalar  , bp[11]);
+                                cp[12] =  (float)Math.Pow (scalar  , bp[12]);
+                                cp[13] =  (float)Math.Pow (scalar  , bp[13]);
+                                cp[14] =  (float)Math.Pow (scalar  , bp[14]);
+                                cp[15] =  (float)Math.Pow (scalar  , bp[15]);
+                                cp[16] =  (float)Math.Pow (scalar  , bp[16]);
+                                cp[17] =  (float)Math.Pow (scalar  , bp[17]);
+                                cp[18] =  (float)Math.Pow (scalar  , bp[18]);
+                                cp[19] =  (float)Math.Pow (scalar  , bp[19]);
+                                cp[20] =  (float)Math.Pow (scalar  , bp[20]);
+                                bp+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  (float)Math.Pow (scalar  , *bp);
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work 
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                
+                fixed ( float* arrAP = arrA)
+                fixed ( float* arrBP = arrB)
+                fixed ( float* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range 
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new  ILRetArray< float>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<float>  powEx(ILInArray<float> A, ILInArray<float> B) {
+            //using (ILScope.Enter(A, B)) { we cannot start a new scope here, since this would prevent A and B to be used implace if applicable
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<float>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<float>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<float>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                dim = -(dim - 1);  // 0 -> 1, 1 -> 0
+                #endregion
+
+                #region parameter preparation
+               
+                float[] retArr;
+               
+                float[] arrA = A.GetArrayForRead();
+               
+                float[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int workItemMultiplierLenA;
+                int workItemMultiplierLenB;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<float>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    workItemMultiplierLenB = outDims[0]; 
+                    workItemMultiplierLenA = dim;  // 0 for column, 1 for row vector
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<float>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    workItemMultiplierLenB = dim;  // 0 for column, 1 for row vector
+                    workItemMultiplierLenA = outDims[0]; 
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one singleton dimension in either A or B");
+                }
+                int itLen = outDims[0]; // (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<float> retStorage = new ILDenseStorage<float>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    float* ap;
+                   
+                    float* bp;
+                   
+                    float* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            if (dim == 0) {
+                                bp = (float*)range.Item3;
+                                cp = (float*)range.Item4; 
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (float*)range.Item2;
+                                    int l = itLen; 
+                                    while (l > 10) {
+                                        cp[0] =  (float)Math.Pow (ap[0]  , bp[0]);
+                                        cp[1] =  (float)Math.Pow (ap[1]  , bp[1]);
+                                        cp[2] =  (float)Math.Pow (ap[2]  , bp[2]);
+                                        cp[3] =  (float)Math.Pow (ap[3]  , bp[3]);
+                                        cp[4] =  (float)Math.Pow (ap[4]  , bp[4]);
+                                        cp[5] =  (float)Math.Pow (ap[5]  , bp[5]);
+                                        cp[6] =  (float)Math.Pow (ap[6]  , bp[6]);
+                                        cp[7] =  (float)Math.Pow (ap[7]  , bp[7]);
+                                        cp[8] =  (float)Math.Pow (ap[8]  , bp[8]);
+                                        cp[9] =  (float)Math.Pow (ap[9]  , bp[9]);
+                                        cp[10] =  (float)Math.Pow (ap[10]  , bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =  (float)Math.Pow (*ap++  , *bp++);
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                ap = (float*)range.Item2;
+                                bp = (float*)range.Item3;
+                                cp = (float*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   float val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  (float)Math.Pow (val  , bp[0]);
+                                        cp[1] =  (float)Math.Pow (val  , bp[1]);
+                                        cp[2] =  (float)Math.Pow (val  , bp[2]);
+                                        cp[3] =  (float)Math.Pow (val  , bp[3]);
+                                        cp[4] =  (float)Math.Pow (val  , bp[4]);
+                                        cp[5] =  (float)Math.Pow (val  , bp[5]);
+                                        cp[6] =  (float)Math.Pow (val  , bp[6]);
+                                        cp[7] =  (float)Math.Pow (val  , bp[7]);
+                                        cp[8] =  (float)Math.Pow (val  , bp[8]);
+                                        cp[9] =  (float)Math.Pow (val  , bp[9]);
+                                        cp[10] =  (float)Math.Pow (val  , bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11; 
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =  (float)Math.Pow (val  , *bp++);
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            if (dim == 0) {
+                                cp = (float*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (float*)range.Item2;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  (float)Math.Pow (ap[0]  , cp[0]);
+                                        cp[1] =  (float)Math.Pow (ap[1]  , cp[1]);
+                                        cp[2] =  (float)Math.Pow (ap[2]  , cp[2]);
+                                        cp[3] =  (float)Math.Pow (ap[3]  , cp[3]);
+                                        cp[4] =  (float)Math.Pow (ap[4]  , cp[4]);
+                                        cp[5] =  (float)Math.Pow (ap[5]  , cp[5]);
+                                        cp[6] =  (float)Math.Pow (ap[6]  , cp[6]);
+                                        cp[7] =  (float)Math.Pow (ap[7]  , cp[7]);
+                                        cp[8] =  (float)Math.Pow (ap[8]  , cp[8]);
+                                        cp[9] =  (float)Math.Pow (ap[9]  , cp[9]);
+                                        cp[10] =  (float)Math.Pow (ap[10]  , cp[10]);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  (float)Math.Pow (*ap++  , *cp);
+                                        cp++; 
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                cp = (float*)range.Item4;
+                                ap = (float*)range.Item2;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    float val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  (float)Math.Pow (val  , cp[0]);
+                                        cp[1] =  (float)Math.Pow (val  , cp[1]);
+                                        cp[2] =  (float)Math.Pow (val  , cp[2]);
+                                        cp[3] =  (float)Math.Pow (val  , cp[3]);
+                                        cp[4] =  (float)Math.Pow (val  , cp[4]);
+                                        cp[5] =  (float)Math.Pow (val  , cp[5]);
+                                        cp[6] =  (float)Math.Pow (val  , cp[6]);
+                                        cp[7] =  (float)Math.Pow (val  , cp[7]);
+                                        cp[8] =  (float)Math.Pow (val  , cp[8]);
+                                        cp[9] =  (float)Math.Pow (val  , cp[9]);
+                                        cp[10] =  (float)Math.Pow (val  , cp[10]);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  (float)Math.Pow (val  , *cp);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            if (dim == 0) {
+                                ap = (float*)range.Item2;
+                                cp = (float*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (float*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  (float)Math.Pow (ap[0]  , bp[0]);
+                                        cp[1] =  (float)Math.Pow (ap[1]  , bp[1]);
+                                        cp[2] =  (float)Math.Pow (ap[2]  , bp[2]);
+                                        cp[3] =  (float)Math.Pow (ap[3]  , bp[3]);
+                                        cp[4] =  (float)Math.Pow (ap[4]  , bp[4]);
+                                        cp[5] =  (float)Math.Pow (ap[5]  , bp[5]);
+                                        cp[6] =  (float)Math.Pow (ap[6]  , bp[6]);
+                                        cp[7] =  (float)Math.Pow (ap[7]  , bp[7]);
+                                        cp[8] =  (float)Math.Pow (ap[8]  , bp[8]);
+                                        cp[9] =  (float)Math.Pow (ap[9]  , bp[9]);
+                                        cp[10] =  (float)Math.Pow (ap[10]  , bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  (float)Math.Pow (*ap  , *bp);
+                                        ap++;
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                ap = (float*)range.Item2;
+                                bp = (float*)range.Item3;
+                                cp = (float*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   float val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  (float)Math.Pow (ap[0]  , val);
+                                        cp[1] =  (float)Math.Pow (ap[1]  , val);
+                                        cp[2] =  (float)Math.Pow (ap[2]  , val);
+                                        cp[3] =  (float)Math.Pow (ap[3]  , val);
+                                        cp[4] =  (float)Math.Pow (ap[4]  , val);
+                                        cp[5] =  (float)Math.Pow (ap[5]  , val);
+                                        cp[6] =  (float)Math.Pow (ap[6]  , val);
+                                        cp[7] =  (float)Math.Pow (ap[7]  , val);
+                                        cp[8] =  (float)Math.Pow (ap[8]  , val);
+                                        cp[9] =  (float)Math.Pow (ap[9]  , val);
+                                        cp[10] =  (float)Math.Pow (ap[10]  , val);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  (float)Math.Pow (*ap  , val);
+                                        ap++;
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            if (dim == 0) {
+                                cp = (float*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (float*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  (float)Math.Pow (cp[0]  , bp[0]);
+                                        cp[1] =  (float)Math.Pow (cp[1]  , bp[1]);
+                                        cp[2] =  (float)Math.Pow (cp[2]  , bp[2]);
+                                        cp[3] =  (float)Math.Pow (cp[3]  , bp[3]);
+                                        cp[4] =  (float)Math.Pow (cp[4]  , bp[4]);
+                                        cp[5] =  (float)Math.Pow (cp[5]  , bp[5]);
+                                        cp[6] =  (float)Math.Pow (cp[6]  , bp[6]);
+                                        cp[7] =  (float)Math.Pow (cp[7]  , bp[7]);
+                                        cp[8] =  (float)Math.Pow (cp[8]  , bp[8]);
+                                        cp[9] =  (float)Math.Pow (cp[9]  , bp[9]);
+                                        cp[10] =  (float)Math.Pow (cp[10]  , bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  (float)Math.Pow (*cp  , *bp);
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                bp = (float*)range.Item3;
+                                cp = (float*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    float val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  (float)Math.Pow (cp[0]  , val);
+                                        cp[1] =  (float)Math.Pow (cp[1]  , val);
+                                        cp[2] =  (float)Math.Pow (cp[2]  , val);
+                                        cp[3] =  (float)Math.Pow (cp[3]  , val);
+                                        cp[4] =  (float)Math.Pow (cp[4]  , val);
+                                        cp[5] =  (float)Math.Pow (cp[5]  , val);
+                                        cp[6] =  (float)Math.Pow (cp[6]  , val);
+                                        cp[7] =  (float)Math.Pow (cp[7]  , val);
+                                        cp[8] =  (float)Math.Pow (cp[8]  , val);
+                                        cp[9] =  (float)Math.Pow (cp[9]  , val);
+                                        cp[10] =  (float)Math.Pow (cp[10]  , val);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l --> 0) {
+                                        *cp =  (float)Math.Pow (*cp  , val);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outDims.NumberOfElements >= Settings.s_minParallelElement1Count
+                    && outDims[1] > 1) {
+                        if (outDims[1] > workItemCount) {
+                        workItemLength = outDims[1] / workItemCount;
+                    } else {
+                        workItemLength = outDims[1] / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outDims[1];
+                    workItemCount = 1;
+                }
+
+                fixed ( float* arrAP = arrA)
+                fixed ( float* arrBP = arrB)
+                fixed ( float* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, IntPtr, IntPtr, IntPtr> range = new Tuple<int, IntPtr, IntPtr, IntPtr>
+                               (workItemLength
+                               , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                               , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                               , (IntPtr)(retArrP + i * outDims[0] * workItemLength)); 
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, IntPtr, IntPtr, IntPtr>
+                                (outDims[1] - i * workItemLength
+                                , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                                , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                                , (IntPtr)(retArrP + i * outDims[0] * workItemLength)));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<float>(retStorage);
+            //}  // no scopes here! it disables implace operations
+        }
+
+        /// <summary>Power elements</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Array with elementwise result of A <sup>B</sup></returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<fcomplex>  pow(ILInArray<fcomplex> A, ILInArray<fcomplex> B) {
+            using (ILScope.Enter(A,B)) {
+                int outLen; 
+                BinOpItMode mode; 
+                fcomplex [] retArr;
+                fcomplex [] arrA = A.GetArrayForRead();
+                fcomplex[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size; 
+                    if (B.IsScalar) {
+                       
+                        return new  ILRetArray<fcomplex> (new  fcomplex [1]{ fcomplex.Pow (A.GetValue(0)  , B.GetValue(0))}, A.Size);
+                    } else if (B.IsEmpty) {
+                        return  ILRetArray<fcomplex>.empty(outDims); 
+                    } else {
+                        outLen = outDims.NumberOfElements; 
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< fcomplex > (outLen);
+                            mode = BinOpItMode.SAN; 
+                        } else {
+                            mode = BinOpItMode.SAI; 
+                        }
+                    }
+                } else {
+                    outDims = A.Size; 
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return  ILRetArray<fcomplex>.empty(A.Size);  
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< fcomplex > (outLen);
+                            mode = BinOpItMode.ASN; 
+                        } else {
+                            mode = BinOpItMode.ASI; 
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  powEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (A.TryGetStorage4InplaceOp(out retArr)) 
+                            mode  = BinOpItMode.AAIA; 
+                        else if (B.TryGetStorage4InplaceOp(out retArr)) 
+                            mode = BinOpItMode.AAIB; 
+                        else {
+                            retArr = ILMemoryPool.Pool.New< fcomplex > (outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<fcomplex> retStorage = new ILDenseStorage<fcomplex>(retArr, outDims);
+                int i = 0, workerCount = 1; 
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    fcomplex* cp = (fcomplex*)range.Item5 + range.Item1;
+                    fcomplex scalar;
+                    int j = range.Item2; 
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           fcomplex* bp = ((fcomplex*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                                cp[0] =  fcomplex.Pow (cp[0]  , bp[0]);
+                                cp[1] =  fcomplex.Pow (cp[1]  , bp[1]);
+                                cp[2] =  fcomplex.Pow (cp[2]  , bp[2]);
+                                cp[3] =  fcomplex.Pow (cp[3]  , bp[3]);
+                                cp[4] =  fcomplex.Pow (cp[4]  , bp[4]);
+                                cp[5] =  fcomplex.Pow (cp[5]  , bp[5]);
+                                cp[6] =  fcomplex.Pow (cp[6]  , bp[6]);
+                                cp[7] =  fcomplex.Pow (cp[7]  , bp[7]);
+                                cp[8] =  fcomplex.Pow (cp[8]  , bp[8]);
+                                cp[9] =  fcomplex.Pow (cp[9]  , bp[9]);
+                                cp[10] =  fcomplex.Pow (cp[10]  , bp[10]);
+                                cp[11] =  fcomplex.Pow (cp[11]  , bp[11]);
+                                cp[12] =  fcomplex.Pow (cp[12]  , bp[12]);
+                                cp[13] =  fcomplex.Pow (cp[13]  , bp[13]);
+                                cp[14] =  fcomplex.Pow (cp[14]  , bp[14]);
+                                cp[15] =  fcomplex.Pow (cp[15]  , bp[15]);
+                                cp[16] =  fcomplex.Pow (cp[16]  , bp[16]);
+                                cp[17] =  fcomplex.Pow (cp[17]  , bp[17]);
+                                cp[18] =  fcomplex.Pow (cp[18]  , bp[18]);
+                                cp[19] =  fcomplex.Pow (cp[19]  , bp[19]);
+                                cp[20] =  fcomplex.Pow (cp[20]  , bp[20]);
+                                cp += 21; bp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  fcomplex.Pow (*cp  , *bp);
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           fcomplex* ap = ((fcomplex*)range.Item3 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  fcomplex.Pow (ap[0]  , cp[0]);
+                                cp[1] =  fcomplex.Pow (ap[1]  , cp[1]);
+                                cp[2] =  fcomplex.Pow (ap[2]  , cp[2]);
+                                cp[3] =  fcomplex.Pow (ap[3]  , cp[3]);
+                                cp[4] =  fcomplex.Pow (ap[4]  , cp[4]);
+                                cp[5] =  fcomplex.Pow (ap[5]  , cp[5]);
+                                cp[6] =  fcomplex.Pow (ap[6]  , cp[6]);
+                                cp[7] =  fcomplex.Pow (ap[7]  , cp[7]);
+                                cp[8] =  fcomplex.Pow (ap[8]  , cp[8]);
+                                cp[9] =  fcomplex.Pow (ap[9]  , cp[9]);
+                                cp[10] =  fcomplex.Pow (ap[10]  , cp[10]);
+                                cp[11] =  fcomplex.Pow (ap[11]  , cp[11]);
+                                cp[12] =  fcomplex.Pow (ap[12]  , cp[12]);
+                                cp[13] =  fcomplex.Pow (ap[13]  , cp[13]);
+                                cp[14] =  fcomplex.Pow (ap[14]  , cp[14]);
+                                cp[15] =  fcomplex.Pow (ap[15]  , cp[15]);
+                                cp[16] =  fcomplex.Pow (ap[16]  , cp[16]);
+                                cp[17] =  fcomplex.Pow (ap[17]  , cp[17]);
+                                cp[18] =  fcomplex.Pow (ap[18]  , cp[18]);
+                                cp[19] =  fcomplex.Pow (ap[19]  , cp[19]);
+                                cp[20] =  fcomplex.Pow (ap[20]  , cp[20]);
+                                ap += 21; cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  fcomplex.Pow (*ap  , *cp);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((fcomplex*)range.Item3 + range.Item1);
+                            bp = ((fcomplex*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  fcomplex.Pow (ap[0]  , bp[0]);
+                                cp[1] =  fcomplex.Pow (ap[1]  , bp[1]);
+                                cp[2] =  fcomplex.Pow (ap[2]  , bp[2]);
+                                cp[3] =  fcomplex.Pow (ap[3]  , bp[3]);
+                                cp[4] =  fcomplex.Pow (ap[4]  , bp[4]);
+                                cp[5] =  fcomplex.Pow (ap[5]  , bp[5]);
+                                cp[6] =  fcomplex.Pow (ap[6]  , bp[6]);
+                                cp[7] =  fcomplex.Pow (ap[7]  , bp[7]);
+                                cp[8] =  fcomplex.Pow (ap[8]  , bp[8]);
+                                cp[9] =  fcomplex.Pow (ap[9]  , bp[9]);
+                                cp[10] =  fcomplex.Pow (ap[10]  , bp[10]);
+                                cp[11] =  fcomplex.Pow (ap[11]  , bp[11]);
+                                cp[12] =  fcomplex.Pow (ap[12]  , bp[12]);
+                                cp[13] =  fcomplex.Pow (ap[13]  , bp[13]);
+                                cp[14] =  fcomplex.Pow (ap[14]  , bp[14]);
+                                cp[15] =  fcomplex.Pow (ap[15]  , bp[15]);
+                                cp[16] =  fcomplex.Pow (ap[16]  , bp[16]);
+                                cp[17] =  fcomplex.Pow (ap[17]  , bp[17]);
+                                cp[18] =  fcomplex.Pow (ap[18]  , bp[18]);
+                                cp[19] =  fcomplex.Pow (ap[19]  , bp[19]);
+                                cp[20] =  fcomplex.Pow (ap[20]  , bp[20]);
+                                ap+=21; bp+=21; cp+=21; j-=21;
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  fcomplex.Pow (*ap  , *bp);
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((fcomplex*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =  fcomplex.Pow (cp[0]  , scalar);
+                                cp[1] =  fcomplex.Pow (cp[1]  , scalar);
+                                cp[2] =  fcomplex.Pow (cp[2]  , scalar);
+                                cp[3] =  fcomplex.Pow (cp[3]  , scalar);
+                                cp[4] =  fcomplex.Pow (cp[4]  , scalar);
+                                cp[5] =  fcomplex.Pow (cp[5]  , scalar);
+                                cp[6] =  fcomplex.Pow (cp[6]  , scalar);
+                                cp[7] =  fcomplex.Pow (cp[7]  , scalar);
+                                cp[8] =  fcomplex.Pow (cp[8]  , scalar);
+                                cp[9] =  fcomplex.Pow (cp[9]  , scalar);
+                                cp[10] =  fcomplex.Pow (cp[10]  , scalar);
+                                cp[11] =  fcomplex.Pow (cp[11]  , scalar);
+                                cp[12] =  fcomplex.Pow (cp[12]  , scalar);
+                                cp[13] =  fcomplex.Pow (cp[13]  , scalar);
+                                cp[14] =  fcomplex.Pow (cp[14]  , scalar);
+                                cp[15] =  fcomplex.Pow (cp[15]  , scalar);
+                                cp[16] =  fcomplex.Pow (cp[16]  , scalar);
+                                cp[17] =  fcomplex.Pow (cp[17]  , scalar);
+                                cp[18] =  fcomplex.Pow (cp[18]  , scalar);
+                                cp[19] =  fcomplex.Pow (cp[19]  , scalar);
+                                cp[20] =  fcomplex.Pow (cp[20]  , scalar);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  fcomplex.Pow (*cp  , scalar);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((fcomplex*)range.Item3 + range.Item1);
+                            scalar = *((fcomplex*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =  fcomplex.Pow (ap[0]  , scalar);
+                                cp[1] =  fcomplex.Pow (ap[1]  , scalar);
+                                cp[2] =  fcomplex.Pow (ap[2]  , scalar);
+                                cp[3] =  fcomplex.Pow (ap[3]  , scalar);
+                                cp[4] =  fcomplex.Pow (ap[4]  , scalar);
+                                cp[5] =  fcomplex.Pow (ap[5]  , scalar);
+                                cp[6] =  fcomplex.Pow (ap[6]  , scalar);
+                                cp[7] =  fcomplex.Pow (ap[7]  , scalar);
+                                cp[8] =  fcomplex.Pow (ap[8]  , scalar);
+                                cp[9] =  fcomplex.Pow (ap[9]  , scalar);
+                                cp[10] =  fcomplex.Pow (ap[10]  , scalar);
+                                cp[11] =  fcomplex.Pow (ap[11]  , scalar);
+                                cp[12] =  fcomplex.Pow (ap[12]  , scalar);
+                                cp[13] =  fcomplex.Pow (ap[13]  , scalar);
+                                cp[14] =  fcomplex.Pow (ap[14]  , scalar);
+                                cp[15] =  fcomplex.Pow (ap[15]  , scalar);
+                                cp[16] =  fcomplex.Pow (ap[16]  , scalar);
+                                cp[17] =  fcomplex.Pow (ap[17]  , scalar);
+                                cp[18] =  fcomplex.Pow (ap[18]  , scalar);
+                                cp[19] =  fcomplex.Pow (ap[19]  , scalar);
+                                cp[20] =  fcomplex.Pow (ap[20]  , scalar);
+                                ap+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  fcomplex.Pow (*ap  , scalar);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((fcomplex*)range.Item3);
+                            while (j > 20) {
+                               
+                                cp[0] =  fcomplex.Pow (scalar  , cp[0]);
+                                cp[1] =  fcomplex.Pow (scalar  , cp[1]);
+                                cp[2] =  fcomplex.Pow (scalar  , cp[2]);
+                                cp[3] =  fcomplex.Pow (scalar  , cp[3]);
+                                cp[4] =  fcomplex.Pow (scalar  , cp[4]);
+                                cp[5] =  fcomplex.Pow (scalar  , cp[5]);
+                                cp[6] =  fcomplex.Pow (scalar  , cp[6]);
+                                cp[7] =  fcomplex.Pow (scalar  , cp[7]);
+                                cp[8] =  fcomplex.Pow (scalar  , cp[8]);
+                                cp[9] =  fcomplex.Pow (scalar  , cp[9]);
+                                cp[10] =  fcomplex.Pow (scalar  , cp[10]);
+                                cp[11] =  fcomplex.Pow (scalar  , cp[11]);
+                                cp[12] =  fcomplex.Pow (scalar  , cp[12]);
+                                cp[13] =  fcomplex.Pow (scalar  , cp[13]);
+                                cp[14] =  fcomplex.Pow (scalar  , cp[14]);
+                                cp[15] =  fcomplex.Pow (scalar  , cp[15]);
+                                cp[16] =  fcomplex.Pow (scalar  , cp[16]);
+                                cp[17] =  fcomplex.Pow (scalar  , cp[17]);
+                                cp[18] =  fcomplex.Pow (scalar  , cp[18]);
+                                cp[19] =  fcomplex.Pow (scalar  , cp[19]);
+                                cp[20] =  fcomplex.Pow (scalar  , cp[20]);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  fcomplex.Pow (scalar  , *cp);
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((fcomplex*)range.Item3);
+                            bp = ((fcomplex*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  fcomplex.Pow (scalar  , bp[0]);
+                                cp[1] =  fcomplex.Pow (scalar  , bp[1]);
+                                cp[2] =  fcomplex.Pow (scalar  , bp[2]);
+                                cp[3] =  fcomplex.Pow (scalar  , bp[3]);
+                                cp[4] =  fcomplex.Pow (scalar  , bp[4]);
+                                cp[5] =  fcomplex.Pow (scalar  , bp[5]);
+                                cp[6] =  fcomplex.Pow (scalar  , bp[6]);
+                                cp[7] =  fcomplex.Pow (scalar  , bp[7]);
+                                cp[8] =  fcomplex.Pow (scalar  , bp[8]);
+                                cp[9] =  fcomplex.Pow (scalar  , bp[9]);
+                                cp[10] =  fcomplex.Pow (scalar  , bp[10]);
+                                cp[11] =  fcomplex.Pow (scalar  , bp[11]);
+                                cp[12] =  fcomplex.Pow (scalar  , bp[12]);
+                                cp[13] =  fcomplex.Pow (scalar  , bp[13]);
+                                cp[14] =  fcomplex.Pow (scalar  , bp[14]);
+                                cp[15] =  fcomplex.Pow (scalar  , bp[15]);
+                                cp[16] =  fcomplex.Pow (scalar  , bp[16]);
+                                cp[17] =  fcomplex.Pow (scalar  , bp[17]);
+                                cp[18] =  fcomplex.Pow (scalar  , bp[18]);
+                                cp[19] =  fcomplex.Pow (scalar  , bp[19]);
+                                cp[20] =  fcomplex.Pow (scalar  , bp[20]);
+                                bp+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  fcomplex.Pow (scalar  , *bp);
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work 
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                
+                fixed ( fcomplex* arrAP = arrA)
+                fixed ( fcomplex* arrBP = arrB)
+                fixed ( fcomplex* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range 
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new  ILRetArray< fcomplex>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<fcomplex>  powEx(ILInArray<fcomplex> A, ILInArray<fcomplex> B) {
+            //using (ILScope.Enter(A, B)) { we cannot start a new scope here, since this would prevent A and B to be used implace if applicable
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<fcomplex>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<fcomplex>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<fcomplex>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                dim = -(dim - 1);  // 0 -> 1, 1 -> 0
+                #endregion
+
+                #region parameter preparation
+               
+                fcomplex[] retArr;
+               
+                fcomplex[] arrA = A.GetArrayForRead();
+               
+                fcomplex[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int workItemMultiplierLenA;
+                int workItemMultiplierLenB;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<fcomplex>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    workItemMultiplierLenB = outDims[0]; 
+                    workItemMultiplierLenA = dim;  // 0 for column, 1 for row vector
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<fcomplex>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    workItemMultiplierLenB = dim;  // 0 for column, 1 for row vector
+                    workItemMultiplierLenA = outDims[0]; 
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one singleton dimension in either A or B");
+                }
+                int itLen = outDims[0]; // (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<fcomplex> retStorage = new ILDenseStorage<fcomplex>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    fcomplex* ap;
+                   
+                    fcomplex* bp;
+                   
+                    fcomplex* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            if (dim == 0) {
+                                bp = (fcomplex*)range.Item3;
+                                cp = (fcomplex*)range.Item4; 
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (fcomplex*)range.Item2;
+                                    int l = itLen; 
+                                    while (l > 10) {
+                                        cp[0] =  fcomplex.Pow (ap[0]  , bp[0]);
+                                        cp[1] =  fcomplex.Pow (ap[1]  , bp[1]);
+                                        cp[2] =  fcomplex.Pow (ap[2]  , bp[2]);
+                                        cp[3] =  fcomplex.Pow (ap[3]  , bp[3]);
+                                        cp[4] =  fcomplex.Pow (ap[4]  , bp[4]);
+                                        cp[5] =  fcomplex.Pow (ap[5]  , bp[5]);
+                                        cp[6] =  fcomplex.Pow (ap[6]  , bp[6]);
+                                        cp[7] =  fcomplex.Pow (ap[7]  , bp[7]);
+                                        cp[8] =  fcomplex.Pow (ap[8]  , bp[8]);
+                                        cp[9] =  fcomplex.Pow (ap[9]  , bp[9]);
+                                        cp[10] =  fcomplex.Pow (ap[10]  , bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =  fcomplex.Pow (*ap++  , *bp++);
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                ap = (fcomplex*)range.Item2;
+                                bp = (fcomplex*)range.Item3;
+                                cp = (fcomplex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   fcomplex val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  fcomplex.Pow (val  , bp[0]);
+                                        cp[1] =  fcomplex.Pow (val  , bp[1]);
+                                        cp[2] =  fcomplex.Pow (val  , bp[2]);
+                                        cp[3] =  fcomplex.Pow (val  , bp[3]);
+                                        cp[4] =  fcomplex.Pow (val  , bp[4]);
+                                        cp[5] =  fcomplex.Pow (val  , bp[5]);
+                                        cp[6] =  fcomplex.Pow (val  , bp[6]);
+                                        cp[7] =  fcomplex.Pow (val  , bp[7]);
+                                        cp[8] =  fcomplex.Pow (val  , bp[8]);
+                                        cp[9] =  fcomplex.Pow (val  , bp[9]);
+                                        cp[10] =  fcomplex.Pow (val  , bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11; 
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =  fcomplex.Pow (val  , *bp++);
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            if (dim == 0) {
+                                cp = (fcomplex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (fcomplex*)range.Item2;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  fcomplex.Pow (ap[0]  , cp[0]);
+                                        cp[1] =  fcomplex.Pow (ap[1]  , cp[1]);
+                                        cp[2] =  fcomplex.Pow (ap[2]  , cp[2]);
+                                        cp[3] =  fcomplex.Pow (ap[3]  , cp[3]);
+                                        cp[4] =  fcomplex.Pow (ap[4]  , cp[4]);
+                                        cp[5] =  fcomplex.Pow (ap[5]  , cp[5]);
+                                        cp[6] =  fcomplex.Pow (ap[6]  , cp[6]);
+                                        cp[7] =  fcomplex.Pow (ap[7]  , cp[7]);
+                                        cp[8] =  fcomplex.Pow (ap[8]  , cp[8]);
+                                        cp[9] =  fcomplex.Pow (ap[9]  , cp[9]);
+                                        cp[10] =  fcomplex.Pow (ap[10]  , cp[10]);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  fcomplex.Pow (*ap++  , *cp);
+                                        cp++; 
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                cp = (fcomplex*)range.Item4;
+                                ap = (fcomplex*)range.Item2;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    fcomplex val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  fcomplex.Pow (val  , cp[0]);
+                                        cp[1] =  fcomplex.Pow (val  , cp[1]);
+                                        cp[2] =  fcomplex.Pow (val  , cp[2]);
+                                        cp[3] =  fcomplex.Pow (val  , cp[3]);
+                                        cp[4] =  fcomplex.Pow (val  , cp[4]);
+                                        cp[5] =  fcomplex.Pow (val  , cp[5]);
+                                        cp[6] =  fcomplex.Pow (val  , cp[6]);
+                                        cp[7] =  fcomplex.Pow (val  , cp[7]);
+                                        cp[8] =  fcomplex.Pow (val  , cp[8]);
+                                        cp[9] =  fcomplex.Pow (val  , cp[9]);
+                                        cp[10] =  fcomplex.Pow (val  , cp[10]);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  fcomplex.Pow (val  , *cp);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            if (dim == 0) {
+                                ap = (fcomplex*)range.Item2;
+                                cp = (fcomplex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (fcomplex*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  fcomplex.Pow (ap[0]  , bp[0]);
+                                        cp[1] =  fcomplex.Pow (ap[1]  , bp[1]);
+                                        cp[2] =  fcomplex.Pow (ap[2]  , bp[2]);
+                                        cp[3] =  fcomplex.Pow (ap[3]  , bp[3]);
+                                        cp[4] =  fcomplex.Pow (ap[4]  , bp[4]);
+                                        cp[5] =  fcomplex.Pow (ap[5]  , bp[5]);
+                                        cp[6] =  fcomplex.Pow (ap[6]  , bp[6]);
+                                        cp[7] =  fcomplex.Pow (ap[7]  , bp[7]);
+                                        cp[8] =  fcomplex.Pow (ap[8]  , bp[8]);
+                                        cp[9] =  fcomplex.Pow (ap[9]  , bp[9]);
+                                        cp[10] =  fcomplex.Pow (ap[10]  , bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  fcomplex.Pow (*ap  , *bp);
+                                        ap++;
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                ap = (fcomplex*)range.Item2;
+                                bp = (fcomplex*)range.Item3;
+                                cp = (fcomplex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   fcomplex val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  fcomplex.Pow (ap[0]  , val);
+                                        cp[1] =  fcomplex.Pow (ap[1]  , val);
+                                        cp[2] =  fcomplex.Pow (ap[2]  , val);
+                                        cp[3] =  fcomplex.Pow (ap[3]  , val);
+                                        cp[4] =  fcomplex.Pow (ap[4]  , val);
+                                        cp[5] =  fcomplex.Pow (ap[5]  , val);
+                                        cp[6] =  fcomplex.Pow (ap[6]  , val);
+                                        cp[7] =  fcomplex.Pow (ap[7]  , val);
+                                        cp[8] =  fcomplex.Pow (ap[8]  , val);
+                                        cp[9] =  fcomplex.Pow (ap[9]  , val);
+                                        cp[10] =  fcomplex.Pow (ap[10]  , val);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  fcomplex.Pow (*ap  , val);
+                                        ap++;
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            if (dim == 0) {
+                                cp = (fcomplex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (fcomplex*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  fcomplex.Pow (cp[0]  , bp[0]);
+                                        cp[1] =  fcomplex.Pow (cp[1]  , bp[1]);
+                                        cp[2] =  fcomplex.Pow (cp[2]  , bp[2]);
+                                        cp[3] =  fcomplex.Pow (cp[3]  , bp[3]);
+                                        cp[4] =  fcomplex.Pow (cp[4]  , bp[4]);
+                                        cp[5] =  fcomplex.Pow (cp[5]  , bp[5]);
+                                        cp[6] =  fcomplex.Pow (cp[6]  , bp[6]);
+                                        cp[7] =  fcomplex.Pow (cp[7]  , bp[7]);
+                                        cp[8] =  fcomplex.Pow (cp[8]  , bp[8]);
+                                        cp[9] =  fcomplex.Pow (cp[9]  , bp[9]);
+                                        cp[10] =  fcomplex.Pow (cp[10]  , bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  fcomplex.Pow (*cp  , *bp);
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                bp = (fcomplex*)range.Item3;
+                                cp = (fcomplex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    fcomplex val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  fcomplex.Pow (cp[0]  , val);
+                                        cp[1] =  fcomplex.Pow (cp[1]  , val);
+                                        cp[2] =  fcomplex.Pow (cp[2]  , val);
+                                        cp[3] =  fcomplex.Pow (cp[3]  , val);
+                                        cp[4] =  fcomplex.Pow (cp[4]  , val);
+                                        cp[5] =  fcomplex.Pow (cp[5]  , val);
+                                        cp[6] =  fcomplex.Pow (cp[6]  , val);
+                                        cp[7] =  fcomplex.Pow (cp[7]  , val);
+                                        cp[8] =  fcomplex.Pow (cp[8]  , val);
+                                        cp[9] =  fcomplex.Pow (cp[9]  , val);
+                                        cp[10] =  fcomplex.Pow (cp[10]  , val);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l --> 0) {
+                                        *cp =  fcomplex.Pow (*cp  , val);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outDims.NumberOfElements >= Settings.s_minParallelElement1Count
+                    && outDims[1] > 1) {
+                        if (outDims[1] > workItemCount) {
+                        workItemLength = outDims[1] / workItemCount;
+                    } else {
+                        workItemLength = outDims[1] / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outDims[1];
+                    workItemCount = 1;
+                }
+
+                fixed ( fcomplex* arrAP = arrA)
+                fixed ( fcomplex* arrBP = arrB)
+                fixed ( fcomplex* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, IntPtr, IntPtr, IntPtr> range = new Tuple<int, IntPtr, IntPtr, IntPtr>
+                               (workItemLength
+                               , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                               , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                               , (IntPtr)(retArrP + i * outDims[0] * workItemLength)); 
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, IntPtr, IntPtr, IntPtr>
+                                (outDims[1] - i * workItemLength
+                                , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                                , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                                , (IntPtr)(retArrP + i * outDims[0] * workItemLength)));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<fcomplex>(retStorage);
+            //}  // no scopes here! it disables implace operations
+        }
+
+        /// <summary>Power elements</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Array with elementwise result of A <sup>B</sup></returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<complex>  pow(ILInArray<complex> A, ILInArray<complex> B) {
+            using (ILScope.Enter(A,B)) {
+                int outLen; 
+                BinOpItMode mode; 
+                complex [] retArr;
+                complex [] arrA = A.GetArrayForRead();
+                complex[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size; 
+                    if (B.IsScalar) {
+                       
+                        return new  ILRetArray<complex> (new  complex [1]{ complex.Pow (A.GetValue(0)  , B.GetValue(0))}, A.Size);
+                    } else if (B.IsEmpty) {
+                        return  ILRetArray<complex>.empty(outDims); 
+                    } else {
+                        outLen = outDims.NumberOfElements; 
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< complex > (outLen);
+                            mode = BinOpItMode.SAN; 
+                        } else {
+                            mode = BinOpItMode.SAI; 
+                        }
+                    }
+                } else {
+                    outDims = A.Size; 
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return  ILRetArray<complex>.empty(A.Size);  
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< complex > (outLen);
+                            mode = BinOpItMode.ASN; 
+                        } else {
+                            mode = BinOpItMode.ASI; 
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  powEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (A.TryGetStorage4InplaceOp(out retArr)) 
+                            mode  = BinOpItMode.AAIA; 
+                        else if (B.TryGetStorage4InplaceOp(out retArr)) 
+                            mode = BinOpItMode.AAIB; 
+                        else {
+                            retArr = ILMemoryPool.Pool.New< complex > (outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<complex> retStorage = new ILDenseStorage<complex>(retArr, outDims);
+                int i = 0, workerCount = 1; 
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    complex* cp = (complex*)range.Item5 + range.Item1;
+                    complex scalar;
+                    int j = range.Item2; 
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           complex* bp = ((complex*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                                cp[0] =  complex.Pow (cp[0]  , bp[0]);
+                                cp[1] =  complex.Pow (cp[1]  , bp[1]);
+                                cp[2] =  complex.Pow (cp[2]  , bp[2]);
+                                cp[3] =  complex.Pow (cp[3]  , bp[3]);
+                                cp[4] =  complex.Pow (cp[4]  , bp[4]);
+                                cp[5] =  complex.Pow (cp[5]  , bp[5]);
+                                cp[6] =  complex.Pow (cp[6]  , bp[6]);
+                                cp[7] =  complex.Pow (cp[7]  , bp[7]);
+                                cp[8] =  complex.Pow (cp[8]  , bp[8]);
+                                cp[9] =  complex.Pow (cp[9]  , bp[9]);
+                                cp[10] =  complex.Pow (cp[10]  , bp[10]);
+                                cp[11] =  complex.Pow (cp[11]  , bp[11]);
+                                cp[12] =  complex.Pow (cp[12]  , bp[12]);
+                                cp[13] =  complex.Pow (cp[13]  , bp[13]);
+                                cp[14] =  complex.Pow (cp[14]  , bp[14]);
+                                cp[15] =  complex.Pow (cp[15]  , bp[15]);
+                                cp[16] =  complex.Pow (cp[16]  , bp[16]);
+                                cp[17] =  complex.Pow (cp[17]  , bp[17]);
+                                cp[18] =  complex.Pow (cp[18]  , bp[18]);
+                                cp[19] =  complex.Pow (cp[19]  , bp[19]);
+                                cp[20] =  complex.Pow (cp[20]  , bp[20]);
+                                cp += 21; bp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  complex.Pow (*cp  , *bp);
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           complex* ap = ((complex*)range.Item3 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  complex.Pow (ap[0]  , cp[0]);
+                                cp[1] =  complex.Pow (ap[1]  , cp[1]);
+                                cp[2] =  complex.Pow (ap[2]  , cp[2]);
+                                cp[3] =  complex.Pow (ap[3]  , cp[3]);
+                                cp[4] =  complex.Pow (ap[4]  , cp[4]);
+                                cp[5] =  complex.Pow (ap[5]  , cp[5]);
+                                cp[6] =  complex.Pow (ap[6]  , cp[6]);
+                                cp[7] =  complex.Pow (ap[7]  , cp[7]);
+                                cp[8] =  complex.Pow (ap[8]  , cp[8]);
+                                cp[9] =  complex.Pow (ap[9]  , cp[9]);
+                                cp[10] =  complex.Pow (ap[10]  , cp[10]);
+                                cp[11] =  complex.Pow (ap[11]  , cp[11]);
+                                cp[12] =  complex.Pow (ap[12]  , cp[12]);
+                                cp[13] =  complex.Pow (ap[13]  , cp[13]);
+                                cp[14] =  complex.Pow (ap[14]  , cp[14]);
+                                cp[15] =  complex.Pow (ap[15]  , cp[15]);
+                                cp[16] =  complex.Pow (ap[16]  , cp[16]);
+                                cp[17] =  complex.Pow (ap[17]  , cp[17]);
+                                cp[18] =  complex.Pow (ap[18]  , cp[18]);
+                                cp[19] =  complex.Pow (ap[19]  , cp[19]);
+                                cp[20] =  complex.Pow (ap[20]  , cp[20]);
+                                ap += 21; cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  complex.Pow (*ap  , *cp);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((complex*)range.Item3 + range.Item1);
+                            bp = ((complex*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  complex.Pow (ap[0]  , bp[0]);
+                                cp[1] =  complex.Pow (ap[1]  , bp[1]);
+                                cp[2] =  complex.Pow (ap[2]  , bp[2]);
+                                cp[3] =  complex.Pow (ap[3]  , bp[3]);
+                                cp[4] =  complex.Pow (ap[4]  , bp[4]);
+                                cp[5] =  complex.Pow (ap[5]  , bp[5]);
+                                cp[6] =  complex.Pow (ap[6]  , bp[6]);
+                                cp[7] =  complex.Pow (ap[7]  , bp[7]);
+                                cp[8] =  complex.Pow (ap[8]  , bp[8]);
+                                cp[9] =  complex.Pow (ap[9]  , bp[9]);
+                                cp[10] =  complex.Pow (ap[10]  , bp[10]);
+                                cp[11] =  complex.Pow (ap[11]  , bp[11]);
+                                cp[12] =  complex.Pow (ap[12]  , bp[12]);
+                                cp[13] =  complex.Pow (ap[13]  , bp[13]);
+                                cp[14] =  complex.Pow (ap[14]  , bp[14]);
+                                cp[15] =  complex.Pow (ap[15]  , bp[15]);
+                                cp[16] =  complex.Pow (ap[16]  , bp[16]);
+                                cp[17] =  complex.Pow (ap[17]  , bp[17]);
+                                cp[18] =  complex.Pow (ap[18]  , bp[18]);
+                                cp[19] =  complex.Pow (ap[19]  , bp[19]);
+                                cp[20] =  complex.Pow (ap[20]  , bp[20]);
+                                ap+=21; bp+=21; cp+=21; j-=21;
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  complex.Pow (*ap  , *bp);
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((complex*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =  complex.Pow (cp[0]  , scalar);
+                                cp[1] =  complex.Pow (cp[1]  , scalar);
+                                cp[2] =  complex.Pow (cp[2]  , scalar);
+                                cp[3] =  complex.Pow (cp[3]  , scalar);
+                                cp[4] =  complex.Pow (cp[4]  , scalar);
+                                cp[5] =  complex.Pow (cp[5]  , scalar);
+                                cp[6] =  complex.Pow (cp[6]  , scalar);
+                                cp[7] =  complex.Pow (cp[7]  , scalar);
+                                cp[8] =  complex.Pow (cp[8]  , scalar);
+                                cp[9] =  complex.Pow (cp[9]  , scalar);
+                                cp[10] =  complex.Pow (cp[10]  , scalar);
+                                cp[11] =  complex.Pow (cp[11]  , scalar);
+                                cp[12] =  complex.Pow (cp[12]  , scalar);
+                                cp[13] =  complex.Pow (cp[13]  , scalar);
+                                cp[14] =  complex.Pow (cp[14]  , scalar);
+                                cp[15] =  complex.Pow (cp[15]  , scalar);
+                                cp[16] =  complex.Pow (cp[16]  , scalar);
+                                cp[17] =  complex.Pow (cp[17]  , scalar);
+                                cp[18] =  complex.Pow (cp[18]  , scalar);
+                                cp[19] =  complex.Pow (cp[19]  , scalar);
+                                cp[20] =  complex.Pow (cp[20]  , scalar);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  complex.Pow (*cp  , scalar);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((complex*)range.Item3 + range.Item1);
+                            scalar = *((complex*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =  complex.Pow (ap[0]  , scalar);
+                                cp[1] =  complex.Pow (ap[1]  , scalar);
+                                cp[2] =  complex.Pow (ap[2]  , scalar);
+                                cp[3] =  complex.Pow (ap[3]  , scalar);
+                                cp[4] =  complex.Pow (ap[4]  , scalar);
+                                cp[5] =  complex.Pow (ap[5]  , scalar);
+                                cp[6] =  complex.Pow (ap[6]  , scalar);
+                                cp[7] =  complex.Pow (ap[7]  , scalar);
+                                cp[8] =  complex.Pow (ap[8]  , scalar);
+                                cp[9] =  complex.Pow (ap[9]  , scalar);
+                                cp[10] =  complex.Pow (ap[10]  , scalar);
+                                cp[11] =  complex.Pow (ap[11]  , scalar);
+                                cp[12] =  complex.Pow (ap[12]  , scalar);
+                                cp[13] =  complex.Pow (ap[13]  , scalar);
+                                cp[14] =  complex.Pow (ap[14]  , scalar);
+                                cp[15] =  complex.Pow (ap[15]  , scalar);
+                                cp[16] =  complex.Pow (ap[16]  , scalar);
+                                cp[17] =  complex.Pow (ap[17]  , scalar);
+                                cp[18] =  complex.Pow (ap[18]  , scalar);
+                                cp[19] =  complex.Pow (ap[19]  , scalar);
+                                cp[20] =  complex.Pow (ap[20]  , scalar);
+                                ap+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  complex.Pow (*ap  , scalar);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((complex*)range.Item3);
+                            while (j > 20) {
+                               
+                                cp[0] =  complex.Pow (scalar  , cp[0]);
+                                cp[1] =  complex.Pow (scalar  , cp[1]);
+                                cp[2] =  complex.Pow (scalar  , cp[2]);
+                                cp[3] =  complex.Pow (scalar  , cp[3]);
+                                cp[4] =  complex.Pow (scalar  , cp[4]);
+                                cp[5] =  complex.Pow (scalar  , cp[5]);
+                                cp[6] =  complex.Pow (scalar  , cp[6]);
+                                cp[7] =  complex.Pow (scalar  , cp[7]);
+                                cp[8] =  complex.Pow (scalar  , cp[8]);
+                                cp[9] =  complex.Pow (scalar  , cp[9]);
+                                cp[10] =  complex.Pow (scalar  , cp[10]);
+                                cp[11] =  complex.Pow (scalar  , cp[11]);
+                                cp[12] =  complex.Pow (scalar  , cp[12]);
+                                cp[13] =  complex.Pow (scalar  , cp[13]);
+                                cp[14] =  complex.Pow (scalar  , cp[14]);
+                                cp[15] =  complex.Pow (scalar  , cp[15]);
+                                cp[16] =  complex.Pow (scalar  , cp[16]);
+                                cp[17] =  complex.Pow (scalar  , cp[17]);
+                                cp[18] =  complex.Pow (scalar  , cp[18]);
+                                cp[19] =  complex.Pow (scalar  , cp[19]);
+                                cp[20] =  complex.Pow (scalar  , cp[20]);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  complex.Pow (scalar  , *cp);
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((complex*)range.Item3);
+                            bp = ((complex*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  complex.Pow (scalar  , bp[0]);
+                                cp[1] =  complex.Pow (scalar  , bp[1]);
+                                cp[2] =  complex.Pow (scalar  , bp[2]);
+                                cp[3] =  complex.Pow (scalar  , bp[3]);
+                                cp[4] =  complex.Pow (scalar  , bp[4]);
+                                cp[5] =  complex.Pow (scalar  , bp[5]);
+                                cp[6] =  complex.Pow (scalar  , bp[6]);
+                                cp[7] =  complex.Pow (scalar  , bp[7]);
+                                cp[8] =  complex.Pow (scalar  , bp[8]);
+                                cp[9] =  complex.Pow (scalar  , bp[9]);
+                                cp[10] =  complex.Pow (scalar  , bp[10]);
+                                cp[11] =  complex.Pow (scalar  , bp[11]);
+                                cp[12] =  complex.Pow (scalar  , bp[12]);
+                                cp[13] =  complex.Pow (scalar  , bp[13]);
+                                cp[14] =  complex.Pow (scalar  , bp[14]);
+                                cp[15] =  complex.Pow (scalar  , bp[15]);
+                                cp[16] =  complex.Pow (scalar  , bp[16]);
+                                cp[17] =  complex.Pow (scalar  , bp[17]);
+                                cp[18] =  complex.Pow (scalar  , bp[18]);
+                                cp[19] =  complex.Pow (scalar  , bp[19]);
+                                cp[20] =  complex.Pow (scalar  , bp[20]);
+                                bp+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  complex.Pow (scalar  , *bp);
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work 
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                
+                fixed ( complex* arrAP = arrA)
+                fixed ( complex* arrBP = arrB)
+                fixed ( complex* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range 
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new  ILRetArray< complex>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<complex>  powEx(ILInArray<complex> A, ILInArray<complex> B) {
+            //using (ILScope.Enter(A, B)) { we cannot start a new scope here, since this would prevent A and B to be used implace if applicable
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<complex>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<complex>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<complex>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                dim = -(dim - 1);  // 0 -> 1, 1 -> 0
+                #endregion
+
+                #region parameter preparation
+               
+                complex[] retArr;
+               
+                complex[] arrA = A.GetArrayForRead();
+               
+                complex[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int workItemMultiplierLenA;
+                int workItemMultiplierLenB;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<complex>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    workItemMultiplierLenB = outDims[0]; 
+                    workItemMultiplierLenA = dim;  // 0 for column, 1 for row vector
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<complex>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    workItemMultiplierLenB = dim;  // 0 for column, 1 for row vector
+                    workItemMultiplierLenA = outDims[0]; 
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one singleton dimension in either A or B");
+                }
+                int itLen = outDims[0]; // (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<complex> retStorage = new ILDenseStorage<complex>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    complex* ap;
+                   
+                    complex* bp;
+                   
+                    complex* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            if (dim == 0) {
+                                bp = (complex*)range.Item3;
+                                cp = (complex*)range.Item4; 
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (complex*)range.Item2;
+                                    int l = itLen; 
+                                    while (l > 10) {
+                                        cp[0] =  complex.Pow (ap[0]  , bp[0]);
+                                        cp[1] =  complex.Pow (ap[1]  , bp[1]);
+                                        cp[2] =  complex.Pow (ap[2]  , bp[2]);
+                                        cp[3] =  complex.Pow (ap[3]  , bp[3]);
+                                        cp[4] =  complex.Pow (ap[4]  , bp[4]);
+                                        cp[5] =  complex.Pow (ap[5]  , bp[5]);
+                                        cp[6] =  complex.Pow (ap[6]  , bp[6]);
+                                        cp[7] =  complex.Pow (ap[7]  , bp[7]);
+                                        cp[8] =  complex.Pow (ap[8]  , bp[8]);
+                                        cp[9] =  complex.Pow (ap[9]  , bp[9]);
+                                        cp[10] =  complex.Pow (ap[10]  , bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =  complex.Pow (*ap++  , *bp++);
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                ap = (complex*)range.Item2;
+                                bp = (complex*)range.Item3;
+                                cp = (complex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   complex val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  complex.Pow (val  , bp[0]);
+                                        cp[1] =  complex.Pow (val  , bp[1]);
+                                        cp[2] =  complex.Pow (val  , bp[2]);
+                                        cp[3] =  complex.Pow (val  , bp[3]);
+                                        cp[4] =  complex.Pow (val  , bp[4]);
+                                        cp[5] =  complex.Pow (val  , bp[5]);
+                                        cp[6] =  complex.Pow (val  , bp[6]);
+                                        cp[7] =  complex.Pow (val  , bp[7]);
+                                        cp[8] =  complex.Pow (val  , bp[8]);
+                                        cp[9] =  complex.Pow (val  , bp[9]);
+                                        cp[10] =  complex.Pow (val  , bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11; 
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =  complex.Pow (val  , *bp++);
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            if (dim == 0) {
+                                cp = (complex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (complex*)range.Item2;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  complex.Pow (ap[0]  , cp[0]);
+                                        cp[1] =  complex.Pow (ap[1]  , cp[1]);
+                                        cp[2] =  complex.Pow (ap[2]  , cp[2]);
+                                        cp[3] =  complex.Pow (ap[3]  , cp[3]);
+                                        cp[4] =  complex.Pow (ap[4]  , cp[4]);
+                                        cp[5] =  complex.Pow (ap[5]  , cp[5]);
+                                        cp[6] =  complex.Pow (ap[6]  , cp[6]);
+                                        cp[7] =  complex.Pow (ap[7]  , cp[7]);
+                                        cp[8] =  complex.Pow (ap[8]  , cp[8]);
+                                        cp[9] =  complex.Pow (ap[9]  , cp[9]);
+                                        cp[10] =  complex.Pow (ap[10]  , cp[10]);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  complex.Pow (*ap++  , *cp);
+                                        cp++; 
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                cp = (complex*)range.Item4;
+                                ap = (complex*)range.Item2;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    complex val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  complex.Pow (val  , cp[0]);
+                                        cp[1] =  complex.Pow (val  , cp[1]);
+                                        cp[2] =  complex.Pow (val  , cp[2]);
+                                        cp[3] =  complex.Pow (val  , cp[3]);
+                                        cp[4] =  complex.Pow (val  , cp[4]);
+                                        cp[5] =  complex.Pow (val  , cp[5]);
+                                        cp[6] =  complex.Pow (val  , cp[6]);
+                                        cp[7] =  complex.Pow (val  , cp[7]);
+                                        cp[8] =  complex.Pow (val  , cp[8]);
+                                        cp[9] =  complex.Pow (val  , cp[9]);
+                                        cp[10] =  complex.Pow (val  , cp[10]);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  complex.Pow (val  , *cp);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            if (dim == 0) {
+                                ap = (complex*)range.Item2;
+                                cp = (complex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (complex*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  complex.Pow (ap[0]  , bp[0]);
+                                        cp[1] =  complex.Pow (ap[1]  , bp[1]);
+                                        cp[2] =  complex.Pow (ap[2]  , bp[2]);
+                                        cp[3] =  complex.Pow (ap[3]  , bp[3]);
+                                        cp[4] =  complex.Pow (ap[4]  , bp[4]);
+                                        cp[5] =  complex.Pow (ap[5]  , bp[5]);
+                                        cp[6] =  complex.Pow (ap[6]  , bp[6]);
+                                        cp[7] =  complex.Pow (ap[7]  , bp[7]);
+                                        cp[8] =  complex.Pow (ap[8]  , bp[8]);
+                                        cp[9] =  complex.Pow (ap[9]  , bp[9]);
+                                        cp[10] =  complex.Pow (ap[10]  , bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  complex.Pow (*ap  , *bp);
+                                        ap++;
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                ap = (complex*)range.Item2;
+                                bp = (complex*)range.Item3;
+                                cp = (complex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   complex val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  complex.Pow (ap[0]  , val);
+                                        cp[1] =  complex.Pow (ap[1]  , val);
+                                        cp[2] =  complex.Pow (ap[2]  , val);
+                                        cp[3] =  complex.Pow (ap[3]  , val);
+                                        cp[4] =  complex.Pow (ap[4]  , val);
+                                        cp[5] =  complex.Pow (ap[5]  , val);
+                                        cp[6] =  complex.Pow (ap[6]  , val);
+                                        cp[7] =  complex.Pow (ap[7]  , val);
+                                        cp[8] =  complex.Pow (ap[8]  , val);
+                                        cp[9] =  complex.Pow (ap[9]  , val);
+                                        cp[10] =  complex.Pow (ap[10]  , val);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  complex.Pow (*ap  , val);
+                                        ap++;
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            if (dim == 0) {
+                                cp = (complex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (complex*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  complex.Pow (cp[0]  , bp[0]);
+                                        cp[1] =  complex.Pow (cp[1]  , bp[1]);
+                                        cp[2] =  complex.Pow (cp[2]  , bp[2]);
+                                        cp[3] =  complex.Pow (cp[3]  , bp[3]);
+                                        cp[4] =  complex.Pow (cp[4]  , bp[4]);
+                                        cp[5] =  complex.Pow (cp[5]  , bp[5]);
+                                        cp[6] =  complex.Pow (cp[6]  , bp[6]);
+                                        cp[7] =  complex.Pow (cp[7]  , bp[7]);
+                                        cp[8] =  complex.Pow (cp[8]  , bp[8]);
+                                        cp[9] =  complex.Pow (cp[9]  , bp[9]);
+                                        cp[10] =  complex.Pow (cp[10]  , bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  complex.Pow (*cp  , *bp);
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                bp = (complex*)range.Item3;
+                                cp = (complex*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    complex val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  complex.Pow (cp[0]  , val);
+                                        cp[1] =  complex.Pow (cp[1]  , val);
+                                        cp[2] =  complex.Pow (cp[2]  , val);
+                                        cp[3] =  complex.Pow (cp[3]  , val);
+                                        cp[4] =  complex.Pow (cp[4]  , val);
+                                        cp[5] =  complex.Pow (cp[5]  , val);
+                                        cp[6] =  complex.Pow (cp[6]  , val);
+                                        cp[7] =  complex.Pow (cp[7]  , val);
+                                        cp[8] =  complex.Pow (cp[8]  , val);
+                                        cp[9] =  complex.Pow (cp[9]  , val);
+                                        cp[10] =  complex.Pow (cp[10]  , val);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l --> 0) {
+                                        *cp =  complex.Pow (*cp  , val);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outDims.NumberOfElements >= Settings.s_minParallelElement1Count
+                    && outDims[1] > 1) {
+                        if (outDims[1] > workItemCount) {
+                        workItemLength = outDims[1] / workItemCount;
+                    } else {
+                        workItemLength = outDims[1] / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outDims[1];
+                    workItemCount = 1;
+                }
+
+                fixed ( complex* arrAP = arrA)
+                fixed ( complex* arrBP = arrB)
+                fixed ( complex* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, IntPtr, IntPtr, IntPtr> range = new Tuple<int, IntPtr, IntPtr, IntPtr>
+                               (workItemLength
+                               , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                               , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                               , (IntPtr)(retArrP + i * outDims[0] * workItemLength)); 
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, IntPtr, IntPtr, IntPtr>
+                                (outDims[1] - i * workItemLength
+                                , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                                , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                                , (IntPtr)(retArrP + i * outDims[0] * workItemLength)));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<complex>(retStorage);
+            //}  // no scopes here! it disables implace operations
+        }
+
+        /// <summary>Power elements</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Array with elementwise result of A <sup>B</sup></returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<byte>  pow(ILInArray<byte> A, ILInArray<byte> B) {
+            using (ILScope.Enter(A,B)) {
+                int outLen; 
+                BinOpItMode mode; 
+                byte [] retArr;
+                byte [] arrA = A.GetArrayForRead();
+                byte[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size; 
+                    if (B.IsScalar) {
+                       
+                        return new  ILRetArray<byte> (new  byte [1]{ saturateBytePow (A.GetValue(0)  , B.GetValue(0))}, A.Size);
+                    } else if (B.IsEmpty) {
+                        return  ILRetArray<byte>.empty(outDims); 
+                    } else {
+                        outLen = outDims.NumberOfElements; 
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< byte > (outLen);
+                            mode = BinOpItMode.SAN; 
+                        } else {
+                            mode = BinOpItMode.SAI; 
+                        }
+                    }
+                } else {
+                    outDims = A.Size; 
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return  ILRetArray<byte>.empty(A.Size);  
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< byte > (outLen);
+                            mode = BinOpItMode.ASN; 
+                        } else {
+                            mode = BinOpItMode.ASI; 
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  powEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (A.TryGetStorage4InplaceOp(out retArr)) 
+                            mode  = BinOpItMode.AAIA; 
+                        else if (B.TryGetStorage4InplaceOp(out retArr)) 
+                            mode = BinOpItMode.AAIB; 
+                        else {
+                            retArr = ILMemoryPool.Pool.New< byte > (outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<byte> retStorage = new ILDenseStorage<byte>(retArr, outDims);
+                int i = 0, workerCount = 1; 
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cp = (byte*)range.Item5 + range.Item1;
+                    byte scalar;
+                    int j = range.Item2; 
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           byte* bp = ((byte*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                                cp[0] =  saturateBytePow (cp[0]  , bp[0]);
+                                cp[1] =  saturateBytePow (cp[1]  , bp[1]);
+                                cp[2] =  saturateBytePow (cp[2]  , bp[2]);
+                                cp[3] =  saturateBytePow (cp[3]  , bp[3]);
+                                cp[4] =  saturateBytePow (cp[4]  , bp[4]);
+                                cp[5] =  saturateBytePow (cp[5]  , bp[5]);
+                                cp[6] =  saturateBytePow (cp[6]  , bp[6]);
+                                cp[7] =  saturateBytePow (cp[7]  , bp[7]);
+                                cp[8] =  saturateBytePow (cp[8]  , bp[8]);
+                                cp[9] =  saturateBytePow (cp[9]  , bp[9]);
+                                cp[10] =  saturateBytePow (cp[10]  , bp[10]);
+                                cp[11] =  saturateBytePow (cp[11]  , bp[11]);
+                                cp[12] =  saturateBytePow (cp[12]  , bp[12]);
+                                cp[13] =  saturateBytePow (cp[13]  , bp[13]);
+                                cp[14] =  saturateBytePow (cp[14]  , bp[14]);
+                                cp[15] =  saturateBytePow (cp[15]  , bp[15]);
+                                cp[16] =  saturateBytePow (cp[16]  , bp[16]);
+                                cp[17] =  saturateBytePow (cp[17]  , bp[17]);
+                                cp[18] =  saturateBytePow (cp[18]  , bp[18]);
+                                cp[19] =  saturateBytePow (cp[19]  , bp[19]);
+                                cp[20] =  saturateBytePow (cp[20]  , bp[20]);
+                                cp += 21; bp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateBytePow (*cp  , *bp);
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           byte* ap = ((byte*)range.Item3 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateBytePow (ap[0]  , cp[0]);
+                                cp[1] =  saturateBytePow (ap[1]  , cp[1]);
+                                cp[2] =  saturateBytePow (ap[2]  , cp[2]);
+                                cp[3] =  saturateBytePow (ap[3]  , cp[3]);
+                                cp[4] =  saturateBytePow (ap[4]  , cp[4]);
+                                cp[5] =  saturateBytePow (ap[5]  , cp[5]);
+                                cp[6] =  saturateBytePow (ap[6]  , cp[6]);
+                                cp[7] =  saturateBytePow (ap[7]  , cp[7]);
+                                cp[8] =  saturateBytePow (ap[8]  , cp[8]);
+                                cp[9] =  saturateBytePow (ap[9]  , cp[9]);
+                                cp[10] =  saturateBytePow (ap[10]  , cp[10]);
+                                cp[11] =  saturateBytePow (ap[11]  , cp[11]);
+                                cp[12] =  saturateBytePow (ap[12]  , cp[12]);
+                                cp[13] =  saturateBytePow (ap[13]  , cp[13]);
+                                cp[14] =  saturateBytePow (ap[14]  , cp[14]);
+                                cp[15] =  saturateBytePow (ap[15]  , cp[15]);
+                                cp[16] =  saturateBytePow (ap[16]  , cp[16]);
+                                cp[17] =  saturateBytePow (ap[17]  , cp[17]);
+                                cp[18] =  saturateBytePow (ap[18]  , cp[18]);
+                                cp[19] =  saturateBytePow (ap[19]  , cp[19]);
+                                cp[20] =  saturateBytePow (ap[20]  , cp[20]);
+                                ap += 21; cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateBytePow (*ap  , *cp);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((byte*)range.Item3 + range.Item1);
+                            bp = ((byte*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateBytePow (ap[0]  , bp[0]);
+                                cp[1] =  saturateBytePow (ap[1]  , bp[1]);
+                                cp[2] =  saturateBytePow (ap[2]  , bp[2]);
+                                cp[3] =  saturateBytePow (ap[3]  , bp[3]);
+                                cp[4] =  saturateBytePow (ap[4]  , bp[4]);
+                                cp[5] =  saturateBytePow (ap[5]  , bp[5]);
+                                cp[6] =  saturateBytePow (ap[6]  , bp[6]);
+                                cp[7] =  saturateBytePow (ap[7]  , bp[7]);
+                                cp[8] =  saturateBytePow (ap[8]  , bp[8]);
+                                cp[9] =  saturateBytePow (ap[9]  , bp[9]);
+                                cp[10] =  saturateBytePow (ap[10]  , bp[10]);
+                                cp[11] =  saturateBytePow (ap[11]  , bp[11]);
+                                cp[12] =  saturateBytePow (ap[12]  , bp[12]);
+                                cp[13] =  saturateBytePow (ap[13]  , bp[13]);
+                                cp[14] =  saturateBytePow (ap[14]  , bp[14]);
+                                cp[15] =  saturateBytePow (ap[15]  , bp[15]);
+                                cp[16] =  saturateBytePow (ap[16]  , bp[16]);
+                                cp[17] =  saturateBytePow (ap[17]  , bp[17]);
+                                cp[18] =  saturateBytePow (ap[18]  , bp[18]);
+                                cp[19] =  saturateBytePow (ap[19]  , bp[19]);
+                                cp[20] =  saturateBytePow (ap[20]  , bp[20]);
+                                ap+=21; bp+=21; cp+=21; j-=21;
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateBytePow (*ap  , *bp);
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((byte*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateBytePow (cp[0]  , scalar);
+                                cp[1] =  saturateBytePow (cp[1]  , scalar);
+                                cp[2] =  saturateBytePow (cp[2]  , scalar);
+                                cp[3] =  saturateBytePow (cp[3]  , scalar);
+                                cp[4] =  saturateBytePow (cp[4]  , scalar);
+                                cp[5] =  saturateBytePow (cp[5]  , scalar);
+                                cp[6] =  saturateBytePow (cp[6]  , scalar);
+                                cp[7] =  saturateBytePow (cp[7]  , scalar);
+                                cp[8] =  saturateBytePow (cp[8]  , scalar);
+                                cp[9] =  saturateBytePow (cp[9]  , scalar);
+                                cp[10] =  saturateBytePow (cp[10]  , scalar);
+                                cp[11] =  saturateBytePow (cp[11]  , scalar);
+                                cp[12] =  saturateBytePow (cp[12]  , scalar);
+                                cp[13] =  saturateBytePow (cp[13]  , scalar);
+                                cp[14] =  saturateBytePow (cp[14]  , scalar);
+                                cp[15] =  saturateBytePow (cp[15]  , scalar);
+                                cp[16] =  saturateBytePow (cp[16]  , scalar);
+                                cp[17] =  saturateBytePow (cp[17]  , scalar);
+                                cp[18] =  saturateBytePow (cp[18]  , scalar);
+                                cp[19] =  saturateBytePow (cp[19]  , scalar);
+                                cp[20] =  saturateBytePow (cp[20]  , scalar);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateBytePow (*cp  , scalar);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((byte*)range.Item3 + range.Item1);
+                            scalar = *((byte*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateBytePow (ap[0]  , scalar);
+                                cp[1] =  saturateBytePow (ap[1]  , scalar);
+                                cp[2] =  saturateBytePow (ap[2]  , scalar);
+                                cp[3] =  saturateBytePow (ap[3]  , scalar);
+                                cp[4] =  saturateBytePow (ap[4]  , scalar);
+                                cp[5] =  saturateBytePow (ap[5]  , scalar);
+                                cp[6] =  saturateBytePow (ap[6]  , scalar);
+                                cp[7] =  saturateBytePow (ap[7]  , scalar);
+                                cp[8] =  saturateBytePow (ap[8]  , scalar);
+                                cp[9] =  saturateBytePow (ap[9]  , scalar);
+                                cp[10] =  saturateBytePow (ap[10]  , scalar);
+                                cp[11] =  saturateBytePow (ap[11]  , scalar);
+                                cp[12] =  saturateBytePow (ap[12]  , scalar);
+                                cp[13] =  saturateBytePow (ap[13]  , scalar);
+                                cp[14] =  saturateBytePow (ap[14]  , scalar);
+                                cp[15] =  saturateBytePow (ap[15]  , scalar);
+                                cp[16] =  saturateBytePow (ap[16]  , scalar);
+                                cp[17] =  saturateBytePow (ap[17]  , scalar);
+                                cp[18] =  saturateBytePow (ap[18]  , scalar);
+                                cp[19] =  saturateBytePow (ap[19]  , scalar);
+                                cp[20] =  saturateBytePow (ap[20]  , scalar);
+                                ap+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateBytePow (*ap  , scalar);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((byte*)range.Item3);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateBytePow (scalar  , cp[0]);
+                                cp[1] =  saturateBytePow (scalar  , cp[1]);
+                                cp[2] =  saturateBytePow (scalar  , cp[2]);
+                                cp[3] =  saturateBytePow (scalar  , cp[3]);
+                                cp[4] =  saturateBytePow (scalar  , cp[4]);
+                                cp[5] =  saturateBytePow (scalar  , cp[5]);
+                                cp[6] =  saturateBytePow (scalar  , cp[6]);
+                                cp[7] =  saturateBytePow (scalar  , cp[7]);
+                                cp[8] =  saturateBytePow (scalar  , cp[8]);
+                                cp[9] =  saturateBytePow (scalar  , cp[9]);
+                                cp[10] =  saturateBytePow (scalar  , cp[10]);
+                                cp[11] =  saturateBytePow (scalar  , cp[11]);
+                                cp[12] =  saturateBytePow (scalar  , cp[12]);
+                                cp[13] =  saturateBytePow (scalar  , cp[13]);
+                                cp[14] =  saturateBytePow (scalar  , cp[14]);
+                                cp[15] =  saturateBytePow (scalar  , cp[15]);
+                                cp[16] =  saturateBytePow (scalar  , cp[16]);
+                                cp[17] =  saturateBytePow (scalar  , cp[17]);
+                                cp[18] =  saturateBytePow (scalar  , cp[18]);
+                                cp[19] =  saturateBytePow (scalar  , cp[19]);
+                                cp[20] =  saturateBytePow (scalar  , cp[20]);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateBytePow (scalar  , *cp);
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((byte*)range.Item3);
+                            bp = ((byte*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  saturateBytePow (scalar  , bp[0]);
+                                cp[1] =  saturateBytePow (scalar  , bp[1]);
+                                cp[2] =  saturateBytePow (scalar  , bp[2]);
+                                cp[3] =  saturateBytePow (scalar  , bp[3]);
+                                cp[4] =  saturateBytePow (scalar  , bp[4]);
+                                cp[5] =  saturateBytePow (scalar  , bp[5]);
+                                cp[6] =  saturateBytePow (scalar  , bp[6]);
+                                cp[7] =  saturateBytePow (scalar  , bp[7]);
+                                cp[8] =  saturateBytePow (scalar  , bp[8]);
+                                cp[9] =  saturateBytePow (scalar  , bp[9]);
+                                cp[10] =  saturateBytePow (scalar  , bp[10]);
+                                cp[11] =  saturateBytePow (scalar  , bp[11]);
+                                cp[12] =  saturateBytePow (scalar  , bp[12]);
+                                cp[13] =  saturateBytePow (scalar  , bp[13]);
+                                cp[14] =  saturateBytePow (scalar  , bp[14]);
+                                cp[15] =  saturateBytePow (scalar  , bp[15]);
+                                cp[16] =  saturateBytePow (scalar  , bp[16]);
+                                cp[17] =  saturateBytePow (scalar  , bp[17]);
+                                cp[18] =  saturateBytePow (scalar  , bp[18]);
+                                cp[19] =  saturateBytePow (scalar  , bp[19]);
+                                cp[20] =  saturateBytePow (scalar  , bp[20]);
+                                bp+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  saturateBytePow (scalar  , *bp);
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work 
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                
+                fixed ( byte* arrAP = arrA)
+                fixed ( byte* arrBP = arrB)
+                fixed ( byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range 
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new  ILRetArray< byte>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<byte>  powEx(ILInArray<byte> A, ILInArray<byte> B) {
+            //using (ILScope.Enter(A, B)) { we cannot start a new scope here, since this would prevent A and B to be used implace if applicable
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<byte>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<byte>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<byte>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                dim = -(dim - 1);  // 0 -> 1, 1 -> 0
+                #endregion
+
+                #region parameter preparation
+               
+                byte[] retArr;
+               
+                byte[] arrA = A.GetArrayForRead();
+               
+                byte[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int workItemMultiplierLenA;
+                int workItemMultiplierLenB;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    workItemMultiplierLenB = outDims[0]; 
+                    workItemMultiplierLenA = dim;  // 0 for column, 1 for row vector
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    workItemMultiplierLenB = dim;  // 0 for column, 1 for row vector
+                    workItemMultiplierLenA = outDims[0]; 
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one singleton dimension in either A or B");
+                }
+                int itLen = outDims[0]; // (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<byte> retStorage = new ILDenseStorage<byte>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    byte* ap;
+                   
+                    byte* bp;
+                   
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            if (dim == 0) {
+                                bp = (byte*)range.Item3;
+                                cp = (byte*)range.Item4; 
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (byte*)range.Item2;
+                                    int l = itLen; 
+                                    while (l > 10) {
+                                        cp[0] =  saturateBytePow (ap[0]  , bp[0]);
+                                        cp[1] =  saturateBytePow (ap[1]  , bp[1]);
+                                        cp[2] =  saturateBytePow (ap[2]  , bp[2]);
+                                        cp[3] =  saturateBytePow (ap[3]  , bp[3]);
+                                        cp[4] =  saturateBytePow (ap[4]  , bp[4]);
+                                        cp[5] =  saturateBytePow (ap[5]  , bp[5]);
+                                        cp[6] =  saturateBytePow (ap[6]  , bp[6]);
+                                        cp[7] =  saturateBytePow (ap[7]  , bp[7]);
+                                        cp[8] =  saturateBytePow (ap[8]  , bp[8]);
+                                        cp[9] =  saturateBytePow (ap[9]  , bp[9]);
+                                        cp[10] =  saturateBytePow (ap[10]  , bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =  saturateBytePow (*ap++  , *bp++);
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                ap = (byte*)range.Item2;
+                                bp = (byte*)range.Item3;
+                                cp = (byte*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   byte val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateBytePow (val  , bp[0]);
+                                        cp[1] =  saturateBytePow (val  , bp[1]);
+                                        cp[2] =  saturateBytePow (val  , bp[2]);
+                                        cp[3] =  saturateBytePow (val  , bp[3]);
+                                        cp[4] =  saturateBytePow (val  , bp[4]);
+                                        cp[5] =  saturateBytePow (val  , bp[5]);
+                                        cp[6] =  saturateBytePow (val  , bp[6]);
+                                        cp[7] =  saturateBytePow (val  , bp[7]);
+                                        cp[8] =  saturateBytePow (val  , bp[8]);
+                                        cp[9] =  saturateBytePow (val  , bp[9]);
+                                        cp[10] =  saturateBytePow (val  , bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11; 
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =  saturateBytePow (val  , *bp++);
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            if (dim == 0) {
+                                cp = (byte*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (byte*)range.Item2;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateBytePow (ap[0]  , cp[0]);
+                                        cp[1] =  saturateBytePow (ap[1]  , cp[1]);
+                                        cp[2] =  saturateBytePow (ap[2]  , cp[2]);
+                                        cp[3] =  saturateBytePow (ap[3]  , cp[3]);
+                                        cp[4] =  saturateBytePow (ap[4]  , cp[4]);
+                                        cp[5] =  saturateBytePow (ap[5]  , cp[5]);
+                                        cp[6] =  saturateBytePow (ap[6]  , cp[6]);
+                                        cp[7] =  saturateBytePow (ap[7]  , cp[7]);
+                                        cp[8] =  saturateBytePow (ap[8]  , cp[8]);
+                                        cp[9] =  saturateBytePow (ap[9]  , cp[9]);
+                                        cp[10] =  saturateBytePow (ap[10]  , cp[10]);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateBytePow (*ap++  , *cp);
+                                        cp++; 
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                cp = (byte*)range.Item4;
+                                ap = (byte*)range.Item2;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    byte val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateBytePow (val  , cp[0]);
+                                        cp[1] =  saturateBytePow (val  , cp[1]);
+                                        cp[2] =  saturateBytePow (val  , cp[2]);
+                                        cp[3] =  saturateBytePow (val  , cp[3]);
+                                        cp[4] =  saturateBytePow (val  , cp[4]);
+                                        cp[5] =  saturateBytePow (val  , cp[5]);
+                                        cp[6] =  saturateBytePow (val  , cp[6]);
+                                        cp[7] =  saturateBytePow (val  , cp[7]);
+                                        cp[8] =  saturateBytePow (val  , cp[8]);
+                                        cp[9] =  saturateBytePow (val  , cp[9]);
+                                        cp[10] =  saturateBytePow (val  , cp[10]);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateBytePow (val  , *cp);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            if (dim == 0) {
+                                ap = (byte*)range.Item2;
+                                cp = (byte*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (byte*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateBytePow (ap[0]  , bp[0]);
+                                        cp[1] =  saturateBytePow (ap[1]  , bp[1]);
+                                        cp[2] =  saturateBytePow (ap[2]  , bp[2]);
+                                        cp[3] =  saturateBytePow (ap[3]  , bp[3]);
+                                        cp[4] =  saturateBytePow (ap[4]  , bp[4]);
+                                        cp[5] =  saturateBytePow (ap[5]  , bp[5]);
+                                        cp[6] =  saturateBytePow (ap[6]  , bp[6]);
+                                        cp[7] =  saturateBytePow (ap[7]  , bp[7]);
+                                        cp[8] =  saturateBytePow (ap[8]  , bp[8]);
+                                        cp[9] =  saturateBytePow (ap[9]  , bp[9]);
+                                        cp[10] =  saturateBytePow (ap[10]  , bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateBytePow (*ap  , *bp);
+                                        ap++;
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                ap = (byte*)range.Item2;
+                                bp = (byte*)range.Item3;
+                                cp = (byte*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   byte val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateBytePow (ap[0]  , val);
+                                        cp[1] =  saturateBytePow (ap[1]  , val);
+                                        cp[2] =  saturateBytePow (ap[2]  , val);
+                                        cp[3] =  saturateBytePow (ap[3]  , val);
+                                        cp[4] =  saturateBytePow (ap[4]  , val);
+                                        cp[5] =  saturateBytePow (ap[5]  , val);
+                                        cp[6] =  saturateBytePow (ap[6]  , val);
+                                        cp[7] =  saturateBytePow (ap[7]  , val);
+                                        cp[8] =  saturateBytePow (ap[8]  , val);
+                                        cp[9] =  saturateBytePow (ap[9]  , val);
+                                        cp[10] =  saturateBytePow (ap[10]  , val);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateBytePow (*ap  , val);
+                                        ap++;
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            if (dim == 0) {
+                                cp = (byte*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (byte*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateBytePow (cp[0]  , bp[0]);
+                                        cp[1] =  saturateBytePow (cp[1]  , bp[1]);
+                                        cp[2] =  saturateBytePow (cp[2]  , bp[2]);
+                                        cp[3] =  saturateBytePow (cp[3]  , bp[3]);
+                                        cp[4] =  saturateBytePow (cp[4]  , bp[4]);
+                                        cp[5] =  saturateBytePow (cp[5]  , bp[5]);
+                                        cp[6] =  saturateBytePow (cp[6]  , bp[6]);
+                                        cp[7] =  saturateBytePow (cp[7]  , bp[7]);
+                                        cp[8] =  saturateBytePow (cp[8]  , bp[8]);
+                                        cp[9] =  saturateBytePow (cp[9]  , bp[9]);
+                                        cp[10] =  saturateBytePow (cp[10]  , bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  saturateBytePow (*cp  , *bp);
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                bp = (byte*)range.Item3;
+                                cp = (byte*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    byte val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  saturateBytePow (cp[0]  , val);
+                                        cp[1] =  saturateBytePow (cp[1]  , val);
+                                        cp[2] =  saturateBytePow (cp[2]  , val);
+                                        cp[3] =  saturateBytePow (cp[3]  , val);
+                                        cp[4] =  saturateBytePow (cp[4]  , val);
+                                        cp[5] =  saturateBytePow (cp[5]  , val);
+                                        cp[6] =  saturateBytePow (cp[6]  , val);
+                                        cp[7] =  saturateBytePow (cp[7]  , val);
+                                        cp[8] =  saturateBytePow (cp[8]  , val);
+                                        cp[9] =  saturateBytePow (cp[9]  , val);
+                                        cp[10] =  saturateBytePow (cp[10]  , val);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l --> 0) {
+                                        *cp =  saturateBytePow (*cp  , val);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outDims.NumberOfElements >= Settings.s_minParallelElement1Count
+                    && outDims[1] > 1) {
+                        if (outDims[1] > workItemCount) {
+                        workItemLength = outDims[1] / workItemCount;
+                    } else {
+                        workItemLength = outDims[1] / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outDims[1];
+                    workItemCount = 1;
+                }
+
+                fixed ( byte* arrAP = arrA)
+                fixed ( byte* arrBP = arrB)
+                fixed ( byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, IntPtr, IntPtr, IntPtr> range = new Tuple<int, IntPtr, IntPtr, IntPtr>
+                               (workItemLength
+                               , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                               , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                               , (IntPtr)(retArrP + i * outDims[0] * workItemLength)); 
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, IntPtr, IntPtr, IntPtr>
+                                (outDims[1] - i * workItemLength
+                                , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                                , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                                , (IntPtr)(retArrP + i * outDims[0] * workItemLength)));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<byte>(retStorage);
+            //}  // no scopes here! it disables implace operations
+        }
+
+        /// <summary>Power elements</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Array with elementwise result of A <sup>B</sup></returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the 
+        /// other array.</para>
+        /// <para>If A or B is a colum vector and the other parameter is an array with a matching colum length, the vector is used to operate on all columns of the array. 
+        /// Similar, if one parameter is a row vector, it is used to operate along the rows of the other array if its number of columns matches the vector length. This feature 
+        /// can be used to replace the (costly) repmat function for most binary operators.</para>
+        /// <para>For all other cases the dimensions of A and B must match.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the size of both arrays does not match any parameter rule.</exception>
+        public unsafe static ILRetArray<double>  pow(ILInArray<double> A, ILInArray<double> B) {
+            using (ILScope.Enter(A,B)) {
+                int outLen; 
+                BinOpItMode mode; 
+                double [] retArr;
+                double [] arrA = A.GetArrayForRead();
+                double[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                #region determine operation mode
+                if (A.IsScalar) {
+                    outDims = B.Size; 
+                    if (B.IsScalar) {
+                       
+                        return new  ILRetArray<double> (new  double [1]{ Math.Pow (A.GetValue(0)  , B.GetValue(0))}, A.Size);
+                    } else if (B.IsEmpty) {
+                        return  ILRetArray<double>.empty(outDims); 
+                    } else {
+                        outLen = outDims.NumberOfElements; 
+                        if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< double > (outLen);
+                            mode = BinOpItMode.SAN; 
+                        } else {
+                            mode = BinOpItMode.SAI; 
+                        }
+                    }
+                } else {
+                    outDims = A.Size; 
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return  ILRetArray<double>.empty(A.Size);  
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                            retArr = ILMemoryPool.Pool.New< double > (outLen);
+                            mode = BinOpItMode.ASN; 
+                        } else {
+                            mode = BinOpItMode.ASI; 
+                        }
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  powEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements; 
+                        if (A.TryGetStorage4InplaceOp(out retArr)) 
+                            mode  = BinOpItMode.AAIA; 
+                        else if (B.TryGetStorage4InplaceOp(out retArr)) 
+                            mode = BinOpItMode.AAIB; 
+                        else {
+                            retArr = ILMemoryPool.Pool.New< double > (outLen);
+                            mode = BinOpItMode.AAN;
+                        }
+                    }
+                }
+                #endregion
+                ILDenseStorage<double> retStorage = new ILDenseStorage<double>(retArr, outDims);
+                int i = 0, workerCount = 1; 
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    double* cp = (double*)range.Item5 + range.Item1;
+                    double scalar;
+                    int j = range.Item2; 
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAIA:
+                           double* bp = ((double*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                                cp[0] =  Math.Pow (cp[0]  , bp[0]);
+                                cp[1] =  Math.Pow (cp[1]  , bp[1]);
+                                cp[2] =  Math.Pow (cp[2]  , bp[2]);
+                                cp[3] =  Math.Pow (cp[3]  , bp[3]);
+                                cp[4] =  Math.Pow (cp[4]  , bp[4]);
+                                cp[5] =  Math.Pow (cp[5]  , bp[5]);
+                                cp[6] =  Math.Pow (cp[6]  , bp[6]);
+                                cp[7] =  Math.Pow (cp[7]  , bp[7]);
+                                cp[8] =  Math.Pow (cp[8]  , bp[8]);
+                                cp[9] =  Math.Pow (cp[9]  , bp[9]);
+                                cp[10] =  Math.Pow (cp[10]  , bp[10]);
+                                cp[11] =  Math.Pow (cp[11]  , bp[11]);
+                                cp[12] =  Math.Pow (cp[12]  , bp[12]);
+                                cp[13] =  Math.Pow (cp[13]  , bp[13]);
+                                cp[14] =  Math.Pow (cp[14]  , bp[14]);
+                                cp[15] =  Math.Pow (cp[15]  , bp[15]);
+                                cp[16] =  Math.Pow (cp[16]  , bp[16]);
+                                cp[17] =  Math.Pow (cp[17]  , bp[17]);
+                                cp[18] =  Math.Pow (cp[18]  , bp[18]);
+                                cp[19] =  Math.Pow (cp[19]  , bp[19]);
+                                cp[20] =  Math.Pow (cp[20]  , bp[20]);
+                                cp += 21; bp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  Math.Pow (*cp  , *bp);
+                                cp++; bp++;
+                            }
+                            break;
+                        case BinOpItMode.AAIB:
+                           double* ap = ((double*)range.Item3 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  Math.Pow (ap[0]  , cp[0]);
+                                cp[1] =  Math.Pow (ap[1]  , cp[1]);
+                                cp[2] =  Math.Pow (ap[2]  , cp[2]);
+                                cp[3] =  Math.Pow (ap[3]  , cp[3]);
+                                cp[4] =  Math.Pow (ap[4]  , cp[4]);
+                                cp[5] =  Math.Pow (ap[5]  , cp[5]);
+                                cp[6] =  Math.Pow (ap[6]  , cp[6]);
+                                cp[7] =  Math.Pow (ap[7]  , cp[7]);
+                                cp[8] =  Math.Pow (ap[8]  , cp[8]);
+                                cp[9] =  Math.Pow (ap[9]  , cp[9]);
+                                cp[10] =  Math.Pow (ap[10]  , cp[10]);
+                                cp[11] =  Math.Pow (ap[11]  , cp[11]);
+                                cp[12] =  Math.Pow (ap[12]  , cp[12]);
+                                cp[13] =  Math.Pow (ap[13]  , cp[13]);
+                                cp[14] =  Math.Pow (ap[14]  , cp[14]);
+                                cp[15] =  Math.Pow (ap[15]  , cp[15]);
+                                cp[16] =  Math.Pow (ap[16]  , cp[16]);
+                                cp[17] =  Math.Pow (ap[17]  , cp[17]);
+                                cp[18] =  Math.Pow (ap[18]  , cp[18]);
+                                cp[19] =  Math.Pow (ap[19]  , cp[19]);
+                                cp[20] =  Math.Pow (ap[20]  , cp[20]);
+                                ap += 21; cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  Math.Pow (*ap  , *cp);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.AAN:
+                            ap = ((double*)range.Item3 + range.Item1);
+                            bp = ((double*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  Math.Pow (ap[0]  , bp[0]);
+                                cp[1] =  Math.Pow (ap[1]  , bp[1]);
+                                cp[2] =  Math.Pow (ap[2]  , bp[2]);
+                                cp[3] =  Math.Pow (ap[3]  , bp[3]);
+                                cp[4] =  Math.Pow (ap[4]  , bp[4]);
+                                cp[5] =  Math.Pow (ap[5]  , bp[5]);
+                                cp[6] =  Math.Pow (ap[6]  , bp[6]);
+                                cp[7] =  Math.Pow (ap[7]  , bp[7]);
+                                cp[8] =  Math.Pow (ap[8]  , bp[8]);
+                                cp[9] =  Math.Pow (ap[9]  , bp[9]);
+                                cp[10] =  Math.Pow (ap[10]  , bp[10]);
+                                cp[11] =  Math.Pow (ap[11]  , bp[11]);
+                                cp[12] =  Math.Pow (ap[12]  , bp[12]);
+                                cp[13] =  Math.Pow (ap[13]  , bp[13]);
+                                cp[14] =  Math.Pow (ap[14]  , bp[14]);
+                                cp[15] =  Math.Pow (ap[15]  , bp[15]);
+                                cp[16] =  Math.Pow (ap[16]  , bp[16]);
+                                cp[17] =  Math.Pow (ap[17]  , bp[17]);
+                                cp[18] =  Math.Pow (ap[18]  , bp[18]);
+                                cp[19] =  Math.Pow (ap[19]  , bp[19]);
+                                cp[20] =  Math.Pow (ap[20]  , bp[20]);
+                                ap+=21; bp+=21; cp+=21; j-=21;
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  Math.Pow (*ap  , *bp);
+                                ap++; bp++; cp++;
+                            }
+                            break;
+                        case BinOpItMode.ASI:
+                            scalar = *((double*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =  Math.Pow (cp[0]  , scalar);
+                                cp[1] =  Math.Pow (cp[1]  , scalar);
+                                cp[2] =  Math.Pow (cp[2]  , scalar);
+                                cp[3] =  Math.Pow (cp[3]  , scalar);
+                                cp[4] =  Math.Pow (cp[4]  , scalar);
+                                cp[5] =  Math.Pow (cp[5]  , scalar);
+                                cp[6] =  Math.Pow (cp[6]  , scalar);
+                                cp[7] =  Math.Pow (cp[7]  , scalar);
+                                cp[8] =  Math.Pow (cp[8]  , scalar);
+                                cp[9] =  Math.Pow (cp[9]  , scalar);
+                                cp[10] =  Math.Pow (cp[10]  , scalar);
+                                cp[11] =  Math.Pow (cp[11]  , scalar);
+                                cp[12] =  Math.Pow (cp[12]  , scalar);
+                                cp[13] =  Math.Pow (cp[13]  , scalar);
+                                cp[14] =  Math.Pow (cp[14]  , scalar);
+                                cp[15] =  Math.Pow (cp[15]  , scalar);
+                                cp[16] =  Math.Pow (cp[16]  , scalar);
+                                cp[17] =  Math.Pow (cp[17]  , scalar);
+                                cp[18] =  Math.Pow (cp[18]  , scalar);
+                                cp[19] =  Math.Pow (cp[19]  , scalar);
+                                cp[20] =  Math.Pow (cp[20]  , scalar);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  Math.Pow (*cp  , scalar);
+                                cp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((double*)range.Item3 + range.Item1);
+                            scalar = *((double*)range.Item4);
+                            while (j > 20) {
+                               
+                                cp[0] =  Math.Pow (ap[0]  , scalar);
+                                cp[1] =  Math.Pow (ap[1]  , scalar);
+                                cp[2] =  Math.Pow (ap[2]  , scalar);
+                                cp[3] =  Math.Pow (ap[3]  , scalar);
+                                cp[4] =  Math.Pow (ap[4]  , scalar);
+                                cp[5] =  Math.Pow (ap[5]  , scalar);
+                                cp[6] =  Math.Pow (ap[6]  , scalar);
+                                cp[7] =  Math.Pow (ap[7]  , scalar);
+                                cp[8] =  Math.Pow (ap[8]  , scalar);
+                                cp[9] =  Math.Pow (ap[9]  , scalar);
+                                cp[10] =  Math.Pow (ap[10]  , scalar);
+                                cp[11] =  Math.Pow (ap[11]  , scalar);
+                                cp[12] =  Math.Pow (ap[12]  , scalar);
+                                cp[13] =  Math.Pow (ap[13]  , scalar);
+                                cp[14] =  Math.Pow (ap[14]  , scalar);
+                                cp[15] =  Math.Pow (ap[15]  , scalar);
+                                cp[16] =  Math.Pow (ap[16]  , scalar);
+                                cp[17] =  Math.Pow (ap[17]  , scalar);
+                                cp[18] =  Math.Pow (ap[18]  , scalar);
+                                cp[19] =  Math.Pow (ap[19]  , scalar);
+                                cp[20] =  Math.Pow (ap[20]  , scalar);
+                                ap+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  Math.Pow (*ap  , scalar);
+                                ap++; cp++; 
+                            }
+                            break;
+                        case BinOpItMode.SAI:
+                            scalar = *((double*)range.Item3);
+                            while (j > 20) {
+                               
+                                cp[0] =  Math.Pow (scalar  , cp[0]);
+                                cp[1] =  Math.Pow (scalar  , cp[1]);
+                                cp[2] =  Math.Pow (scalar  , cp[2]);
+                                cp[3] =  Math.Pow (scalar  , cp[3]);
+                                cp[4] =  Math.Pow (scalar  , cp[4]);
+                                cp[5] =  Math.Pow (scalar  , cp[5]);
+                                cp[6] =  Math.Pow (scalar  , cp[6]);
+                                cp[7] =  Math.Pow (scalar  , cp[7]);
+                                cp[8] =  Math.Pow (scalar  , cp[8]);
+                                cp[9] =  Math.Pow (scalar  , cp[9]);
+                                cp[10] =  Math.Pow (scalar  , cp[10]);
+                                cp[11] =  Math.Pow (scalar  , cp[11]);
+                                cp[12] =  Math.Pow (scalar  , cp[12]);
+                                cp[13] =  Math.Pow (scalar  , cp[13]);
+                                cp[14] =  Math.Pow (scalar  , cp[14]);
+                                cp[15] =  Math.Pow (scalar  , cp[15]);
+                                cp[16] =  Math.Pow (scalar  , cp[16]);
+                                cp[17] =  Math.Pow (scalar  , cp[17]);
+                                cp[18] =  Math.Pow (scalar  , cp[18]);
+                                cp[19] =  Math.Pow (scalar  , cp[19]);
+                                cp[20] =  Math.Pow (scalar  , cp[20]);
+                                cp += 21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  Math.Pow (scalar  , *cp);
+                                cp++;
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((double*)range.Item3);
+                            bp = ((double*)range.Item4 + range.Item1);
+                            while (j > 20) {
+                               
+                                cp[0] =  Math.Pow (scalar  , bp[0]);
+                                cp[1] =  Math.Pow (scalar  , bp[1]);
+                                cp[2] =  Math.Pow (scalar  , bp[2]);
+                                cp[3] =  Math.Pow (scalar  , bp[3]);
+                                cp[4] =  Math.Pow (scalar  , bp[4]);
+                                cp[5] =  Math.Pow (scalar  , bp[5]);
+                                cp[6] =  Math.Pow (scalar  , bp[6]);
+                                cp[7] =  Math.Pow (scalar  , bp[7]);
+                                cp[8] =  Math.Pow (scalar  , bp[8]);
+                                cp[9] =  Math.Pow (scalar  , bp[9]);
+                                cp[10] =  Math.Pow (scalar  , bp[10]);
+                                cp[11] =  Math.Pow (scalar  , bp[11]);
+                                cp[12] =  Math.Pow (scalar  , bp[12]);
+                                cp[13] =  Math.Pow (scalar  , bp[13]);
+                                cp[14] =  Math.Pow (scalar  , bp[14]);
+                                cp[15] =  Math.Pow (scalar  , bp[15]);
+                                cp[16] =  Math.Pow (scalar  , bp[16]);
+                                cp[17] =  Math.Pow (scalar  , bp[17]);
+                                cp[18] =  Math.Pow (scalar  , bp[18]);
+                                cp[19] =  Math.Pow (scalar  , bp[19]);
+                                cp[20] =  Math.Pow (scalar  , bp[20]);
+                                bp+=21; cp+=21; j -= 21; 
+                            }
+                            while (j --> 0) {
+                               
+                                *cp =  Math.Pow (scalar  , *bp);
+                                bp++; cp++;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                    //retStorage.PendingEvents.Signal(); 
+                };
+
+                #region do the work 
+                int workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                
+                fixed ( double* arrAP = arrA)
+                fixed ( double* arrBP = arrB)
+                fixed ( double* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range 
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+
+                #endregion
+                return new  ILRetArray< double>(retStorage);
+            }
+        }
+
+        private static unsafe ILRetArray<double>  powEx(ILInArray<double> A, ILInArray<double> B) {
+            //using (ILScope.Enter(A, B)) { we cannot start a new scope here, since this would prevent A and B to be used implace if applicable
+
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return empty<double>(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return empty<double>(B.S);
+                } else if (B.IsEmpty) {
+                    return empty<double>(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                dim = -(dim - 1);  // 0 -> 1, 1 -> 0
+                #endregion
+
+                #region parameter preparation
+               
+                double[] retArr;
+               
+                double[] arrA = A.GetArrayForRead();
+               
+                double[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int workItemMultiplierLenA;
+                int workItemMultiplierLenB;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    if (!B.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<double>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.VAN;
+                    } else {
+                        mode = BinOptItExMode.VAI;
+                    }
+                    workItemMultiplierLenB = outDims[0]; 
+                    workItemMultiplierLenA = dim;  // 0 for column, 1 for row vector
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                        retArr = ILMemoryPool.Pool.New<double>(outDims.NumberOfElements);
+                        mode = BinOptItExMode.AVN;
+                    } else {
+                        mode = BinOptItExMode.AVI;
+                    }
+                    workItemMultiplierLenB = dim;  // 0 for column, 1 for row vector
+                    workItemMultiplierLenA = outDims[0]; 
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one singleton dimension in either A or B");
+                }
+                int itLen = outDims[0]; // (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                #endregion
+
+                #region worker loops definition
+                ILDenseStorage<double> retStorage = new ILDenseStorage<double>(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    double* ap;
+                   
+                    double* bp;
+                   
+                    double* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            if (dim == 0) {
+                                bp = (double*)range.Item3;
+                                cp = (double*)range.Item4; 
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (double*)range.Item2;
+                                    int l = itLen; 
+                                    while (l > 10) {
+                                        cp[0] =  Math.Pow (ap[0]  , bp[0]);
+                                        cp[1] =  Math.Pow (ap[1]  , bp[1]);
+                                        cp[2] =  Math.Pow (ap[2]  , bp[2]);
+                                        cp[3] =  Math.Pow (ap[3]  , bp[3]);
+                                        cp[4] =  Math.Pow (ap[4]  , bp[4]);
+                                        cp[5] =  Math.Pow (ap[5]  , bp[5]);
+                                        cp[6] =  Math.Pow (ap[6]  , bp[6]);
+                                        cp[7] =  Math.Pow (ap[7]  , bp[7]);
+                                        cp[8] =  Math.Pow (ap[8]  , bp[8]);
+                                        cp[9] =  Math.Pow (ap[9]  , bp[9]);
+                                        cp[10] =  Math.Pow (ap[10]  , bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =  Math.Pow (*ap++  , *bp++);
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                ap = (double*)range.Item2;
+                                bp = (double*)range.Item3;
+                                cp = (double*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   double val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  Math.Pow (val  , bp[0]);
+                                        cp[1] =  Math.Pow (val  , bp[1]);
+                                        cp[2] =  Math.Pow (val  , bp[2]);
+                                        cp[3] =  Math.Pow (val  , bp[3]);
+                                        cp[4] =  Math.Pow (val  , bp[4]);
+                                        cp[5] =  Math.Pow (val  , bp[5]);
+                                        cp[6] =  Math.Pow (val  , bp[6]);
+                                        cp[7] =  Math.Pow (val  , bp[7]);
+                                        cp[8] =  Math.Pow (val  , bp[8]);
+                                        cp[9] =  Math.Pow (val  , bp[9]);
+                                        cp[10] =  Math.Pow (val  , bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11; 
+                                    }
+                                    while (l-- > 0) {
+                                        *cp++ =  Math.Pow (val  , *bp++);
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.VAI:
+                            if (dim == 0) {
+                                cp = (double*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    ap = (double*)range.Item2;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  Math.Pow (ap[0]  , cp[0]);
+                                        cp[1] =  Math.Pow (ap[1]  , cp[1]);
+                                        cp[2] =  Math.Pow (ap[2]  , cp[2]);
+                                        cp[3] =  Math.Pow (ap[3]  , cp[3]);
+                                        cp[4] =  Math.Pow (ap[4]  , cp[4]);
+                                        cp[5] =  Math.Pow (ap[5]  , cp[5]);
+                                        cp[6] =  Math.Pow (ap[6]  , cp[6]);
+                                        cp[7] =  Math.Pow (ap[7]  , cp[7]);
+                                        cp[8] =  Math.Pow (ap[8]  , cp[8]);
+                                        cp[9] =  Math.Pow (ap[9]  , cp[9]);
+                                        cp[10] =  Math.Pow (ap[10]  , cp[10]);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  Math.Pow (*ap++  , *cp);
+                                        cp++; 
+                                    }
+                                }
+                            } else {
+                                // dim == 1
+                                cp = (double*)range.Item4;
+                                ap = (double*)range.Item2;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    double val = *ap++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  Math.Pow (val  , cp[0]);
+                                        cp[1] =  Math.Pow (val  , cp[1]);
+                                        cp[2] =  Math.Pow (val  , cp[2]);
+                                        cp[3] =  Math.Pow (val  , cp[3]);
+                                        cp[4] =  Math.Pow (val  , cp[4]);
+                                        cp[5] =  Math.Pow (val  , cp[5]);
+                                        cp[6] =  Math.Pow (val  , cp[6]);
+                                        cp[7] =  Math.Pow (val  , cp[7]);
+                                        cp[8] =  Math.Pow (val  , cp[8]);
+                                        cp[9] =  Math.Pow (val  , cp[9]);
+                                        cp[10] =  Math.Pow (val  , cp[10]);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  Math.Pow (val  , *cp);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            if (dim == 0) {
+                                ap = (double*)range.Item2;
+                                cp = (double*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (double*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  Math.Pow (ap[0]  , bp[0]);
+                                        cp[1] =  Math.Pow (ap[1]  , bp[1]);
+                                        cp[2] =  Math.Pow (ap[2]  , bp[2]);
+                                        cp[3] =  Math.Pow (ap[3]  , bp[3]);
+                                        cp[4] =  Math.Pow (ap[4]  , bp[4]);
+                                        cp[5] =  Math.Pow (ap[5]  , bp[5]);
+                                        cp[6] =  Math.Pow (ap[6]  , bp[6]);
+                                        cp[7] =  Math.Pow (ap[7]  , bp[7]);
+                                        cp[8] =  Math.Pow (ap[8]  , bp[8]);
+                                        cp[9] =  Math.Pow (ap[9]  , bp[9]);
+                                        cp[10] =  Math.Pow (ap[10]  , bp[10]);
+                                        ap += 11;
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  Math.Pow (*ap  , *bp);
+                                        ap++;
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                ap = (double*)range.Item2;
+                                bp = (double*)range.Item3;
+                                cp = (double*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   double val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  Math.Pow (ap[0]  , val);
+                                        cp[1] =  Math.Pow (ap[1]  , val);
+                                        cp[2] =  Math.Pow (ap[2]  , val);
+                                        cp[3] =  Math.Pow (ap[3]  , val);
+                                        cp[4] =  Math.Pow (ap[4]  , val);
+                                        cp[5] =  Math.Pow (ap[5]  , val);
+                                        cp[6] =  Math.Pow (ap[6]  , val);
+                                        cp[7] =  Math.Pow (ap[7]  , val);
+                                        cp[8] =  Math.Pow (ap[8]  , val);
+                                        cp[9] =  Math.Pow (ap[9]  , val);
+                                        cp[10] =  Math.Pow (ap[10]  , val);
+                                        ap += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  Math.Pow (*ap  , val);
+                                        ap++;
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVI:
+                            if (dim == 0) {
+                                cp = (double*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                    bp = (double*)range.Item3;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  Math.Pow (cp[0]  , bp[0]);
+                                        cp[1] =  Math.Pow (cp[1]  , bp[1]);
+                                        cp[2] =  Math.Pow (cp[2]  , bp[2]);
+                                        cp[3] =  Math.Pow (cp[3]  , bp[3]);
+                                        cp[4] =  Math.Pow (cp[4]  , bp[4]);
+                                        cp[5] =  Math.Pow (cp[5]  , bp[5]);
+                                        cp[6] =  Math.Pow (cp[6]  , bp[6]);
+                                        cp[7] =  Math.Pow (cp[7]  , bp[7]);
+                                        cp[8] =  Math.Pow (cp[8]  , bp[8]);
+                                        cp[9] =  Math.Pow (cp[9]  , bp[9]);
+                                        cp[10] =  Math.Pow (cp[10]  , bp[10]);
+                                        bp += 11;
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l-- > 0) {
+                                        *cp =  Math.Pow (*cp  , *bp);
+                                        bp++;
+                                        cp++;
+                                    }
+                                }
+                            } else {
+                                // dim = 1
+                                bp = (double*)range.Item3;
+                                cp = (double*)range.Item4;
+                                for (int s = 0; s < range.Item1; s++) {
+                                   
+                                    double val = *bp++;
+                                    int l = itLen;
+                                    while (l > 10) {
+                                        cp[0] =  Math.Pow (cp[0]  , val);
+                                        cp[1] =  Math.Pow (cp[1]  , val);
+                                        cp[2] =  Math.Pow (cp[2]  , val);
+                                        cp[3] =  Math.Pow (cp[3]  , val);
+                                        cp[4] =  Math.Pow (cp[4]  , val);
+                                        cp[5] =  Math.Pow (cp[5]  , val);
+                                        cp[6] =  Math.Pow (cp[6]  , val);
+                                        cp[7] =  Math.Pow (cp[7]  , val);
+                                        cp[8] =  Math.Pow (cp[8]  , val);
+                                        cp[9] =  Math.Pow (cp[9]  , val);
+                                        cp[10] =  Math.Pow (cp[10]  , val);
+                                        cp += 11;
+                                        l -= 11;
+                                    }
+                                    while (l --> 0) {
+                                        *cp =  Math.Pow (*cp  , val);
+                                        cp++;
+                                    }
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                if (Settings.s_maxNumberThreads > 1 && outDims.NumberOfElements >= Settings.s_minParallelElement1Count
+                    && outDims[1] > 1) {
+                        if (outDims[1] > workItemCount) {
+                        workItemLength = outDims[1] / workItemCount;
+                    } else {
+                        workItemLength = outDims[1] / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outDims[1];
+                    workItemCount = 1;
+                }
+
+                fixed ( double* arrAP = arrA)
+                fixed ( double* arrBP = arrB)
+                fixed ( double* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, IntPtr, IntPtr, IntPtr> range = new Tuple<int, IntPtr, IntPtr, IntPtr>
+                               (workItemLength
+                               , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                               , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                               , (IntPtr)(retArrP + i * outDims[0] * workItemLength)); 
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, IntPtr, IntPtr, IntPtr>
+                                (outDims[1] - i * workItemLength
+                                , (IntPtr)(arrAP + i * workItemMultiplierLenA * workItemLength)
+                                , (IntPtr)(arrBP + i * workItemMultiplierLenB * workItemLength)
+                                , (IntPtr)(retArrP + i * outDims[0] * workItemLength)));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetArray<double>(retStorage);
+            //}  // no scopes here! it disables implace operations
+        }
+
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/prod.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/prod.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/prod.cs	(revision 9102)
@@ -0,0 +1,803 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions;
+
+namespace ILNumerics {
+    public partial class ILMath {
+
+
+
+        
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>Product of array elements along specific dimension</summary>
+        /// <param name="A">Input array</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns><para>Array of same size as A, having dim's dimension reduced to 1, if all elements along that dimension are nonzero, '0' else. </para></returns>
+        public static  ILRetArray<double>  prod (ILInArray<double> A, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (dim >= A.Size.NumberOfDimensions)
+                    throw new ILArgumentException("dimension parameter out of range!");
+                if (A.IsEmpty)
+                    return new  ILRetArray<double>(A.Size);
+                if (A.IsScalar) {
+                    return A.C;
+                }
+                ILSize inDim = A.Size;
+                int[] newDims = inDim.ToIntArray();
+               
+                if (inDim[dim] == 1) return A.C;
+
+                int newLength;
+               
+                double[] retArr;
+                // build ILSize
+                newLength = inDim.NumberOfElements / newDims[dim];
+                newDims[dim] = 1;
+                retArr = ILMemoryPool.Pool.New< double>(newLength);
+                ILSize newDimension = new ILSize(newDims);
+                int incOut = newDimension.SequentialIndexDistance(dim);
+                int dimLen = inDim[dim];
+                int nrHigherDims = inDim.NumberOfElements / dimLen;
+                if (dim == 0) {
+                    #region physical along 1st leading dimension
+                    unsafe {
+                        fixed ( double* pOutArr = retArr)
+                        fixed ( double* pInArr = A.GetArrayForRead()) {
+                           
+                            double* lastElement;
+                           
+                            double* tmpOut = pOutArr;
+                           
+                            double* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                lastElement = tmpIn + dimLen;
+                                *tmpOut = 1.0;
+                                while (tmpIn < lastElement) {
+                                   
+                                    double inVal = *(tmpIn++);
+                                   
+                                    /*dummy*/
+                                   
+                                    *tmpOut  *=   (double) /*dummy*/ (inVal)  ; 
+                                }
+                               
+                                /*dummy*/
+                                tmpOut++;
+                            }
+                        }
+                    }
+                    #endregion
+                } else {
+                    #region physical along abitrary dimension
+                    // sum along abitrary dimension 
+                    unsafe {
+                        fixed ( double* pOutArr = retArr)
+                        fixed ( double* pInArr = A.GetArrayForRead()) {
+                           
+                            double* lastElementOut = newLength + pOutArr - 1;
+                            int inLength = inDim.NumberOfElements - 1;
+                           
+                            double* lastElementIn = pInArr + inLength;
+                            int inc = inDim.SequentialIndexDistance(dim);
+                           
+                            double* tmpOut = pOutArr;
+                            int outLength = newLength - 1;
+                           
+                            double* leadEnd;
+                           
+                            double* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                leadEnd = tmpIn + dimLen * inc;
+                                *tmpOut = 1.0;
+                                while (tmpIn < leadEnd) {
+                                   
+                                    double inVal = *(tmpIn);
+                                    tmpIn += inc;
+                                   
+                                    /*dummy*/
+                                   
+                                    *tmpOut  *=  (double) /*dummy*/ (inVal)  ; //
+                                }
+                               
+                                /*dummy*/
+                                tmpOut += inc;
+                                if (tmpOut > lastElementOut)
+                                    tmpOut = pOutArr + ((tmpOut - pOutArr) - outLength);
+                                if (tmpIn > lastElementIn)
+                                    tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                            }
+                        }
+                    }
+                    #endregion
+                }
+                return new  ILRetArray<double>(retArr, newDims);
+            }
+        }
+        /// <summary>Product of array elements along specific dimension</summary>
+        /// <param name="A">Input array</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns><para>Array of same size as A, having dim's dimension reduced to 1, if all elements along that dimension are nonzero, '0' else. </para></returns>
+        public static  ILRetArray<Int64>  prod (ILInArray<Int64> A, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (dim >= A.Size.NumberOfDimensions)
+                    throw new ILArgumentException("dimension parameter out of range!");
+                if (A.IsEmpty)
+                    return new  ILRetArray<Int64>(A.Size);
+                if (A.IsScalar) {
+                    return A.C;
+                }
+                ILSize inDim = A.Size;
+                int[] newDims = inDim.ToIntArray();
+               
+                if (inDim[dim] == 1) return A.C;
+
+                int newLength;
+               
+                Int64[] retArr;
+                // build ILSize
+                newLength = inDim.NumberOfElements / newDims[dim];
+                newDims[dim] = 1;
+                retArr = ILMemoryPool.Pool.New< Int64>(newLength);
+                ILSize newDimension = new ILSize(newDims);
+                int incOut = newDimension.SequentialIndexDistance(dim);
+                int dimLen = inDim[dim];
+                int nrHigherDims = inDim.NumberOfElements / dimLen;
+                if (dim == 0) {
+                    #region physical along 1st leading dimension
+                    unsafe {
+                        fixed ( Int64* pOutArr = retArr)
+                        fixed ( Int64* pInArr = A.GetArrayForRead()) {
+                           
+                            Int64* lastElement;
+                           
+                            Int64* tmpOut = pOutArr;
+                           
+                            Int64* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                lastElement = tmpIn + dimLen;
+                                *tmpOut = 1;
+                                while (tmpIn < lastElement) {
+                                   
+                                    Int64 inVal = *(tmpIn++);
+                                   
+                                    /*dummy*/
+                                   
+                                    *tmpOut  *=   (Int64) /*dummy*/ (inVal)  ; 
+                                }
+                               
+                                /*dummy*/
+                                tmpOut++;
+                            }
+                        }
+                    }
+                    #endregion
+                } else {
+                    #region physical along abitrary dimension
+                    // sum along abitrary dimension 
+                    unsafe {
+                        fixed ( Int64* pOutArr = retArr)
+                        fixed ( Int64* pInArr = A.GetArrayForRead()) {
+                           
+                            Int64* lastElementOut = newLength + pOutArr - 1;
+                            int inLength = inDim.NumberOfElements - 1;
+                           
+                            Int64* lastElementIn = pInArr + inLength;
+                            int inc = inDim.SequentialIndexDistance(dim);
+                           
+                            Int64* tmpOut = pOutArr;
+                            int outLength = newLength - 1;
+                           
+                            Int64* leadEnd;
+                           
+                            Int64* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                leadEnd = tmpIn + dimLen * inc;
+                                *tmpOut = 1;
+                                while (tmpIn < leadEnd) {
+                                   
+                                    Int64 inVal = *(tmpIn);
+                                    tmpIn += inc;
+                                   
+                                    /*dummy*/
+                                   
+                                    *tmpOut  *=  (Int64) /*dummy*/ (inVal)  ; //
+                                }
+                               
+                                /*dummy*/
+                                tmpOut += inc;
+                                if (tmpOut > lastElementOut)
+                                    tmpOut = pOutArr + ((tmpOut - pOutArr) - outLength);
+                                if (tmpIn > lastElementIn)
+                                    tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                            }
+                        }
+                    }
+                    #endregion
+                }
+                return new  ILRetArray<Int64>(retArr, newDims);
+            }
+        }
+        /// <summary>Product of array elements along specific dimension</summary>
+        /// <param name="A">Input array</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns><para>Array of same size as A, having dim's dimension reduced to 1, if all elements along that dimension are nonzero, '0' else. </para></returns>
+        public static  ILRetArray<Int32>  prod (ILInArray<Int32> A, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (dim >= A.Size.NumberOfDimensions)
+                    throw new ILArgumentException("dimension parameter out of range!");
+                if (A.IsEmpty)
+                    return new  ILRetArray<Int32>(A.Size);
+                if (A.IsScalar) {
+                    return A.C;
+                }
+                ILSize inDim = A.Size;
+                int[] newDims = inDim.ToIntArray();
+               
+                if (inDim[dim] == 1) return A.C;
+
+                int newLength;
+               
+                Int32[] retArr;
+                // build ILSize
+                newLength = inDim.NumberOfElements / newDims[dim];
+                newDims[dim] = 1;
+                retArr = ILMemoryPool.Pool.New< Int32>(newLength);
+                ILSize newDimension = new ILSize(newDims);
+                int incOut = newDimension.SequentialIndexDistance(dim);
+                int dimLen = inDim[dim];
+                int nrHigherDims = inDim.NumberOfElements / dimLen;
+                if (dim == 0) {
+                    #region physical along 1st leading dimension
+                    unsafe {
+                        fixed ( Int32* pOutArr = retArr)
+                        fixed ( Int32* pInArr = A.GetArrayForRead()) {
+                           
+                            Int32* lastElement;
+                           
+                            Int32* tmpOut = pOutArr;
+                           
+                            Int32* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                lastElement = tmpIn + dimLen;
+                                *tmpOut = 1;
+                                while (tmpIn < lastElement) {
+                                   
+                                    Int32 inVal = *(tmpIn++);
+                                   
+                                    /*dummy*/
+                                   
+                                    *tmpOut  *=   (Int32) /*dummy*/ (inVal)  ; 
+                                }
+                               
+                                /*dummy*/
+                                tmpOut++;
+                            }
+                        }
+                    }
+                    #endregion
+                } else {
+                    #region physical along abitrary dimension
+                    // sum along abitrary dimension 
+                    unsafe {
+                        fixed ( Int32* pOutArr = retArr)
+                        fixed ( Int32* pInArr = A.GetArrayForRead()) {
+                           
+                            Int32* lastElementOut = newLength + pOutArr - 1;
+                            int inLength = inDim.NumberOfElements - 1;
+                           
+                            Int32* lastElementIn = pInArr + inLength;
+                            int inc = inDim.SequentialIndexDistance(dim);
+                           
+                            Int32* tmpOut = pOutArr;
+                            int outLength = newLength - 1;
+                           
+                            Int32* leadEnd;
+                           
+                            Int32* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                leadEnd = tmpIn + dimLen * inc;
+                                *tmpOut = 1;
+                                while (tmpIn < leadEnd) {
+                                   
+                                    Int32 inVal = *(tmpIn);
+                                    tmpIn += inc;
+                                   
+                                    /*dummy*/
+                                   
+                                    *tmpOut  *=  (Int32) /*dummy*/ (inVal)  ; //
+                                }
+                               
+                                /*dummy*/
+                                tmpOut += inc;
+                                if (tmpOut > lastElementOut)
+                                    tmpOut = pOutArr + ((tmpOut - pOutArr) - outLength);
+                                if (tmpIn > lastElementIn)
+                                    tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                            }
+                        }
+                    }
+                    #endregion
+                }
+                return new  ILRetArray<Int32>(retArr, newDims);
+            }
+        }
+        /// <summary>Product of array elements along specific dimension</summary>
+        /// <param name="A">Input array</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns><para>Array of same size as A, having dim's dimension reduced to 1, if all elements along that dimension are nonzero, '0' else. </para></returns>
+        public static  ILRetArray<byte>  prod (ILInArray<byte> A, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (dim >= A.Size.NumberOfDimensions)
+                    throw new ILArgumentException("dimension parameter out of range!");
+                if (A.IsEmpty)
+                    return new  ILRetArray<byte>(A.Size);
+                if (A.IsScalar) {
+                    return A.C;
+                }
+                ILSize inDim = A.Size;
+                int[] newDims = inDim.ToIntArray();
+               
+                if (inDim[dim] == 1) return A.C;
+
+                int newLength;
+               
+                byte[] retArr;
+                // build ILSize
+                newLength = inDim.NumberOfElements / newDims[dim];
+                newDims[dim] = 1;
+                retArr = ILMemoryPool.Pool.New< byte>(newLength);
+                ILSize newDimension = new ILSize(newDims);
+                int incOut = newDimension.SequentialIndexDistance(dim);
+                int dimLen = inDim[dim];
+                int nrHigherDims = inDim.NumberOfElements / dimLen;
+                if (dim == 0) {
+                    #region physical along 1st leading dimension
+                    unsafe {
+                        fixed ( byte* pOutArr = retArr)
+                        fixed ( byte* pInArr = A.GetArrayForRead()) {
+                           
+                            byte* lastElement;
+                           
+                            byte* tmpOut = pOutArr;
+                           
+                            byte* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                lastElement = tmpIn + dimLen;
+                                *tmpOut = (byte)1;
+                                while (tmpIn < lastElement) {
+                                   
+                                    byte inVal = *(tmpIn++);
+                                   
+                                    /*dummy*/
+                                   
+                                    *tmpOut  *=   (byte) /*dummy*/ (inVal)  ; 
+                                }
+                               
+                                /*dummy*/
+                                tmpOut++;
+                            }
+                        }
+                    }
+                    #endregion
+                } else {
+                    #region physical along abitrary dimension
+                    // sum along abitrary dimension 
+                    unsafe {
+                        fixed ( byte* pOutArr = retArr)
+                        fixed ( byte* pInArr = A.GetArrayForRead()) {
+                           
+                            byte* lastElementOut = newLength + pOutArr - 1;
+                            int inLength = inDim.NumberOfElements - 1;
+                           
+                            byte* lastElementIn = pInArr + inLength;
+                            int inc = inDim.SequentialIndexDistance(dim);
+                           
+                            byte* tmpOut = pOutArr;
+                            int outLength = newLength - 1;
+                           
+                            byte* leadEnd;
+                           
+                            byte* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                leadEnd = tmpIn + dimLen * inc;
+                                *tmpOut = (byte)1;
+                                while (tmpIn < leadEnd) {
+                                   
+                                    byte inVal = *(tmpIn);
+                                    tmpIn += inc;
+                                   
+                                    /*dummy*/
+                                   
+                                    *tmpOut  *=  (byte) /*dummy*/ (inVal)  ; //
+                                }
+                               
+                                /*dummy*/
+                                tmpOut += inc;
+                                if (tmpOut > lastElementOut)
+                                    tmpOut = pOutArr + ((tmpOut - pOutArr) - outLength);
+                                if (tmpIn > lastElementIn)
+                                    tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                            }
+                        }
+                    }
+                    #endregion
+                }
+                return new  ILRetArray<byte>(retArr, newDims);
+            }
+        }
+        /// <summary>Product of array elements along specific dimension</summary>
+        /// <param name="A">Input array</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns><para>Array of same size as A, having dim's dimension reduced to 1, if all elements along that dimension are nonzero, '0' else. </para></returns>
+        public static  ILRetArray<fcomplex>  prod (ILInArray<fcomplex> A, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (dim >= A.Size.NumberOfDimensions)
+                    throw new ILArgumentException("dimension parameter out of range!");
+                if (A.IsEmpty)
+                    return new  ILRetArray<fcomplex>(A.Size);
+                if (A.IsScalar) {
+                    return A.C;
+                }
+                ILSize inDim = A.Size;
+                int[] newDims = inDim.ToIntArray();
+               
+                if (inDim[dim] == 1) return A.C;
+
+                int newLength;
+               
+                fcomplex[] retArr;
+                // build ILSize
+                newLength = inDim.NumberOfElements / newDims[dim];
+                newDims[dim] = 1;
+                retArr = ILMemoryPool.Pool.New< fcomplex>(newLength);
+                ILSize newDimension = new ILSize(newDims);
+                int incOut = newDimension.SequentialIndexDistance(dim);
+                int dimLen = inDim[dim];
+                int nrHigherDims = inDim.NumberOfElements / dimLen;
+                if (dim == 0) {
+                    #region physical along 1st leading dimension
+                    unsafe {
+                        fixed ( fcomplex* pOutArr = retArr)
+                        fixed ( fcomplex* pInArr = A.GetArrayForRead()) {
+                           
+                            fcomplex* lastElement;
+                           
+                            fcomplex* tmpOut = pOutArr;
+                           
+                            fcomplex* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                lastElement = tmpIn + dimLen;
+                                *tmpOut = new fcomplex(1f,0f);
+                                while (tmpIn < lastElement) {
+                                   
+                                    fcomplex inVal = *(tmpIn++);
+                                   
+                                    /*dummy*/
+                                   
+                                    *tmpOut  *=   (fcomplex) /*dummy*/ (inVal)  ; 
+                                }
+                               
+                                /*dummy*/
+                                tmpOut++;
+                            }
+                        }
+                    }
+                    #endregion
+                } else {
+                    #region physical along abitrary dimension
+                    // sum along abitrary dimension 
+                    unsafe {
+                        fixed ( fcomplex* pOutArr = retArr)
+                        fixed ( fcomplex* pInArr = A.GetArrayForRead()) {
+                           
+                            fcomplex* lastElementOut = newLength + pOutArr - 1;
+                            int inLength = inDim.NumberOfElements - 1;
+                           
+                            fcomplex* lastElementIn = pInArr + inLength;
+                            int inc = inDim.SequentialIndexDistance(dim);
+                           
+                            fcomplex* tmpOut = pOutArr;
+                            int outLength = newLength - 1;
+                           
+                            fcomplex* leadEnd;
+                           
+                            fcomplex* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                leadEnd = tmpIn + dimLen * inc;
+                                *tmpOut = new fcomplex(1f,0f);
+                                while (tmpIn < leadEnd) {
+                                   
+                                    fcomplex inVal = *(tmpIn);
+                                    tmpIn += inc;
+                                   
+                                    /*dummy*/
+                                   
+                                    *tmpOut  *=  (fcomplex) /*dummy*/ (inVal)  ; //
+                                }
+                               
+                                /*dummy*/
+                                tmpOut += inc;
+                                if (tmpOut > lastElementOut)
+                                    tmpOut = pOutArr + ((tmpOut - pOutArr) - outLength);
+                                if (tmpIn > lastElementIn)
+                                    tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                            }
+                        }
+                    }
+                    #endregion
+                }
+                return new  ILRetArray<fcomplex>(retArr, newDims);
+            }
+        }
+        /// <summary>Product of array elements along specific dimension</summary>
+        /// <param name="A">Input array</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns><para>Array of same size as A, having dim's dimension reduced to 1, if any elements along that dimension are nonzero, '0' else. </para></returns>
+        public static  ILRetArray<float>  prod (ILInArray<float> A, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (dim >= A.Size.NumberOfDimensions)
+                    throw new ILArgumentException("dimension parameter out of range!");
+                if (A.IsEmpty)
+                    return new  ILRetArray<float>(A.Size);
+                if (A.IsScalar) {
+                    return A.C;
+                }
+                ILSize inDim = A.Size;
+                int[] newDims = inDim.ToIntArray();
+               
+                if (inDim[dim] == 1) return A.C;
+
+                int newLength;
+               
+                float[] retArr;
+                // build ILSize
+                newLength = inDim.NumberOfElements / newDims[dim];
+                newDims[dim] = 1;
+                retArr = ILMemoryPool.Pool.New< float>(newLength);
+                ILSize newDimension = new ILSize(newDims);
+                int incOut = newDimension.SequentialIndexDistance(dim);
+                int dimLen = inDim[dim];
+                int nrHigherDims = inDim.NumberOfElements / dimLen;
+                if (dim == 0) {
+                    #region physical along 1st leading dimension
+                    unsafe {
+                        fixed ( float* pOutArr = retArr)
+                        fixed ( float* pInArr = A.GetArrayForRead()) {
+                           
+                            float* lastElement;
+                           
+                            float* tmpOut = pOutArr;
+                           
+                            float* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                lastElement = tmpIn + dimLen;
+                                *tmpOut = 1f;
+                                while (tmpIn < lastElement) {
+                                   
+                                    float inVal = *(tmpIn++);
+                                   
+                                    /*dummy*/
+                                   
+                                    *tmpOut  *=   (float) /*dummy*/ (inVal)  ; 
+                                }
+                               
+                                /*dummy*/
+                                tmpOut++;
+                            }
+                        }
+                    }
+                    #endregion
+                } else {
+                    #region physical along abitrary dimension
+                    // sum along abitrary dimension 
+                    unsafe {
+                        fixed ( float* pOutArr = retArr)
+                        fixed ( float* pInArr = A.GetArrayForRead()) {
+                           
+                            float* lastElementOut = newLength + pOutArr - 1;
+                            int inLength = inDim.NumberOfElements - 1;
+                           
+                            float* lastElementIn = pInArr + inLength;
+                            int inc = inDim.SequentialIndexDistance(dim);
+                           
+                            float* tmpOut = pOutArr;
+                            int outLength = newLength - 1;
+                           
+                            float* leadEnd;
+                           
+                            float* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                leadEnd = tmpIn + dimLen * inc;
+                                *tmpOut = 1f;
+                                while (tmpIn < leadEnd) {
+                                   
+                                    float inVal = *(tmpIn);
+                                    tmpIn += inc;
+                                   
+                                    /*dummy*/
+                                   
+                                    *tmpOut  *=  (float) /*dummy*/ (inVal)  ; //
+                                }
+                               
+                                /*dummy*/
+                                tmpOut += inc;
+                                if (tmpOut > lastElementOut)
+                                    tmpOut = pOutArr + ((tmpOut - pOutArr) - outLength);
+                                if (tmpIn > lastElementIn)
+                                    tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                            }
+                        }
+                    }
+                    #endregion
+                }
+                return new  ILRetArray<float>(retArr, newDims);
+            }
+        }
+        /// <summary>Product of array elements along specific dimension</summary>
+        /// <param name="A">Input array</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns><para>Array of same size as A, having dim's dimension reduced to 1, if any elements along that dimension are nonzero, '0' else. </para></returns>
+        public static  ILRetArray<complex>  prod (ILInArray<complex> A, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+                if (dim >= A.Size.NumberOfDimensions)
+                    throw new ILArgumentException("dimension parameter out of range!");
+                if (A.IsEmpty)
+                    return new  ILRetArray<complex>(A.Size);
+                if (A.IsScalar) {
+                    return A.C;
+                }
+                ILSize inDim = A.Size;
+                int[] newDims = inDim.ToIntArray();
+               
+                if (inDim[dim] == 1) return A.C;
+
+                int newLength;
+               
+                complex[] retArr;
+                // build ILSize
+                newLength = inDim.NumberOfElements / newDims[dim];
+                newDims[dim] = 1;
+                retArr = ILMemoryPool.Pool.New< complex>(newLength);
+                ILSize newDimension = new ILSize(newDims);
+                int incOut = newDimension.SequentialIndexDistance(dim);
+                int dimLen = inDim[dim];
+                int nrHigherDims = inDim.NumberOfElements / dimLen;
+                if (dim == 0) {
+                    #region physical along 1st leading dimension
+                    unsafe {
+                        fixed ( complex* pOutArr = retArr)
+                        fixed ( complex* pInArr = A.GetArrayForRead()) {
+                           
+                            complex* lastElement;
+                           
+                            complex* tmpOut = pOutArr;
+                           
+                            complex* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                lastElement = tmpIn + dimLen;
+                                *tmpOut = new complex(1.0,0.0);
+                                while (tmpIn < lastElement) {
+                                   
+                                    complex inVal = *(tmpIn++);
+                                   
+                                    /*dummy*/
+                                   
+                                    *tmpOut  *=   (complex) /*dummy*/ (inVal)  ; 
+                                }
+                               
+                                /*dummy*/
+                                tmpOut++;
+                            }
+                        }
+                    }
+                    #endregion
+                } else {
+                    #region physical along abitrary dimension
+                    // sum along abitrary dimension 
+                    unsafe {
+                        fixed ( complex* pOutArr = retArr)
+                        fixed ( complex* pInArr = A.GetArrayForRead()) {
+                           
+                            complex* lastElementOut = newLength + pOutArr - 1;
+                            int inLength = inDim.NumberOfElements - 1;
+                           
+                            complex* lastElementIn = pInArr + inLength;
+                            int inc = inDim.SequentialIndexDistance(dim);
+                           
+                            complex* tmpOut = pOutArr;
+                            int outLength = newLength - 1;
+                           
+                            complex* leadEnd;
+                           
+                            complex* tmpIn = pInArr;
+                            for (int h = nrHigherDims; h-- > 0; ) {
+                                leadEnd = tmpIn + dimLen * inc;
+                                *tmpOut = new complex(1.0,0.0);
+                                while (tmpIn < leadEnd) {
+                                   
+                                    complex inVal = *(tmpIn);
+                                    tmpIn += inc;
+                                   
+                                    /*dummy*/
+                                   
+                                    *tmpOut  *=  (complex) /*dummy*/ (inVal)  ; //
+                                }
+                               
+                                /*dummy*/
+                                tmpOut += inc;
+                                if (tmpOut > lastElementOut)
+                                    tmpOut = pOutArr + ((tmpOut - pOutArr) - outLength);
+                                if (tmpIn > lastElementIn)
+                                    tmpIn = pInArr + ((tmpIn - pInArr) - inLength);
+                            }
+                        }
+                    }
+                    #endregion
+                }
+                return new  ILRetArray<complex>(retArr, newDims);
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/qr.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/qr.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/qr.cs	(revision 9102)
@@ -0,0 +1,996 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions; 
+
+
+
+namespace ILNumerics {
+    public partial class ILMath {
+
+
+        /// <summary>
+        /// QR decomposition - raw Lapack output
+        /// </summary>
+        /// <param name="A">Input matrix A</param>
+        /// <returns>Orthonormal / unitary matrix Q and upper triangular 
+        /// matrix R packed into single matrix. This is the output of the 
+        /// lapack function ?geqrf.</returns>
+        /// <remarks><para>Input matrix A will not be altered. </para>
+        /// <para>The matrix returned is the direct output of the lapack 
+        /// function [d,s,c,z]geqrf respectively. This means that it contains 
+        /// the decomposition factors Q and R, but they are combined into a 
+        /// single matrix for performance reasons. If you need one of the factors, 
+        /// you would use the overloaded function 
+        /// <see cref="ILNumerics.ILMath.qr(ILInArray{double},ILOutArray{double})"/> 
+        /// instead, which returns those factors separately.</para></remarks>
+        internal static ILRetArray<double> qr( ILInArray<double> A ) {
+            using (ILScope.Enter(A)) {
+                if (!A.IsMatrix)
+                    throw new ILArgumentException("input A must be matrix");
+                int m = A.Size[0], n = A.Size[1];
+                ILArray<double> ret = A.C;
+                 double[] tau = ILMemoryPool.Pool.New<  double>((m < n) ? m : n);
+                int info = 0;
+                /*!HC:lapack_*geqrf*/
+                Lapack.dgeqrf(m, n, ret.GetArrayForWrite(), m, tau, ref info);
+                if (info < 0)
+                    throw new ILArgumentException("an unknown error occoured during decomposition");
+                return ret;
+            }
+        }
+        /// <summary>
+        /// QR decomposition, returning Q and R
+        /// </summary>
+        /// <param name="A">Input matrix A of size [m x n]</param>
+        /// <param name="outR">[Output] Upper triangular matrix R as 
+        /// result of decomposition, size [m x n]</param>
+        /// <returns>Orthonormal / unitary matrix Q as result of decomposition, size [m x m]</returns>
+        /// <remarks>The function returns Q and R such that the equation 
+        /// <para>A = Q * R</para> holds within roundoff errors. ('*' denotes 
+        /// matrix multiplication)</remarks>
+        public static ILRetArray<double> qr(
+                                      ILInArray<double> A,
+                                      ILOutArray<double> outR ) {
+            return qr(A, outR, false);
+        }
+        /// <summary>
+        /// QR decomposition, returning Q and R, optionally economical sized
+        /// </summary>
+        /// <param name="A">Input matrix A of size [m x n]</param>
+        /// <param name="outR">[Output] Upper triangular matrix R as 
+        /// result of decomposition, size [m x n]</param>
+        /// <param name="economySize">If true, the size of Q and R will 
+        /// be [m x m] and [m x n] respectively. However, if m &lt; n, 
+        /// the economySize parameter has no effect. </param>
+        /// <returns>Orthonormal real / unitary complex matrix Q as result 
+        /// of decomposition. Size [m x m] or [m x min(m,n)], depending 
+        /// on <paramref name="economySize"/> (see remarks below)</returns>
+        /// <remarks>The function returns Q and R such that the equation 
+        /// <para>A = Q * R</para> holds with roundoff errors. ('*' 
+        /// denotes matrix multiplication.)</remarks>
+        public static ILRetArray<double> qr( ILInArray<double> A
+            , ILOutArray<double> outR, bool economySize ) {
+            using (ILScope.Enter(A)) {
+                if (Object.Equals(outR, null)) {
+                    return qr(A);
+                }
+                int m = A.Size[0];
+                int n = A.Size[1];
+                if (m < n && economySize) return qr(A, outR, false);
+                ILArray<double> ret = empty<double>(ILSize.Empty00);
+                if (m == 0 || n == 0) {
+                    if (!object.Equals(outR,null))
+                        outR.a = empty<double>(new ILSize(m, n));
+                    return empty<double>(A.Size);
+                }
+                int minMN = (m < n) ? m : n;
+                int info = 0;
+                 double[] tau = ILMemoryPool.Pool.New<  double>(minMN);
+                if (m >= n) {
+                    ret.a = zeros<double>(m, (economySize) ? minMN : m);
+                } else {
+                    // economySize is always false ... !
+                    // a temporary array is needed for extraction of the compact lapack Q (?geqrf)
+                    ret.a = zeros<double>(m, n);
+                }
+                ret[full, r(0, n - 1)] = A[full, full]; 
+                 double[] QArr = ret.GetArrayForWrite();
+                /*!HC:lapack_*geqrf*/
+                Lapack.dgeqrf(m, n, QArr, m, tau, ref info);
+                if (info != 0) {
+                    throw new ILArgumentException("error inside lapack library (?geqrf). info=" + info.ToString());
+                }
+                // extract R, Q
+                if (economySize) {
+                    outR.a = copyUpperTriangle(QArr, m, n, minMN);
+                    /*!HC:lapack_*orgqr*/
+                    Lapack.dorgqr(m, minMN, minMN, QArr, m, tau, ref info);
+                } else {
+                    outR.a = copyUpperTriangle(QArr, m, n, m);
+                    /*!HC:lapack_*orgqr*/
+                    Lapack.dorgqr(m, m, minMN, QArr, m, tau, ref info);
+                    if (m < n)
+                        ret.a = ret[full,r(0,m - 1)];
+                }
+                if (info != 0)
+                    throw new ILArgumentException("error in lapack library (???gqr). info=" + info.ToString());
+                return ret;
+            }
+        }
+        /// <summary>
+        /// QR decomposition with pivoting
+        /// </summary>
+        /// <param name="A">Input matrix A of size [m x n]</param>
+        /// <param name="outR">[Output] Upper triangular matrix 
+        /// R as result of decomposition. Size [m x n] or [min(m,n) x n] 
+        /// (see remarks). </param>
+        /// <param name="outE">[Output] Permutation matrix from pivoting. Size [m x m]</param>
+        /// <returns>Orthonormal / unitary matrix Q as result of decomposition. 
+        /// Size [m x min(m,n)]</returns>
+        /// <remarks>The function returns Q, R and E such that the equation 
+        /// <para>A * E = Q * R</para> holds with roundoff errors, where '*' 
+        /// denotes matrix multiplication. E reflects the pivoting done 
+        /// inside LAPACK in order to give R increasingly diagonal elements.</remarks>
+        /// <seealso cref="ILNumerics.ILMath.qr(ILInArray{double}, ILOutArray{double}, ILOutArray{double},bool)"/>
+        public static  ILRetArray<double> qr(
+                                    ILInArray<double> A,
+                                    ILOutArray< double> outR,
+                                    ILOutArray< double> outE ) {
+            return qr(A, outR, outE, false);
+        }
+        /// <summary>
+        /// QR decomposition with pivoting, possibly economical sized
+        /// </summary>
+        /// <param name="A">Input matrix A of size [m x n]</param>
+        /// <param name="outR">[Output] Upper triangular matrix R as 
+        /// result of decomposition. Size [m x n] or [min(m,n) x n] depending 
+        /// on <paramref name="economySize"/> (see remarks).</param>
+        /// <param name="economySize"><para>If true, <list type="bullet">
+        /// <item>the size of Q and R will be [m x m] and [m x n] respectively. 
+        /// However, if m &lt; n, the economySize parameter has no effect on 
+        /// those sizes.</item>
+        /// <item>the output parameter E will be returned as row permutation 
+        /// vector rather than as permutation matrix</item></list></para>
+        /// <para>If false, this function acts exactly as its overload 
+        /// <see cref="ILNumerics.ILMath.qr(ILInArray{double}, ILOutArray{double}, ILOutArray{double})"/></para>
+        /// </param>
+        /// <param name="outE">[Output] Permutation matrix from pivoting. Size [m x m]. 
+        /// If this is not null, the permutation matrix/ vector E will be returned.
+        /// <para>E is of size [n x n], if <paramref name="economySize"/> is 
+        /// true, a row vector of length n otherwise</para></param>
+        /// <returns>Orthonormal / unitary matrix Q as result of decomposition. 
+        /// Size [m x m] or [m x min(m,n)], depending on <paramref name="economySize"/> 
+        /// (see remarks below)</returns>
+        /// <remarks><para> If <paramref name="economySize"/> is false, the function 
+        /// returns Q, R and E such that the equation A * E = Q * R holds within 
+        /// roundoff errors. </para>
+        /// <para>If <paramref name="economySize"/> is true, E will be a permutation 
+        /// vector and the equation A[":",E] == Q * R holds (except roundoff).</para>
+        /// <para>E reflects the pivoting of A done inside LAPACK in order to give R 
+        /// increasingly diagonal elements.</para></remarks>
+        public static ILRetArray<double> qr(
+                        ILInArray<  double> A,
+                        ILOutArray<  double> outR,
+                        ILOutArray<  double> outE,
+                        bool economySize ) {
+            using (ILScope.Enter(A)) {
+                if (Object.Equals(outR, null)) {
+                    return qr(A);
+                }
+                int m = A.Size[0];
+                int n = A.Size[1];
+                if (m < n && economySize) return qr(A, outR, false);
+                if (m == 0 || n == 0) {
+                    if (!object.Equals(outR,null)) 
+                        outR.a = zeros< double>(m, n);
+                    if (!object.Equals(outE,null))
+                        outE.a = zeros< double>(1, 0);
+                    return empty<double>(A.Size);
+                }
+                // prepare IPVT
+                if (object.Equals(outE, null))
+                    return qr(A, outR, economySize);
+                if (!economySize) {
+                    outE.a = zeros< double>( n, n);
+                } else {
+                    outE.a = zeros< double>( 1, n);
+                }
+                int[] ipvt = ILMemoryPool.Pool.New<int>(n);
+                int minMN = (m < n) ? m : n;
+                int info = 0;
+                 double[] tau = ILMemoryPool.Pool.New<  double>(minMN);
+                 double[] QArr;
+                ILArray<double> ret;
+                if (m >= n) {
+                    ret = zeros<double>(m, (economySize) ? minMN : m);
+                } else {
+                    // economySize is always false ... !
+                    // a temporary array is needed for extraction of the compact lapack Q (?geqrf)
+                    ret = zeros<double>( m, n);
+                }
+                ret[full,r(0,n-1)] = A[full,full]; 
+                QArr = ret.GetArrayForWrite();
+                /*!HC:lapack_*geqp3*/
+                Lapack.dgeqp3(m, n, QArr, m, ipvt, tau, ref info);
+                if (info != 0) {
+                    throw new ILArgumentException("error inside lapack library (?geqrf). info=" + info.ToString());
+                }
+                // extract R, Q
+                 double[] eArr = outE.GetArrayForWrite();
+                if (economySize) {
+                    outR.a = copyUpperTriangle(QArr, m, n, minMN);
+                    /*!HC:lapack_*orgqr*/
+                    Lapack.dorgqr(m, minMN, minMN, QArr, m, tau, ref info);
+                    // transform E into out typed vector
+                    for (int i = 0; i < n; i++) {
+                        eArr[i] = ipvt[i] - 1;
+                    }
+                } else {
+                    outR.a = copyUpperTriangle(QArr, m, n, m);
+                    /*!HC:lapack_*orgqr*/
+                    Lapack.dorgqr(m, m, minMN, QArr, m, tau, ref info);
+                    if (m < n)
+                        ret.a = ret[full,r(0,m - 1)];
+                    // transform E into matrix
+                    for (int i = 0; i < n; i++) {
+                        eArr[(ipvt[i] - 1) + n * i] =  1.0;
+                    }
+                }
+                if (info != 0)
+                    throw new ILArgumentException("error in lapack library (???gqr). info=" + info.ToString());
+                return ret;
+            }
+        }
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// QR decomposition - raw Lapack output
+        /// </summary>
+        /// <param name="A">Input matrix A</param>
+        /// <returns>Orthonormal / unitary matrix Q and upper triangular 
+        /// matrix R packed into single matrix. This is the output of the 
+        /// lapack function ?geqrf.</returns>
+        /// <remarks><para>Input matrix A will not be altered. </para>
+        /// <para>The matrix returned is the direct output of the lapack 
+        /// function [d,s,c,z]geqrf respectively. This means that it contains 
+        /// the decomposition factors Q and R, but they are combined into a 
+        /// single matrix for performance reasons. If you need one of the factors, 
+        /// you would use the overloaded function 
+        /// <see cref="ILNumerics.ILMath.qr(ILInArray{double},ILOutArray{double})"/> 
+        /// instead, which returns those factors separately.</para></remarks>
+        internal static ILRetArray<float> qr( ILInArray<float> A ) {
+            using (ILScope.Enter(A)) {
+                if (!A.IsMatrix)
+                    throw new ILArgumentException("input A must be matrix");
+                int m = A.Size[0], n = A.Size[1];
+                ILArray<float> ret = A.C;
+                float[] tau = ILMemoryPool.Pool.New<  float>((m < n) ? m : n);
+                int info = 0;
+               
+                Lapack.sgeqrf(m, n, ret.GetArrayForWrite(), m, tau, ref info);
+                if (info < 0)
+                    throw new ILArgumentException("an unknown error occoured during decomposition");
+                return ret;
+            }
+        }
+        /// <summary>
+        /// QR decomposition, returning Q and R
+        /// </summary>
+        /// <param name="A">Input matrix A of size [m x n]</param>
+        /// <param name="outR">[Output] Upper triangular matrix R as 
+        /// result of decomposition, size [m x n]</param>
+        /// <returns>Orthonormal / unitary matrix Q as result of decomposition, size [m x m]</returns>
+        /// <remarks>The function returns Q and R such that the equation 
+        /// <para>A = Q * R</para> holds within roundoff errors. ('*' denotes 
+        /// matrix multiplication)</remarks>
+        public static ILRetArray<float> qr(
+                                      ILInArray<float> A,
+                                      ILOutArray<float> outR ) {
+            return qr(A, outR, false);
+        }
+        /// <summary>
+        /// QR decomposition, returning Q and R, optionally economical sized
+        /// </summary>
+        /// <param name="A">Input matrix A of size [m x n]</param>
+        /// <param name="outR">[Output] Upper triangular matrix R as 
+        /// result of decomposition, size [m x n]</param>
+        /// <param name="economySize">If true, the size of Q and R will 
+        /// be [m x m] and [m x n] respectively. However, if m &lt; n, 
+        /// the economySize parameter has no effect. </param>
+        /// <returns>Orthonormal real / unitary complex matrix Q as result 
+        /// of decomposition. Size [m x m] or [m x min(m,n)], depending 
+        /// on <paramref name="economySize"/> (see remarks below)</returns>
+        /// <remarks>The function returns Q and R such that the equation 
+        /// <para>A = Q * R</para> holds with roundoff errors. ('*' 
+        /// denotes matrix multiplication.)</remarks>
+        public static ILRetArray<float> qr( ILInArray<float> A
+            , ILOutArray<float> outR, bool economySize ) {
+            using (ILScope.Enter(A)) {
+                if (Object.Equals(outR, null)) {
+                    return qr(A);
+                }
+                int m = A.Size[0];
+                int n = A.Size[1];
+                if (m < n && economySize) return qr(A, outR, false);
+                ILArray<float> ret = empty<float>(ILSize.Empty00);
+                if (m == 0 || n == 0) {
+                    if (!object.Equals(outR,null))
+                        outR.a = empty<float>(new ILSize(m, n));
+                    return empty<float>(A.Size);
+                }
+                int minMN = (m < n) ? m : n;
+                int info = 0;
+                float[] tau = ILMemoryPool.Pool.New<  float>(minMN);
+                if (m >= n) {
+                    ret.a = zeros<float>(m, (economySize) ? minMN : m);
+                } else {
+                    // economySize is always false ... !
+                    // a temporary array is needed for extraction of the compact lapack Q (?geqrf)
+                    ret.a = zeros<float>(m, n);
+                }
+                ret[full, r(0, n - 1)] = A[full, full]; 
+                float[] QArr = ret.GetArrayForWrite();
+               
+                Lapack.sgeqrf(m, n, QArr, m, tau, ref info);
+                if (info != 0) {
+                    throw new ILArgumentException("error inside lapack library (?geqrf). info=" + info.ToString());
+                }
+                // extract R, Q
+                if (economySize) {
+                    outR.a = copyUpperTriangle(QArr, m, n, minMN);
+                   
+                    Lapack.sorgqr(m, minMN, minMN, QArr, m, tau, ref info);
+                } else {
+                    outR.a = copyUpperTriangle(QArr, m, n, m);
+                   
+                    Lapack.sorgqr(m, m, minMN, QArr, m, tau, ref info);
+                    if (m < n)
+                        ret.a = ret[full,r(0,m - 1)];
+                }
+                if (info != 0)
+                    throw new ILArgumentException("error in lapack library (???gqr). info=" + info.ToString());
+                return ret;
+            }
+        }
+        /// <summary>
+        /// QR decomposition with pivoting
+        /// </summary>
+        /// <param name="A">Input matrix A of size [m x n]</param>
+        /// <param name="outR">[Output] Upper triangular matrix 
+        /// R as result of decomposition. Size [m x n] or [min(m,n) x n] 
+        /// (see remarks). </param>
+        /// <param name="outE">[Output] Permutation matrix from pivoting. Size [m x m]</param>
+        /// <returns>Orthonormal / unitary matrix Q as result of decomposition. 
+        /// Size [m x min(m,n)]</returns>
+        /// <remarks>The function returns Q, R and E such that the equation 
+        /// <para>A * E = Q * R</para> holds with roundoff errors, where '*' 
+        /// denotes matrix multiplication. E reflects the pivoting done 
+        /// inside LAPACK in order to give R increasingly diagonal elements.</remarks>
+        /// <seealso cref="ILNumerics.ILMath.qr(ILInArray{double}, ILOutArray{double}, ILOutArray{double},bool)"/>
+        public static  ILRetArray<float> qr(
+                                    ILInArray<float> A,
+                                    ILOutArray< float> outR,
+                                    ILOutArray< float> outE ) {
+            return qr(A, outR, outE, false);
+        }
+        /// <summary>
+        /// QR decomposition with pivoting, possibly economical sized
+        /// </summary>
+        /// <param name="A">Input matrix A of size [m x n]</param>
+        /// <param name="outR">[Output] Upper triangular matrix R as 
+        /// result of decomposition. Size [m x n] or [min(m,n) x n] depending 
+        /// on <paramref name="economySize"/> (see remarks).</param>
+        /// <param name="economySize"><para>If true, <list type="bullet">
+        /// <item>the size of Q and R will be [m x m] and [m x n] respectively. 
+        /// However, if m &lt; n, the economySize parameter has no effect on 
+        /// those sizes.</item>
+        /// <item>the output parameter E will be returned as row permutation 
+        /// vector rather than as permutation matrix</item></list></para>
+        /// <para>If false, this function acts exactly as its overload 
+        /// <see cref="ILNumerics.ILMath.qr(ILInArray{double}, ILOutArray{double}, ILOutArray{double})"/></para>
+        /// </param>
+        /// <param name="outE">[Output] Permutation matrix from pivoting. Size [m x m]. 
+        /// If this is not null, the permutation matrix/ vector E will be returned.
+        /// <para>E is of size [n x n], if <paramref name="economySize"/> is 
+        /// true, a row vector of length n otherwise</para></param>
+        /// <returns>Orthonormal / unitary matrix Q as result of decomposition. 
+        /// Size [m x m] or [m x min(m,n)], depending on <paramref name="economySize"/> 
+        /// (see remarks below)</returns>
+        /// <remarks><para> If <paramref name="economySize"/> is false, the function 
+        /// returns Q, R and E such that the equation A * E = Q * R holds within 
+        /// roundoff errors. </para>
+        /// <para>If <paramref name="economySize"/> is true, E will be a permutation 
+        /// vector and the equation A[":",E] == Q * R holds (except roundoff).</para>
+        /// <para>E reflects the pivoting of A done inside LAPACK in order to give R 
+        /// increasingly diagonal elements.</para></remarks>
+        public static ILRetArray<float> qr(
+                        ILInArray<  float> A,
+                        ILOutArray<  float> outR,
+                        ILOutArray<  float> outE,
+                        bool economySize ) {
+            using (ILScope.Enter(A)) {
+                if (Object.Equals(outR, null)) {
+                    return qr(A);
+                }
+                int m = A.Size[0];
+                int n = A.Size[1];
+                if (m < n && economySize) return qr(A, outR, false);
+                if (m == 0 || n == 0) {
+                    if (!object.Equals(outR,null)) 
+                        outR.a = zeros< float>(m, n);
+                    if (!object.Equals(outE,null))
+                        outE.a = zeros< float>(1, 0);
+                    return empty<float>(A.Size);
+                }
+                // prepare IPVT
+                if (object.Equals(outE, null))
+                    return qr(A, outR, economySize);
+                if (!economySize) {
+                    outE.a = zeros< float>( n, n);
+                } else {
+                    outE.a = zeros< float>( 1, n);
+                }
+                int[] ipvt = ILMemoryPool.Pool.New<int>(n);
+                int minMN = (m < n) ? m : n;
+                int info = 0;
+                float[] tau = ILMemoryPool.Pool.New<  float>(minMN);
+                float[] QArr;
+                ILArray<float> ret;
+                if (m >= n) {
+                    ret = zeros<float>(m, (economySize) ? minMN : m);
+                } else {
+                    // economySize is always false ... !
+                    // a temporary array is needed for extraction of the compact lapack Q (?geqrf)
+                    ret = zeros<float>( m, n);
+                }
+                ret[full,r(0,n-1)] = A[full,full]; 
+                QArr = ret.GetArrayForWrite();
+               
+                Lapack.sgeqp3(m, n, QArr, m, ipvt, tau, ref info);
+                if (info != 0) {
+                    throw new ILArgumentException("error inside lapack library (?geqrf). info=" + info.ToString());
+                }
+                // extract R, Q
+                float[] eArr = outE.GetArrayForWrite();
+                if (economySize) {
+                    outR.a = copyUpperTriangle(QArr, m, n, minMN);
+                   
+                    Lapack.sorgqr(m, minMN, minMN, QArr, m, tau, ref info);
+                    // transform E into out typed vector
+                    for (int i = 0; i < n; i++) {
+                        eArr[i] = ipvt[i] - 1;
+                    }
+                } else {
+                    outR.a = copyUpperTriangle(QArr, m, n, m);
+                   
+                    Lapack.sorgqr(m, m, minMN, QArr, m, tau, ref info);
+                    if (m < n)
+                        ret.a = ret[full,r(0,m - 1)];
+                    // transform E into matrix
+                    for (int i = 0; i < n; i++) {
+                        eArr[(ipvt[i] - 1) + n * i] =  1.0f;
+                    }
+                }
+                if (info != 0)
+                    throw new ILArgumentException("error in lapack library (???gqr). info=" + info.ToString());
+                return ret;
+            }
+        }
+
+        /// <summary>
+        /// QR decomposition - raw Lapack output
+        /// </summary>
+        /// <param name="A">Input matrix A</param>
+        /// <returns>Orthonormal / unitary matrix Q and upper triangular 
+        /// matrix R packed into single matrix. This is the output of the 
+        /// lapack function ?geqrf.</returns>
+        /// <remarks><para>Input matrix A will not be altered. </para>
+        /// <para>The matrix returned is the direct output of the lapack 
+        /// function [d,s,c,z]geqrf respectively. This means that it contains 
+        /// the decomposition factors Q and R, but they are combined into a 
+        /// single matrix for performance reasons. If you need one of the factors, 
+        /// you would use the overloaded function 
+        /// <see cref="ILNumerics.ILMath.qr(ILInArray{double},ILOutArray{double})"/> 
+        /// instead, which returns those factors separately.</para></remarks>
+        internal static ILRetArray<fcomplex> qr( ILInArray<fcomplex> A ) {
+            using (ILScope.Enter(A)) {
+                if (!A.IsMatrix)
+                    throw new ILArgumentException("input A must be matrix");
+                int m = A.Size[0], n = A.Size[1];
+                ILArray<fcomplex> ret = A.C;
+                fcomplex[] tau = ILMemoryPool.Pool.New<  fcomplex>((m < n) ? m : n);
+                int info = 0;
+               
+                Lapack.cgeqrf(m, n, ret.GetArrayForWrite(), m, tau, ref info);
+                if (info < 0)
+                    throw new ILArgumentException("an unknown error occoured during decomposition");
+                return ret;
+            }
+        }
+        /// <summary>
+        /// QR decomposition, returning Q and R
+        /// </summary>
+        /// <param name="A">Input matrix A of size [m x n]</param>
+        /// <param name="outR">[Output] Upper triangular matrix R as 
+        /// result of decomposition, size [m x n]</param>
+        /// <returns>Orthonormal / unitary matrix Q as result of decomposition, size [m x m]</returns>
+        /// <remarks>The function returns Q and R such that the equation 
+        /// <para>A = Q * R</para> holds within roundoff errors. ('*' denotes 
+        /// matrix multiplication)</remarks>
+        public static ILRetArray<fcomplex> qr(
+                                      ILInArray<fcomplex> A,
+                                      ILOutArray<fcomplex> outR ) {
+            return qr(A, outR, false);
+        }
+        /// <summary>
+        /// QR decomposition, returning Q and R, optionally economical sized
+        /// </summary>
+        /// <param name="A">Input matrix A of size [m x n]</param>
+        /// <param name="outR">[Output] Upper triangular matrix R as 
+        /// result of decomposition, size [m x n]</param>
+        /// <param name="economySize">If true, the size of Q and R will 
+        /// be [m x m] and [m x n] respectively. However, if m &lt; n, 
+        /// the economySize parameter has no effect. </param>
+        /// <returns>Orthonormal real / unitary complex matrix Q as result 
+        /// of decomposition. Size [m x m] or [m x min(m,n)], depending 
+        /// on <paramref name="economySize"/> (see remarks below)</returns>
+        /// <remarks>The function returns Q and R such that the equation 
+        /// <para>A = Q * R</para> holds with roundoff errors. ('*' 
+        /// denotes matrix multiplication.)</remarks>
+        public static ILRetArray<fcomplex> qr( ILInArray<fcomplex> A
+            , ILOutArray<fcomplex> outR, bool economySize ) {
+            using (ILScope.Enter(A)) {
+                if (Object.Equals(outR, null)) {
+                    return qr(A);
+                }
+                int m = A.Size[0];
+                int n = A.Size[1];
+                if (m < n && economySize) return qr(A, outR, false);
+                ILArray<fcomplex> ret = empty<fcomplex>(ILSize.Empty00);
+                if (m == 0 || n == 0) {
+                    if (!object.Equals(outR,null))
+                        outR.a = empty<fcomplex>(new ILSize(m, n));
+                    return empty<fcomplex>(A.Size);
+                }
+                int minMN = (m < n) ? m : n;
+                int info = 0;
+                fcomplex[] tau = ILMemoryPool.Pool.New<  fcomplex>(minMN);
+                if (m >= n) {
+                    ret.a = zeros<fcomplex>(m, (economySize) ? minMN : m);
+                } else {
+                    // economySize is always false ... !
+                    // a temporary array is needed for extraction of the compact lapack Q (?geqrf)
+                    ret.a = zeros<fcomplex>(m, n);
+                }
+                ret[full, r(0, n - 1)] = A[full, full]; 
+                fcomplex[] QArr = ret.GetArrayForWrite();
+               
+                Lapack.cgeqrf(m, n, QArr, m, tau, ref info);
+                if (info != 0) {
+                    throw new ILArgumentException("error inside lapack library (?geqrf). info=" + info.ToString());
+                }
+                // extract R, Q
+                if (economySize) {
+                    outR.a = copyUpperTriangle(QArr, m, n, minMN);
+                   
+                    Lapack.cungqr(m, minMN, minMN, QArr, m, tau, ref info);
+                } else {
+                    outR.a = copyUpperTriangle(QArr, m, n, m);
+                   
+                    Lapack.cungqr(m, m, minMN, QArr, m, tau, ref info);
+                    if (m < n)
+                        ret.a = ret[full,r(0,m - 1)];
+                }
+                if (info != 0)
+                    throw new ILArgumentException("error in lapack library (???gqr). info=" + info.ToString());
+                return ret;
+            }
+        }
+        /// <summary>
+        /// QR decomposition with pivoting
+        /// </summary>
+        /// <param name="A">Input matrix A of size [m x n]</param>
+        /// <param name="outR">[Output] Upper triangular matrix 
+        /// R as result of decomposition. Size [m x n] or [min(m,n) x n] 
+        /// (see remarks). </param>
+        /// <param name="outE">[Output] Permutation matrix from pivoting. Size [m x m]</param>
+        /// <returns>Orthonormal / unitary matrix Q as result of decomposition. 
+        /// Size [m x min(m,n)]</returns>
+        /// <remarks>The function returns Q, R and E such that the equation 
+        /// <para>A * E = Q * R</para> holds with roundoff errors, where '*' 
+        /// denotes matrix multiplication. E reflects the pivoting done 
+        /// inside LAPACK in order to give R increasingly diagonal elements.</remarks>
+        /// <seealso cref="ILNumerics.ILMath.qr(ILInArray{double}, ILOutArray{double}, ILOutArray{double},bool)"/>
+        public static  ILRetArray<fcomplex> qr(
+                                    ILInArray<fcomplex> A,
+                                    ILOutArray< fcomplex> outR,
+                                    ILOutArray< fcomplex> outE ) {
+            return qr(A, outR, outE, false);
+        }
+        /// <summary>
+        /// QR decomposition with pivoting, possibly economical sized
+        /// </summary>
+        /// <param name="A">Input matrix A of size [m x n]</param>
+        /// <param name="outR">[Output] Upper triangular matrix R as 
+        /// result of decomposition. Size [m x n] or [min(m,n) x n] depending 
+        /// on <paramref name="economySize"/> (see remarks).</param>
+        /// <param name="economySize"><para>If true, <list type="bullet">
+        /// <item>the size of Q and R will be [m x m] and [m x n] respectively. 
+        /// However, if m &lt; n, the economySize parameter has no effect on 
+        /// those sizes.</item>
+        /// <item>the output parameter E will be returned as row permutation 
+        /// vector rather than as permutation matrix</item></list></para>
+        /// <para>If false, this function acts exactly as its overload 
+        /// <see cref="ILNumerics.ILMath.qr(ILInArray{double}, ILOutArray{double}, ILOutArray{double})"/></para>
+        /// </param>
+        /// <param name="outE">[Output] Permutation matrix from pivoting. Size [m x m]. 
+        /// If this is not null, the permutation matrix/ vector E will be returned.
+        /// <para>E is of size [n x n], if <paramref name="economySize"/> is 
+        /// true, a row vector of length n otherwise</para></param>
+        /// <returns>Orthonormal / unitary matrix Q as result of decomposition. 
+        /// Size [m x m] or [m x min(m,n)], depending on <paramref name="economySize"/> 
+        /// (see remarks below)</returns>
+        /// <remarks><para> If <paramref name="economySize"/> is false, the function 
+        /// returns Q, R and E such that the equation A * E = Q * R holds within 
+        /// roundoff errors. </para>
+        /// <para>If <paramref name="economySize"/> is true, E will be a permutation 
+        /// vector and the equation A[":",E] == Q * R holds (except roundoff).</para>
+        /// <para>E reflects the pivoting of A done inside LAPACK in order to give R 
+        /// increasingly diagonal elements.</para></remarks>
+        public static ILRetArray<fcomplex> qr(
+                        ILInArray<  fcomplex> A,
+                        ILOutArray<  fcomplex> outR,
+                        ILOutArray<  fcomplex> outE,
+                        bool economySize ) {
+            using (ILScope.Enter(A)) {
+                if (Object.Equals(outR, null)) {
+                    return qr(A);
+                }
+                int m = A.Size[0];
+                int n = A.Size[1];
+                if (m < n && economySize) return qr(A, outR, false);
+                if (m == 0 || n == 0) {
+                    if (!object.Equals(outR,null)) 
+                        outR.a = zeros< fcomplex>(m, n);
+                    if (!object.Equals(outE,null))
+                        outE.a = zeros< fcomplex>(1, 0);
+                    return empty<fcomplex>(A.Size);
+                }
+                // prepare IPVT
+                if (object.Equals(outE, null))
+                    return qr(A, outR, economySize);
+                if (!economySize) {
+                    outE.a = zeros< fcomplex>( n, n);
+                } else {
+                    outE.a = zeros< fcomplex>( 1, n);
+                }
+                int[] ipvt = ILMemoryPool.Pool.New<int>(n);
+                int minMN = (m < n) ? m : n;
+                int info = 0;
+                fcomplex[] tau = ILMemoryPool.Pool.New<  fcomplex>(minMN);
+                fcomplex[] QArr;
+                ILArray<fcomplex> ret;
+                if (m >= n) {
+                    ret = zeros<fcomplex>(m, (economySize) ? minMN : m);
+                } else {
+                    // economySize is always false ... !
+                    // a temporary array is needed for extraction of the compact lapack Q (?geqrf)
+                    ret = zeros<fcomplex>( m, n);
+                }
+                ret[full,r(0,n-1)] = A[full,full]; 
+                QArr = ret.GetArrayForWrite();
+               
+                Lapack.cgeqp3(m, n, QArr, m, ipvt, tau, ref info);
+                if (info != 0) {
+                    throw new ILArgumentException("error inside lapack library (?geqrf). info=" + info.ToString());
+                }
+                // extract R, Q
+                fcomplex[] eArr = outE.GetArrayForWrite();
+                if (economySize) {
+                    outR.a = copyUpperTriangle(QArr, m, n, minMN);
+                   
+                    Lapack.cungqr(m, minMN, minMN, QArr, m, tau, ref info);
+                    // transform E into out typed vector
+                    for (int i = 0; i < n; i++) {
+                        eArr[i] = ipvt[i] - 1;
+                    }
+                } else {
+                    outR.a = copyUpperTriangle(QArr, m, n, m);
+                   
+                    Lapack.cungqr(m, m, minMN, QArr, m, tau, ref info);
+                    if (m < n)
+                        ret.a = ret[full,r(0,m - 1)];
+                    // transform E into matrix
+                    for (int i = 0; i < n; i++) {
+                        eArr[(ipvt[i] - 1) + n * i] =  1.0f;
+                    }
+                }
+                if (info != 0)
+                    throw new ILArgumentException("error in lapack library (???gqr). info=" + info.ToString());
+                return ret;
+            }
+        }
+
+        /// <summary>
+        /// QR decomposition - raw Lapack output
+        /// </summary>
+        /// <param name="A">Input matrix A</param>
+        /// <returns>Orthonormal / unitary matrix Q and upper triangular 
+        /// matrix R packed into single matrix. This is the output of the 
+        /// lapack function ?geqrf.</returns>
+        /// <remarks><para>Input matrix A will not be altered. </para>
+        /// <para>The matrix returned is the direct output of the lapack 
+        /// function [d,s,c,z]geqrf respectively. This means that it contains 
+        /// the decomposition factors Q and R, but they are combined into a 
+        /// single matrix for performance reasons. If you need one of the factors, 
+        /// you would use the overloaded function 
+        /// <see cref="ILNumerics.ILMath.qr(ILInArray{double},ILOutArray{double})"/> 
+        /// instead, which returns those factors separately.</para></remarks>
+        internal static ILRetArray<complex> qr( ILInArray<complex> A ) {
+            using (ILScope.Enter(A)) {
+                if (!A.IsMatrix)
+                    throw new ILArgumentException("input A must be matrix");
+                int m = A.Size[0], n = A.Size[1];
+                ILArray<complex> ret = A.C;
+                complex[] tau = ILMemoryPool.Pool.New<  complex>((m < n) ? m : n);
+                int info = 0;
+               
+                Lapack.zgeqrf(m, n, ret.GetArrayForWrite(), m, tau, ref info);
+                if (info < 0)
+                    throw new ILArgumentException("an unknown error occoured during decomposition");
+                return ret;
+            }
+        }
+        /// <summary>
+        /// QR decomposition, returning Q and R
+        /// </summary>
+        /// <param name="A">Input matrix A of size [m x n]</param>
+        /// <param name="outR">[Output] Upper triangular matrix R as 
+        /// result of decomposition, size [m x n]</param>
+        /// <returns>Orthonormal / unitary matrix Q as result of decomposition, size [m x m]</returns>
+        /// <remarks>The function returns Q and R such that the equation 
+        /// <para>A = Q * R</para> holds within roundoff errors. ('*' denotes 
+        /// matrix multiplication)</remarks>
+        public static ILRetArray<complex> qr(
+                                      ILInArray<complex> A,
+                                      ILOutArray<complex> outR ) {
+            return qr(A, outR, false);
+        }
+        /// <summary>
+        /// QR decomposition, returning Q and R, optionally economical sized
+        /// </summary>
+        /// <param name="A">Input matrix A of size [m x n]</param>
+        /// <param name="outR">[Output] Upper triangular matrix R as 
+        /// result of decomposition, size [m x n]</param>
+        /// <param name="economySize">If true, the size of Q and R will 
+        /// be [m x m] and [m x n] respectively. However, if m &lt; n, 
+        /// the economySize parameter has no effect. </param>
+        /// <returns>Orthonormal real / unitary complex matrix Q as result 
+        /// of decomposition. Size [m x m] or [m x min(m,n)], depending 
+        /// on <paramref name="economySize"/> (see remarks below)</returns>
+        /// <remarks>The function returns Q and R such that the equation 
+        /// <para>A = Q * R</para> holds with roundoff errors. ('*' 
+        /// denotes matrix multiplication.)</remarks>
+        public static ILRetArray<complex> qr( ILInArray<complex> A
+            , ILOutArray<complex> outR, bool economySize ) {
+            using (ILScope.Enter(A)) {
+                if (Object.Equals(outR, null)) {
+                    return qr(A);
+                }
+                int m = A.Size[0];
+                int n = A.Size[1];
+                if (m < n && economySize) return qr(A, outR, false);
+                ILArray<complex> ret = empty<complex>(ILSize.Empty00);
+                if (m == 0 || n == 0) {
+                    if (!object.Equals(outR,null))
+                        outR.a = empty<complex>(new ILSize(m, n));
+                    return empty<complex>(A.Size);
+                }
+                int minMN = (m < n) ? m : n;
+                int info = 0;
+                complex[] tau = ILMemoryPool.Pool.New<  complex>(minMN);
+                if (m >= n) {
+                    ret.a = zeros<complex>(m, (economySize) ? minMN : m);
+                } else {
+                    // economySize is always false ... !
+                    // a temporary array is needed for extraction of the compact lapack Q (?geqrf)
+                    ret.a = zeros<complex>(m, n);
+                }
+                ret[full, r(0, n - 1)] = A[full, full]; 
+                complex[] QArr = ret.GetArrayForWrite();
+               
+                Lapack.zgeqrf(m, n, QArr, m, tau, ref info);
+                if (info != 0) {
+                    throw new ILArgumentException("error inside lapack library (?geqrf). info=" + info.ToString());
+                }
+                // extract R, Q
+                if (economySize) {
+                    outR.a = copyUpperTriangle(QArr, m, n, minMN);
+                   
+                    Lapack.zungqr(m, minMN, minMN, QArr, m, tau, ref info);
+                } else {
+                    outR.a = copyUpperTriangle(QArr, m, n, m);
+                   
+                    Lapack.zungqr(m, m, minMN, QArr, m, tau, ref info);
+                    if (m < n)
+                        ret.a = ret[full,r(0,m - 1)];
+                }
+                if (info != 0)
+                    throw new ILArgumentException("error in lapack library (???gqr). info=" + info.ToString());
+                return ret;
+            }
+        }
+        /// <summary>
+        /// QR decomposition with pivoting
+        /// </summary>
+        /// <param name="A">Input matrix A of size [m x n]</param>
+        /// <param name="outR">[Output] Upper triangular matrix 
+        /// R as result of decomposition. Size [m x n] or [min(m,n) x n] 
+        /// (see remarks). </param>
+        /// <param name="outE">[Output] Permutation matrix from pivoting. Size [m x m]</param>
+        /// <returns>Orthonormal / unitary matrix Q as result of decomposition. 
+        /// Size [m x min(m,n)]</returns>
+        /// <remarks>The function returns Q, R and E such that the equation 
+        /// <para>A * E = Q * R</para> holds with roundoff errors, where '*' 
+        /// denotes matrix multiplication. E reflects the pivoting done 
+        /// inside LAPACK in order to give R increasingly diagonal elements.</remarks>
+        /// <seealso cref="ILNumerics.ILMath.qr(ILInArray{double}, ILOutArray{double}, ILOutArray{double},bool)"/>
+        public static  ILRetArray<complex> qr(
+                                    ILInArray<complex> A,
+                                    ILOutArray< complex> outR,
+                                    ILOutArray< complex> outE ) {
+            return qr(A, outR, outE, false);
+        }
+        /// <summary>
+        /// QR decomposition with pivoting, possibly economical sized
+        /// </summary>
+        /// <param name="A">Input matrix A of size [m x n]</param>
+        /// <param name="outR">[Output] Upper triangular matrix R as 
+        /// result of decomposition. Size [m x n] or [min(m,n) x n] depending 
+        /// on <paramref name="economySize"/> (see remarks).</param>
+        /// <param name="economySize"><para>If true, <list type="bullet">
+        /// <item>the size of Q and R will be [m x m] and [m x n] respectively. 
+        /// However, if m &lt; n, the economySize parameter has no effect on 
+        /// those sizes.</item>
+        /// <item>the output parameter E will be returned as row permutation 
+        /// vector rather than as permutation matrix</item></list></para>
+        /// <para>If false, this function acts exactly as its overload 
+        /// <see cref="ILNumerics.ILMath.qr(ILInArray{double}, ILOutArray{double}, ILOutArray{double})"/></para>
+        /// </param>
+        /// <param name="outE">[Output] Permutation matrix from pivoting. Size [m x m]. 
+        /// If this is not null, the permutation matrix/ vector E will be returned.
+        /// <para>E is of size [n x n], if <paramref name="economySize"/> is 
+        /// true, a row vector of length n otherwise</para></param>
+        /// <returns>Orthonormal / unitary matrix Q as result of decomposition. 
+        /// Size [m x m] or [m x min(m,n)], depending on <paramref name="economySize"/> 
+        /// (see remarks below)</returns>
+        /// <remarks><para> If <paramref name="economySize"/> is false, the function 
+        /// returns Q, R and E such that the equation A * E = Q * R holds within 
+        /// roundoff errors. </para>
+        /// <para>If <paramref name="economySize"/> is true, E will be a permutation 
+        /// vector and the equation A[":",E] == Q * R holds (except roundoff).</para>
+        /// <para>E reflects the pivoting of A done inside LAPACK in order to give R 
+        /// increasingly diagonal elements.</para></remarks>
+        public static ILRetArray<complex> qr(
+                        ILInArray<  complex> A,
+                        ILOutArray<  complex> outR,
+                        ILOutArray<  complex> outE,
+                        bool economySize ) {
+            using (ILScope.Enter(A)) {
+                if (Object.Equals(outR, null)) {
+                    return qr(A);
+                }
+                int m = A.Size[0];
+                int n = A.Size[1];
+                if (m < n && economySize) return qr(A, outR, false);
+                if (m == 0 || n == 0) {
+                    if (!object.Equals(outR,null)) 
+                        outR.a = zeros< complex>(m, n);
+                    if (!object.Equals(outE,null))
+                        outE.a = zeros< complex>(1, 0);
+                    return empty<complex>(A.Size);
+                }
+                // prepare IPVT
+                if (object.Equals(outE, null))
+                    return qr(A, outR, economySize);
+                if (!economySize) {
+                    outE.a = zeros< complex>( n, n);
+                } else {
+                    outE.a = zeros< complex>( 1, n);
+                }
+                int[] ipvt = ILMemoryPool.Pool.New<int>(n);
+                int minMN = (m < n) ? m : n;
+                int info = 0;
+                complex[] tau = ILMemoryPool.Pool.New<  complex>(minMN);
+                complex[] QArr;
+                ILArray<complex> ret;
+                if (m >= n) {
+                    ret = zeros<complex>(m, (economySize) ? minMN : m);
+                } else {
+                    // economySize is always false ... !
+                    // a temporary array is needed for extraction of the compact lapack Q (?geqrf)
+                    ret = zeros<complex>( m, n);
+                }
+                ret[full,r(0,n-1)] = A[full,full]; 
+                QArr = ret.GetArrayForWrite();
+               
+                Lapack.zgeqp3(m, n, QArr, m, ipvt, tau, ref info);
+                if (info != 0) {
+                    throw new ILArgumentException("error inside lapack library (?geqrf). info=" + info.ToString());
+                }
+                // extract R, Q
+                complex[] eArr = outE.GetArrayForWrite();
+                if (economySize) {
+                    outR.a = copyUpperTriangle(QArr, m, n, minMN);
+                   
+                    Lapack.zungqr(m, minMN, minMN, QArr, m, tau, ref info);
+                    // transform E into out typed vector
+                    for (int i = 0; i < n; i++) {
+                        eArr[i] = ipvt[i] - 1;
+                    }
+                } else {
+                    outR.a = copyUpperTriangle(QArr, m, n, m);
+                   
+                    Lapack.zungqr(m, m, minMN, QArr, m, tau, ref info);
+                    if (m < n)
+                        ret.a = ret[full,r(0,m - 1)];
+                    // transform E into matrix
+                    for (int i = 0; i < n; i++) {
+                        eArr[(ipvt[i] - 1) + n * i] =  1.0;
+                    }
+                }
+                if (info != 0)
+                    throw new ILArgumentException("error in lapack library (???gqr). info=" + info.ToString());
+                return ret;
+            }
+        }
+
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/r.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/r.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/r.cs	(revision 9102)
@@ -0,0 +1,112 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using ILNumerics.Misc; 
+using ILNumerics.Storage; 
+
+namespace ILNumerics {
+    public partial class ILMath {
+
+        /// <summary>
+        /// Region creator for subarray specifications
+        /// </summary>
+        /// <param name="start">Begin of region, index of first element</param>
+        /// <param name="end">End of region, last element</param>
+        /// <returns>An array which specifies all indices of the region</returns>
+        /// <remarks>The r function provides a shorter way to specify regions in subarray
+        /// expressions. Other than alternatives like <see cref="ILNumerics.ILMath.vec"/>, 
+        /// it also enables the use of the <see cref="ILNumerics.ILMath.end"/> keyword - even in 
+        /// conjunction with simple mathematical expressions.</remarks>
+        /// <example><code>ILArray&lt;double&gt; A = counter(5,4,3), B;
+        /// 
+        /// // the following subarrays will all create the same B: 
+        /// B = A[full,r(1,end-1),full]; 
+        /// B = A[r(0,end),"1,2",":"];
+        /// B = A[":;1:2;0:end"];
+        /// 
+        /// // however, these expression will <b>not</b> work:
+        /// B = A[":;0:end-1,:"]; // 'end' expression evaluation is not supported in strings. 
+        /// </code></example>
+        public static ILBaseArray r(ILBaseArray start, ILBaseArray end) {
+            return r(start,1,end); 
+        }
+        /// <summary>
+        /// Stepped region creator for subarray specifications
+        /// </summary>
+        /// <param name="start">Begin of region, index of first element</param>
+        /// <param name="end">End of region, last element</param>
+        /// <param name="step">Increment, distance between created indices</param>
+        /// <returns>An array which specifies the indices of the region</returns>
+        /// <remarks>The r function provides a shorter way to specify regions in subarray
+        /// expressions. Other than alternatives like <see cref="ILNumerics.ILMath.vec"/>, 
+        /// it also enables the use of the <see cref="ILNumerics.ILMath.end"/> keyword - even in 
+        /// conjunction with simple mathematical expressions.</remarks>
+        /// <example><code>ILArray&lt;double&gt; A = counter(5,4,3), B;
+        /// 
+        /// // the following subarrays will all create the same B: 
+        /// B = A[full,r(1,end-1),full]; 
+        /// B = A[r(0,end),"1,2",":"];
+        /// B = A[":;1:2;0:end"];
+        /// 
+        /// // however, these expression will <b>not</b> work:
+        /// B = A[":;0:end-1,:"]; // 'end' expression evaluation is not supported in strings. 
+        /// </code></example>
+        public static ILBaseArray r(ILBaseArray start, ILBaseArray step, ILBaseArray end) {
+            ILRegularRange retRange = new ILRegularRange (start, step, end); 
+            return new ILRetArray<ILRegularRange>(new ILDenseStorage<ILRegularRange>(
+                                new ILRegularRange[]{ retRange},ILSize.Scalar1_1)); 
+        }
+
+        private static ILArray<ILFullRange> s_fullRange = null; 
+        /// <summary>
+        /// Address the whole dimension for subarray access
+        /// </summary>
+        public static ILBaseArray full {
+            get { 
+                if (object.Equals(s_fullRange, null)) 
+                    s_fullRange = returnType<ILFullRange>(); 
+                return s_fullRange; 
+            }
+        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/rand.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/rand.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/rand.cs	(revision 9102)
@@ -0,0 +1,97 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.InteropServices; 
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Native;
+using ILNumerics.Exceptions;
+
+namespace ILNumerics {
+
+	public partial class ILMath {
+
+        [ThreadStatic]
+        private static Random m_randomGenerator;
+        /// <summary>
+        /// Random number generator used for any generation of random numbers.
+        /// </summary>
+        /// <remarks>This property is thread safe (by using the [ThreadStatic] attribute).</remarks>
+        protected static Random RandomGenerator {
+            get {
+                if (m_randomGenerator == null) {
+                    m_randomGenerator = new Random(Environment.TickCount + System.Threading.Thread.CurrentThread.ManagedThreadId);
+                }
+                return m_randomGenerator;
+            }
+        }
+        /// <summary>
+        /// Pseudo random N-dimensional array elements.
+        /// </summary>
+        /// <param name="dimensions">int array or single int paramters specifying 
+        /// dimensions for new array to be created.</param>
+        /// <returns>N-dimensional array filled with random numbers.</returns>
+        /// <remarks><para>The elements lie within the range 0.0 ... 1.0 and are uniformly 
+        /// distributed.</para>
+        /// <para>The initial seed will be set to Environment.TickCount on the first call.</para></remarks>
+        public static ILRetArray<double> rand(params int[] dimensions) {
+            ILSize dim = new ILSize(dimensions);
+            double[] data = ILMemoryPool.Pool.New<double>(dim.NumberOfElements);
+            if (dim.NumberOfElements < ILNumerics.Settings.s_minParallelElement1Count) {
+                unsafe {
+                    fixed (double* pRetArray = data) {
+                        double* pCurIdx = pRetArray;
+                        double* pLastElement = pCurIdx + dim.NumberOfElements;
+                        while (pCurIdx < pLastElement)
+                            *pCurIdx++ = RandomGenerator.NextDouble();
+                    }
+                }
+            } else {
+                System.Threading.Tasks.Parallel.For(0, dim.NumberOfElements, i => {
+                    data[i] = RandomGenerator.NextDouble();
+                });
+            }
+            return new ILRetArray<double>(data, dim);
+        }
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/randn.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/randn.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/randn.cs	(revision 9102)
@@ -0,0 +1,102 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.InteropServices; 
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Native;
+using ILNumerics.Exceptions;
+
+namespace ILNumerics {
+
+    public partial class ILMath {
+
+        [ThreadStatic]
+        private static ILNRandom m_nrandomGenerator;
+        internal static ILNRandom NRandomGenerator {
+            get {
+                if (m_nrandomGenerator == null)
+                    m_nrandomGenerator = new ILNRandom(Environment.TickCount + System.Threading.Thread.CurrentThread.ManagedThreadId);
+                return m_nrandomGenerator; 
+            }
+        }
+
+        /// <summary>
+        /// Normal randomly-distributed N-dimensional array elements.
+        /// </summary>
+        /// <param name="dimensions">int array or single int paramters specifying 
+        /// dimensions for new array to be created.</param>
+        /// <returns>N-dimensional array filled with random numbers.</returns>
+        /// <remarks>The elements lie within the range 0.0 ... 1.0 and are choosen to be normally 
+        /// distributed.</remarks>
+        public static ILRetArray<double> randn(params int[] dimensions) {
+            ILSize dim;
+            if (dimensions.Length == 1)
+                dim = new ILSize(dimensions[0], dimensions[0]);
+            else
+                dim = new ILSize(dimensions);
+            double[] data = ILMemoryPool.Pool.New<double>(dim.NumberOfElements);
+            if (dim.NumberOfElements < ILNumerics.Settings.s_minParallelElement1Count)
+            {
+                unsafe
+                {
+                    fixed (double* pRetArray = data)
+                    {
+                        double* pCurIdx = pRetArray;
+                        double* pLastElement = pCurIdx + dim.NumberOfElements;
+                        while (pCurIdx < pLastElement)
+                            *pCurIdx++ = NRandomGenerator.NextDouble();
+                    }
+                }
+            }
+            else
+            {
+                System.Threading.Tasks.Parallel.For(0, dim.NumberOfElements, i =>
+                {
+                    data[i] = NRandomGenerator.NextDouble();
+                });
+            }
+            return new ILRetArray<double>(data, dim);
+        }
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/randperm.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/randperm.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/randperm.cs	(revision 9102)
@@ -0,0 +1,67 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using ILNumerics.Misc; 
+using ILNumerics.Exceptions; 
+
+namespace ILNumerics {
+    public partial class ILMath {
+
+        /// <summary>
+        /// Create a random permutation of integers 
+        /// </summary>
+        /// <param name="length">Number of unique integers to be created</param>
+        /// <returns>Vector of length 'length' and element type double</returns>
+        public static ILRetArray<double> randperm(ILBaseArray length) {
+            using (ILScope.Enter(length)) {
+                if (object.Equals(length, null) || !length.IsScalar ||!length.IsNumeric) {
+                    throw new ILArgumentException("the length parameter must be a positive integer");
+                }
+                int len = (int)toint32(length); 
+                ILArray<double> ret = empty();
+                sort(rand(1, len), ret, 1, false);
+                return ret;
+            }
+        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/rank.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/rank.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/rank.cs	(revision 9102)
@@ -0,0 +1,186 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions;
+
+namespace ILNumerics  {
+    public partial class ILMath {
+
+
+
+
+        /// <summary>
+        /// Rank of matrix A
+        /// </summary>
+        /// <param name="A">Input matrix</param>
+        /// <param name="tolerance">[Optional]Tolerance used to decide, if a singular value is 
+        /// treated as zero. If a value &lt; 0 is specified the tolerance will be determined automatically (see below - default = -1.0)</param>
+        /// <returns>Rank of matrix A</returns>
+        /// <remarks>The rank is the number of singular values greater than 
+        /// tolerance. If tolerance is smaller than zero, the following equation is used as 
+        /// default: \\
+        /// tol = length(A) * norm(A) * MachineParameterDouble.epsilon \\
+        /// with 
+        /// <list type="bullet">
+        /// <item>length(A) - the longest dimension of A</item>
+        /// <item>norm(A) being the largest singular value of A, </item>
+        /// <item>MachineParameterDouble.eps - the distance between 1 and the smallest next greater value</item>
+        /// </list>
+        /// </remarks>
+        public static ILRetArray< double> rank( ILInArray< double> A, double tolerance = -1.0 ) {
+            using (ILScope.Enter(A)) {
+                if (A.Size.NumberOfDimensions > 2)
+                    throw new ILArgumentSizeException("The input array must be matrix or vector");
+                ILArray< double> ret = svd(A);
+                if (tolerance < 0) {
+                    tolerance = A.Size.Longest * max(ret).GetValue(0) *  MachineParameterDouble.eps;
+                }
+                // count vector elements: ret is vector returned from svd
+                return find(ret > ( double)tolerance).Length;
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+
+
+        /// <summary>
+        /// Rank of matrix A
+        /// </summary>
+        /// <param name="A">Input matrix</param>
+        /// <param name="tolerance">[Optional]Tolerance used to decide, if a singular value is 
+        /// treated as zero. If a value &lt; 0 is specified the tolerance will be determined automatically (see below - default = -1.0)</param>
+        /// <returns>Rank of matrix A</returns>
+        /// <remarks>The rank is the number of singular values greater than 
+        /// tolerance. If tolerance is smaller than zero, the following equation is used as 
+        /// default: \\
+        /// tol = length(A) * norm(A) * MachineParameterDouble.epsilon \\
+        /// with 
+        /// <list type="bullet">
+        /// <item>length(A) - the longest dimension of A</item>
+        /// <item>norm(A) being the largest singular value of A, </item>
+        /// <item>MachineParameterDouble.eps - the distance between 1 and the smallest next greater value</item>
+        /// </list>
+        /// </remarks>
+        public static ILRetArray< float> rank( ILInArray< fcomplex> A, double tolerance = -1.0 ) {
+            using (ILScope.Enter(A)) {
+                if (A.Size.NumberOfDimensions > 2)
+                    throw new ILArgumentSizeException("The input array must be matrix or vector");
+                ILArray< float> ret = svd(A);
+                if (tolerance < 0) {
+                    tolerance = A.Size.Longest * max(ret).GetValue(0) *  MachineParameterSingle.eps;
+                }
+                // count vector elements: ret is vector returned from svd
+                return find(ret > ( float)tolerance).Length;
+            }
+        }
+
+
+        /// <summary>
+        /// Rank of matrix A
+        /// </summary>
+        /// <param name="A">Input matrix</param>
+        /// <param name="tolerance">[Optional]Tolerance used to decide, if a singular value is 
+        /// treated as zero. If a value &lt; 0 is specified the tolerance will be determined automatically (see below - default = -1.0)</param>
+        /// <returns>Rank of matrix A</returns>
+        /// <remarks>The rank is the number of singular values greater than 
+        /// tolerance. If tolerance is smaller than zero, the following equation is used as 
+        /// default: \\
+        /// tol = length(A) * norm(A) * MachineParameterDouble.epsilon \\
+        /// with 
+        /// <list type="bullet">
+        /// <item>length(A) - the longest dimension of A</item>
+        /// <item>norm(A) being the largest singular value of A, </item>
+        /// <item>MachineParameterDouble.eps - the distance between 1 and the smallest next greater value</item>
+        /// </list>
+        /// </remarks>
+        public static ILRetArray< float> rank( ILInArray< float> A, double tolerance = -1.0 ) {
+            using (ILScope.Enter(A)) {
+                if (A.Size.NumberOfDimensions > 2)
+                    throw new ILArgumentSizeException("The input array must be matrix or vector");
+                ILArray< float> ret = svd(A);
+                if (tolerance < 0) {
+                    tolerance = A.Size.Longest * max(ret).GetValue(0) *  MachineParameterSingle.eps;
+                }
+                // count vector elements: ret is vector returned from svd
+                return find(ret > ( float)tolerance).Length;
+            }
+        }
+
+
+        /// <summary>
+        /// Rank of matrix A
+        /// </summary>
+        /// <param name="A">Input matrix</param>
+        /// <param name="tolerance">[Optional]Tolerance used to decide, if a singular value is 
+        /// treated as zero. If a value &lt; 0 is specified the tolerance will be determined automatically (see below - default = -1.0)</param>
+        /// <returns>Rank of matrix A</returns>
+        /// <remarks>The rank is the number of singular values greater than 
+        /// tolerance. If tolerance is smaller than zero, the following equation is used as 
+        /// default: \\
+        /// tol = length(A) * norm(A) * MachineParameterDouble.epsilon \\
+        /// with 
+        /// <list type="bullet">
+        /// <item>length(A) - the longest dimension of A</item>
+        /// <item>norm(A) being the largest singular value of A, </item>
+        /// <item>MachineParameterDouble.eps - the distance between 1 and the smallest next greater value</item>
+        /// </list>
+        /// </remarks>
+        public static ILRetArray< double> rank( ILInArray< complex> A, double tolerance = -1.0 ) {
+            using (ILScope.Enter(A)) {
+                if (A.Size.NumberOfDimensions > 2)
+                    throw new ILArgumentSizeException("The input array must be matrix or vector");
+                ILArray< double> ret = svd(A);
+                if (tolerance < 0) {
+                    tolerance = A.Size.Longest * max(ret).GetValue(0) *  MachineParameterDouble.eps;
+                }
+                // count vector elements: ret is vector returned from svd
+                return find(ret > ( double)tolerance).Length;
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/real.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/real.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/real.cs	(revision 9102)
@@ -0,0 +1,96 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions;
+
+
+namespace ILNumerics  {
+    public partial class ILMath {
+
+        /// <summary>
+        /// Real part of complex array
+        /// </summary>
+        /// <param name="X">Complex input array</param>
+        /// <returns>Real part of complex array</returns>
+        public static ILRetArray<double> real(ILInArray<complex> X) {
+            using (ILScope.Enter(X)) {
+                ILArray< double> ret = zeros<double>(X.Size);
+                
+                double[] retArr = ret.GetArrayForWrite();
+                
+                complex[] XArr = X.GetArrayForRead();
+                int nrX = X.Size.NumberOfElements;
+                for (int i = 0; i < nrX; i++) {
+                    retArr[i] = XArr[i].real;
+                }
+                return ret;
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// Real part of complex array
+        /// </summary>
+        /// <param name="X">Complex input array</param>
+        /// <returns>Real part of complex array</returns>
+        public static ILRetArray<float> real(ILInArray<fcomplex> X) {
+            using (ILScope.Enter(X)) {
+                ILArray< float> ret = zeros<float>(X.Size);
+               
+                float[] retArr = ret.GetArrayForWrite();
+               
+                fcomplex[] XArr = X.GetArrayForRead();
+                int nrX = X.Size.NumberOfElements;
+                for (int i = 0; i < nrX; i++) {
+                    retArr[i] = XArr[i].real;
+                }
+                return ret;
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+   }
+
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/real2complex.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/real2complex.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/real2complex.cs	(revision 9102)
@@ -0,0 +1,289 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions;
+
+
+
+namespace ILNumerics  {
+    public partial class ILMath {
+
+        /// <summary>
+        /// Convert real array to complex array
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Complex array with A as real part, imaginary part is zero</returns>
+        public static ILRetArray<complex> real2complex( ILInArray< double> A ) {
+            using (ILScope.Enter(A)) {
+                int nrX = A.Size.NumberOfElements;
+                complex[] retArr = ILMemoryPool.Pool.New<complex>(nrX);
+                ILRetArray<complex> ret = new ILRetArray<complex>(retArr, A.Size);
+                
+                double[] inArr = A.GetArrayForRead();
+                for (int i = 0; i < nrX; i++) {
+                    retArr[i] = new complex((double)inArr[i], 0.0);
+                }
+                return ret;
+            }
+        }
+        /// <summary>
+        /// Create complex array out of real and imaginary parts
+        /// </summary>
+        /// <param name="real">Real array for real part</param>
+        /// <param name="imag">Real array for imaginary part</param>
+        /// <returns>Complex array having the real- and part imaginary parts constructed out of 
+        /// real and imag.</returns>
+        /// <remarks>Real and imag must have the same number of elements.
+        /// The array returned will have the same size as the input arrays.</remarks>
+        public static ILRetArray<complex> real2complex( ILInArray< double> real, ILInArray< double> imag ) {
+            using (ILScope.Enter(real, imag)) {
+                int nrX = real.Size.NumberOfElements;
+                if (nrX != imag.Size.NumberOfElements)
+                    throw new ILArgumentSizeException("size of real and imag input arrays must match!");
+                complex[] retArr = ILMemoryPool.Pool.New<complex>(nrX);
+                ILRetArray<complex> ret = new ILRetArray<complex>(retArr, real.Size);
+                
+                double[] inArrReal = real.GetArrayForRead();
+                
+                double[] inArrImag = imag.GetArrayForRead();
+                for (int i = 0; i < nrX; i++) {
+                    retArr[i].real = (double)inArrReal[i];
+                    retArr[i].imag = (double)inArrImag[i];
+                }
+                return ret;
+            }
+        }
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// Convert real array to complex array
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Complex array with A as real part, imaginary part is zero</returns>
+        public static ILRetArray<complex> real2complex( ILInArray< byte> A ) {
+            using (ILScope.Enter(A)) {
+                int nrX = A.Size.NumberOfElements;
+                complex[] retArr = ILMemoryPool.Pool.New<complex>(nrX);
+                ILRetArray<complex> ret = new ILRetArray<complex>(retArr, A.Size);
+               
+                byte[] inArr = A.GetArrayForRead();
+                for (int i = 0; i < nrX; i++) {
+                    retArr[i] = new complex((double)inArr[i], 0.0);
+                }
+                return ret;
+            }
+        }
+        /// <summary>
+        /// Create complex array out of real and imaginary parts
+        /// </summary>
+        /// <param name="real">Real array for real part</param>
+        /// <param name="imag">Real array for imaginary part</param>
+        /// <returns>Complex array having the real- and part imaginary parts constructed out of 
+        /// real and imag.</returns>
+        /// <remarks>Real and imag must have the same number of elements.
+        /// The array returned will have the same size as the input arrays.</remarks>
+        public static ILRetArray<complex> real2complex( ILInArray< byte> real, ILInArray< byte> imag ) {
+            using (ILScope.Enter(real, imag)) {
+                int nrX = real.Size.NumberOfElements;
+                if (nrX != imag.Size.NumberOfElements)
+                    throw new ILArgumentSizeException("size of real and imag input arrays must match!");
+                complex[] retArr = ILMemoryPool.Pool.New<complex>(nrX);
+                ILRetArray<complex> ret = new ILRetArray<complex>(retArr, real.Size);
+               
+                byte[] inArrReal = real.GetArrayForRead();
+               
+                byte[] inArrImag = imag.GetArrayForRead();
+                for (int i = 0; i < nrX; i++) {
+                    retArr[i].real = (double)inArrReal[i];
+                    retArr[i].imag = (double)inArrImag[i];
+                }
+                return ret;
+            }
+        }
+
+        /// <summary>
+        /// Convert real array to complex array
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Complex array with A as real part, imaginary part is zero</returns>
+        public static ILRetArray<complex> real2complex( ILInArray< Int64> A ) {
+            using (ILScope.Enter(A)) {
+                int nrX = A.Size.NumberOfElements;
+                complex[] retArr = ILMemoryPool.Pool.New<complex>(nrX);
+                ILRetArray<complex> ret = new ILRetArray<complex>(retArr, A.Size);
+               
+                Int64[] inArr = A.GetArrayForRead();
+                for (int i = 0; i < nrX; i++) {
+                    retArr[i] = new complex((double)inArr[i], 0.0);
+                }
+                return ret;
+            }
+        }
+        /// <summary>
+        /// Create complex array out of real and imaginary parts
+        /// </summary>
+        /// <param name="real">Real array for real part</param>
+        /// <param name="imag">Real array for imaginary part</param>
+        /// <returns>Complex array having the real- and part imaginary parts constructed out of 
+        /// real and imag.</returns>
+        /// <remarks>Real and imag must have the same number of elements.
+        /// The array returned will have the same size as the input arrays.</remarks>
+        public static ILRetArray<complex> real2complex( ILInArray< Int64> real, ILInArray< Int64> imag ) {
+            using (ILScope.Enter(real, imag)) {
+                int nrX = real.Size.NumberOfElements;
+                if (nrX != imag.Size.NumberOfElements)
+                    throw new ILArgumentSizeException("size of real and imag input arrays must match!");
+                complex[] retArr = ILMemoryPool.Pool.New<complex>(nrX);
+                ILRetArray<complex> ret = new ILRetArray<complex>(retArr, real.Size);
+               
+                Int64[] inArrReal = real.GetArrayForRead();
+               
+                Int64[] inArrImag = imag.GetArrayForRead();
+                for (int i = 0; i < nrX; i++) {
+                    retArr[i].real = (double)inArrReal[i];
+                    retArr[i].imag = (double)inArrImag[i];
+                }
+                return ret;
+            }
+        }
+
+        /// <summary>
+        /// Convert real array to complex array
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Complex array with A as real part, imaginary part is zero</returns>
+        public static ILRetArray<complex> real2complex( ILInArray< Int32> A ) {
+            using (ILScope.Enter(A)) {
+                int nrX = A.Size.NumberOfElements;
+                complex[] retArr = ILMemoryPool.Pool.New<complex>(nrX);
+                ILRetArray<complex> ret = new ILRetArray<complex>(retArr, A.Size);
+               
+                Int32[] inArr = A.GetArrayForRead();
+                for (int i = 0; i < nrX; i++) {
+                    retArr[i] = new complex((double)inArr[i], 0.0);
+                }
+                return ret;
+            }
+        }
+        /// <summary>
+        /// Create complex array out of real and imaginary parts
+        /// </summary>
+        /// <param name="real">Real array for real part</param>
+        /// <param name="imag">Real array for imaginary part</param>
+        /// <returns>Complex array having the real- and part imaginary parts constructed out of 
+        /// real and imag.</returns>
+        /// <remarks>Real and imag must have the same number of elements.
+        /// The array returned will have the same size as the input arrays.</remarks>
+        public static ILRetArray<complex> real2complex( ILInArray< Int32> real, ILInArray< Int32> imag ) {
+            using (ILScope.Enter(real, imag)) {
+                int nrX = real.Size.NumberOfElements;
+                if (nrX != imag.Size.NumberOfElements)
+                    throw new ILArgumentSizeException("size of real and imag input arrays must match!");
+                complex[] retArr = ILMemoryPool.Pool.New<complex>(nrX);
+                ILRetArray<complex> ret = new ILRetArray<complex>(retArr, real.Size);
+               
+                Int32[] inArrReal = real.GetArrayForRead();
+               
+                Int32[] inArrImag = imag.GetArrayForRead();
+                for (int i = 0; i < nrX; i++) {
+                    retArr[i].real = (double)inArrReal[i];
+                    retArr[i].imag = (double)inArrImag[i];
+                }
+                return ret;
+            }
+        }
+
+        /// <summary>
+        /// Convert real array to complex array
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Complex array with A as real part, imaginary part is zero</returns>
+        public static ILRetArray<complex> real2complex( ILInArray< float> A ) {
+            using (ILScope.Enter(A)) {
+                int nrX = A.Size.NumberOfElements;
+                complex[] retArr = ILMemoryPool.Pool.New<complex>(nrX);
+                ILRetArray<complex> ret = new ILRetArray<complex>(retArr, A.Size);
+               
+                float[] inArr = A.GetArrayForRead();
+                for (int i = 0; i < nrX; i++) {
+                    retArr[i] = new complex((double)inArr[i], 0.0);
+                }
+                return ret;
+            }
+        }
+        /// <summary>
+        /// Create complex array out of real and imaginary parts
+        /// </summary>
+        /// <param name="real">Real array for real part</param>
+        /// <param name="imag">Real array for imaginary part</param>
+        /// <returns>Complex array having the real- and part imaginary parts constructed out of 
+        /// real and imag.</returns>
+        /// <remarks>Real and imag must have the same number of elements.
+        /// The array returned will have the same size as the input arrays.</remarks>
+        public static ILRetArray<complex> real2complex( ILInArray< float> real, ILInArray< float> imag ) {
+            using (ILScope.Enter(real, imag)) {
+                int nrX = real.Size.NumberOfElements;
+                if (nrX != imag.Size.NumberOfElements)
+                    throw new ILArgumentSizeException("size of real and imag input arrays must match!");
+                complex[] retArr = ILMemoryPool.Pool.New<complex>(nrX);
+                ILRetArray<complex> ret = new ILRetArray<complex>(retArr, real.Size);
+               
+                float[] inArrReal = real.GetArrayForRead();
+               
+                float[] inArrImag = imag.GetArrayForRead();
+                for (int i = 0; i < nrX; i++) {
+                    retArr[i].real = (double)inArrReal[i];
+                    retArr[i].imag = (double)inArrImag[i];
+                }
+                return ret;
+            }
+        }
+
+
+#endregion HYCALPER AUTO GENERATED CODE
+   }
+
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/real2fcomplex.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/real2fcomplex.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/real2fcomplex.cs	(revision 9102)
@@ -0,0 +1,292 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions;
+
+
+
+namespace ILNumerics  {
+    
+    public partial class ILMath {
+    
+
+        /// <summary>
+        /// Convert real array to fcomplex array
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns>fcomplex array with A as real part, imaginary part is zero</returns>
+        public static ILRetArray<fcomplex> real2fcomplex (ILInArray< double > A) {
+            using (ILScope.Enter(A)) {
+                int nrX = A.Size.NumberOfElements;
+                fcomplex[] retArr = ILMemoryPool.Pool.New<fcomplex>(nrX);
+                ILRetArray<fcomplex> ret = new ILRetArray<fcomplex>(retArr, A.Size);
+                
+                double[] inArr = A.GetArrayForRead();
+                for (int i = 0; i < nrX; i++) {
+                    retArr[i] = new fcomplex((float)inArr[i], 0f);
+                }
+                return ret;
+            }
+        }
+        /// <summary>
+        /// Create fcomplex array out of real and imaginary parts
+        /// </summary>
+        /// <param name="real">Real array for real part</param>
+        /// <param name="imag">Real array for imaginary part</param>
+        /// <returns>fcomplex array having the real- and part imaginary parts constructed out of 
+        /// real and imag.</returns>
+        /// <remarks>real and imag must have the same number of elements.
+        /// The array returned will have the same size as the input arrays.</remarks>
+        public static ILRetArray<fcomplex> real2fcomplex (ILInArray< double > real, ILInArray< double > imag) {
+            using (ILScope.Enter(real, imag)) {
+                int nrX = real.Size.NumberOfElements;
+                if (nrX != imag.Size.NumberOfElements)
+                    throw new ILArgumentSizeException("size of real and imag input arrays must match!");
+                fcomplex[] retArr = ILMemoryPool.Pool.New<fcomplex>(nrX);
+                ILRetArray<fcomplex> ret = new ILRetArray<fcomplex>(retArr, real.Size);
+                
+                double[] inArrReal = real.GetArrayForRead();
+                
+                double[] inArrImag = imag.GetArrayForRead();
+                for (int i = 0; i < nrX; i++) {
+                    retArr[i].real = (float)inArrReal[i];
+                    retArr[i].imag = (float)inArrImag[i];
+                }
+                return ret;
+            }
+        }
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// Convert real array to fcomplex array
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns>fcomplex array with A as real part, imaginary part is zero</returns>
+        public static ILRetArray<fcomplex> real2fcomplex (ILInArray< byte > A) {
+            using (ILScope.Enter(A)) {
+                int nrX = A.Size.NumberOfElements;
+                fcomplex[] retArr = ILMemoryPool.Pool.New<fcomplex>(nrX);
+                ILRetArray<fcomplex> ret = new ILRetArray<fcomplex>(retArr, A.Size);
+               
+                byte[] inArr = A.GetArrayForRead();
+                for (int i = 0; i < nrX; i++) {
+                    retArr[i] = new fcomplex((float)inArr[i], 0f);
+                }
+                return ret;
+            }
+        }
+        /// <summary>
+        /// Create fcomplex array out of real and imaginary parts
+        /// </summary>
+        /// <param name="real">Real array for real part</param>
+        /// <param name="imag">Real array for imaginary part</param>
+        /// <returns>fcomplex array having the real- and part imaginary parts constructed out of 
+        /// real and imag.</returns>
+        /// <remarks>real and imag must have the same number of elements.
+        /// The array returned will have the same size as the input arrays.</remarks>
+        public static ILRetArray<fcomplex> real2fcomplex (ILInArray< byte > real, ILInArray< byte > imag) {
+            using (ILScope.Enter(real, imag)) {
+                int nrX = real.Size.NumberOfElements;
+                if (nrX != imag.Size.NumberOfElements)
+                    throw new ILArgumentSizeException("size of real and imag input arrays must match!");
+                fcomplex[] retArr = ILMemoryPool.Pool.New<fcomplex>(nrX);
+                ILRetArray<fcomplex> ret = new ILRetArray<fcomplex>(retArr, real.Size);
+               
+                byte[] inArrReal = real.GetArrayForRead();
+               
+                byte[] inArrImag = imag.GetArrayForRead();
+                for (int i = 0; i < nrX; i++) {
+                    retArr[i].real = (float)inArrReal[i];
+                    retArr[i].imag = (float)inArrImag[i];
+                }
+                return ret;
+            }
+        }
+
+        /// <summary>
+        /// Convert real array to fcomplex array
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns>fcomplex array with A as real part, imaginary part is zero</returns>
+        public static ILRetArray<fcomplex> real2fcomplex (ILInArray< Int64 > A) {
+            using (ILScope.Enter(A)) {
+                int nrX = A.Size.NumberOfElements;
+                fcomplex[] retArr = ILMemoryPool.Pool.New<fcomplex>(nrX);
+                ILRetArray<fcomplex> ret = new ILRetArray<fcomplex>(retArr, A.Size);
+               
+                Int64[] inArr = A.GetArrayForRead();
+                for (int i = 0; i < nrX; i++) {
+                    retArr[i] = new fcomplex((float)inArr[i], 0f);
+                }
+                return ret;
+            }
+        }
+        /// <summary>
+        /// Create fcomplex array out of real and imaginary parts
+        /// </summary>
+        /// <param name="real">Real array for real part</param>
+        /// <param name="imag">Real array for imaginary part</param>
+        /// <returns>fcomplex array having the real- and part imaginary parts constructed out of 
+        /// real and imag.</returns>
+        /// <remarks>real and imag must have the same number of elements.
+        /// The array returned will have the same size as the input arrays.</remarks>
+        public static ILRetArray<fcomplex> real2fcomplex (ILInArray< Int64 > real, ILInArray< Int64 > imag) {
+            using (ILScope.Enter(real, imag)) {
+                int nrX = real.Size.NumberOfElements;
+                if (nrX != imag.Size.NumberOfElements)
+                    throw new ILArgumentSizeException("size of real and imag input arrays must match!");
+                fcomplex[] retArr = ILMemoryPool.Pool.New<fcomplex>(nrX);
+                ILRetArray<fcomplex> ret = new ILRetArray<fcomplex>(retArr, real.Size);
+               
+                Int64[] inArrReal = real.GetArrayForRead();
+               
+                Int64[] inArrImag = imag.GetArrayForRead();
+                for (int i = 0; i < nrX; i++) {
+                    retArr[i].real = (float)inArrReal[i];
+                    retArr[i].imag = (float)inArrImag[i];
+                }
+                return ret;
+            }
+        }
+
+        /// <summary>
+        /// Convert real array to fcomplex array
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns>fcomplex array with A as real part, imaginary part is zero</returns>
+        public static ILRetArray<fcomplex> real2fcomplex (ILInArray< Int32 > A) {
+            using (ILScope.Enter(A)) {
+                int nrX = A.Size.NumberOfElements;
+                fcomplex[] retArr = ILMemoryPool.Pool.New<fcomplex>(nrX);
+                ILRetArray<fcomplex> ret = new ILRetArray<fcomplex>(retArr, A.Size);
+               
+                Int32[] inArr = A.GetArrayForRead();
+                for (int i = 0; i < nrX; i++) {
+                    retArr[i] = new fcomplex((float)inArr[i], 0f);
+                }
+                return ret;
+            }
+        }
+        /// <summary>
+        /// Create fcomplex array out of real and imaginary parts
+        /// </summary>
+        /// <param name="real">Real array for real part</param>
+        /// <param name="imag">Real array for imaginary part</param>
+        /// <returns>fcomplex array having the real- and part imaginary parts constructed out of 
+        /// real and imag.</returns>
+        /// <remarks>real and imag must have the same number of elements.
+        /// The array returned will have the same size as the input arrays.</remarks>
+        public static ILRetArray<fcomplex> real2fcomplex (ILInArray< Int32 > real, ILInArray< Int32 > imag) {
+            using (ILScope.Enter(real, imag)) {
+                int nrX = real.Size.NumberOfElements;
+                if (nrX != imag.Size.NumberOfElements)
+                    throw new ILArgumentSizeException("size of real and imag input arrays must match!");
+                fcomplex[] retArr = ILMemoryPool.Pool.New<fcomplex>(nrX);
+                ILRetArray<fcomplex> ret = new ILRetArray<fcomplex>(retArr, real.Size);
+               
+                Int32[] inArrReal = real.GetArrayForRead();
+               
+                Int32[] inArrImag = imag.GetArrayForRead();
+                for (int i = 0; i < nrX; i++) {
+                    retArr[i].real = (float)inArrReal[i];
+                    retArr[i].imag = (float)inArrImag[i];
+                }
+                return ret;
+            }
+        }
+
+        /// <summary>
+        /// Convert real array to fcomplex array
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns>fcomplex array with A as real part, imaginary part is zero</returns>
+        public static ILRetArray<fcomplex> real2fcomplex (ILInArray< float > A) {
+            using (ILScope.Enter(A)) {
+                int nrX = A.Size.NumberOfElements;
+                fcomplex[] retArr = ILMemoryPool.Pool.New<fcomplex>(nrX);
+                ILRetArray<fcomplex> ret = new ILRetArray<fcomplex>(retArr, A.Size);
+               
+                float[] inArr = A.GetArrayForRead();
+                for (int i = 0; i < nrX; i++) {
+                    retArr[i] = new fcomplex((float)inArr[i], 0f);
+                }
+                return ret;
+            }
+        }
+        /// <summary>
+        /// Create fcomplex array out of real and imaginary parts
+        /// </summary>
+        /// <param name="real">Real array for real part</param>
+        /// <param name="imag">Real array for imaginary part</param>
+        /// <returns>fcomplex array having the real- and part imaginary parts constructed out of 
+        /// real and imag.</returns>
+        /// <remarks>real and imag must have the same number of elements.
+        /// The array returned will have the same size as the input arrays.</remarks>
+        public static ILRetArray<fcomplex> real2fcomplex (ILInArray< float > real, ILInArray< float > imag) {
+            using (ILScope.Enter(real, imag)) {
+                int nrX = real.Size.NumberOfElements;
+                if (nrX != imag.Size.NumberOfElements)
+                    throw new ILArgumentSizeException("size of real and imag input arrays must match!");
+                fcomplex[] retArr = ILMemoryPool.Pool.New<fcomplex>(nrX);
+                ILRetArray<fcomplex> ret = new ILRetArray<fcomplex>(retArr, real.Size);
+               
+                float[] inArrReal = real.GetArrayForRead();
+               
+                float[] inArrImag = imag.GetArrayForRead();
+                for (int i = 0; i < nrX; i++) {
+                    retArr[i].real = (float)inArrReal[i];
+                    retArr[i].imag = (float)inArrImag[i];
+                }
+                return ret;
+            }
+        }
+
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/repmat.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/repmat.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/repmat.cs	(revision 9102)
@@ -0,0 +1,147 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+
+
+
+namespace ILNumerics {
+    public partial class ILMath {
+
+
+        /// <summary>
+        /// Array replication 
+        /// </summary>
+        /// <param name="X">Input array to be replicated</param>
+        /// <param name="size">Dimensions specifier, number of rows, columns .. to replicate this array</param>
+        /// <returns>Reference ILArray as replication of X</returns>
+        public static ILRetArray<double> repmat(ILInArray<double> X, params int[] size) {
+            using (ILScope.Enter(X)) {
+                return new ILRetArray<double>(X.Storage.Repmat(size));
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// Array replication 
+        /// </summary>
+        /// <param name="X">Input array to be replicated</param>
+        /// <param name="size">Dimensions specifier, number of rows, columns .. to replicate this array</param>
+        /// <returns>Reference ILArray as replication of X</returns>
+        public static ILRetArray<fcomplex> repmat(ILInArray<fcomplex> X, params int[] size) {
+            using (ILScope.Enter(X)) {
+                return new ILRetArray<fcomplex>(X.Storage.Repmat(size));
+            }
+        }
+        /// <summary>
+        /// Array replication 
+        /// </summary>
+        /// <param name="X">Input array to be replicated</param>
+        /// <param name="size">Dimensions specifier, number of rows, columns .. to replicate this array</param>
+        /// <returns>Reference ILArray as replication of X</returns>
+        public static ILRetArray<complex> repmat(ILInArray<complex> X, params int[] size) {
+            using (ILScope.Enter(X)) {
+                return new ILRetArray<complex>(X.Storage.Repmat(size));
+            }
+        }
+        /// <summary>
+        /// Array replication 
+        /// </summary>
+        /// <param name="X">Input array to be replicated</param>
+        /// <param name="size">Dimensions specifier, number of rows, columns .. to replicate this array</param>
+        /// <returns>Reference ILArray as replication of X</returns>
+        public static ILRetArray<byte> repmat(ILInArray<byte> X, params int[] size) {
+            using (ILScope.Enter(X)) {
+                return new ILRetArray<byte>(X.Storage.Repmat(size));
+            }
+        }
+        /// <summary>
+        /// Array replication 
+        /// </summary>
+        /// <param name="X">Input array to be replicated</param>
+        /// <param name="size">Dimensions specifier, number of rows, columns .. to replicate this array</param>
+        /// <returns>Reference ILArray as replication of X</returns>
+        public static ILRetArray<Int64> repmat(ILInArray<Int64> X, params int[] size) {
+            using (ILScope.Enter(X)) {
+                return new ILRetArray<Int64>(X.Storage.Repmat(size));
+            }
+        }
+        /// <summary>
+        /// Array replication 
+        /// </summary>
+        /// <param name="X">Input array to be replicated</param>
+        /// <param name="size">Dimensions specifier, number of rows, columns .. to replicate this array</param>
+        /// <returns>Reference ILArray as replication of X</returns>
+        public static ILRetArray<Int32> repmat(ILInArray<Int32> X, params int[] size) {
+            using (ILScope.Enter(X)) {
+                return new ILRetArray<Int32>(X.Storage.Repmat(size));
+            }
+        }
+        /// <summary>
+        /// Array replication 
+        /// </summary>
+        /// <param name="X">Input array to be replicated</param>
+        /// <param name="size">Dimensions specifier, number of rows, columns .. to replicate this array</param>
+        /// <returns>Reference ILArray as replication of X</returns>
+        public static ILRetArray<float> repmat(ILInArray<float> X, params int[] size) {
+            using (ILScope.Enter(X)) {
+                return new ILRetArray<float>(X.Storage.Repmat(size));
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// Array replication 
+        /// </summary>
+        /// <param name="X">Input array to be replicated</param>
+        /// <param name="size">Dimensions specifier, number of rows, columns .. to replicate this array</param>
+        /// <returns>Reference ILArray as replication of X</returns>
+        public static ILRetArray<T> repmat<T>(ILInArray<T> X, params int[] size) {
+            using (ILScope.Enter(X)) {
+                return new ILRetArray<T>(X.Storage.Repmat(size));
+            }
+        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/reshape.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/reshape.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/reshape.cs	(revision 9102)
@@ -0,0 +1,315 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+
+
+
+namespace ILNumerics {
+    public partial class ILMath {
+
+
+        /// <summary>
+        /// Array reshaping
+        /// </summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="dim">New dimension</param>
+        /// <returns>Reshaped array</returns>
+        /// <remarks>A will not be changed. A new array is created, having 
+        /// the size and number of dimensions specified by dim. </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentSizeException"> 
+        /// If the number of elements in A and the number of elements for the 
+        /// new dimensions specified by <paramref name="dim"/> 
+        /// do not match.</exception>
+        public static ILRetArray<double> reshape(ILInArray<double> A, ILSize dim) {
+            using (ILScope.Enter(A))
+                return A.Reshape(dim);
+        }
+        /// <summary>
+        /// Array reshaping
+        /// </summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="newDimensions">New dimensions. This may be 
+        /// a comma seperated list or an int array</param>
+        /// <returns>Reshaped array</returns>
+        /// <remarks>A will not be changed. A new array is created, having 
+        /// the size and number of dimensions specified by <paramref name="newDimensions"/>. </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentSizeException"> 
+        /// If the number of elements in A and the number of elements specified 
+        /// by <paramref name="newDimensions"/> do not match.</exception>
+        public static ILRetArray<double> reshape(ILInArray<double> A, params int[] newDimensions) {
+            using (ILScope.Enter(A))
+                return A.Reshape(new ILSize(newDimensions)); 
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// Array reshaping
+        /// </summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="dim">New dimension</param>
+        /// <returns>Reshaped array</returns>
+        /// <remarks>A will not be changed. A new array is created, having 
+        /// the size and number of dimensions specified by dim. </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentSizeException"> 
+        /// If the number of elements in A and the number of elements for the 
+        /// new dimensions specified by <paramref name="dim"/> 
+        /// do not match.</exception>
+        public static ILRetArray<fcomplex> reshape(ILInArray<fcomplex> A, ILSize dim) {
+            using (ILScope.Enter(A))
+                return A.Reshape(dim);
+        }
+        /// <summary>
+        /// Array reshaping
+        /// </summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="newDimensions">New dimensions. This may be 
+        /// a comma seperated list or an int array</param>
+        /// <returns>Reshaped array</returns>
+        /// <remarks>A will not be changed. A new array is created, having 
+        /// the size and number of dimensions specified by <paramref name="newDimensions"/>. </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentSizeException"> 
+        /// If the number of elements in A and the number of elements specified 
+        /// by <paramref name="newDimensions"/> do not match.</exception>
+        public static ILRetArray<fcomplex> reshape(ILInArray<fcomplex> A, params int[] newDimensions) {
+            using (ILScope.Enter(A))
+                return A.Reshape(new ILSize(newDimensions)); 
+        }
+        /// <summary>
+        /// Array reshaping
+        /// </summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="dim">New dimension</param>
+        /// <returns>Reshaped array</returns>
+        /// <remarks>A will not be changed. A new array is created, having 
+        /// the size and number of dimensions specified by dim. </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentSizeException"> 
+        /// If the number of elements in A and the number of elements for the 
+        /// new dimensions specified by <paramref name="dim"/> 
+        /// do not match.</exception>
+        public static ILRetArray<complex> reshape(ILInArray<complex> A, ILSize dim) {
+            using (ILScope.Enter(A))
+                return A.Reshape(dim);
+        }
+        /// <summary>
+        /// Array reshaping
+        /// </summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="newDimensions">New dimensions. This may be 
+        /// a comma seperated list or an int array</param>
+        /// <returns>Reshaped array</returns>
+        /// <remarks>A will not be changed. A new array is created, having 
+        /// the size and number of dimensions specified by <paramref name="newDimensions"/>. </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentSizeException"> 
+        /// If the number of elements in A and the number of elements specified 
+        /// by <paramref name="newDimensions"/> do not match.</exception>
+        public static ILRetArray<complex> reshape(ILInArray<complex> A, params int[] newDimensions) {
+            using (ILScope.Enter(A))
+                return A.Reshape(new ILSize(newDimensions)); 
+        }
+        /// <summary>
+        /// Array reshaping
+        /// </summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="dim">New dimension</param>
+        /// <returns>Reshaped array</returns>
+        /// <remarks>A will not be changed. A new array is created, having 
+        /// the size and number of dimensions specified by dim. </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentSizeException"> 
+        /// If the number of elements in A and the number of elements for the 
+        /// new dimensions specified by <paramref name="dim"/> 
+        /// do not match.</exception>
+        public static ILRetArray<byte> reshape(ILInArray<byte> A, ILSize dim) {
+            using (ILScope.Enter(A))
+                return A.Reshape(dim);
+        }
+        /// <summary>
+        /// Array reshaping
+        /// </summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="newDimensions">New dimensions. This may be 
+        /// a comma seperated list or an int array</param>
+        /// <returns>Reshaped array</returns>
+        /// <remarks>A will not be changed. A new array is created, having 
+        /// the size and number of dimensions specified by <paramref name="newDimensions"/>. </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentSizeException"> 
+        /// If the number of elements in A and the number of elements specified 
+        /// by <paramref name="newDimensions"/> do not match.</exception>
+        public static ILRetArray<byte> reshape(ILInArray<byte> A, params int[] newDimensions) {
+            using (ILScope.Enter(A))
+                return A.Reshape(new ILSize(newDimensions)); 
+        }
+        /// <summary>
+        /// Array reshaping
+        /// </summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="dim">New dimension</param>
+        /// <returns>Reshaped array</returns>
+        /// <remarks>A will not be changed. A new array is created, having 
+        /// the size and number of dimensions specified by dim. </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentSizeException"> 
+        /// If the number of elements in A and the number of elements for the 
+        /// new dimensions specified by <paramref name="dim"/> 
+        /// do not match.</exception>
+        public static ILRetArray<Int64> reshape(ILInArray<Int64> A, ILSize dim) {
+            using (ILScope.Enter(A))
+                return A.Reshape(dim);
+        }
+        /// <summary>
+        /// Array reshaping
+        /// </summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="newDimensions">New dimensions. This may be 
+        /// a comma seperated list or an int array</param>
+        /// <returns>Reshaped array</returns>
+        /// <remarks>A will not be changed. A new array is created, having 
+        /// the size and number of dimensions specified by <paramref name="newDimensions"/>. </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentSizeException"> 
+        /// If the number of elements in A and the number of elements specified 
+        /// by <paramref name="newDimensions"/> do not match.</exception>
+        public static ILRetArray<Int64> reshape(ILInArray<Int64> A, params int[] newDimensions) {
+            using (ILScope.Enter(A))
+                return A.Reshape(new ILSize(newDimensions)); 
+        }
+        /// <summary>
+        /// Array reshaping
+        /// </summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="dim">New dimension</param>
+        /// <returns>Reshaped array</returns>
+        /// <remarks>A will not be changed. A new array is created, having 
+        /// the size and number of dimensions specified by dim. </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentSizeException"> 
+        /// If the number of elements in A and the number of elements for the 
+        /// new dimensions specified by <paramref name="dim"/> 
+        /// do not match.</exception>
+        public static ILRetArray<Int32> reshape(ILInArray<Int32> A, ILSize dim) {
+            using (ILScope.Enter(A))
+                return A.Reshape(dim);
+        }
+        /// <summary>
+        /// Array reshaping
+        /// </summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="newDimensions">New dimensions. This may be 
+        /// a comma seperated list or an int array</param>
+        /// <returns>Reshaped array</returns>
+        /// <remarks>A will not be changed. A new array is created, having 
+        /// the size and number of dimensions specified by <paramref name="newDimensions"/>. </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentSizeException"> 
+        /// If the number of elements in A and the number of elements specified 
+        /// by <paramref name="newDimensions"/> do not match.</exception>
+        public static ILRetArray<Int32> reshape(ILInArray<Int32> A, params int[] newDimensions) {
+            using (ILScope.Enter(A))
+                return A.Reshape(new ILSize(newDimensions)); 
+        }
+        /// <summary>
+        /// Array reshaping
+        /// </summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="dim">New dimension</param>
+        /// <returns>Reshaped array</returns>
+        /// <remarks>A will not be changed. A new array is created, having 
+        /// the size and number of dimensions specified by dim. </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentSizeException"> 
+        /// If the number of elements in A and the number of elements for the 
+        /// new dimensions specified by <paramref name="dim"/> 
+        /// do not match.</exception>
+        public static ILRetArray<float> reshape(ILInArray<float> A, ILSize dim) {
+            using (ILScope.Enter(A))
+                return A.Reshape(dim);
+        }
+        /// <summary>
+        /// Array reshaping
+        /// </summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="newDimensions">New dimensions. This may be 
+        /// a comma seperated list or an int array</param>
+        /// <returns>Reshaped array</returns>
+        /// <remarks>A will not be changed. A new array is created, having 
+        /// the size and number of dimensions specified by <paramref name="newDimensions"/>. </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentSizeException"> 
+        /// If the number of elements in A and the number of elements specified 
+        /// by <paramref name="newDimensions"/> do not match.</exception>
+        public static ILRetArray<float> reshape(ILInArray<float> A, params int[] newDimensions) {
+            using (ILScope.Enter(A))
+                return A.Reshape(new ILSize(newDimensions)); 
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// Array reshaping
+        /// </summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="newDimensions">New dimensions array. This may be 
+        /// a comma seperated list or an int array</param>
+        /// <returns>Reshaped array</returns>
+        /// <remarks>A will not be changed. A new array is created, having 
+        /// the size and number of dimensions specified by <paramref name="newDimensions"/>. </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentSizeException"> 
+        /// If the number of elements in A and the number of elements specified 
+        /// by <paramref name="newDimensions"/> 
+        /// do not match.</exception>
+        public static ILRetArray<T> reshape<T>(ILInArray<T> A, params int[] newDimensions) {
+            return A.Reshape(new ILSize(newDimensions));
+        }
+        /// <summary>
+        /// Array reshaping
+        /// </summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="dim">New dimension</param>
+        /// <returns>Reshaped array</returns>
+        /// <remarks>A will not be changed. A new reference array is created, having 
+        /// the size and number of dimensions specified by dim. </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentSizeException"> 
+        /// If the number of elements in A and the number of elements for the 
+        /// new dimensions specified by <paramref name="dim"/> 
+        /// do not match.</exception>
+        public static ILRetArray<T> reshape<T>(ILInArray<T> A, ILSize dim) {
+            using (ILScope.Enter(A))
+                return A.Reshape(dim); 
+        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/round.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/round.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/round.cs	(revision 9102)
@@ -0,0 +1,558 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics;
+using ILNumerics.Exceptions; 
+using ILNumerics.Storage; 
+using ILNumerics.Misc; 
+
+
+namespace ILNumerics {
+
+    public partial class ILMath {
+      
+
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>Round to nearest integer</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Array of same size as A with elements rounded to nearest integer</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<complex>  round (ILInArray< complex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<complex>(A.Size); 
+                ILSize inDim = A.Size;
+                complex[] arrA = A.GetArrayForRead(); 
+                complex [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<complex>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<complex> retStorage = new ILDenseStorage<complex>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    complex* cp = ((complex*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  complex.Round(cp[0]  )  /*dummy*/;
+                            cp[1] =  complex.Round(cp[1]  )  /*dummy*/;
+                            cp[2] =  complex.Round(cp[2]  )  /*dummy*/;
+                            cp[3] =  complex.Round(cp[3]  )  /*dummy*/;
+                            cp[4] =  complex.Round(cp[4]  )  /*dummy*/;
+                            cp[5] =  complex.Round(cp[5]  )  /*dummy*/;
+                            cp[6] =  complex.Round(cp[6]  )  /*dummy*/;
+                            cp[7] =  complex.Round(cp[7]  )  /*dummy*/;
+                            cp[8] =  complex.Round(cp[8]  )  /*dummy*/;
+                            cp[9] =  complex.Round(cp[9]  )  /*dummy*/;
+                            cp[10] =  complex.Round(cp[10]  )  /*dummy*/;
+                            cp[11] =  complex.Round(cp[11]  )  /*dummy*/;
+                            cp[12] =  complex.Round(cp[12]  )  /*dummy*/;
+                            cp[13] =  complex.Round(cp[13]  )  /*dummy*/;
+                            cp[14] =  complex.Round(cp[14]  )  /*dummy*/;
+                            cp[15] =  complex.Round(cp[15]  )  /*dummy*/;
+                            cp[16] =  complex.Round(cp[16]  )  /*dummy*/;
+                            cp[17] =  complex.Round(cp[17]  )  /*dummy*/;
+                            cp[18] =  complex.Round(cp[18]  )  /*dummy*/;
+                            cp[19] =  complex.Round(cp[19]  )  /*dummy*/;
+                            cp[20] =  complex.Round(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.Round(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        complex* ap = ((complex*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  complex.Round(ap[0]  )  /*dummy*/;
+                            cp[1] =  complex.Round(ap[1]  )  /*dummy*/;
+                            cp[2] =  complex.Round(ap[2]  )  /*dummy*/;
+                            cp[3] =  complex.Round(ap[3]  )  /*dummy*/;
+                            cp[4] =  complex.Round(ap[4]  )  /*dummy*/;
+                            cp[5] =  complex.Round(ap[5]  )  /*dummy*/;
+                            cp[6] =  complex.Round(ap[6]  )  /*dummy*/;
+                            cp[7] =  complex.Round(ap[7]  )  /*dummy*/;
+                            cp[8] =  complex.Round(ap[8]  )  /*dummy*/;
+                            cp[9] =  complex.Round(ap[9]  )  /*dummy*/;
+                            cp[10] =  complex.Round(ap[10]  )  /*dummy*/;
+                            cp[11] =  complex.Round(ap[11]  )  /*dummy*/;
+                            cp[12] =  complex.Round(ap[12]  )  /*dummy*/;
+                            cp[13] =  complex.Round(ap[13]  )  /*dummy*/;
+                            cp[14] =  complex.Round(ap[14]  )  /*dummy*/;
+                            cp[15] =  complex.Round(ap[15]  )  /*dummy*/;
+                            cp[16] =  complex.Round(ap[16]  )  /*dummy*/;
+                            cp[17] =  complex.Round(ap[17]  )  /*dummy*/;
+                            cp[18] =  complex.Round(ap[18]  )  /*dummy*/;
+                            cp[19] =  complex.Round(ap[19]  )  /*dummy*/;
+                            cp[20] =  complex.Round(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.Round(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( complex* arrAP = arrA)
+                fixed ( complex* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<complex>(retStorage);
+            }
+        }
+        /// <summary>Round to nearest integer</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Array of same size as A with elements rounded to nearest integer</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<fcomplex>  round (ILInArray< fcomplex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<fcomplex>(A.Size); 
+                ILSize inDim = A.Size;
+                fcomplex[] arrA = A.GetArrayForRead(); 
+                fcomplex [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<fcomplex>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<fcomplex> retStorage = new ILDenseStorage<fcomplex>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    fcomplex* cp = ((fcomplex*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  fcomplex.Round(cp[0]  )  /*dummy*/;
+                            cp[1] =  fcomplex.Round(cp[1]  )  /*dummy*/;
+                            cp[2] =  fcomplex.Round(cp[2]  )  /*dummy*/;
+                            cp[3] =  fcomplex.Round(cp[3]  )  /*dummy*/;
+                            cp[4] =  fcomplex.Round(cp[4]  )  /*dummy*/;
+                            cp[5] =  fcomplex.Round(cp[5]  )  /*dummy*/;
+                            cp[6] =  fcomplex.Round(cp[6]  )  /*dummy*/;
+                            cp[7] =  fcomplex.Round(cp[7]  )  /*dummy*/;
+                            cp[8] =  fcomplex.Round(cp[8]  )  /*dummy*/;
+                            cp[9] =  fcomplex.Round(cp[9]  )  /*dummy*/;
+                            cp[10] =  fcomplex.Round(cp[10]  )  /*dummy*/;
+                            cp[11] =  fcomplex.Round(cp[11]  )  /*dummy*/;
+                            cp[12] =  fcomplex.Round(cp[12]  )  /*dummy*/;
+                            cp[13] =  fcomplex.Round(cp[13]  )  /*dummy*/;
+                            cp[14] =  fcomplex.Round(cp[14]  )  /*dummy*/;
+                            cp[15] =  fcomplex.Round(cp[15]  )  /*dummy*/;
+                            cp[16] =  fcomplex.Round(cp[16]  )  /*dummy*/;
+                            cp[17] =  fcomplex.Round(cp[17]  )  /*dummy*/;
+                            cp[18] =  fcomplex.Round(cp[18]  )  /*dummy*/;
+                            cp[19] =  fcomplex.Round(cp[19]  )  /*dummy*/;
+                            cp[20] =  fcomplex.Round(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.Round(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        fcomplex* ap = ((fcomplex*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  fcomplex.Round(ap[0]  )  /*dummy*/;
+                            cp[1] =  fcomplex.Round(ap[1]  )  /*dummy*/;
+                            cp[2] =  fcomplex.Round(ap[2]  )  /*dummy*/;
+                            cp[3] =  fcomplex.Round(ap[3]  )  /*dummy*/;
+                            cp[4] =  fcomplex.Round(ap[4]  )  /*dummy*/;
+                            cp[5] =  fcomplex.Round(ap[5]  )  /*dummy*/;
+                            cp[6] =  fcomplex.Round(ap[6]  )  /*dummy*/;
+                            cp[7] =  fcomplex.Round(ap[7]  )  /*dummy*/;
+                            cp[8] =  fcomplex.Round(ap[8]  )  /*dummy*/;
+                            cp[9] =  fcomplex.Round(ap[9]  )  /*dummy*/;
+                            cp[10] =  fcomplex.Round(ap[10]  )  /*dummy*/;
+                            cp[11] =  fcomplex.Round(ap[11]  )  /*dummy*/;
+                            cp[12] =  fcomplex.Round(ap[12]  )  /*dummy*/;
+                            cp[13] =  fcomplex.Round(ap[13]  )  /*dummy*/;
+                            cp[14] =  fcomplex.Round(ap[14]  )  /*dummy*/;
+                            cp[15] =  fcomplex.Round(ap[15]  )  /*dummy*/;
+                            cp[16] =  fcomplex.Round(ap[16]  )  /*dummy*/;
+                            cp[17] =  fcomplex.Round(ap[17]  )  /*dummy*/;
+                            cp[18] =  fcomplex.Round(ap[18]  )  /*dummy*/;
+                            cp[19] =  fcomplex.Round(ap[19]  )  /*dummy*/;
+                            cp[20] =  fcomplex.Round(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.Round(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( fcomplex* arrAP = arrA)
+                fixed ( fcomplex* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<fcomplex>(retStorage);
+            }
+        }
+        /// <summary>Round to nearest integer</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Array of same size as A with elements rounded to nearest integer</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<float>  round (ILInArray< float > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<float>(A.Size); 
+                ILSize inDim = A.Size;
+                float[] arrA = A.GetArrayForRead(); 
+                float [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<float>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<float> retStorage = new ILDenseStorage<float>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    float* cp = ((float*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  (float)Math.Round(cp[0]  )  /*dummy*/;
+                            cp[1] =  (float)Math.Round(cp[1]  )  /*dummy*/;
+                            cp[2] =  (float)Math.Round(cp[2]  )  /*dummy*/;
+                            cp[3] =  (float)Math.Round(cp[3]  )  /*dummy*/;
+                            cp[4] =  (float)Math.Round(cp[4]  )  /*dummy*/;
+                            cp[5] =  (float)Math.Round(cp[5]  )  /*dummy*/;
+                            cp[6] =  (float)Math.Round(cp[6]  )  /*dummy*/;
+                            cp[7] =  (float)Math.Round(cp[7]  )  /*dummy*/;
+                            cp[8] =  (float)Math.Round(cp[8]  )  /*dummy*/;
+                            cp[9] =  (float)Math.Round(cp[9]  )  /*dummy*/;
+                            cp[10] =  (float)Math.Round(cp[10]  )  /*dummy*/;
+                            cp[11] =  (float)Math.Round(cp[11]  )  /*dummy*/;
+                            cp[12] =  (float)Math.Round(cp[12]  )  /*dummy*/;
+                            cp[13] =  (float)Math.Round(cp[13]  )  /*dummy*/;
+                            cp[14] =  (float)Math.Round(cp[14]  )  /*dummy*/;
+                            cp[15] =  (float)Math.Round(cp[15]  )  /*dummy*/;
+                            cp[16] =  (float)Math.Round(cp[16]  )  /*dummy*/;
+                            cp[17] =  (float)Math.Round(cp[17]  )  /*dummy*/;
+                            cp[18] =  (float)Math.Round(cp[18]  )  /*dummy*/;
+                            cp[19] =  (float)Math.Round(cp[19]  )  /*dummy*/;
+                            cp[20] =  (float)Math.Round(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  (float)Math.Round(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        float* ap = ((float*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  (float)Math.Round(ap[0]  )  /*dummy*/;
+                            cp[1] =  (float)Math.Round(ap[1]  )  /*dummy*/;
+                            cp[2] =  (float)Math.Round(ap[2]  )  /*dummy*/;
+                            cp[3] =  (float)Math.Round(ap[3]  )  /*dummy*/;
+                            cp[4] =  (float)Math.Round(ap[4]  )  /*dummy*/;
+                            cp[5] =  (float)Math.Round(ap[5]  )  /*dummy*/;
+                            cp[6] =  (float)Math.Round(ap[6]  )  /*dummy*/;
+                            cp[7] =  (float)Math.Round(ap[7]  )  /*dummy*/;
+                            cp[8] =  (float)Math.Round(ap[8]  )  /*dummy*/;
+                            cp[9] =  (float)Math.Round(ap[9]  )  /*dummy*/;
+                            cp[10] =  (float)Math.Round(ap[10]  )  /*dummy*/;
+                            cp[11] =  (float)Math.Round(ap[11]  )  /*dummy*/;
+                            cp[12] =  (float)Math.Round(ap[12]  )  /*dummy*/;
+                            cp[13] =  (float)Math.Round(ap[13]  )  /*dummy*/;
+                            cp[14] =  (float)Math.Round(ap[14]  )  /*dummy*/;
+                            cp[15] =  (float)Math.Round(ap[15]  )  /*dummy*/;
+                            cp[16] =  (float)Math.Round(ap[16]  )  /*dummy*/;
+                            cp[17] =  (float)Math.Round(ap[17]  )  /*dummy*/;
+                            cp[18] =  (float)Math.Round(ap[18]  )  /*dummy*/;
+                            cp[19] =  (float)Math.Round(ap[19]  )  /*dummy*/;
+                            cp[20] =  (float)Math.Round(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  (float)Math.Round(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( float* arrAP = arrA)
+                fixed ( float* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<float>(retStorage);
+            }
+        }
+        /// <summary>Round to nearest integer</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Array of same size as A with elements rounded to nearest integer</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<double>  round (ILInArray< double > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<double>(A.Size); 
+                ILSize inDim = A.Size;
+                double[] arrA = A.GetArrayForRead(); 
+                double [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<double>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<double> retStorage = new ILDenseStorage<double>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    double* cp = ((double*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  Math.Round(cp[0]  )  /*dummy*/;
+                            cp[1] =  Math.Round(cp[1]  )  /*dummy*/;
+                            cp[2] =  Math.Round(cp[2]  )  /*dummy*/;
+                            cp[3] =  Math.Round(cp[3]  )  /*dummy*/;
+                            cp[4] =  Math.Round(cp[4]  )  /*dummy*/;
+                            cp[5] =  Math.Round(cp[5]  )  /*dummy*/;
+                            cp[6] =  Math.Round(cp[6]  )  /*dummy*/;
+                            cp[7] =  Math.Round(cp[7]  )  /*dummy*/;
+                            cp[8] =  Math.Round(cp[8]  )  /*dummy*/;
+                            cp[9] =  Math.Round(cp[9]  )  /*dummy*/;
+                            cp[10] =  Math.Round(cp[10]  )  /*dummy*/;
+                            cp[11] =  Math.Round(cp[11]  )  /*dummy*/;
+                            cp[12] =  Math.Round(cp[12]  )  /*dummy*/;
+                            cp[13] =  Math.Round(cp[13]  )  /*dummy*/;
+                            cp[14] =  Math.Round(cp[14]  )  /*dummy*/;
+                            cp[15] =  Math.Round(cp[15]  )  /*dummy*/;
+                            cp[16] =  Math.Round(cp[16]  )  /*dummy*/;
+                            cp[17] =  Math.Round(cp[17]  )  /*dummy*/;
+                            cp[18] =  Math.Round(cp[18]  )  /*dummy*/;
+                            cp[19] =  Math.Round(cp[19]  )  /*dummy*/;
+                            cp[20] =  Math.Round(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Math.Round(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        double* ap = ((double*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  Math.Round(ap[0]  )  /*dummy*/;
+                            cp[1] =  Math.Round(ap[1]  )  /*dummy*/;
+                            cp[2] =  Math.Round(ap[2]  )  /*dummy*/;
+                            cp[3] =  Math.Round(ap[3]  )  /*dummy*/;
+                            cp[4] =  Math.Round(ap[4]  )  /*dummy*/;
+                            cp[5] =  Math.Round(ap[5]  )  /*dummy*/;
+                            cp[6] =  Math.Round(ap[6]  )  /*dummy*/;
+                            cp[7] =  Math.Round(ap[7]  )  /*dummy*/;
+                            cp[8] =  Math.Round(ap[8]  )  /*dummy*/;
+                            cp[9] =  Math.Round(ap[9]  )  /*dummy*/;
+                            cp[10] =  Math.Round(ap[10]  )  /*dummy*/;
+                            cp[11] =  Math.Round(ap[11]  )  /*dummy*/;
+                            cp[12] =  Math.Round(ap[12]  )  /*dummy*/;
+                            cp[13] =  Math.Round(ap[13]  )  /*dummy*/;
+                            cp[14] =  Math.Round(ap[14]  )  /*dummy*/;
+                            cp[15] =  Math.Round(ap[15]  )  /*dummy*/;
+                            cp[16] =  Math.Round(ap[16]  )  /*dummy*/;
+                            cp[17] =  Math.Round(ap[17]  )  /*dummy*/;
+                            cp[18] =  Math.Round(ap[18]  )  /*dummy*/;
+                            cp[19] =  Math.Round(ap[19]  )  /*dummy*/;
+                            cp[20] =  Math.Round(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Math.Round(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( double* arrAP = arrA)
+                fixed ( double* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<double>(retStorage);
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/set.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/set.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/set.cs	(revision 9102)
@@ -0,0 +1,39 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/sign.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/sign.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/sign.cs	(revision 9102)
@@ -0,0 +1,1054 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics;
+using ILNumerics.Exceptions;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+
+
+namespace ILNumerics {
+
+    public partial class ILMath {
+     
+
+                        
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>Signum of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Array with elements signaling the sign of corresponding elements of A</returns>
+        /// <remarks><para>The signum function produces following values: <list type="bullet"><item>-1 - for elements &lt; zero,</item><item> 0 - for elements equal zero,</item><item> 1 - for elements &gt; zero,</item></list></para><para>If the input array is empty, an empty array will be returned.</para>
+        ///                         <para>The array returned will be a solid array.</para></remarks>
+        public unsafe static  ILRetArray<double>  sign (ILInArray< double > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<double>(A.Size); 
+                ILSize inDim = A.Size;
+                double[] arrA = A.GetArrayForRead(); 
+                double [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<double>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<double> retStorage = new ILDenseStorage<double>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    double* cp = ((double*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  (double)Math.Sign(cp[0]  )  /*dummy*/;
+                            cp[1] =  (double)Math.Sign(cp[1]  )  /*dummy*/;
+                            cp[2] =  (double)Math.Sign(cp[2]  )  /*dummy*/;
+                            cp[3] =  (double)Math.Sign(cp[3]  )  /*dummy*/;
+                            cp[4] =  (double)Math.Sign(cp[4]  )  /*dummy*/;
+                            cp[5] =  (double)Math.Sign(cp[5]  )  /*dummy*/;
+                            cp[6] =  (double)Math.Sign(cp[6]  )  /*dummy*/;
+                            cp[7] =  (double)Math.Sign(cp[7]  )  /*dummy*/;
+                            cp[8] =  (double)Math.Sign(cp[8]  )  /*dummy*/;
+                            cp[9] =  (double)Math.Sign(cp[9]  )  /*dummy*/;
+                            cp[10] =  (double)Math.Sign(cp[10]  )  /*dummy*/;
+                            cp[11] =  (double)Math.Sign(cp[11]  )  /*dummy*/;
+                            cp[12] =  (double)Math.Sign(cp[12]  )  /*dummy*/;
+                            cp[13] =  (double)Math.Sign(cp[13]  )  /*dummy*/;
+                            cp[14] =  (double)Math.Sign(cp[14]  )  /*dummy*/;
+                            cp[15] =  (double)Math.Sign(cp[15]  )  /*dummy*/;
+                            cp[16] =  (double)Math.Sign(cp[16]  )  /*dummy*/;
+                            cp[17] =  (double)Math.Sign(cp[17]  )  /*dummy*/;
+                            cp[18] =  (double)Math.Sign(cp[18]  )  /*dummy*/;
+                            cp[19] =  (double)Math.Sign(cp[19]  )  /*dummy*/;
+                            cp[20] =  (double)Math.Sign(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  (double)Math.Sign(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        double* ap = ((double*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  (double)Math.Sign(ap[0]  )  /*dummy*/;
+                            cp[1] =  (double)Math.Sign(ap[1]  )  /*dummy*/;
+                            cp[2] =  (double)Math.Sign(ap[2]  )  /*dummy*/;
+                            cp[3] =  (double)Math.Sign(ap[3]  )  /*dummy*/;
+                            cp[4] =  (double)Math.Sign(ap[4]  )  /*dummy*/;
+                            cp[5] =  (double)Math.Sign(ap[5]  )  /*dummy*/;
+                            cp[6] =  (double)Math.Sign(ap[6]  )  /*dummy*/;
+                            cp[7] =  (double)Math.Sign(ap[7]  )  /*dummy*/;
+                            cp[8] =  (double)Math.Sign(ap[8]  )  /*dummy*/;
+                            cp[9] =  (double)Math.Sign(ap[9]  )  /*dummy*/;
+                            cp[10] =  (double)Math.Sign(ap[10]  )  /*dummy*/;
+                            cp[11] =  (double)Math.Sign(ap[11]  )  /*dummy*/;
+                            cp[12] =  (double)Math.Sign(ap[12]  )  /*dummy*/;
+                            cp[13] =  (double)Math.Sign(ap[13]  )  /*dummy*/;
+                            cp[14] =  (double)Math.Sign(ap[14]  )  /*dummy*/;
+                            cp[15] =  (double)Math.Sign(ap[15]  )  /*dummy*/;
+                            cp[16] =  (double)Math.Sign(ap[16]  )  /*dummy*/;
+                            cp[17] =  (double)Math.Sign(ap[17]  )  /*dummy*/;
+                            cp[18] =  (double)Math.Sign(ap[18]  )  /*dummy*/;
+                            cp[19] =  (double)Math.Sign(ap[19]  )  /*dummy*/;
+                            cp[20] =  (double)Math.Sign(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  (double)Math.Sign(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( double* arrAP = arrA)
+                fixed ( double* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<double>(retStorage);
+            }
+        }
+        /// <summary>Signum of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Array with elements signaling the sign of corresponding elements of A</returns>
+        /// <remarks><para>The signum function produces following values: <list type="bullet"><item>-1 - for elements &lt; zero,</item><item> 0 - for elements equal zero,</item><item> 1 - for elements &gt; zero,</item></list></para><para>If the input array is empty, an empty array will be returned.</para>
+        ///                         <para>The array returned will be a solid array.</para></remarks>
+        public unsafe static  ILRetArray<float>  sign (ILInArray< float > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<float>(A.Size); 
+                ILSize inDim = A.Size;
+                float[] arrA = A.GetArrayForRead(); 
+                float [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<float>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<float> retStorage = new ILDenseStorage<float>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    float* cp = ((float*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  (float)Math.Sign(cp[0]  )  /*dummy*/;
+                            cp[1] =  (float)Math.Sign(cp[1]  )  /*dummy*/;
+                            cp[2] =  (float)Math.Sign(cp[2]  )  /*dummy*/;
+                            cp[3] =  (float)Math.Sign(cp[3]  )  /*dummy*/;
+                            cp[4] =  (float)Math.Sign(cp[4]  )  /*dummy*/;
+                            cp[5] =  (float)Math.Sign(cp[5]  )  /*dummy*/;
+                            cp[6] =  (float)Math.Sign(cp[6]  )  /*dummy*/;
+                            cp[7] =  (float)Math.Sign(cp[7]  )  /*dummy*/;
+                            cp[8] =  (float)Math.Sign(cp[8]  )  /*dummy*/;
+                            cp[9] =  (float)Math.Sign(cp[9]  )  /*dummy*/;
+                            cp[10] =  (float)Math.Sign(cp[10]  )  /*dummy*/;
+                            cp[11] =  (float)Math.Sign(cp[11]  )  /*dummy*/;
+                            cp[12] =  (float)Math.Sign(cp[12]  )  /*dummy*/;
+                            cp[13] =  (float)Math.Sign(cp[13]  )  /*dummy*/;
+                            cp[14] =  (float)Math.Sign(cp[14]  )  /*dummy*/;
+                            cp[15] =  (float)Math.Sign(cp[15]  )  /*dummy*/;
+                            cp[16] =  (float)Math.Sign(cp[16]  )  /*dummy*/;
+                            cp[17] =  (float)Math.Sign(cp[17]  )  /*dummy*/;
+                            cp[18] =  (float)Math.Sign(cp[18]  )  /*dummy*/;
+                            cp[19] =  (float)Math.Sign(cp[19]  )  /*dummy*/;
+                            cp[20] =  (float)Math.Sign(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  (float)Math.Sign(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        float* ap = ((float*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  (float)Math.Sign(ap[0]  )  /*dummy*/;
+                            cp[1] =  (float)Math.Sign(ap[1]  )  /*dummy*/;
+                            cp[2] =  (float)Math.Sign(ap[2]  )  /*dummy*/;
+                            cp[3] =  (float)Math.Sign(ap[3]  )  /*dummy*/;
+                            cp[4] =  (float)Math.Sign(ap[4]  )  /*dummy*/;
+                            cp[5] =  (float)Math.Sign(ap[5]  )  /*dummy*/;
+                            cp[6] =  (float)Math.Sign(ap[6]  )  /*dummy*/;
+                            cp[7] =  (float)Math.Sign(ap[7]  )  /*dummy*/;
+                            cp[8] =  (float)Math.Sign(ap[8]  )  /*dummy*/;
+                            cp[9] =  (float)Math.Sign(ap[9]  )  /*dummy*/;
+                            cp[10] =  (float)Math.Sign(ap[10]  )  /*dummy*/;
+                            cp[11] =  (float)Math.Sign(ap[11]  )  /*dummy*/;
+                            cp[12] =  (float)Math.Sign(ap[12]  )  /*dummy*/;
+                            cp[13] =  (float)Math.Sign(ap[13]  )  /*dummy*/;
+                            cp[14] =  (float)Math.Sign(ap[14]  )  /*dummy*/;
+                            cp[15] =  (float)Math.Sign(ap[15]  )  /*dummy*/;
+                            cp[16] =  (float)Math.Sign(ap[16]  )  /*dummy*/;
+                            cp[17] =  (float)Math.Sign(ap[17]  )  /*dummy*/;
+                            cp[18] =  (float)Math.Sign(ap[18]  )  /*dummy*/;
+                            cp[19] =  (float)Math.Sign(ap[19]  )  /*dummy*/;
+                            cp[20] =  (float)Math.Sign(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  (float)Math.Sign(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( float* arrAP = arrA)
+                fixed ( float* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<float>(retStorage);
+            }
+        }
+        /// <summary>Signum of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Array with elements signaling the sign of corresponding elements of A</returns>
+        /// <remarks><para>The signum function for each element a is computed by: a / abs(a). Therefore, values returned will all lay on the unit circle.</para><para>If the input array is empty, an empty array will be returned.</para>
+        ///                         <para>The array returned will be a solid array.</para></remarks>
+        public unsafe static  ILRetArray<fcomplex>  sign (ILInArray< fcomplex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<fcomplex>(A.Size); 
+                ILSize inDim = A.Size;
+                fcomplex[] arrA = A.GetArrayForRead(); 
+                fcomplex [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<fcomplex>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<fcomplex> retStorage = new ILDenseStorage<fcomplex>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    fcomplex* cp = ((fcomplex*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  fcomplex.Sign(cp[0]  )  /*dummy*/;
+                            cp[1] =  fcomplex.Sign(cp[1]  )  /*dummy*/;
+                            cp[2] =  fcomplex.Sign(cp[2]  )  /*dummy*/;
+                            cp[3] =  fcomplex.Sign(cp[3]  )  /*dummy*/;
+                            cp[4] =  fcomplex.Sign(cp[4]  )  /*dummy*/;
+                            cp[5] =  fcomplex.Sign(cp[5]  )  /*dummy*/;
+                            cp[6] =  fcomplex.Sign(cp[6]  )  /*dummy*/;
+                            cp[7] =  fcomplex.Sign(cp[7]  )  /*dummy*/;
+                            cp[8] =  fcomplex.Sign(cp[8]  )  /*dummy*/;
+                            cp[9] =  fcomplex.Sign(cp[9]  )  /*dummy*/;
+                            cp[10] =  fcomplex.Sign(cp[10]  )  /*dummy*/;
+                            cp[11] =  fcomplex.Sign(cp[11]  )  /*dummy*/;
+                            cp[12] =  fcomplex.Sign(cp[12]  )  /*dummy*/;
+                            cp[13] =  fcomplex.Sign(cp[13]  )  /*dummy*/;
+                            cp[14] =  fcomplex.Sign(cp[14]  )  /*dummy*/;
+                            cp[15] =  fcomplex.Sign(cp[15]  )  /*dummy*/;
+                            cp[16] =  fcomplex.Sign(cp[16]  )  /*dummy*/;
+                            cp[17] =  fcomplex.Sign(cp[17]  )  /*dummy*/;
+                            cp[18] =  fcomplex.Sign(cp[18]  )  /*dummy*/;
+                            cp[19] =  fcomplex.Sign(cp[19]  )  /*dummy*/;
+                            cp[20] =  fcomplex.Sign(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.Sign(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        fcomplex* ap = ((fcomplex*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  fcomplex.Sign(ap[0]  )  /*dummy*/;
+                            cp[1] =  fcomplex.Sign(ap[1]  )  /*dummy*/;
+                            cp[2] =  fcomplex.Sign(ap[2]  )  /*dummy*/;
+                            cp[3] =  fcomplex.Sign(ap[3]  )  /*dummy*/;
+                            cp[4] =  fcomplex.Sign(ap[4]  )  /*dummy*/;
+                            cp[5] =  fcomplex.Sign(ap[5]  )  /*dummy*/;
+                            cp[6] =  fcomplex.Sign(ap[6]  )  /*dummy*/;
+                            cp[7] =  fcomplex.Sign(ap[7]  )  /*dummy*/;
+                            cp[8] =  fcomplex.Sign(ap[8]  )  /*dummy*/;
+                            cp[9] =  fcomplex.Sign(ap[9]  )  /*dummy*/;
+                            cp[10] =  fcomplex.Sign(ap[10]  )  /*dummy*/;
+                            cp[11] =  fcomplex.Sign(ap[11]  )  /*dummy*/;
+                            cp[12] =  fcomplex.Sign(ap[12]  )  /*dummy*/;
+                            cp[13] =  fcomplex.Sign(ap[13]  )  /*dummy*/;
+                            cp[14] =  fcomplex.Sign(ap[14]  )  /*dummy*/;
+                            cp[15] =  fcomplex.Sign(ap[15]  )  /*dummy*/;
+                            cp[16] =  fcomplex.Sign(ap[16]  )  /*dummy*/;
+                            cp[17] =  fcomplex.Sign(ap[17]  )  /*dummy*/;
+                            cp[18] =  fcomplex.Sign(ap[18]  )  /*dummy*/;
+                            cp[19] =  fcomplex.Sign(ap[19]  )  /*dummy*/;
+                            cp[20] =  fcomplex.Sign(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.Sign(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( fcomplex* arrAP = arrA)
+                fixed ( fcomplex* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<fcomplex>(retStorage);
+            }
+        }
+        /// <summary>Signum of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Array with elements signaling the sign of corresponding elements of A</returns>
+        /// <remarks><para>The signum function for each element a is computed by: a / abs(a). Therefore, values returned will all lay on the unit circle.</para><para>If the input array is empty, an empty array will be returned.</para>
+        ///                         <para>The array returned will be a solid array.</para></remarks>
+        public unsafe static  ILRetArray<complex>  sign (ILInArray< complex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<complex>(A.Size); 
+                ILSize inDim = A.Size;
+                complex[] arrA = A.GetArrayForRead(); 
+                complex [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<complex>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<complex> retStorage = new ILDenseStorage<complex>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    complex* cp = ((complex*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  complex.Sign(cp[0]  )  /*dummy*/;
+                            cp[1] =  complex.Sign(cp[1]  )  /*dummy*/;
+                            cp[2] =  complex.Sign(cp[2]  )  /*dummy*/;
+                            cp[3] =  complex.Sign(cp[3]  )  /*dummy*/;
+                            cp[4] =  complex.Sign(cp[4]  )  /*dummy*/;
+                            cp[5] =  complex.Sign(cp[5]  )  /*dummy*/;
+                            cp[6] =  complex.Sign(cp[6]  )  /*dummy*/;
+                            cp[7] =  complex.Sign(cp[7]  )  /*dummy*/;
+                            cp[8] =  complex.Sign(cp[8]  )  /*dummy*/;
+                            cp[9] =  complex.Sign(cp[9]  )  /*dummy*/;
+                            cp[10] =  complex.Sign(cp[10]  )  /*dummy*/;
+                            cp[11] =  complex.Sign(cp[11]  )  /*dummy*/;
+                            cp[12] =  complex.Sign(cp[12]  )  /*dummy*/;
+                            cp[13] =  complex.Sign(cp[13]  )  /*dummy*/;
+                            cp[14] =  complex.Sign(cp[14]  )  /*dummy*/;
+                            cp[15] =  complex.Sign(cp[15]  )  /*dummy*/;
+                            cp[16] =  complex.Sign(cp[16]  )  /*dummy*/;
+                            cp[17] =  complex.Sign(cp[17]  )  /*dummy*/;
+                            cp[18] =  complex.Sign(cp[18]  )  /*dummy*/;
+                            cp[19] =  complex.Sign(cp[19]  )  /*dummy*/;
+                            cp[20] =  complex.Sign(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.Sign(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        complex* ap = ((complex*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  complex.Sign(ap[0]  )  /*dummy*/;
+                            cp[1] =  complex.Sign(ap[1]  )  /*dummy*/;
+                            cp[2] =  complex.Sign(ap[2]  )  /*dummy*/;
+                            cp[3] =  complex.Sign(ap[3]  )  /*dummy*/;
+                            cp[4] =  complex.Sign(ap[4]  )  /*dummy*/;
+                            cp[5] =  complex.Sign(ap[5]  )  /*dummy*/;
+                            cp[6] =  complex.Sign(ap[6]  )  /*dummy*/;
+                            cp[7] =  complex.Sign(ap[7]  )  /*dummy*/;
+                            cp[8] =  complex.Sign(ap[8]  )  /*dummy*/;
+                            cp[9] =  complex.Sign(ap[9]  )  /*dummy*/;
+                            cp[10] =  complex.Sign(ap[10]  )  /*dummy*/;
+                            cp[11] =  complex.Sign(ap[11]  )  /*dummy*/;
+                            cp[12] =  complex.Sign(ap[12]  )  /*dummy*/;
+                            cp[13] =  complex.Sign(ap[13]  )  /*dummy*/;
+                            cp[14] =  complex.Sign(ap[14]  )  /*dummy*/;
+                            cp[15] =  complex.Sign(ap[15]  )  /*dummy*/;
+                            cp[16] =  complex.Sign(ap[16]  )  /*dummy*/;
+                            cp[17] =  complex.Sign(ap[17]  )  /*dummy*/;
+                            cp[18] =  complex.Sign(ap[18]  )  /*dummy*/;
+                            cp[19] =  complex.Sign(ap[19]  )  /*dummy*/;
+                            cp[20] =  complex.Sign(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.Sign(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( complex* arrAP = arrA)
+                fixed ( complex* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<complex>(retStorage);
+            }
+        }
+        /// <summary>Signum of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Array with elements signaling the sign of corresponding elements of A</returns>
+        /// <remarks><para>The signum function produces following values: <list type="bullet"><item>-1 - for elements &lt; zero,</item><item> 0 - for elements equal zero,</item><item> 1 - for elements &gt; zero,</item></list></para><para>If the input array is empty, an empty array will be returned.</para>
+        ///                         <para>The array returned will be a solid array.</para></remarks>
+        public unsafe static  ILRetArray<Int64>  sign (ILInArray< Int64 > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<Int64>(A.Size); 
+                ILSize inDim = A.Size;
+                Int64[] arrA = A.GetArrayForRead(); 
+                Int64 [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<Int64>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<Int64> retStorage = new ILDenseStorage<Int64>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    Int64* cp = ((Int64*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  (Int64)Math.Sign(cp[0]  )  /*dummy*/;
+                            cp[1] =  (Int64)Math.Sign(cp[1]  )  /*dummy*/;
+                            cp[2] =  (Int64)Math.Sign(cp[2]  )  /*dummy*/;
+                            cp[3] =  (Int64)Math.Sign(cp[3]  )  /*dummy*/;
+                            cp[4] =  (Int64)Math.Sign(cp[4]  )  /*dummy*/;
+                            cp[5] =  (Int64)Math.Sign(cp[5]  )  /*dummy*/;
+                            cp[6] =  (Int64)Math.Sign(cp[6]  )  /*dummy*/;
+                            cp[7] =  (Int64)Math.Sign(cp[7]  )  /*dummy*/;
+                            cp[8] =  (Int64)Math.Sign(cp[8]  )  /*dummy*/;
+                            cp[9] =  (Int64)Math.Sign(cp[9]  )  /*dummy*/;
+                            cp[10] =  (Int64)Math.Sign(cp[10]  )  /*dummy*/;
+                            cp[11] =  (Int64)Math.Sign(cp[11]  )  /*dummy*/;
+                            cp[12] =  (Int64)Math.Sign(cp[12]  )  /*dummy*/;
+                            cp[13] =  (Int64)Math.Sign(cp[13]  )  /*dummy*/;
+                            cp[14] =  (Int64)Math.Sign(cp[14]  )  /*dummy*/;
+                            cp[15] =  (Int64)Math.Sign(cp[15]  )  /*dummy*/;
+                            cp[16] =  (Int64)Math.Sign(cp[16]  )  /*dummy*/;
+                            cp[17] =  (Int64)Math.Sign(cp[17]  )  /*dummy*/;
+                            cp[18] =  (Int64)Math.Sign(cp[18]  )  /*dummy*/;
+                            cp[19] =  (Int64)Math.Sign(cp[19]  )  /*dummy*/;
+                            cp[20] =  (Int64)Math.Sign(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  (Int64)Math.Sign(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        Int64* ap = ((Int64*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  (Int64)Math.Sign(ap[0]  )  /*dummy*/;
+                            cp[1] =  (Int64)Math.Sign(ap[1]  )  /*dummy*/;
+                            cp[2] =  (Int64)Math.Sign(ap[2]  )  /*dummy*/;
+                            cp[3] =  (Int64)Math.Sign(ap[3]  )  /*dummy*/;
+                            cp[4] =  (Int64)Math.Sign(ap[4]  )  /*dummy*/;
+                            cp[5] =  (Int64)Math.Sign(ap[5]  )  /*dummy*/;
+                            cp[6] =  (Int64)Math.Sign(ap[6]  )  /*dummy*/;
+                            cp[7] =  (Int64)Math.Sign(ap[7]  )  /*dummy*/;
+                            cp[8] =  (Int64)Math.Sign(ap[8]  )  /*dummy*/;
+                            cp[9] =  (Int64)Math.Sign(ap[9]  )  /*dummy*/;
+                            cp[10] =  (Int64)Math.Sign(ap[10]  )  /*dummy*/;
+                            cp[11] =  (Int64)Math.Sign(ap[11]  )  /*dummy*/;
+                            cp[12] =  (Int64)Math.Sign(ap[12]  )  /*dummy*/;
+                            cp[13] =  (Int64)Math.Sign(ap[13]  )  /*dummy*/;
+                            cp[14] =  (Int64)Math.Sign(ap[14]  )  /*dummy*/;
+                            cp[15] =  (Int64)Math.Sign(ap[15]  )  /*dummy*/;
+                            cp[16] =  (Int64)Math.Sign(ap[16]  )  /*dummy*/;
+                            cp[17] =  (Int64)Math.Sign(ap[17]  )  /*dummy*/;
+                            cp[18] =  (Int64)Math.Sign(ap[18]  )  /*dummy*/;
+                            cp[19] =  (Int64)Math.Sign(ap[19]  )  /*dummy*/;
+                            cp[20] =  (Int64)Math.Sign(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  (Int64)Math.Sign(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( Int64* arrAP = arrA)
+                fixed ( Int64* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<Int64>(retStorage);
+            }
+        }
+        /// <summary>Signum of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Array with elements signaling the sign of corresponding elements of A</returns>
+        /// <remarks><para>The signum function produces following values: <list type="bullet"><item>-1 - for elements &lt; zero,</item><item> 0 - for elements equal zero,</item><item> 1 - for elements &gt; zero,</item></list></para><para>If the input array is empty, an empty array will be returned.</para>
+        ///                         <para>The array returned will be a solid array.</para></remarks>
+        public unsafe static  ILRetArray<Int32>  sign (ILInArray< Int32 > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<Int32>(A.Size); 
+                ILSize inDim = A.Size;
+                Int32[] arrA = A.GetArrayForRead(); 
+                Int32 [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<Int32>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<Int32> retStorage = new ILDenseStorage<Int32>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    Int32* cp = ((Int32*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  (Int32)Math.Sign(cp[0]  )  /*dummy*/;
+                            cp[1] =  (Int32)Math.Sign(cp[1]  )  /*dummy*/;
+                            cp[2] =  (Int32)Math.Sign(cp[2]  )  /*dummy*/;
+                            cp[3] =  (Int32)Math.Sign(cp[3]  )  /*dummy*/;
+                            cp[4] =  (Int32)Math.Sign(cp[4]  )  /*dummy*/;
+                            cp[5] =  (Int32)Math.Sign(cp[5]  )  /*dummy*/;
+                            cp[6] =  (Int32)Math.Sign(cp[6]  )  /*dummy*/;
+                            cp[7] =  (Int32)Math.Sign(cp[7]  )  /*dummy*/;
+                            cp[8] =  (Int32)Math.Sign(cp[8]  )  /*dummy*/;
+                            cp[9] =  (Int32)Math.Sign(cp[9]  )  /*dummy*/;
+                            cp[10] =  (Int32)Math.Sign(cp[10]  )  /*dummy*/;
+                            cp[11] =  (Int32)Math.Sign(cp[11]  )  /*dummy*/;
+                            cp[12] =  (Int32)Math.Sign(cp[12]  )  /*dummy*/;
+                            cp[13] =  (Int32)Math.Sign(cp[13]  )  /*dummy*/;
+                            cp[14] =  (Int32)Math.Sign(cp[14]  )  /*dummy*/;
+                            cp[15] =  (Int32)Math.Sign(cp[15]  )  /*dummy*/;
+                            cp[16] =  (Int32)Math.Sign(cp[16]  )  /*dummy*/;
+                            cp[17] =  (Int32)Math.Sign(cp[17]  )  /*dummy*/;
+                            cp[18] =  (Int32)Math.Sign(cp[18]  )  /*dummy*/;
+                            cp[19] =  (Int32)Math.Sign(cp[19]  )  /*dummy*/;
+                            cp[20] =  (Int32)Math.Sign(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  (Int32)Math.Sign(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        Int32* ap = ((Int32*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  (Int32)Math.Sign(ap[0]  )  /*dummy*/;
+                            cp[1] =  (Int32)Math.Sign(ap[1]  )  /*dummy*/;
+                            cp[2] =  (Int32)Math.Sign(ap[2]  )  /*dummy*/;
+                            cp[3] =  (Int32)Math.Sign(ap[3]  )  /*dummy*/;
+                            cp[4] =  (Int32)Math.Sign(ap[4]  )  /*dummy*/;
+                            cp[5] =  (Int32)Math.Sign(ap[5]  )  /*dummy*/;
+                            cp[6] =  (Int32)Math.Sign(ap[6]  )  /*dummy*/;
+                            cp[7] =  (Int32)Math.Sign(ap[7]  )  /*dummy*/;
+                            cp[8] =  (Int32)Math.Sign(ap[8]  )  /*dummy*/;
+                            cp[9] =  (Int32)Math.Sign(ap[9]  )  /*dummy*/;
+                            cp[10] =  (Int32)Math.Sign(ap[10]  )  /*dummy*/;
+                            cp[11] =  (Int32)Math.Sign(ap[11]  )  /*dummy*/;
+                            cp[12] =  (Int32)Math.Sign(ap[12]  )  /*dummy*/;
+                            cp[13] =  (Int32)Math.Sign(ap[13]  )  /*dummy*/;
+                            cp[14] =  (Int32)Math.Sign(ap[14]  )  /*dummy*/;
+                            cp[15] =  (Int32)Math.Sign(ap[15]  )  /*dummy*/;
+                            cp[16] =  (Int32)Math.Sign(ap[16]  )  /*dummy*/;
+                            cp[17] =  (Int32)Math.Sign(ap[17]  )  /*dummy*/;
+                            cp[18] =  (Int32)Math.Sign(ap[18]  )  /*dummy*/;
+                            cp[19] =  (Int32)Math.Sign(ap[19]  )  /*dummy*/;
+                            cp[20] =  (Int32)Math.Sign(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  (Int32)Math.Sign(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( Int32* arrAP = arrA)
+                fixed ( Int32* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<Int32>(retStorage);
+            }
+        }
+        /// <summary>Signum of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Array with elements signaling the sign of corresponding elements of A</returns>
+        /// <remarks><para>The signum function produces following values: <list type="bullet"><item>-1 - for elements &lt; zero,</item><item> 0 - for elements equal zero,</item><item> 1 - for elements &gt; zero,</item></list></para><para>If the input array is empty, an empty array will be returned.</para>
+        ///                         <para>The array returned will be a solid array.</para></remarks>
+        public unsafe static  ILRetArray<Int16>  sign (ILInArray< Int16 > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<Int16>(A.Size); 
+                ILSize inDim = A.Size;
+                Int16[] arrA = A.GetArrayForRead(); 
+                Int16 [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<Int16>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<Int16> retStorage = new ILDenseStorage<Int16>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    Int16* cp = ((Int16*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  (Int16)Math.Sign(cp[0]  )  /*dummy*/;
+                            cp[1] =  (Int16)Math.Sign(cp[1]  )  /*dummy*/;
+                            cp[2] =  (Int16)Math.Sign(cp[2]  )  /*dummy*/;
+                            cp[3] =  (Int16)Math.Sign(cp[3]  )  /*dummy*/;
+                            cp[4] =  (Int16)Math.Sign(cp[4]  )  /*dummy*/;
+                            cp[5] =  (Int16)Math.Sign(cp[5]  )  /*dummy*/;
+                            cp[6] =  (Int16)Math.Sign(cp[6]  )  /*dummy*/;
+                            cp[7] =  (Int16)Math.Sign(cp[7]  )  /*dummy*/;
+                            cp[8] =  (Int16)Math.Sign(cp[8]  )  /*dummy*/;
+                            cp[9] =  (Int16)Math.Sign(cp[9]  )  /*dummy*/;
+                            cp[10] =  (Int16)Math.Sign(cp[10]  )  /*dummy*/;
+                            cp[11] =  (Int16)Math.Sign(cp[11]  )  /*dummy*/;
+                            cp[12] =  (Int16)Math.Sign(cp[12]  )  /*dummy*/;
+                            cp[13] =  (Int16)Math.Sign(cp[13]  )  /*dummy*/;
+                            cp[14] =  (Int16)Math.Sign(cp[14]  )  /*dummy*/;
+                            cp[15] =  (Int16)Math.Sign(cp[15]  )  /*dummy*/;
+                            cp[16] =  (Int16)Math.Sign(cp[16]  )  /*dummy*/;
+                            cp[17] =  (Int16)Math.Sign(cp[17]  )  /*dummy*/;
+                            cp[18] =  (Int16)Math.Sign(cp[18]  )  /*dummy*/;
+                            cp[19] =  (Int16)Math.Sign(cp[19]  )  /*dummy*/;
+                            cp[20] =  (Int16)Math.Sign(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  (Int16)Math.Sign(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        Int16* ap = ((Int16*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  (Int16)Math.Sign(ap[0]  )  /*dummy*/;
+                            cp[1] =  (Int16)Math.Sign(ap[1]  )  /*dummy*/;
+                            cp[2] =  (Int16)Math.Sign(ap[2]  )  /*dummy*/;
+                            cp[3] =  (Int16)Math.Sign(ap[3]  )  /*dummy*/;
+                            cp[4] =  (Int16)Math.Sign(ap[4]  )  /*dummy*/;
+                            cp[5] =  (Int16)Math.Sign(ap[5]  )  /*dummy*/;
+                            cp[6] =  (Int16)Math.Sign(ap[6]  )  /*dummy*/;
+                            cp[7] =  (Int16)Math.Sign(ap[7]  )  /*dummy*/;
+                            cp[8] =  (Int16)Math.Sign(ap[8]  )  /*dummy*/;
+                            cp[9] =  (Int16)Math.Sign(ap[9]  )  /*dummy*/;
+                            cp[10] =  (Int16)Math.Sign(ap[10]  )  /*dummy*/;
+                            cp[11] =  (Int16)Math.Sign(ap[11]  )  /*dummy*/;
+                            cp[12] =  (Int16)Math.Sign(ap[12]  )  /*dummy*/;
+                            cp[13] =  (Int16)Math.Sign(ap[13]  )  /*dummy*/;
+                            cp[14] =  (Int16)Math.Sign(ap[14]  )  /*dummy*/;
+                            cp[15] =  (Int16)Math.Sign(ap[15]  )  /*dummy*/;
+                            cp[16] =  (Int16)Math.Sign(ap[16]  )  /*dummy*/;
+                            cp[17] =  (Int16)Math.Sign(ap[17]  )  /*dummy*/;
+                            cp[18] =  (Int16)Math.Sign(ap[18]  )  /*dummy*/;
+                            cp[19] =  (Int16)Math.Sign(ap[19]  )  /*dummy*/;
+                            cp[20] =  (Int16)Math.Sign(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  (Int16)Math.Sign(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( Int16* arrAP = arrA)
+                fixed ( Int16* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<Int16>(retStorage);
+            }
+        }
+        /// <summary>Signum of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Array with elements signaling the sign of corresponding elements of A</returns>
+        /// <remarks><para>The signum function produces following values: <list type="bullet"><item>-1 - for elements &lt; zero,</item><item> 0 - for elements equal zero,</item><item> 1 - for elements &gt; zero,</item></list></para><para>If the input array is empty, an empty array will be returned.</para>
+        ///                         <para>The array returned will be a solid array.</para></remarks>
+        public unsafe static  ILRetArray<byte>  sign (ILInArray< byte > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<byte>(A.Size); 
+                ILSize inDim = A.Size;
+                byte[] arrA = A.GetArrayForRead(); 
+                byte [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<byte> retStorage = new ILDenseStorage<byte>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    byte* cp = ((byte*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  (byte)Math.Sign(cp[0]  )  /*dummy*/;
+                            cp[1] =  (byte)Math.Sign(cp[1]  )  /*dummy*/;
+                            cp[2] =  (byte)Math.Sign(cp[2]  )  /*dummy*/;
+                            cp[3] =  (byte)Math.Sign(cp[3]  )  /*dummy*/;
+                            cp[4] =  (byte)Math.Sign(cp[4]  )  /*dummy*/;
+                            cp[5] =  (byte)Math.Sign(cp[5]  )  /*dummy*/;
+                            cp[6] =  (byte)Math.Sign(cp[6]  )  /*dummy*/;
+                            cp[7] =  (byte)Math.Sign(cp[7]  )  /*dummy*/;
+                            cp[8] =  (byte)Math.Sign(cp[8]  )  /*dummy*/;
+                            cp[9] =  (byte)Math.Sign(cp[9]  )  /*dummy*/;
+                            cp[10] =  (byte)Math.Sign(cp[10]  )  /*dummy*/;
+                            cp[11] =  (byte)Math.Sign(cp[11]  )  /*dummy*/;
+                            cp[12] =  (byte)Math.Sign(cp[12]  )  /*dummy*/;
+                            cp[13] =  (byte)Math.Sign(cp[13]  )  /*dummy*/;
+                            cp[14] =  (byte)Math.Sign(cp[14]  )  /*dummy*/;
+                            cp[15] =  (byte)Math.Sign(cp[15]  )  /*dummy*/;
+                            cp[16] =  (byte)Math.Sign(cp[16]  )  /*dummy*/;
+                            cp[17] =  (byte)Math.Sign(cp[17]  )  /*dummy*/;
+                            cp[18] =  (byte)Math.Sign(cp[18]  )  /*dummy*/;
+                            cp[19] =  (byte)Math.Sign(cp[19]  )  /*dummy*/;
+                            cp[20] =  (byte)Math.Sign(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  (byte)Math.Sign(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        byte* ap = ((byte*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  (byte)Math.Sign(ap[0]  )  /*dummy*/;
+                            cp[1] =  (byte)Math.Sign(ap[1]  )  /*dummy*/;
+                            cp[2] =  (byte)Math.Sign(ap[2]  )  /*dummy*/;
+                            cp[3] =  (byte)Math.Sign(ap[3]  )  /*dummy*/;
+                            cp[4] =  (byte)Math.Sign(ap[4]  )  /*dummy*/;
+                            cp[5] =  (byte)Math.Sign(ap[5]  )  /*dummy*/;
+                            cp[6] =  (byte)Math.Sign(ap[6]  )  /*dummy*/;
+                            cp[7] =  (byte)Math.Sign(ap[7]  )  /*dummy*/;
+                            cp[8] =  (byte)Math.Sign(ap[8]  )  /*dummy*/;
+                            cp[9] =  (byte)Math.Sign(ap[9]  )  /*dummy*/;
+                            cp[10] =  (byte)Math.Sign(ap[10]  )  /*dummy*/;
+                            cp[11] =  (byte)Math.Sign(ap[11]  )  /*dummy*/;
+                            cp[12] =  (byte)Math.Sign(ap[12]  )  /*dummy*/;
+                            cp[13] =  (byte)Math.Sign(ap[13]  )  /*dummy*/;
+                            cp[14] =  (byte)Math.Sign(ap[14]  )  /*dummy*/;
+                            cp[15] =  (byte)Math.Sign(ap[15]  )  /*dummy*/;
+                            cp[16] =  (byte)Math.Sign(ap[16]  )  /*dummy*/;
+                            cp[17] =  (byte)Math.Sign(ap[17]  )  /*dummy*/;
+                            cp[18] =  (byte)Math.Sign(ap[18]  )  /*dummy*/;
+                            cp[19] =  (byte)Math.Sign(ap[19]  )  /*dummy*/;
+                            cp[20] =  (byte)Math.Sign(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  (byte)Math.Sign(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( byte* arrAP = arrA)
+                fixed ( byte* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<byte>(retStorage);
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/sin.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/sin.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/sin.cs	(revision 9102)
@@ -0,0 +1,588 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics;
+using ILNumerics.Exceptions; 
+using ILNumerics.Storage; 
+using ILNumerics.Misc; 
+
+
+
+namespace ILNumerics {
+    public partial class ILMath {
+
+        // VERSION WITHOUT UNSAFE CODE: 
+
+        //Action<object> worker = data => {
+        //    Tuple<int, int, bool> range = (Tuple<int, int, bool>)data;
+
+        //    int start = range.Item1;
+        //    int endEx = range.Item2 + start;
+        //    if (range.Item3) { 
+        //        // inplace
+        //        for (int k = start; k < retArr.Length; k++) {
+        //            if (k >= endEx) break; 
+        //            retArr[k] = Math.Abs(retArr[k]);
+        //        }
+        //    } else {
+        //        for (int k = start; k < retArr.Length; k++) {
+        //            if (k >= endEx) break;
+        //            retArr[k] = Math.Abs(arrA[k]);
+        //        }
+        //    }
+        //    System.Threading.Interlocked.Decrement(ref workerCount);
+        //    //retStorage.PendingEvents.Signal(); 
+        //};
+
+        ////retStorage.PendingEvents = new System.Threading.CountdownEvent(workItemCount); 
+        //for (; i < workItemCount - 1; i++) {
+        //    Tuple<int, int, bool> range = Tuple.Create(i * workItemLength, workItemLength, inplace);
+        //    System.Threading.Interlocked.Increment(ref workerCount);
+        //    ILThreadPool.QueueUserWorkItem(i,worker, range);
+        //}
+        //// the last (or may the only) chunk is done right here
+        //worker(Tuple.Create(i * workItemLength, outLen - i * workItemLength,inplace));
+
+
+        /// <summary>Sinus of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Sinus of elements from input array</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<double>  sin (ILInArray< double > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<double>(A.Size); 
+                ILSize inDim = A.Size;
+                 double[] arrA = A.GetArrayForRead(); 
+                 double [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+                
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<double>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<double> retStorage = new ILDenseStorage<double>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                    
+                    double* cp = ((double*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  Math.Sin(cp[0]  )  /*dummy*/;
+                            cp[1] =  Math.Sin(cp[1]  )  /*dummy*/;
+                            cp[2] =  Math.Sin(cp[2]  )  /*dummy*/;
+                            cp[3] =  Math.Sin(cp[3]  )  /*dummy*/;
+                            cp[4] =  Math.Sin(cp[4]  )  /*dummy*/;
+                            cp[5] =  Math.Sin(cp[5]  )  /*dummy*/;
+                            cp[6] =  Math.Sin(cp[6]  )  /*dummy*/;
+                            cp[7] =  Math.Sin(cp[7]  )  /*dummy*/;
+                            cp[8] =  Math.Sin(cp[8]  )  /*dummy*/;
+                            cp[9] =  Math.Sin(cp[9]  )  /*dummy*/;
+                            cp[10] =  Math.Sin(cp[10]  )  /*dummy*/;
+                            cp[11] =  Math.Sin(cp[11]  )  /*dummy*/;
+                            cp[12] =  Math.Sin(cp[12]  )  /*dummy*/;
+                            cp[13] =  Math.Sin(cp[13]  )  /*dummy*/;
+                            cp[14] =  Math.Sin(cp[14]  )  /*dummy*/;
+                            cp[15] =  Math.Sin(cp[15]  )  /*dummy*/;
+                            cp[16] =  Math.Sin(cp[16]  )  /*dummy*/;
+                            cp[17] =  Math.Sin(cp[17]  )  /*dummy*/;
+                            cp[18] =  Math.Sin(cp[18]  )  /*dummy*/;
+                            cp[19] =  Math.Sin(cp[19]  )  /*dummy*/;
+                            cp[20] =  Math.Sin(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Math.Sin(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                         double* ap = ((double*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  Math.Sin(ap[0]  )  /*dummy*/;
+                            cp[1] =  Math.Sin(ap[1]  )  /*dummy*/;
+                            cp[2] =  Math.Sin(ap[2]  )  /*dummy*/;
+                            cp[3] =  Math.Sin(ap[3]  )  /*dummy*/;
+                            cp[4] =  Math.Sin(ap[4]  )  /*dummy*/;
+                            cp[5] =  Math.Sin(ap[5]  )  /*dummy*/;
+                            cp[6] =  Math.Sin(ap[6]  )  /*dummy*/;
+                            cp[7] =  Math.Sin(ap[7]  )  /*dummy*/;
+                            cp[8] =  Math.Sin(ap[8]  )  /*dummy*/;
+                            cp[9] =  Math.Sin(ap[9]  )  /*dummy*/;
+                            cp[10] =  Math.Sin(ap[10]  )  /*dummy*/;
+                            cp[11] =  Math.Sin(ap[11]  )  /*dummy*/;
+                            cp[12] =  Math.Sin(ap[12]  )  /*dummy*/;
+                            cp[13] =  Math.Sin(ap[13]  )  /*dummy*/;
+                            cp[14] =  Math.Sin(ap[14]  )  /*dummy*/;
+                            cp[15] =  Math.Sin(ap[15]  )  /*dummy*/;
+                            cp[16] =  Math.Sin(ap[16]  )  /*dummy*/;
+                            cp[17] =  Math.Sin(ap[17]  )  /*dummy*/;
+                            cp[18] =  Math.Sin(ap[18]  )  /*dummy*/;
+                            cp[19] =  Math.Sin(ap[19]  )  /*dummy*/;
+                            cp[20] =  Math.Sin(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Math.Sin(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( double* arrAP = arrA)
+                fixed ( double* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<double>(retStorage);
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>Sinus of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Sinus of elements from input array</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<complex>  sin (ILInArray< complex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<complex>(A.Size); 
+                ILSize inDim = A.Size;
+                complex[] arrA = A.GetArrayForRead(); 
+                complex [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<complex>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<complex> retStorage = new ILDenseStorage<complex>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    complex* cp = ((complex*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  complex.Sin(cp[0]  )  /*dummy*/;
+                            cp[1] =  complex.Sin(cp[1]  )  /*dummy*/;
+                            cp[2] =  complex.Sin(cp[2]  )  /*dummy*/;
+                            cp[3] =  complex.Sin(cp[3]  )  /*dummy*/;
+                            cp[4] =  complex.Sin(cp[4]  )  /*dummy*/;
+                            cp[5] =  complex.Sin(cp[5]  )  /*dummy*/;
+                            cp[6] =  complex.Sin(cp[6]  )  /*dummy*/;
+                            cp[7] =  complex.Sin(cp[7]  )  /*dummy*/;
+                            cp[8] =  complex.Sin(cp[8]  )  /*dummy*/;
+                            cp[9] =  complex.Sin(cp[9]  )  /*dummy*/;
+                            cp[10] =  complex.Sin(cp[10]  )  /*dummy*/;
+                            cp[11] =  complex.Sin(cp[11]  )  /*dummy*/;
+                            cp[12] =  complex.Sin(cp[12]  )  /*dummy*/;
+                            cp[13] =  complex.Sin(cp[13]  )  /*dummy*/;
+                            cp[14] =  complex.Sin(cp[14]  )  /*dummy*/;
+                            cp[15] =  complex.Sin(cp[15]  )  /*dummy*/;
+                            cp[16] =  complex.Sin(cp[16]  )  /*dummy*/;
+                            cp[17] =  complex.Sin(cp[17]  )  /*dummy*/;
+                            cp[18] =  complex.Sin(cp[18]  )  /*dummy*/;
+                            cp[19] =  complex.Sin(cp[19]  )  /*dummy*/;
+                            cp[20] =  complex.Sin(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.Sin(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        complex* ap = ((complex*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  complex.Sin(ap[0]  )  /*dummy*/;
+                            cp[1] =  complex.Sin(ap[1]  )  /*dummy*/;
+                            cp[2] =  complex.Sin(ap[2]  )  /*dummy*/;
+                            cp[3] =  complex.Sin(ap[3]  )  /*dummy*/;
+                            cp[4] =  complex.Sin(ap[4]  )  /*dummy*/;
+                            cp[5] =  complex.Sin(ap[5]  )  /*dummy*/;
+                            cp[6] =  complex.Sin(ap[6]  )  /*dummy*/;
+                            cp[7] =  complex.Sin(ap[7]  )  /*dummy*/;
+                            cp[8] =  complex.Sin(ap[8]  )  /*dummy*/;
+                            cp[9] =  complex.Sin(ap[9]  )  /*dummy*/;
+                            cp[10] =  complex.Sin(ap[10]  )  /*dummy*/;
+                            cp[11] =  complex.Sin(ap[11]  )  /*dummy*/;
+                            cp[12] =  complex.Sin(ap[12]  )  /*dummy*/;
+                            cp[13] =  complex.Sin(ap[13]  )  /*dummy*/;
+                            cp[14] =  complex.Sin(ap[14]  )  /*dummy*/;
+                            cp[15] =  complex.Sin(ap[15]  )  /*dummy*/;
+                            cp[16] =  complex.Sin(ap[16]  )  /*dummy*/;
+                            cp[17] =  complex.Sin(ap[17]  )  /*dummy*/;
+                            cp[18] =  complex.Sin(ap[18]  )  /*dummy*/;
+                            cp[19] =  complex.Sin(ap[19]  )  /*dummy*/;
+                            cp[20] =  complex.Sin(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.Sin(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( complex* arrAP = arrA)
+                fixed ( complex* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<complex>(retStorage);
+            }
+        }
+        /// <summary>Sinus of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Sinus of elements from input array</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<fcomplex>  sin (ILInArray< fcomplex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<fcomplex>(A.Size); 
+                ILSize inDim = A.Size;
+                fcomplex[] arrA = A.GetArrayForRead(); 
+                fcomplex [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<fcomplex>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<fcomplex> retStorage = new ILDenseStorage<fcomplex>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    fcomplex* cp = ((fcomplex*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  fcomplex.Sin(cp[0]  )  /*dummy*/;
+                            cp[1] =  fcomplex.Sin(cp[1]  )  /*dummy*/;
+                            cp[2] =  fcomplex.Sin(cp[2]  )  /*dummy*/;
+                            cp[3] =  fcomplex.Sin(cp[3]  )  /*dummy*/;
+                            cp[4] =  fcomplex.Sin(cp[4]  )  /*dummy*/;
+                            cp[5] =  fcomplex.Sin(cp[5]  )  /*dummy*/;
+                            cp[6] =  fcomplex.Sin(cp[6]  )  /*dummy*/;
+                            cp[7] =  fcomplex.Sin(cp[7]  )  /*dummy*/;
+                            cp[8] =  fcomplex.Sin(cp[8]  )  /*dummy*/;
+                            cp[9] =  fcomplex.Sin(cp[9]  )  /*dummy*/;
+                            cp[10] =  fcomplex.Sin(cp[10]  )  /*dummy*/;
+                            cp[11] =  fcomplex.Sin(cp[11]  )  /*dummy*/;
+                            cp[12] =  fcomplex.Sin(cp[12]  )  /*dummy*/;
+                            cp[13] =  fcomplex.Sin(cp[13]  )  /*dummy*/;
+                            cp[14] =  fcomplex.Sin(cp[14]  )  /*dummy*/;
+                            cp[15] =  fcomplex.Sin(cp[15]  )  /*dummy*/;
+                            cp[16] =  fcomplex.Sin(cp[16]  )  /*dummy*/;
+                            cp[17] =  fcomplex.Sin(cp[17]  )  /*dummy*/;
+                            cp[18] =  fcomplex.Sin(cp[18]  )  /*dummy*/;
+                            cp[19] =  fcomplex.Sin(cp[19]  )  /*dummy*/;
+                            cp[20] =  fcomplex.Sin(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.Sin(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        fcomplex* ap = ((fcomplex*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  fcomplex.Sin(ap[0]  )  /*dummy*/;
+                            cp[1] =  fcomplex.Sin(ap[1]  )  /*dummy*/;
+                            cp[2] =  fcomplex.Sin(ap[2]  )  /*dummy*/;
+                            cp[3] =  fcomplex.Sin(ap[3]  )  /*dummy*/;
+                            cp[4] =  fcomplex.Sin(ap[4]  )  /*dummy*/;
+                            cp[5] =  fcomplex.Sin(ap[5]  )  /*dummy*/;
+                            cp[6] =  fcomplex.Sin(ap[6]  )  /*dummy*/;
+                            cp[7] =  fcomplex.Sin(ap[7]  )  /*dummy*/;
+                            cp[8] =  fcomplex.Sin(ap[8]  )  /*dummy*/;
+                            cp[9] =  fcomplex.Sin(ap[9]  )  /*dummy*/;
+                            cp[10] =  fcomplex.Sin(ap[10]  )  /*dummy*/;
+                            cp[11] =  fcomplex.Sin(ap[11]  )  /*dummy*/;
+                            cp[12] =  fcomplex.Sin(ap[12]  )  /*dummy*/;
+                            cp[13] =  fcomplex.Sin(ap[13]  )  /*dummy*/;
+                            cp[14] =  fcomplex.Sin(ap[14]  )  /*dummy*/;
+                            cp[15] =  fcomplex.Sin(ap[15]  )  /*dummy*/;
+                            cp[16] =  fcomplex.Sin(ap[16]  )  /*dummy*/;
+                            cp[17] =  fcomplex.Sin(ap[17]  )  /*dummy*/;
+                            cp[18] =  fcomplex.Sin(ap[18]  )  /*dummy*/;
+                            cp[19] =  fcomplex.Sin(ap[19]  )  /*dummy*/;
+                            cp[20] =  fcomplex.Sin(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.Sin(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( fcomplex* arrAP = arrA)
+                fixed ( fcomplex* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<fcomplex>(retStorage);
+            }
+        }
+        /// <summary>Sinus of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Sinus of elements from input array</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<float>  sin (ILInArray< float > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<float>(A.Size); 
+                ILSize inDim = A.Size;
+                float[] arrA = A.GetArrayForRead(); 
+                float [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<float>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<float> retStorage = new ILDenseStorage<float>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    float* cp = ((float*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  (float)Math.Sin(cp[0]  )  /*dummy*/;
+                            cp[1] =  (float)Math.Sin(cp[1]  )  /*dummy*/;
+                            cp[2] =  (float)Math.Sin(cp[2]  )  /*dummy*/;
+                            cp[3] =  (float)Math.Sin(cp[3]  )  /*dummy*/;
+                            cp[4] =  (float)Math.Sin(cp[4]  )  /*dummy*/;
+                            cp[5] =  (float)Math.Sin(cp[5]  )  /*dummy*/;
+                            cp[6] =  (float)Math.Sin(cp[6]  )  /*dummy*/;
+                            cp[7] =  (float)Math.Sin(cp[7]  )  /*dummy*/;
+                            cp[8] =  (float)Math.Sin(cp[8]  )  /*dummy*/;
+                            cp[9] =  (float)Math.Sin(cp[9]  )  /*dummy*/;
+                            cp[10] =  (float)Math.Sin(cp[10]  )  /*dummy*/;
+                            cp[11] =  (float)Math.Sin(cp[11]  )  /*dummy*/;
+                            cp[12] =  (float)Math.Sin(cp[12]  )  /*dummy*/;
+                            cp[13] =  (float)Math.Sin(cp[13]  )  /*dummy*/;
+                            cp[14] =  (float)Math.Sin(cp[14]  )  /*dummy*/;
+                            cp[15] =  (float)Math.Sin(cp[15]  )  /*dummy*/;
+                            cp[16] =  (float)Math.Sin(cp[16]  )  /*dummy*/;
+                            cp[17] =  (float)Math.Sin(cp[17]  )  /*dummy*/;
+                            cp[18] =  (float)Math.Sin(cp[18]  )  /*dummy*/;
+                            cp[19] =  (float)Math.Sin(cp[19]  )  /*dummy*/;
+                            cp[20] =  (float)Math.Sin(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  (float)Math.Sin(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        float* ap = ((float*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  (float)Math.Sin(ap[0]  )  /*dummy*/;
+                            cp[1] =  (float)Math.Sin(ap[1]  )  /*dummy*/;
+                            cp[2] =  (float)Math.Sin(ap[2]  )  /*dummy*/;
+                            cp[3] =  (float)Math.Sin(ap[3]  )  /*dummy*/;
+                            cp[4] =  (float)Math.Sin(ap[4]  )  /*dummy*/;
+                            cp[5] =  (float)Math.Sin(ap[5]  )  /*dummy*/;
+                            cp[6] =  (float)Math.Sin(ap[6]  )  /*dummy*/;
+                            cp[7] =  (float)Math.Sin(ap[7]  )  /*dummy*/;
+                            cp[8] =  (float)Math.Sin(ap[8]  )  /*dummy*/;
+                            cp[9] =  (float)Math.Sin(ap[9]  )  /*dummy*/;
+                            cp[10] =  (float)Math.Sin(ap[10]  )  /*dummy*/;
+                            cp[11] =  (float)Math.Sin(ap[11]  )  /*dummy*/;
+                            cp[12] =  (float)Math.Sin(ap[12]  )  /*dummy*/;
+                            cp[13] =  (float)Math.Sin(ap[13]  )  /*dummy*/;
+                            cp[14] =  (float)Math.Sin(ap[14]  )  /*dummy*/;
+                            cp[15] =  (float)Math.Sin(ap[15]  )  /*dummy*/;
+                            cp[16] =  (float)Math.Sin(ap[16]  )  /*dummy*/;
+                            cp[17] =  (float)Math.Sin(ap[17]  )  /*dummy*/;
+                            cp[18] =  (float)Math.Sin(ap[18]  )  /*dummy*/;
+                            cp[19] =  (float)Math.Sin(ap[19]  )  /*dummy*/;
+                            cp[20] =  (float)Math.Sin(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  (float)Math.Sin(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( float* arrAP = arrA)
+                fixed ( float* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<float>(retStorage);
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+   }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/sinh.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/sinh.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/sinh.cs	(revision 9102)
@@ -0,0 +1,559 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics;
+using ILNumerics.Exceptions; 
+using ILNumerics.Storage; 
+using ILNumerics.Misc; 
+
+
+
+namespace ILNumerics {
+
+    public partial class ILMath {
+
+
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>Hyperbolic sine of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Hyperbolic sine of array elements</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<complex>  sinh (ILInArray< complex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<complex>(A.Size); 
+                ILSize inDim = A.Size;
+                complex[] arrA = A.GetArrayForRead(); 
+                complex [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<complex>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<complex> retStorage = new ILDenseStorage<complex>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    complex* cp = ((complex*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  complex.Sinh(cp[0]  )  /*dummy*/;
+                            cp[1] =  complex.Sinh(cp[1]  )  /*dummy*/;
+                            cp[2] =  complex.Sinh(cp[2]  )  /*dummy*/;
+                            cp[3] =  complex.Sinh(cp[3]  )  /*dummy*/;
+                            cp[4] =  complex.Sinh(cp[4]  )  /*dummy*/;
+                            cp[5] =  complex.Sinh(cp[5]  )  /*dummy*/;
+                            cp[6] =  complex.Sinh(cp[6]  )  /*dummy*/;
+                            cp[7] =  complex.Sinh(cp[7]  )  /*dummy*/;
+                            cp[8] =  complex.Sinh(cp[8]  )  /*dummy*/;
+                            cp[9] =  complex.Sinh(cp[9]  )  /*dummy*/;
+                            cp[10] =  complex.Sinh(cp[10]  )  /*dummy*/;
+                            cp[11] =  complex.Sinh(cp[11]  )  /*dummy*/;
+                            cp[12] =  complex.Sinh(cp[12]  )  /*dummy*/;
+                            cp[13] =  complex.Sinh(cp[13]  )  /*dummy*/;
+                            cp[14] =  complex.Sinh(cp[14]  )  /*dummy*/;
+                            cp[15] =  complex.Sinh(cp[15]  )  /*dummy*/;
+                            cp[16] =  complex.Sinh(cp[16]  )  /*dummy*/;
+                            cp[17] =  complex.Sinh(cp[17]  )  /*dummy*/;
+                            cp[18] =  complex.Sinh(cp[18]  )  /*dummy*/;
+                            cp[19] =  complex.Sinh(cp[19]  )  /*dummy*/;
+                            cp[20] =  complex.Sinh(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.Sinh(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        complex* ap = ((complex*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  complex.Sinh(ap[0]  )  /*dummy*/;
+                            cp[1] =  complex.Sinh(ap[1]  )  /*dummy*/;
+                            cp[2] =  complex.Sinh(ap[2]  )  /*dummy*/;
+                            cp[3] =  complex.Sinh(ap[3]  )  /*dummy*/;
+                            cp[4] =  complex.Sinh(ap[4]  )  /*dummy*/;
+                            cp[5] =  complex.Sinh(ap[5]  )  /*dummy*/;
+                            cp[6] =  complex.Sinh(ap[6]  )  /*dummy*/;
+                            cp[7] =  complex.Sinh(ap[7]  )  /*dummy*/;
+                            cp[8] =  complex.Sinh(ap[8]  )  /*dummy*/;
+                            cp[9] =  complex.Sinh(ap[9]  )  /*dummy*/;
+                            cp[10] =  complex.Sinh(ap[10]  )  /*dummy*/;
+                            cp[11] =  complex.Sinh(ap[11]  )  /*dummy*/;
+                            cp[12] =  complex.Sinh(ap[12]  )  /*dummy*/;
+                            cp[13] =  complex.Sinh(ap[13]  )  /*dummy*/;
+                            cp[14] =  complex.Sinh(ap[14]  )  /*dummy*/;
+                            cp[15] =  complex.Sinh(ap[15]  )  /*dummy*/;
+                            cp[16] =  complex.Sinh(ap[16]  )  /*dummy*/;
+                            cp[17] =  complex.Sinh(ap[17]  )  /*dummy*/;
+                            cp[18] =  complex.Sinh(ap[18]  )  /*dummy*/;
+                            cp[19] =  complex.Sinh(ap[19]  )  /*dummy*/;
+                            cp[20] =  complex.Sinh(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.Sinh(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( complex* arrAP = arrA)
+                fixed ( complex* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<complex>(retStorage);
+            }
+        }
+        /// <summary>Hyperbolic sine of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Hyperbolic sine of array elements</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<fcomplex>  sinh (ILInArray< fcomplex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<fcomplex>(A.Size); 
+                ILSize inDim = A.Size;
+                fcomplex[] arrA = A.GetArrayForRead(); 
+                fcomplex [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<fcomplex>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<fcomplex> retStorage = new ILDenseStorage<fcomplex>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    fcomplex* cp = ((fcomplex*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  fcomplex.Sinh(cp[0]  )  /*dummy*/;
+                            cp[1] =  fcomplex.Sinh(cp[1]  )  /*dummy*/;
+                            cp[2] =  fcomplex.Sinh(cp[2]  )  /*dummy*/;
+                            cp[3] =  fcomplex.Sinh(cp[3]  )  /*dummy*/;
+                            cp[4] =  fcomplex.Sinh(cp[4]  )  /*dummy*/;
+                            cp[5] =  fcomplex.Sinh(cp[5]  )  /*dummy*/;
+                            cp[6] =  fcomplex.Sinh(cp[6]  )  /*dummy*/;
+                            cp[7] =  fcomplex.Sinh(cp[7]  )  /*dummy*/;
+                            cp[8] =  fcomplex.Sinh(cp[8]  )  /*dummy*/;
+                            cp[9] =  fcomplex.Sinh(cp[9]  )  /*dummy*/;
+                            cp[10] =  fcomplex.Sinh(cp[10]  )  /*dummy*/;
+                            cp[11] =  fcomplex.Sinh(cp[11]  )  /*dummy*/;
+                            cp[12] =  fcomplex.Sinh(cp[12]  )  /*dummy*/;
+                            cp[13] =  fcomplex.Sinh(cp[13]  )  /*dummy*/;
+                            cp[14] =  fcomplex.Sinh(cp[14]  )  /*dummy*/;
+                            cp[15] =  fcomplex.Sinh(cp[15]  )  /*dummy*/;
+                            cp[16] =  fcomplex.Sinh(cp[16]  )  /*dummy*/;
+                            cp[17] =  fcomplex.Sinh(cp[17]  )  /*dummy*/;
+                            cp[18] =  fcomplex.Sinh(cp[18]  )  /*dummy*/;
+                            cp[19] =  fcomplex.Sinh(cp[19]  )  /*dummy*/;
+                            cp[20] =  fcomplex.Sinh(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.Sinh(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        fcomplex* ap = ((fcomplex*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  fcomplex.Sinh(ap[0]  )  /*dummy*/;
+                            cp[1] =  fcomplex.Sinh(ap[1]  )  /*dummy*/;
+                            cp[2] =  fcomplex.Sinh(ap[2]  )  /*dummy*/;
+                            cp[3] =  fcomplex.Sinh(ap[3]  )  /*dummy*/;
+                            cp[4] =  fcomplex.Sinh(ap[4]  )  /*dummy*/;
+                            cp[5] =  fcomplex.Sinh(ap[5]  )  /*dummy*/;
+                            cp[6] =  fcomplex.Sinh(ap[6]  )  /*dummy*/;
+                            cp[7] =  fcomplex.Sinh(ap[7]  )  /*dummy*/;
+                            cp[8] =  fcomplex.Sinh(ap[8]  )  /*dummy*/;
+                            cp[9] =  fcomplex.Sinh(ap[9]  )  /*dummy*/;
+                            cp[10] =  fcomplex.Sinh(ap[10]  )  /*dummy*/;
+                            cp[11] =  fcomplex.Sinh(ap[11]  )  /*dummy*/;
+                            cp[12] =  fcomplex.Sinh(ap[12]  )  /*dummy*/;
+                            cp[13] =  fcomplex.Sinh(ap[13]  )  /*dummy*/;
+                            cp[14] =  fcomplex.Sinh(ap[14]  )  /*dummy*/;
+                            cp[15] =  fcomplex.Sinh(ap[15]  )  /*dummy*/;
+                            cp[16] =  fcomplex.Sinh(ap[16]  )  /*dummy*/;
+                            cp[17] =  fcomplex.Sinh(ap[17]  )  /*dummy*/;
+                            cp[18] =  fcomplex.Sinh(ap[18]  )  /*dummy*/;
+                            cp[19] =  fcomplex.Sinh(ap[19]  )  /*dummy*/;
+                            cp[20] =  fcomplex.Sinh(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.Sinh(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( fcomplex* arrAP = arrA)
+                fixed ( fcomplex* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<fcomplex>(retStorage);
+            }
+        }
+        /// <summary>Hyperbolic sine of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Hyperbolic sine of array elements</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<float>  sinh (ILInArray< float > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<float>(A.Size); 
+                ILSize inDim = A.Size;
+                float[] arrA = A.GetArrayForRead(); 
+                float [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<float>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<float> retStorage = new ILDenseStorage<float>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    float* cp = ((float*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  (float)Math.Sinh(cp[0]  )  /*dummy*/;
+                            cp[1] =  (float)Math.Sinh(cp[1]  )  /*dummy*/;
+                            cp[2] =  (float)Math.Sinh(cp[2]  )  /*dummy*/;
+                            cp[3] =  (float)Math.Sinh(cp[3]  )  /*dummy*/;
+                            cp[4] =  (float)Math.Sinh(cp[4]  )  /*dummy*/;
+                            cp[5] =  (float)Math.Sinh(cp[5]  )  /*dummy*/;
+                            cp[6] =  (float)Math.Sinh(cp[6]  )  /*dummy*/;
+                            cp[7] =  (float)Math.Sinh(cp[7]  )  /*dummy*/;
+                            cp[8] =  (float)Math.Sinh(cp[8]  )  /*dummy*/;
+                            cp[9] =  (float)Math.Sinh(cp[9]  )  /*dummy*/;
+                            cp[10] =  (float)Math.Sinh(cp[10]  )  /*dummy*/;
+                            cp[11] =  (float)Math.Sinh(cp[11]  )  /*dummy*/;
+                            cp[12] =  (float)Math.Sinh(cp[12]  )  /*dummy*/;
+                            cp[13] =  (float)Math.Sinh(cp[13]  )  /*dummy*/;
+                            cp[14] =  (float)Math.Sinh(cp[14]  )  /*dummy*/;
+                            cp[15] =  (float)Math.Sinh(cp[15]  )  /*dummy*/;
+                            cp[16] =  (float)Math.Sinh(cp[16]  )  /*dummy*/;
+                            cp[17] =  (float)Math.Sinh(cp[17]  )  /*dummy*/;
+                            cp[18] =  (float)Math.Sinh(cp[18]  )  /*dummy*/;
+                            cp[19] =  (float)Math.Sinh(cp[19]  )  /*dummy*/;
+                            cp[20] =  (float)Math.Sinh(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  (float)Math.Sinh(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        float* ap = ((float*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  (float)Math.Sinh(ap[0]  )  /*dummy*/;
+                            cp[1] =  (float)Math.Sinh(ap[1]  )  /*dummy*/;
+                            cp[2] =  (float)Math.Sinh(ap[2]  )  /*dummy*/;
+                            cp[3] =  (float)Math.Sinh(ap[3]  )  /*dummy*/;
+                            cp[4] =  (float)Math.Sinh(ap[4]  )  /*dummy*/;
+                            cp[5] =  (float)Math.Sinh(ap[5]  )  /*dummy*/;
+                            cp[6] =  (float)Math.Sinh(ap[6]  )  /*dummy*/;
+                            cp[7] =  (float)Math.Sinh(ap[7]  )  /*dummy*/;
+                            cp[8] =  (float)Math.Sinh(ap[8]  )  /*dummy*/;
+                            cp[9] =  (float)Math.Sinh(ap[9]  )  /*dummy*/;
+                            cp[10] =  (float)Math.Sinh(ap[10]  )  /*dummy*/;
+                            cp[11] =  (float)Math.Sinh(ap[11]  )  /*dummy*/;
+                            cp[12] =  (float)Math.Sinh(ap[12]  )  /*dummy*/;
+                            cp[13] =  (float)Math.Sinh(ap[13]  )  /*dummy*/;
+                            cp[14] =  (float)Math.Sinh(ap[14]  )  /*dummy*/;
+                            cp[15] =  (float)Math.Sinh(ap[15]  )  /*dummy*/;
+                            cp[16] =  (float)Math.Sinh(ap[16]  )  /*dummy*/;
+                            cp[17] =  (float)Math.Sinh(ap[17]  )  /*dummy*/;
+                            cp[18] =  (float)Math.Sinh(ap[18]  )  /*dummy*/;
+                            cp[19] =  (float)Math.Sinh(ap[19]  )  /*dummy*/;
+                            cp[20] =  (float)Math.Sinh(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  (float)Math.Sinh(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( float* arrAP = arrA)
+                fixed ( float* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<float>(retStorage);
+            }
+        }
+        /// <summary>Hyperbolic sine of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Hyperbolic sine of array elements</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<double>  sinh (ILInArray< double > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<double>(A.Size); 
+                ILSize inDim = A.Size;
+                double[] arrA = A.GetArrayForRead(); 
+                double [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<double>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<double> retStorage = new ILDenseStorage<double>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    double* cp = ((double*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  Math.Sinh(cp[0]  )  /*dummy*/;
+                            cp[1] =  Math.Sinh(cp[1]  )  /*dummy*/;
+                            cp[2] =  Math.Sinh(cp[2]  )  /*dummy*/;
+                            cp[3] =  Math.Sinh(cp[3]  )  /*dummy*/;
+                            cp[4] =  Math.Sinh(cp[4]  )  /*dummy*/;
+                            cp[5] =  Math.Sinh(cp[5]  )  /*dummy*/;
+                            cp[6] =  Math.Sinh(cp[6]  )  /*dummy*/;
+                            cp[7] =  Math.Sinh(cp[7]  )  /*dummy*/;
+                            cp[8] =  Math.Sinh(cp[8]  )  /*dummy*/;
+                            cp[9] =  Math.Sinh(cp[9]  )  /*dummy*/;
+                            cp[10] =  Math.Sinh(cp[10]  )  /*dummy*/;
+                            cp[11] =  Math.Sinh(cp[11]  )  /*dummy*/;
+                            cp[12] =  Math.Sinh(cp[12]  )  /*dummy*/;
+                            cp[13] =  Math.Sinh(cp[13]  )  /*dummy*/;
+                            cp[14] =  Math.Sinh(cp[14]  )  /*dummy*/;
+                            cp[15] =  Math.Sinh(cp[15]  )  /*dummy*/;
+                            cp[16] =  Math.Sinh(cp[16]  )  /*dummy*/;
+                            cp[17] =  Math.Sinh(cp[17]  )  /*dummy*/;
+                            cp[18] =  Math.Sinh(cp[18]  )  /*dummy*/;
+                            cp[19] =  Math.Sinh(cp[19]  )  /*dummy*/;
+                            cp[20] =  Math.Sinh(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Math.Sinh(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        double* ap = ((double*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  Math.Sinh(ap[0]  )  /*dummy*/;
+                            cp[1] =  Math.Sinh(ap[1]  )  /*dummy*/;
+                            cp[2] =  Math.Sinh(ap[2]  )  /*dummy*/;
+                            cp[3] =  Math.Sinh(ap[3]  )  /*dummy*/;
+                            cp[4] =  Math.Sinh(ap[4]  )  /*dummy*/;
+                            cp[5] =  Math.Sinh(ap[5]  )  /*dummy*/;
+                            cp[6] =  Math.Sinh(ap[6]  )  /*dummy*/;
+                            cp[7] =  Math.Sinh(ap[7]  )  /*dummy*/;
+                            cp[8] =  Math.Sinh(ap[8]  )  /*dummy*/;
+                            cp[9] =  Math.Sinh(ap[9]  )  /*dummy*/;
+                            cp[10] =  Math.Sinh(ap[10]  )  /*dummy*/;
+                            cp[11] =  Math.Sinh(ap[11]  )  /*dummy*/;
+                            cp[12] =  Math.Sinh(ap[12]  )  /*dummy*/;
+                            cp[13] =  Math.Sinh(ap[13]  )  /*dummy*/;
+                            cp[14] =  Math.Sinh(ap[14]  )  /*dummy*/;
+                            cp[15] =  Math.Sinh(ap[15]  )  /*dummy*/;
+                            cp[16] =  Math.Sinh(ap[16]  )  /*dummy*/;
+                            cp[17] =  Math.Sinh(ap[17]  )  /*dummy*/;
+                            cp[18] =  Math.Sinh(ap[18]  )  /*dummy*/;
+                            cp[19] =  Math.Sinh(ap[19]  )  /*dummy*/;
+                            cp[20] =  Math.Sinh(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Math.Sinh(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( double* arrAP = arrA)
+                fixed ( double* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<double>(retStorage);
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/slash.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/slash.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/slash.cs	(revision 9102)
@@ -0,0 +1,1152 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions; 
+
+
+
+namespace ILNumerics {
+    public partial class ILMath {
+
+
+        
+        /// <summary>
+        /// Solve linear equation system
+        /// </summary>
+        /// <param name="A">Matrix A. Size [n x q]</param>
+        /// <param name="B">Right hand side B. Size [n x m]</param>
+        /// <returns>Solution x solving the equation system: multiply(A, x) = B. Size [n x m]</returns>
+        /// <remarks><para>Depending on the structure and properties of A, the equation system will be solved in different ways:
+        /// <list type="bullet">
+        /// <item>If A is square (q == n) and an <b>upper or lower triangular</b> matrix, the system will directly be solved via backward- or forward substitution. Therefore the Lapack function ?trtrs will be used, whenever the memory layout of A is suitable. This may be the case even for reference ILArray's! 
+        /// <example><code><![CDATA[ILArray<double> A = ILMath.randn(4); // construct 4 x 4 matrix 
+        /// A = A.T; // A is a reference array now! The transpose is fast and does not consume much memory
+        /// // now construct a right side and solve the equations: 
+        /// ILArray<double> B = new ILArray<double> (1.0,2.0,3.0).T; 
+        /// ILMath.linsolve(A,B); // ... will be carried out via Lapack, even for all arrays involved being reference arrays! ]]></code></example></item>
+        /// <item><para>if A is square and symmetric or hermitian, A will be decomposed into a triangular equation system using cholesky factorization and Lapack. The system is than solved using performant Lapack routines.</para>
+        /// <para>If during the cholesky factorization A was found to be <b>not positive definite</b> - the cholesky factorization is canceled. </para></item>
+        /// <item>otherwise, if A is square only, it will be decomposed into upper and lower triangular martices using LU decomposition and Lapack. The triangular system is than solved using performant Lapack routines.</item>
+        /// <item>otherwise, if A is of size [q x n] and q != n, the system is solved using QR decomposition. A may be rank deficient. The solution is computed by use of the Lapack routine '?gelsy' and may be a reference array.</item>
+        /// </list></para>
+        /// <para>Compatibility with Matlab<sup>(R)</sup>: If A is square, the algorithm used follows the same logic as Matlab up to Rel 14, with the exception of Hessenberg matrices wich are solved via LU factorization here. The un-squared case is handled differently. A direct Lapack driver function (?gelsy) is used here. Therefore the solutions might differ! However, the solution will of course fullfill the equation A * x = B without round off errrors. </para>
+        /// <para>For specifiying the rank of A in the unsquare case (q != n), <see cref="ILNumerics.ILMath.eps"/> is used.</para></remarks>
+        public static ILRetArray< double > linsolve(ILInArray< double > A, ILInArray< double > B) {
+            if (object.Equals(A,null) || object.Equals(B,null))
+                throw new ILArgumentException("parameter must not be null!");
+            using (ILScope.Enter(A, B)) {
+                MatrixProperties props = MatrixProperties.None;
+                if (A.Size[0] == A.Size[1]) {
+                    props |= MatrixProperties.Square;
+                    if (ILMath.istriup(A)) {
+                        props |= MatrixProperties.UpperTriangular;
+                        return linsolve(A, B, ref props);
+                    }
+                    if (ILMath.istrilow(A)) {
+                        props |= MatrixProperties.LowerTriangular;
+                        return linsolve(A, B, ref props);
+                    }
+                    if (ILMath.ishermitian(A)) {
+                        // give cholesky a try
+                        props |= MatrixProperties.Hermitian;
+                        props |= MatrixProperties.PositivDefinite;
+                        ILArray< double> ret = linsolve(A, B, ref props);
+                        if (!object.Equals(ret, null)) {
+                            return ret;
+                        } else {
+                            props ^= MatrixProperties.PositivDefinite;
+                        }
+                    }
+                }
+                return linsolve(A, B, ref props);
+            }
+        }
+
+        /// <summary>
+        /// Solve linear equation system
+        /// </summary>
+        /// <param name="A">Matrix A. Size [n x q]</param>
+        /// <param name="B">Right hand side B. Size [n x m]</param>
+        /// <param name="props">Matrix properties. If defined, no checks are made for the structure of A. If the 
+        /// matrix A was found to be (close to or) singular, the 'MatrixProperties.Singular' flag in props will be set. 
+        /// This flag should be tested on return, in order to verify the reliability of the solution.</param>
+        /// <returns>The solution x solving multiply(A,x) = B. Size [n x m]</returns>
+        /// <remarks><para>Depending on the <paramref name="props"/> parameter the equation system will be solved 
+        /// differently for special structures of A:
+        /// <list type="bullet">
+        /// <item>If A is square (q == n) and an <b>upper or lower triangular</b> matrix, the system will directly 
+        /// be solved via backward- or forward substitution. Therefore the Lapack function ?trtrs will be used, 
+        /// whenever the memory layout of A is suitable. This may be the case even for reference ILArray's! 
+        /// <example><code><![CDATA[ILArray<double> A = ILMath.randn(4); // construct 4 x 4 matrix 
+        /// A = A.T; // A is a reference array now! The transpose is fast and does not consume much memory
+        /// // now construct a right side and solve the equations: 
+        /// ILArray<double> B = new ILArray<double> (1.0,2.0,3.0).T; 
+        /// ILMath.linsolve(A,B); // ... will be carried out via Lapack, even for all arrays involved being reference arrays! ]]></code></example></item>
+        /// <item><para>If A is square and symmetric or hermitian, A will be decomposed into a triangular equation 
+        /// system using cholesky factorization and Lapack. The system is than solved using performant Lapack routines.</para>
+        /// <para>If during the cholesky factorization A was found to be <b>not positive definite</b> - the 
+        /// corresponding flag in props will be cleaned and <c>null</c> will be returned.</para></item>
+        /// <item>Otherwise if A is square only, it will be decomposed into upper and lower triangular matrices 
+        /// using LU decomposition and Lapack. The triangular system is than solved using performant Lapack routines.</item>
+        /// <item>Otherwise, if A is of size [q x n] and q != n, the system is solved using QR decomposition. 
+        /// A may be rank deficient. The solution is computed by use of the Lapack routine '?gelsy' and may be a 
+        /// reference array.</item>
+        /// </list></para>
+        /// <para>Compatibility with Matlab<sup>(R)</sup>: If A is square, the algorithm used follows the same 
+        /// logic as Matlab up to Rel 14, with the exception of Hessenberg matrices wich are solved via LU 
+        /// factorization here. The un-squared case is handled differently. A direct Lapack driver function 
+        /// (?gelsy) is used here. Therefore the solutions might differ! However, the solution will of course 
+        /// fullfill the equation A * x = B without round off errrors. </para>
+        /// <para>For specifiying the rank of A in the unsquare case (q != n), 
+        /// <see cref="ILNumerics.ILMath.eps"/> is used.</para></remarks>
+        public static ILRetArray< double > linsolve(ILInArray< double > A, ILInArray< double > B, ref MatrixProperties props) {
+            if (object.Equals(A,null)) 
+                throw new ILArgumentException("input argument A must not be null!"); 
+            if (object.Equals(B,null))
+                throw new ILArgumentException("input argument B must not be null!");
+            using (ILScope.Enter(A, B)) {
+                if (A.IsEmpty || B.IsEmpty)
+                    return empty< double>(A.Size);
+                if (A.Size[0] != B.Size[0])
+                    throw new ILArgumentException("number of rows for matrix A must match number of rows for RHS!");
+                int info = 0, m = A.Size[0];
+                ILArray< double> ret = empty<double>(ILSize.Empty00);
+                if (m == A.Size[1]) {
+                    props |= MatrixProperties.Square;
+                    if ((props & MatrixProperties.LowerTriangular) != 0) {
+                        ret.a = solveLowerTriangularSystem(A, B, ref info);
+                        if (info > 0)
+                            props |= MatrixProperties.Singular;
+                        return ret;
+                    }
+                    if ((props & MatrixProperties.UpperTriangular) != 0) {
+                        ret.a = solveUpperTriangularSystem(A, B, ref info);
+                        if (info > 0)
+                            props |= MatrixProperties.Singular;
+                        return ret;
+                    }
+                    if ((props & MatrixProperties.Hermitian) != 0) {
+                        ILDenseStorage< double> cholFact = A.Storage.copyUpperTriangle(m);
+                        /*!HC:lapack_*potrf*/
+                        Lapack.dpotrf('U', m, cholFact.GetArrayForWrite(), m, ref info);
+                        if (info > 0) {
+                            props ^= MatrixProperties.Hermitian;
+                            cholFact.Dispose(); 
+                            return null;
+                        } else {
+                            // solve 
+                            ret.a = B.C;
+                            /*!HC:lapack_*potrs*/
+                            Lapack.dpotrs('U', m, B.Size[1], cholFact.GetArrayForWrite(), m, ret.GetArrayForWrite(), m, ref info);
+                            cholFact.Dispose(); 
+                            return ret;
+                        }
+                    } else {
+                        // attempt complete (expensive) LU factorization 
+                        ILArray< double> L = A.C;
+                        int[] pivInd = ILMemoryPool.Pool.New<int>(m);
+                        /*!HC:lapack_*getrf*/
+                        Lapack.dgetrf(m, m, L.GetArrayForWrite(), m, pivInd, ref info);
+                        if (info > 0)
+                            props |= MatrixProperties.Singular;
+                        ret.a = B.C;
+                        /*!HC:lapack_*getrs*/
+                        Lapack.dgetrs('N', m, B.Size[1], L.GetArrayForWrite(), m, pivInd, ret.GetArrayForWrite(), m, ref info);
+                        if (info < 0)
+                            throw new ILArgumentException("failed to solve via lapack dgetrs");
+                        return ret;
+                    }
+                } else {
+                    // under- / overdetermined system
+                    int n = A.Size[1], rank = 0, minMN = (m < n) ? m : n, maxMN = (m > n) ? m : n;
+                    int nrhs = B.Size[1];
+                    if (B.Size[0] != m)
+                        throw new ILArgumentException("right hand side matrix B must match input A!");
+                    ILArray</*!HCinArr1*/ double> tmpA = A.C;
+                    if (m < n) {
+                        ret.a = zeros< double>(n, nrhs);
+                        ret[r(0, m - 1), full] = B.C;
+                    } else {
+                        ret.a = B.C;
+                    }
+                    int[] JPVT = new int[n];
+                    /*!HC:Lapack.?gelsy*/
+                    Lapack.dgelsy(m, n, B.Size[1], tmpA.GetArrayForWrite(), m, ret.GetArrayForWrite(),
+                        maxMN, JPVT,  ILMath.MachineParameterDouble.eps,
+                        ref rank, ref info);
+                    if (n < m) {
+                        ret.a = ret[r(0, n - 1), full];
+                    }
+                    if (rank < minMN)
+                        props |= MatrixProperties.RankDeficient;
+                    return ret;
+                }
+            }
+        }
+        
+        /// <summary>
+        /// Solve system of linear equations A*x = b, with A being a upper triangular matrix
+        /// </summary>
+        /// <param name="A">Input matrix of size [n x n], must be upper triangular. No check is made for that!</param>
+        /// <param name="B">Solution vector or matrix. Size [n x m]</param>
+        /// <param name="singularityDetect">[Output] This value gives the row of A, where a singularity has been detected (if any). If A is not singular, this will be a negative value.</param>
+        /// <returns>Solution x solving A * x = b.</returns>
+        /// <remarks><para>The solution will be determined via backward substitution</para>
+        /// <para>Make sure, A and b are of correct size, since no checks are made for that!</para>
+        /// <para>This function is used by ILMath.linsolve. There should be rare need for you to call this function directly.</para>
+        /// <para>Elements of A below the main diagonal will not be accessed.</para>
+        /// <para>If A has been found to be singular, the array returned will contain NaN values for corresponding elements!</para></remarks>
+        internal static ILRetArray< double > solveUpperTriangularSystem (ILInArray< double > A, ILInArray< double > B, ref int singularityDetect) {
+            System.Diagnostics.Debug.Assert(B.Size[1] >= 0); 
+            System.Diagnostics.Debug.Assert(B.Size[0] == A.Size[1]); 
+            System.Diagnostics.Debug.Assert(A.Size[0] == A.Size[1]);
+            using (ILScope.Enter(A, B)) {
+                singularityDetect = -1;
+                int n = A.Size[0];
+                int m = B.Size[1];
+                int info = 0;
+                ILArray< double> ret = B.C;
+                
+                double[] retArr = ret.GetArrayForWrite();
+                // solve using Lapack
+                unsafe {
+                    fixed ( double* ptrA = A.GetArrayForRead())
+                    fixed ( double* ptrB = ret.GetArrayForWrite()) {
+                        /*!HC:lapack.?trtrs*/
+                        Lapack.dtrtrs('U', 'N', 'N', A.Size[0], B.Size[1], (IntPtr)ptrA, A.Size[0], (IntPtr)ptrB, B.Size[0], ref info);
+                    }
+                }
+                if (info < 0)
+                    throw new ILArgumentException("error inside Lapack function ?trtrs for argument: " + (-info));
+                if (info > 0) {
+                    singularityDetect = info - 1;
+                    for (m = 0; m < ret.Size[1]; m++) {
+                        info = m * n + singularityDetect;
+                        for (int i = singularityDetect; i < n; i++) {
+                            retArr[info++] =  double.NaN;
+                        }
+                    }
+                } else {
+                    singularityDetect = -1;
+                }
+                return ret;
+            }
+        }
+
+        /// <summary>
+        /// Solve system of linear equations A*x = b, with A being a lower triangular matrix
+        /// </summary>
+        /// <param name="A">Input matrix of size [n x n], must be lower triangular. No check is made for that!</param>
+        /// <param name="B">Solution vector. Size [n x 1]</param>
+        /// <param name="singularityDetect">[Output] This value gives the row of A, where a singularity has been detected (if any). If A is not singular, this will be a negative value.</param>
+        /// <returns>Solution x solving A * x = b.</returns>
+        /// <remarks><para>The solution will be determined via forward substitution</para>
+        /// <para>Make sure, A and b are of correct size, since no checks are made for that!</para>
+        /// <para>This function is used by ILMath.linsolve. There should be rare need for you to call this function directly.</para>
+        /// <para>Elements of A above the main diagonal will not be accessed.</para>
+        /// <para>If A has been found to be singular, the array returned will contain NaN values for corresponding elements!</para></remarks>
+        internal static ILRetArray< double> solveLowerTriangularSystem( ILInArray< double> A, ILInArray< double> B, ref int singularityDetect ) {
+            System.Diagnostics.Debug.Assert(B.Size[1] >= 0);
+            System.Diagnostics.Debug.Assert(B.Size[0] == A.Size[1]);
+            System.Diagnostics.Debug.Assert(A.Size[0] == A.Size[1]);
+            using (ILScope.Enter(A, B)) {
+                singularityDetect = -1;
+                int n = A.Size[0];
+                int m = B.Size[1];
+                int info = 0;
+                ILArray< double> ret = B.C;
+                
+                double[] retArr = ret.GetArrayForWrite();
+                // solve using Lapack
+                unsafe {
+                    fixed ( double* ptrA = A.GetArrayForRead())
+                    fixed ( double* ptrB = ret.GetArrayForWrite()) {
+                        /*!HC:lapack.?trtrs*/
+                        Lapack.dtrtrs('L', 'N', 'N', A.Size[0], B.Size[1], (IntPtr)ptrA, A.Size[0], (IntPtr)ptrB, B.Size[0], ref info);
+                    }
+                }
+                if (info < 0)
+                    throw new ILArgumentException("error inside Lapack function ?trtrs for argument: " + (-info));
+                if (info > 0) {
+                    singularityDetect = info - 1;
+                    for (m = 0; m < ret.Size[1]; m++) {
+                        info = m * n + singularityDetect;
+                        for (int i = singularityDetect; i < n; i++) {
+                            retArr[info++] =  double.NaN;
+                        }
+                    }
+                } else {
+                    singularityDetect = -1;
+                }
+                return ret;
+            }
+        }
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+        
+        /// <summary>
+        /// Solve linear equation system
+        /// </summary>
+        /// <param name="A">Matrix A. Size [n x q]</param>
+        /// <param name="B">Right hand side B. Size [n x m]</param>
+        /// <returns>Solution x solving the equation system: multiply(A, x) = B. Size [n x m]</returns>
+        /// <remarks><para>Depending on the structure and properties of A, the equation system will be solved in different ways:
+        /// <list type="bullet">
+        /// <item>If A is square (q == n) and an <b>upper or lower triangular</b> matrix, the system will directly be solved via backward- or forward substitution. Therefore the Lapack function ?trtrs will be used, whenever the memory layout of A is suitable. This may be the case even for reference ILArray's! 
+        /// <example><code><![CDATA[ILArray<double> A = ILMath.randn(4); // construct 4 x 4 matrix 
+        /// A = A.T; // A is a reference array now! The transpose is fast and does not consume much memory
+        /// // now construct a right side and solve the equations: 
+        /// ILArray<double> B = new ILArray<double> (1.0,2.0,3.0).T; 
+        /// ILMath.linsolve(A,B); // ... will be carried out via Lapack, even for all arrays involved being reference arrays! ]]></code></example></item>
+        /// <item><para>if A is square and symmetric or hermitian, A will be decomposed into a triangular equation system using cholesky factorization and Lapack. The system is than solved using performant Lapack routines.</para>
+        /// <para>If during the cholesky factorization A was found to be <b>not positive definite</b> - the cholesky factorization is canceled. </para></item>
+        /// <item>otherwise, if A is square only, it will be decomposed into upper and lower triangular martices using LU decomposition and Lapack. The triangular system is than solved using performant Lapack routines.</item>
+        /// <item>otherwise, if A is of size [q x n] and q != n, the system is solved using QR decomposition. A may be rank deficient. The solution is computed by use of the Lapack routine '?gelsy' and may be a reference array.</item>
+        /// </list></para>
+        /// <para>Compatibility with Matlab<sup>(R)</sup>: If A is square, the algorithm used follows the same logic as Matlab up to Rel 14, with the exception of Hessenberg matrices wich are solved via LU factorization here. The un-squared case is handled differently. A direct Lapack driver function (?gelsy) is used here. Therefore the solutions might differ! However, the solution will of course fullfill the equation A * x = B without round off errrors. </para>
+        /// <para>For specifiying the rank of A in the unsquare case (q != n), <see cref="ILNumerics.ILMath.eps"/> is used.</para></remarks>
+        public static ILRetArray< float > linsolve(ILInArray< float > A, ILInArray< float > B) {
+            if (object.Equals(A,null) || object.Equals(B,null))
+                throw new ILArgumentException("parameter must not be null!");
+            using (ILScope.Enter(A, B)) {
+                MatrixProperties props = MatrixProperties.None;
+                if (A.Size[0] == A.Size[1]) {
+                    props |= MatrixProperties.Square;
+                    if (ILMath.istriup(A)) {
+                        props |= MatrixProperties.UpperTriangular;
+                        return linsolve(A, B, ref props);
+                    }
+                    if (ILMath.istrilow(A)) {
+                        props |= MatrixProperties.LowerTriangular;
+                        return linsolve(A, B, ref props);
+                    }
+                    if (ILMath.ishermitian(A)) {
+                        // give cholesky a try
+                        props |= MatrixProperties.Hermitian;
+                        props |= MatrixProperties.PositivDefinite;
+                        ILArray< float> ret = linsolve(A, B, ref props);
+                        if (!object.Equals(ret, null)) {
+                            return ret;
+                        } else {
+                            props ^= MatrixProperties.PositivDefinite;
+                        }
+                    }
+                }
+                return linsolve(A, B, ref props);
+            }
+        }
+
+        /// <summary>
+        /// Solve linear equation system
+        /// </summary>
+        /// <param name="A">Matrix A. Size [n x q]</param>
+        /// <param name="B">Right hand side B. Size [n x m]</param>
+        /// <param name="props">Matrix properties. If defined, no checks are made for the structure of A. If the 
+        /// matrix A was found to be (close to or) singular, the 'MatrixProperties.Singular' flag in props will be set. 
+        /// This flag should be tested on return, in order to verify the reliability of the solution.</param>
+        /// <returns>The solution x solving multiply(A,x) = B. Size [n x m]</returns>
+        /// <remarks><para>Depending on the <paramref name="props"/> parameter the equation system will be solved 
+        /// differently for special structures of A:
+        /// <list type="bullet">
+        /// <item>If A is square (q == n) and an <b>upper or lower triangular</b> matrix, the system will directly 
+        /// be solved via backward- or forward substitution. Therefore the Lapack function ?trtrs will be used, 
+        /// whenever the memory layout of A is suitable. This may be the case even for reference ILArray's! 
+        /// <example><code><![CDATA[ILArray<double> A = ILMath.randn(4); // construct 4 x 4 matrix 
+        /// A = A.T; // A is a reference array now! The transpose is fast and does not consume much memory
+        /// // now construct a right side and solve the equations: 
+        /// ILArray<double> B = new ILArray<double> (1.0,2.0,3.0).T; 
+        /// ILMath.linsolve(A,B); // ... will be carried out via Lapack, even for all arrays involved being reference arrays! ]]></code></example></item>
+        /// <item><para>If A is square and symmetric or hermitian, A will be decomposed into a triangular equation 
+        /// system using cholesky factorization and Lapack. The system is than solved using performant Lapack routines.</para>
+        /// <para>If during the cholesky factorization A was found to be <b>not positive definite</b> - the 
+        /// corresponding flag in props will be cleaned and <c>null</c> will be returned.</para></item>
+        /// <item>Otherwise if A is square only, it will be decomposed into upper and lower triangular matrices 
+        /// using LU decomposition and Lapack. The triangular system is than solved using performant Lapack routines.</item>
+        /// <item>Otherwise, if A is of size [q x n] and q != n, the system is solved using QR decomposition. 
+        /// A may be rank deficient. The solution is computed by use of the Lapack routine '?gelsy' and may be a 
+        /// reference array.</item>
+        /// </list></para>
+        /// <para>Compatibility with Matlab<sup>(R)</sup>: If A is square, the algorithm used follows the same 
+        /// logic as Matlab up to Rel 14, with the exception of Hessenberg matrices wich are solved via LU 
+        /// factorization here. The un-squared case is handled differently. A direct Lapack driver function 
+        /// (?gelsy) is used here. Therefore the solutions might differ! However, the solution will of course 
+        /// fullfill the equation A * x = B without round off errrors. </para>
+        /// <para>For specifiying the rank of A in the unsquare case (q != n), 
+        /// <see cref="ILNumerics.ILMath.eps"/> is used.</para></remarks>
+        public static ILRetArray< float > linsolve(ILInArray< float > A, ILInArray< float > B, ref MatrixProperties props) {
+            if (object.Equals(A,null)) 
+                throw new ILArgumentException("input argument A must not be null!"); 
+            if (object.Equals(B,null))
+                throw new ILArgumentException("input argument B must not be null!");
+            using (ILScope.Enter(A, B)) {
+                if (A.IsEmpty || B.IsEmpty)
+                    return empty< float>(A.Size);
+                if (A.Size[0] != B.Size[0])
+                    throw new ILArgumentException("number of rows for matrix A must match number of rows for RHS!");
+                int info = 0, m = A.Size[0];
+                ILArray< float> ret = empty<float>(ILSize.Empty00);
+                if (m == A.Size[1]) {
+                    props |= MatrixProperties.Square;
+                    if ((props & MatrixProperties.LowerTriangular) != 0) {
+                        ret.a = solveLowerTriangularSystem(A, B, ref info);
+                        if (info > 0)
+                            props |= MatrixProperties.Singular;
+                        return ret;
+                    }
+                    if ((props & MatrixProperties.UpperTriangular) != 0) {
+                        ret.a = solveUpperTriangularSystem(A, B, ref info);
+                        if (info > 0)
+                            props |= MatrixProperties.Singular;
+                        return ret;
+                    }
+                    if ((props & MatrixProperties.Hermitian) != 0) {
+                        ILDenseStorage< float> cholFact = A.Storage.copyUpperTriangle(m);
+                       
+                        Lapack.spotrf('U', m, cholFact.GetArrayForWrite(), m, ref info);
+                        if (info > 0) {
+                            props ^= MatrixProperties.Hermitian;
+                            cholFact.Dispose(); 
+                            return null;
+                        } else {
+                            // solve 
+                            ret.a = B.C;
+                           
+                            Lapack.spotrs('U', m, B.Size[1], cholFact.GetArrayForWrite(), m, ret.GetArrayForWrite(), m, ref info);
+                            cholFact.Dispose(); 
+                            return ret;
+                        }
+                    } else {
+                        // attempt complete (expensive) LU factorization 
+                        ILArray< float> L = A.C;
+                        int[] pivInd = ILMemoryPool.Pool.New<int>(m);
+                       
+                        Lapack.sgetrf(m, m, L.GetArrayForWrite(), m, pivInd, ref info);
+                        if (info > 0)
+                            props |= MatrixProperties.Singular;
+                        ret.a = B.C;
+                       
+                        Lapack.sgetrs('N', m, B.Size[1], L.GetArrayForWrite(), m, pivInd, ret.GetArrayForWrite(), m, ref info);
+                        if (info < 0)
+                            throw new ILArgumentException("failed to solve via lapack dgetrs");
+                        return ret;
+                    }
+                } else {
+                    // under- / overdetermined system
+                    int n = A.Size[1], rank = 0, minMN = (m < n) ? m : n, maxMN = (m > n) ? m : n;
+                    int nrhs = B.Size[1];
+                    if (B.Size[0] != m)
+                        throw new ILArgumentException("right hand side matrix B must match input A!");
+                    ILArray< float> tmpA = A.C;
+                    if (m < n) {
+                        ret.a = zeros< float>(n, nrhs);
+                        ret[r(0, m - 1), full] = B.C;
+                    } else {
+                        ret.a = B.C;
+                    }
+                    int[] JPVT = new int[n];
+                   
+                    Lapack.sgelsy(m, n, B.Size[1], tmpA.GetArrayForWrite(), m, ret.GetArrayForWrite(),
+                        maxMN, JPVT,  ILMath.MachineParameterSingle.eps,
+                        ref rank, ref info);
+                    if (n < m) {
+                        ret.a = ret[r(0, n - 1), full];
+                    }
+                    if (rank < minMN)
+                        props |= MatrixProperties.RankDeficient;
+                    return ret;
+                }
+            }
+        }
+        
+        /// <summary>
+        /// Solve system of linear equations A*x = b, with A being a upper triangular matrix
+        /// </summary>
+        /// <param name="A">Input matrix of size [n x n], must be upper triangular. No check is made for that!</param>
+        /// <param name="B">Solution vector or matrix. Size [n x m]</param>
+        /// <param name="singularityDetect">[Output] This value gives the row of A, where a singularity has been detected (if any). If A is not singular, this will be a negative value.</param>
+        /// <returns>Solution x solving A * x = b.</returns>
+        /// <remarks><para>The solution will be determined via backward substitution</para>
+        /// <para>Make sure, A and b are of correct size, since no checks are made for that!</para>
+        /// <para>This function is used by ILMath.linsolve. There should be rare need for you to call this function directly.</para>
+        /// <para>Elements of A below the main diagonal will not be accessed.</para>
+        /// <para>If A has been found to be singular, the array returned will contain NaN values for corresponding elements!</para></remarks>
+        internal static ILRetArray< float > solveUpperTriangularSystem (ILInArray< float > A, ILInArray< float > B, ref int singularityDetect) {
+            System.Diagnostics.Debug.Assert(B.Size[1] >= 0); 
+            System.Diagnostics.Debug.Assert(B.Size[0] == A.Size[1]); 
+            System.Diagnostics.Debug.Assert(A.Size[0] == A.Size[1]);
+            using (ILScope.Enter(A, B)) {
+                singularityDetect = -1;
+                int n = A.Size[0];
+                int m = B.Size[1];
+                int info = 0;
+                ILArray< float> ret = B.C;
+               
+                float[] retArr = ret.GetArrayForWrite();
+                // solve using Lapack
+                unsafe {
+                    fixed ( float* ptrA = A.GetArrayForRead())
+                    fixed ( float* ptrB = ret.GetArrayForWrite()) {
+                       
+                        Lapack.strtrs('U', 'N', 'N', A.Size[0], B.Size[1], (IntPtr)ptrA, A.Size[0], (IntPtr)ptrB, B.Size[0], ref info);
+                    }
+                }
+                if (info < 0)
+                    throw new ILArgumentException("error inside Lapack function ?trtrs for argument: " + (-info));
+                if (info > 0) {
+                    singularityDetect = info - 1;
+                    for (m = 0; m < ret.Size[1]; m++) {
+                        info = m * n + singularityDetect;
+                        for (int i = singularityDetect; i < n; i++) {
+                            retArr[info++] =  float.NaN;
+                        }
+                    }
+                } else {
+                    singularityDetect = -1;
+                }
+                return ret;
+            }
+        }
+
+        /// <summary>
+        /// Solve system of linear equations A*x = b, with A being a lower triangular matrix
+        /// </summary>
+        /// <param name="A">Input matrix of size [n x n], must be lower triangular. No check is made for that!</param>
+        /// <param name="B">Solution vector. Size [n x 1]</param>
+        /// <param name="singularityDetect">[Output] This value gives the row of A, where a singularity has been detected (if any). If A is not singular, this will be a negative value.</param>
+        /// <returns>Solution x solving A * x = b.</returns>
+        /// <remarks><para>The solution will be determined via forward substitution</para>
+        /// <para>Make sure, A and b are of correct size, since no checks are made for that!</para>
+        /// <para>This function is used by ILMath.linsolve. There should be rare need for you to call this function directly.</para>
+        /// <para>Elements of A above the main diagonal will not be accessed.</para>
+        /// <para>If A has been found to be singular, the array returned will contain NaN values for corresponding elements!</para></remarks>
+        internal static ILRetArray< float> solveLowerTriangularSystem( ILInArray< float> A, ILInArray< float> B, ref int singularityDetect ) {
+            System.Diagnostics.Debug.Assert(B.Size[1] >= 0);
+            System.Diagnostics.Debug.Assert(B.Size[0] == A.Size[1]);
+            System.Diagnostics.Debug.Assert(A.Size[0] == A.Size[1]);
+            using (ILScope.Enter(A, B)) {
+                singularityDetect = -1;
+                int n = A.Size[0];
+                int m = B.Size[1];
+                int info = 0;
+                ILArray< float> ret = B.C;
+               
+                float[] retArr = ret.GetArrayForWrite();
+                // solve using Lapack
+                unsafe {
+                    fixed ( float* ptrA = A.GetArrayForRead())
+                    fixed ( float* ptrB = ret.GetArrayForWrite()) {
+                       
+                        Lapack.strtrs('L', 'N', 'N', A.Size[0], B.Size[1], (IntPtr)ptrA, A.Size[0], (IntPtr)ptrB, B.Size[0], ref info);
+                    }
+                }
+                if (info < 0)
+                    throw new ILArgumentException("error inside Lapack function ?trtrs for argument: " + (-info));
+                if (info > 0) {
+                    singularityDetect = info - 1;
+                    for (m = 0; m < ret.Size[1]; m++) {
+                        info = m * n + singularityDetect;
+                        for (int i = singularityDetect; i < n; i++) {
+                            retArr[info++] =  float.NaN;
+                        }
+                    }
+                } else {
+                    singularityDetect = -1;
+                }
+                return ret;
+            }
+        }
+
+        
+        /// <summary>
+        /// Solve linear equation system
+        /// </summary>
+        /// <param name="A">Matrix A. Size [n x q]</param>
+        /// <param name="B">Right hand side B. Size [n x m]</param>
+        /// <returns>Solution x solving the equation system: multiply(A, x) = B. Size [n x m]</returns>
+        /// <remarks><para>Depending on the structure and properties of A, the equation system will be solved in different ways:
+        /// <list type="bullet">
+        /// <item>If A is square (q == n) and an <b>upper or lower triangular</b> matrix, the system will directly be solved via backward- or forward substitution. Therefore the Lapack function ?trtrs will be used, whenever the memory layout of A is suitable. This may be the case even for reference ILArray's! 
+        /// <example><code><![CDATA[ILArray<double> A = ILMath.randn(4); // construct 4 x 4 matrix 
+        /// A = A.T; // A is a reference array now! The transpose is fast and does not consume much memory
+        /// // now construct a right side and solve the equations: 
+        /// ILArray<double> B = new ILArray<double> (1.0,2.0,3.0).T; 
+        /// ILMath.linsolve(A,B); // ... will be carried out via Lapack, even for all arrays involved being reference arrays! ]]></code></example></item>
+        /// <item><para>if A is square and symmetric or hermitian, A will be decomposed into a triangular equation system using cholesky factorization and Lapack. The system is than solved using performant Lapack routines.</para>
+        /// <para>If during the cholesky factorization A was found to be <b>not positive definite</b> - the cholesky factorization is canceled. </para></item>
+        /// <item>otherwise, if A is square only, it will be decomposed into upper and lower triangular martices using LU decomposition and Lapack. The triangular system is than solved using performant Lapack routines.</item>
+        /// <item>otherwise, if A is of size [q x n] and q != n, the system is solved using QR decomposition. A may be rank deficient. The solution is computed by use of the Lapack routine '?gelsy' and may be a reference array.</item>
+        /// </list></para>
+        /// <para>Compatibility with Matlab<sup>(R)</sup>: If A is square, the algorithm used follows the same logic as Matlab up to Rel 14, with the exception of Hessenberg matrices wich are solved via LU factorization here. The un-squared case is handled differently. A direct Lapack driver function (?gelsy) is used here. Therefore the solutions might differ! However, the solution will of course fullfill the equation A * x = B without round off errrors. </para>
+        /// <para>For specifiying the rank of A in the unsquare case (q != n), <see cref="ILNumerics.ILMath.eps"/> is used.</para></remarks>
+        public static ILRetArray< fcomplex > linsolve(ILInArray< fcomplex > A, ILInArray< fcomplex > B) {
+            if (object.Equals(A,null) || object.Equals(B,null))
+                throw new ILArgumentException("parameter must not be null!");
+            using (ILScope.Enter(A, B)) {
+                MatrixProperties props = MatrixProperties.None;
+                if (A.Size[0] == A.Size[1]) {
+                    props |= MatrixProperties.Square;
+                    if (ILMath.istriup(A)) {
+                        props |= MatrixProperties.UpperTriangular;
+                        return linsolve(A, B, ref props);
+                    }
+                    if (ILMath.istrilow(A)) {
+                        props |= MatrixProperties.LowerTriangular;
+                        return linsolve(A, B, ref props);
+                    }
+                    if (ILMath.ishermitian(A)) {
+                        // give cholesky a try
+                        props |= MatrixProperties.Hermitian;
+                        props |= MatrixProperties.PositivDefinite;
+                        ILArray< fcomplex> ret = linsolve(A, B, ref props);
+                        if (!object.Equals(ret, null)) {
+                            return ret;
+                        } else {
+                            props ^= MatrixProperties.PositivDefinite;
+                        }
+                    }
+                }
+                return linsolve(A, B, ref props);
+            }
+        }
+
+        /// <summary>
+        /// Solve linear equation system
+        /// </summary>
+        /// <param name="A">Matrix A. Size [n x q]</param>
+        /// <param name="B">Right hand side B. Size [n x m]</param>
+        /// <param name="props">Matrix properties. If defined, no checks are made for the structure of A. If the 
+        /// matrix A was found to be (close to or) singular, the 'MatrixProperties.Singular' flag in props will be set. 
+        /// This flag should be tested on return, in order to verify the reliability of the solution.</param>
+        /// <returns>The solution x solving multiply(A,x) = B. Size [n x m]</returns>
+        /// <remarks><para>Depending on the <paramref name="props"/> parameter the equation system will be solved 
+        /// differently for special structures of A:
+        /// <list type="bullet">
+        /// <item>If A is square (q == n) and an <b>upper or lower triangular</b> matrix, the system will directly 
+        /// be solved via backward- or forward substitution. Therefore the Lapack function ?trtrs will be used, 
+        /// whenever the memory layout of A is suitable. This may be the case even for reference ILArray's! 
+        /// <example><code><![CDATA[ILArray<double> A = ILMath.randn(4); // construct 4 x 4 matrix 
+        /// A = A.T; // A is a reference array now! The transpose is fast and does not consume much memory
+        /// // now construct a right side and solve the equations: 
+        /// ILArray<double> B = new ILArray<double> (1.0,2.0,3.0).T; 
+        /// ILMath.linsolve(A,B); // ... will be carried out via Lapack, even for all arrays involved being reference arrays! ]]></code></example></item>
+        /// <item><para>If A is square and symmetric or hermitian, A will be decomposed into a triangular equation 
+        /// system using cholesky factorization and Lapack. The system is than solved using performant Lapack routines.</para>
+        /// <para>If during the cholesky factorization A was found to be <b>not positive definite</b> - the 
+        /// corresponding flag in props will be cleaned and <c>null</c> will be returned.</para></item>
+        /// <item>Otherwise if A is square only, it will be decomposed into upper and lower triangular matrices 
+        /// using LU decomposition and Lapack. The triangular system is than solved using performant Lapack routines.</item>
+        /// <item>Otherwise, if A is of size [q x n] and q != n, the system is solved using QR decomposition. 
+        /// A may be rank deficient. The solution is computed by use of the Lapack routine '?gelsy' and may be a 
+        /// reference array.</item>
+        /// </list></para>
+        /// <para>Compatibility with Matlab<sup>(R)</sup>: If A is square, the algorithm used follows the same 
+        /// logic as Matlab up to Rel 14, with the exception of Hessenberg matrices wich are solved via LU 
+        /// factorization here. The un-squared case is handled differently. A direct Lapack driver function 
+        /// (?gelsy) is used here. Therefore the solutions might differ! However, the solution will of course 
+        /// fullfill the equation A * x = B without round off errrors. </para>
+        /// <para>For specifiying the rank of A in the unsquare case (q != n), 
+        /// <see cref="ILNumerics.ILMath.eps"/> is used.</para></remarks>
+        public static ILRetArray< fcomplex > linsolve(ILInArray< fcomplex > A, ILInArray< fcomplex > B, ref MatrixProperties props) {
+            if (object.Equals(A,null)) 
+                throw new ILArgumentException("input argument A must not be null!"); 
+            if (object.Equals(B,null))
+                throw new ILArgumentException("input argument B must not be null!");
+            using (ILScope.Enter(A, B)) {
+                if (A.IsEmpty || B.IsEmpty)
+                    return empty< fcomplex>(A.Size);
+                if (A.Size[0] != B.Size[0])
+                    throw new ILArgumentException("number of rows for matrix A must match number of rows for RHS!");
+                int info = 0, m = A.Size[0];
+                ILArray< fcomplex> ret = empty<fcomplex>(ILSize.Empty00);
+                if (m == A.Size[1]) {
+                    props |= MatrixProperties.Square;
+                    if ((props & MatrixProperties.LowerTriangular) != 0) {
+                        ret.a = solveLowerTriangularSystem(A, B, ref info);
+                        if (info > 0)
+                            props |= MatrixProperties.Singular;
+                        return ret;
+                    }
+                    if ((props & MatrixProperties.UpperTriangular) != 0) {
+                        ret.a = solveUpperTriangularSystem(A, B, ref info);
+                        if (info > 0)
+                            props |= MatrixProperties.Singular;
+                        return ret;
+                    }
+                    if ((props & MatrixProperties.Hermitian) != 0) {
+                        ILDenseStorage< fcomplex> cholFact = A.Storage.copyUpperTriangle(m);
+                       
+                        Lapack.cpotrf('U', m, cholFact.GetArrayForWrite(), m, ref info);
+                        if (info > 0) {
+                            props ^= MatrixProperties.Hermitian;
+                            cholFact.Dispose(); 
+                            return null;
+                        } else {
+                            // solve 
+                            ret.a = B.C;
+                           
+                            Lapack.cpotrs('U', m, B.Size[1], cholFact.GetArrayForWrite(), m, ret.GetArrayForWrite(), m, ref info);
+                            cholFact.Dispose(); 
+                            return ret;
+                        }
+                    } else {
+                        // attempt complete (expensive) LU factorization 
+                        ILArray< fcomplex> L = A.C;
+                        int[] pivInd = ILMemoryPool.Pool.New<int>(m);
+                       
+                        Lapack.cgetrf(m, m, L.GetArrayForWrite(), m, pivInd, ref info);
+                        if (info > 0)
+                            props |= MatrixProperties.Singular;
+                        ret.a = B.C;
+                       
+                        Lapack.cgetrs('N', m, B.Size[1], L.GetArrayForWrite(), m, pivInd, ret.GetArrayForWrite(), m, ref info);
+                        if (info < 0)
+                            throw new ILArgumentException("failed to solve via lapack dgetrs");
+                        return ret;
+                    }
+                } else {
+                    // under- / overdetermined system
+                    int n = A.Size[1], rank = 0, minMN = (m < n) ? m : n, maxMN = (m > n) ? m : n;
+                    int nrhs = B.Size[1];
+                    if (B.Size[0] != m)
+                        throw new ILArgumentException("right hand side matrix B must match input A!");
+                    ILArray< fcomplex> tmpA = A.C;
+                    if (m < n) {
+                        ret.a = zeros< fcomplex>(n, nrhs);
+                        ret[r(0, m - 1), full] = B.C;
+                    } else {
+                        ret.a = B.C;
+                    }
+                    int[] JPVT = new int[n];
+                   
+                    Lapack.cgelsy(m, n, B.Size[1], tmpA.GetArrayForWrite(), m, ret.GetArrayForWrite(),
+                        maxMN, JPVT,  ILMath.MachineParameterSingle.eps,
+                        ref rank, ref info);
+                    if (n < m) {
+                        ret.a = ret[r(0, n - 1), full];
+                    }
+                    if (rank < minMN)
+                        props |= MatrixProperties.RankDeficient;
+                    return ret;
+                }
+            }
+        }
+        
+        /// <summary>
+        /// Solve system of linear equations A*x = b, with A being a upper triangular matrix
+        /// </summary>
+        /// <param name="A">Input matrix of size [n x n], must be upper triangular. No check is made for that!</param>
+        /// <param name="B">Solution vector or matrix. Size [n x m]</param>
+        /// <param name="singularityDetect">[Output] This value gives the row of A, where a singularity has been detected (if any). If A is not singular, this will be a negative value.</param>
+        /// <returns>Solution x solving A * x = b.</returns>
+        /// <remarks><para>The solution will be determined via backward substitution</para>
+        /// <para>Make sure, A and b are of correct size, since no checks are made for that!</para>
+        /// <para>This function is used by ILMath.linsolve. There should be rare need for you to call this function directly.</para>
+        /// <para>Elements of A below the main diagonal will not be accessed.</para>
+        /// <para>If A has been found to be singular, the array returned will contain NaN values for corresponding elements!</para></remarks>
+        internal static ILRetArray< fcomplex > solveUpperTriangularSystem (ILInArray< fcomplex > A, ILInArray< fcomplex > B, ref int singularityDetect) {
+            System.Diagnostics.Debug.Assert(B.Size[1] >= 0); 
+            System.Diagnostics.Debug.Assert(B.Size[0] == A.Size[1]); 
+            System.Diagnostics.Debug.Assert(A.Size[0] == A.Size[1]);
+            using (ILScope.Enter(A, B)) {
+                singularityDetect = -1;
+                int n = A.Size[0];
+                int m = B.Size[1];
+                int info = 0;
+                ILArray< fcomplex> ret = B.C;
+               
+                fcomplex[] retArr = ret.GetArrayForWrite();
+                // solve using Lapack
+                unsafe {
+                    fixed ( fcomplex* ptrA = A.GetArrayForRead())
+                    fixed ( fcomplex* ptrB = ret.GetArrayForWrite()) {
+                       
+                        Lapack.ctrtrs('U', 'N', 'N', A.Size[0], B.Size[1], (IntPtr)ptrA, A.Size[0], (IntPtr)ptrB, B.Size[0], ref info);
+                    }
+                }
+                if (info < 0)
+                    throw new ILArgumentException("error inside Lapack function ?trtrs for argument: " + (-info));
+                if (info > 0) {
+                    singularityDetect = info - 1;
+                    for (m = 0; m < ret.Size[1]; m++) {
+                        info = m * n + singularityDetect;
+                        for (int i = singularityDetect; i < n; i++) {
+                            retArr[info++] =  new fcomplex(float.NaN,float.NaN);
+                        }
+                    }
+                } else {
+                    singularityDetect = -1;
+                }
+                return ret;
+            }
+        }
+
+        /// <summary>
+        /// Solve system of linear equations A*x = b, with A being a lower triangular matrix
+        /// </summary>
+        /// <param name="A">Input matrix of size [n x n], must be lower triangular. No check is made for that!</param>
+        /// <param name="B">Solution vector. Size [n x 1]</param>
+        /// <param name="singularityDetect">[Output] This value gives the row of A, where a singularity has been detected (if any). If A is not singular, this will be a negative value.</param>
+        /// <returns>Solution x solving A * x = b.</returns>
+        /// <remarks><para>The solution will be determined via forward substitution</para>
+        /// <para>Make sure, A and b are of correct size, since no checks are made for that!</para>
+        /// <para>This function is used by ILMath.linsolve. There should be rare need for you to call this function directly.</para>
+        /// <para>Elements of A above the main diagonal will not be accessed.</para>
+        /// <para>If A has been found to be singular, the array returned will contain NaN values for corresponding elements!</para></remarks>
+        internal static ILRetArray< fcomplex> solveLowerTriangularSystem( ILInArray< fcomplex> A, ILInArray< fcomplex> B, ref int singularityDetect ) {
+            System.Diagnostics.Debug.Assert(B.Size[1] >= 0);
+            System.Diagnostics.Debug.Assert(B.Size[0] == A.Size[1]);
+            System.Diagnostics.Debug.Assert(A.Size[0] == A.Size[1]);
+            using (ILScope.Enter(A, B)) {
+                singularityDetect = -1;
+                int n = A.Size[0];
+                int m = B.Size[1];
+                int info = 0;
+                ILArray< fcomplex> ret = B.C;
+               
+                fcomplex[] retArr = ret.GetArrayForWrite();
+                // solve using Lapack
+                unsafe {
+                    fixed ( fcomplex* ptrA = A.GetArrayForRead())
+                    fixed ( fcomplex* ptrB = ret.GetArrayForWrite()) {
+                       
+                        Lapack.ctrtrs('L', 'N', 'N', A.Size[0], B.Size[1], (IntPtr)ptrA, A.Size[0], (IntPtr)ptrB, B.Size[0], ref info);
+                    }
+                }
+                if (info < 0)
+                    throw new ILArgumentException("error inside Lapack function ?trtrs for argument: " + (-info));
+                if (info > 0) {
+                    singularityDetect = info - 1;
+                    for (m = 0; m < ret.Size[1]; m++) {
+                        info = m * n + singularityDetect;
+                        for (int i = singularityDetect; i < n; i++) {
+                            retArr[info++] =  new fcomplex(float.NaN,float.NaN);
+                        }
+                    }
+                } else {
+                    singularityDetect = -1;
+                }
+                return ret;
+            }
+        }
+
+        
+        /// <summary>
+        /// Solve linear equation system
+        /// </summary>
+        /// <param name="A">Matrix A. Size [n x q]</param>
+        /// <param name="B">Right hand side B. Size [n x m]</param>
+        /// <returns>Solution x solving the equation system: multiply(A, x) = B. Size [n x m]</returns>
+        /// <remarks><para>Depending on the structure and properties of A, the equation system will be solved in different ways:
+        /// <list type="bullet">
+        /// <item>If A is square (q == n) and an <b>upper or lower triangular</b> matrix, the system will directly be solved via backward- or forward substitution. Therefore the Lapack function ?trtrs will be used, whenever the memory layout of A is suitable. This may be the case even for reference ILArray's! 
+        /// <example><code><![CDATA[ILArray<double> A = ILMath.randn(4); // construct 4 x 4 matrix 
+        /// A = A.T; // A is a reference array now! The transpose is fast and does not consume much memory
+        /// // now construct a right side and solve the equations: 
+        /// ILArray<double> B = new ILArray<double> (1.0,2.0,3.0).T; 
+        /// ILMath.linsolve(A,B); // ... will be carried out via Lapack, even for all arrays involved being reference arrays! ]]></code></example></item>
+        /// <item><para>if A is square and symmetric or hermitian, A will be decomposed into a triangular equation system using cholesky factorization and Lapack. The system is than solved using performant Lapack routines.</para>
+        /// <para>If during the cholesky factorization A was found to be <b>not positive definite</b> - the cholesky factorization is canceled. </para></item>
+        /// <item>otherwise, if A is square only, it will be decomposed into upper and lower triangular martices using LU decomposition and Lapack. The triangular system is than solved using performant Lapack routines.</item>
+        /// <item>otherwise, if A is of size [q x n] and q != n, the system is solved using QR decomposition. A may be rank deficient. The solution is computed by use of the Lapack routine '?gelsy' and may be a reference array.</item>
+        /// </list></para>
+        /// <para>Compatibility with Matlab<sup>(R)</sup>: If A is square, the algorithm used follows the same logic as Matlab up to Rel 14, with the exception of Hessenberg matrices wich are solved via LU factorization here. The un-squared case is handled differently. A direct Lapack driver function (?gelsy) is used here. Therefore the solutions might differ! However, the solution will of course fullfill the equation A * x = B without round off errrors. </para>
+        /// <para>For specifiying the rank of A in the unsquare case (q != n), <see cref="ILNumerics.ILMath.eps"/> is used.</para></remarks>
+        public static ILRetArray< complex > linsolve(ILInArray< complex > A, ILInArray< complex > B) {
+            if (object.Equals(A,null) || object.Equals(B,null))
+                throw new ILArgumentException("parameter must not be null!");
+            using (ILScope.Enter(A, B)) {
+                MatrixProperties props = MatrixProperties.None;
+                if (A.Size[0] == A.Size[1]) {
+                    props |= MatrixProperties.Square;
+                    if (ILMath.istriup(A)) {
+                        props |= MatrixProperties.UpperTriangular;
+                        return linsolve(A, B, ref props);
+                    }
+                    if (ILMath.istrilow(A)) {
+                        props |= MatrixProperties.LowerTriangular;
+                        return linsolve(A, B, ref props);
+                    }
+                    if (ILMath.ishermitian(A)) {
+                        // give cholesky a try
+                        props |= MatrixProperties.Hermitian;
+                        props |= MatrixProperties.PositivDefinite;
+                        ILArray< complex> ret = linsolve(A, B, ref props);
+                        if (!object.Equals(ret, null)) {
+                            return ret;
+                        } else {
+                            props ^= MatrixProperties.PositivDefinite;
+                        }
+                    }
+                }
+                return linsolve(A, B, ref props);
+            }
+        }
+
+        /// <summary>
+        /// Solve linear equation system
+        /// </summary>
+        /// <param name="A">Matrix A. Size [n x q]</param>
+        /// <param name="B">Right hand side B. Size [n x m]</param>
+        /// <param name="props">Matrix properties. If defined, no checks are made for the structure of A. If the 
+        /// matrix A was found to be (close to or) singular, the 'MatrixProperties.Singular' flag in props will be set. 
+        /// This flag should be tested on return, in order to verify the reliability of the solution.</param>
+        /// <returns>The solution x solving multiply(A,x) = B. Size [n x m]</returns>
+        /// <remarks><para>Depending on the <paramref name="props"/> parameter the equation system will be solved 
+        /// differently for special structures of A:
+        /// <list type="bullet">
+        /// <item>If A is square (q == n) and an <b>upper or lower triangular</b> matrix, the system will directly 
+        /// be solved via backward- or forward substitution. Therefore the Lapack function ?trtrs will be used, 
+        /// whenever the memory layout of A is suitable. This may be the case even for reference ILArray's! 
+        /// <example><code><![CDATA[ILArray<double> A = ILMath.randn(4); // construct 4 x 4 matrix 
+        /// A = A.T; // A is a reference array now! The transpose is fast and does not consume much memory
+        /// // now construct a right side and solve the equations: 
+        /// ILArray<double> B = new ILArray<double> (1.0,2.0,3.0).T; 
+        /// ILMath.linsolve(A,B); // ... will be carried out via Lapack, even for all arrays involved being reference arrays! ]]></code></example></item>
+        /// <item><para>If A is square and symmetric or hermitian, A will be decomposed into a triangular equation 
+        /// system using cholesky factorization and Lapack. The system is than solved using performant Lapack routines.</para>
+        /// <para>If during the cholesky factorization A was found to be <b>not positive definite</b> - the 
+        /// corresponding flag in props will be cleaned and <c>null</c> will be returned.</para></item>
+        /// <item>Otherwise if A is square only, it will be decomposed into upper and lower triangular matrices 
+        /// using LU decomposition and Lapack. The triangular system is than solved using performant Lapack routines.</item>
+        /// <item>Otherwise, if A is of size [q x n] and q != n, the system is solved using QR decomposition. 
+        /// A may be rank deficient. The solution is computed by use of the Lapack routine '?gelsy' and may be a 
+        /// reference array.</item>
+        /// </list></para>
+        /// <para>Compatibility with Matlab<sup>(R)</sup>: If A is square, the algorithm used follows the same 
+        /// logic as Matlab up to Rel 14, with the exception of Hessenberg matrices wich are solved via LU 
+        /// factorization here. The un-squared case is handled differently. A direct Lapack driver function 
+        /// (?gelsy) is used here. Therefore the solutions might differ! However, the solution will of course 
+        /// fullfill the equation A * x = B without round off errrors. </para>
+        /// <para>For specifiying the rank of A in the unsquare case (q != n), 
+        /// <see cref="ILNumerics.ILMath.eps"/> is used.</para></remarks>
+        public static ILRetArray< complex > linsolve(ILInArray< complex > A, ILInArray< complex > B, ref MatrixProperties props) {
+            if (object.Equals(A,null)) 
+                throw new ILArgumentException("input argument A must not be null!"); 
+            if (object.Equals(B,null))
+                throw new ILArgumentException("input argument B must not be null!");
+            using (ILScope.Enter(A, B)) {
+                if (A.IsEmpty || B.IsEmpty)
+                    return empty< complex>(A.Size);
+                if (A.Size[0] != B.Size[0])
+                    throw new ILArgumentException("number of rows for matrix A must match number of rows for RHS!");
+                int info = 0, m = A.Size[0];
+                ILArray< complex> ret = empty<complex>(ILSize.Empty00);
+                if (m == A.Size[1]) {
+                    props |= MatrixProperties.Square;
+                    if ((props & MatrixProperties.LowerTriangular) != 0) {
+                        ret.a = solveLowerTriangularSystem(A, B, ref info);
+                        if (info > 0)
+                            props |= MatrixProperties.Singular;
+                        return ret;
+                    }
+                    if ((props & MatrixProperties.UpperTriangular) != 0) {
+                        ret.a = solveUpperTriangularSystem(A, B, ref info);
+                        if (info > 0)
+                            props |= MatrixProperties.Singular;
+                        return ret;
+                    }
+                    if ((props & MatrixProperties.Hermitian) != 0) {
+                        ILDenseStorage< complex> cholFact = A.Storage.copyUpperTriangle(m);
+                       
+                        Lapack.zpotrf('U', m, cholFact.GetArrayForWrite(), m, ref info);
+                        if (info > 0) {
+                            props ^= MatrixProperties.Hermitian;
+                            cholFact.Dispose(); 
+                            return null;
+                        } else {
+                            // solve 
+                            ret.a = B.C;
+                           
+                            Lapack.zpotrs('U', m, B.Size[1], cholFact.GetArrayForWrite(), m, ret.GetArrayForWrite(), m, ref info);
+                            cholFact.Dispose(); 
+                            return ret;
+                        }
+                    } else {
+                        // attempt complete (expensive) LU factorization 
+                        ILArray< complex> L = A.C;
+                        int[] pivInd = ILMemoryPool.Pool.New<int>(m);
+                       
+                        Lapack.zgetrf(m, m, L.GetArrayForWrite(), m, pivInd, ref info);
+                        if (info > 0)
+                            props |= MatrixProperties.Singular;
+                        ret.a = B.C;
+                       
+                        Lapack.zgetrs('N', m, B.Size[1], L.GetArrayForWrite(), m, pivInd, ret.GetArrayForWrite(), m, ref info);
+                        if (info < 0)
+                            throw new ILArgumentException("failed to solve via lapack dgetrs");
+                        return ret;
+                    }
+                } else {
+                    // under- / overdetermined system
+                    int n = A.Size[1], rank = 0, minMN = (m < n) ? m : n, maxMN = (m > n) ? m : n;
+                    int nrhs = B.Size[1];
+                    if (B.Size[0] != m)
+                        throw new ILArgumentException("right hand side matrix B must match input A!");
+                    ILArray< complex> tmpA = A.C;
+                    if (m < n) {
+                        ret.a = zeros< complex>(n, nrhs);
+                        ret[r(0, m - 1), full] = B.C;
+                    } else {
+                        ret.a = B.C;
+                    }
+                    int[] JPVT = new int[n];
+                   
+                    Lapack.zgelsy(m, n, B.Size[1], tmpA.GetArrayForWrite(), m, ret.GetArrayForWrite(),
+                        maxMN, JPVT,  ILMath.MachineParameterDouble.eps,
+                        ref rank, ref info);
+                    if (n < m) {
+                        ret.a = ret[r(0, n - 1), full];
+                    }
+                    if (rank < minMN)
+                        props |= MatrixProperties.RankDeficient;
+                    return ret;
+                }
+            }
+        }
+        
+        /// <summary>
+        /// Solve system of linear equations A*x = b, with A being a upper triangular matrix
+        /// </summary>
+        /// <param name="A">Input matrix of size [n x n], must be upper triangular. No check is made for that!</param>
+        /// <param name="B">Solution vector or matrix. Size [n x m]</param>
+        /// <param name="singularityDetect">[Output] This value gives the row of A, where a singularity has been detected (if any). If A is not singular, this will be a negative value.</param>
+        /// <returns>Solution x solving A * x = b.</returns>
+        /// <remarks><para>The solution will be determined via backward substitution</para>
+        /// <para>Make sure, A and b are of correct size, since no checks are made for that!</para>
+        /// <para>This function is used by ILMath.linsolve. There should be rare need for you to call this function directly.</para>
+        /// <para>Elements of A below the main diagonal will not be accessed.</para>
+        /// <para>If A has been found to be singular, the array returned will contain NaN values for corresponding elements!</para></remarks>
+        internal static ILRetArray< complex > solveUpperTriangularSystem (ILInArray< complex > A, ILInArray< complex > B, ref int singularityDetect) {
+            System.Diagnostics.Debug.Assert(B.Size[1] >= 0); 
+            System.Diagnostics.Debug.Assert(B.Size[0] == A.Size[1]); 
+            System.Diagnostics.Debug.Assert(A.Size[0] == A.Size[1]);
+            using (ILScope.Enter(A, B)) {
+                singularityDetect = -1;
+                int n = A.Size[0];
+                int m = B.Size[1];
+                int info = 0;
+                ILArray< complex> ret = B.C;
+               
+                complex[] retArr = ret.GetArrayForWrite();
+                // solve using Lapack
+                unsafe {
+                    fixed ( complex* ptrA = A.GetArrayForRead())
+                    fixed ( complex* ptrB = ret.GetArrayForWrite()) {
+                       
+                        Lapack.ztrtrs('U', 'N', 'N', A.Size[0], B.Size[1], (IntPtr)ptrA, A.Size[0], (IntPtr)ptrB, B.Size[0], ref info);
+                    }
+                }
+                if (info < 0)
+                    throw new ILArgumentException("error inside Lapack function ?trtrs for argument: " + (-info));
+                if (info > 0) {
+                    singularityDetect = info - 1;
+                    for (m = 0; m < ret.Size[1]; m++) {
+                        info = m * n + singularityDetect;
+                        for (int i = singularityDetect; i < n; i++) {
+                            retArr[info++] =  new complex(double.NaN,double.NaN);
+                        }
+                    }
+                } else {
+                    singularityDetect = -1;
+                }
+                return ret;
+            }
+        }
+
+        /// <summary>
+        /// Solve system of linear equations A*x = b, with A being a lower triangular matrix
+        /// </summary>
+        /// <param name="A">Input matrix of size [n x n], must be lower triangular. No check is made for that!</param>
+        /// <param name="B">Solution vector. Size [n x 1]</param>
+        /// <param name="singularityDetect">[Output] This value gives the row of A, where a singularity has been detected (if any). If A is not singular, this will be a negative value.</param>
+        /// <returns>Solution x solving A * x = b.</returns>
+        /// <remarks><para>The solution will be determined via forward substitution</para>
+        /// <para>Make sure, A and b are of correct size, since no checks are made for that!</para>
+        /// <para>This function is used by ILMath.linsolve. There should be rare need for you to call this function directly.</para>
+        /// <para>Elements of A above the main diagonal will not be accessed.</para>
+        /// <para>If A has been found to be singular, the array returned will contain NaN values for corresponding elements!</para></remarks>
+        internal static ILRetArray< complex> solveLowerTriangularSystem( ILInArray< complex> A, ILInArray< complex> B, ref int singularityDetect ) {
+            System.Diagnostics.Debug.Assert(B.Size[1] >= 0);
+            System.Diagnostics.Debug.Assert(B.Size[0] == A.Size[1]);
+            System.Diagnostics.Debug.Assert(A.Size[0] == A.Size[1]);
+            using (ILScope.Enter(A, B)) {
+                singularityDetect = -1;
+                int n = A.Size[0];
+                int m = B.Size[1];
+                int info = 0;
+                ILArray< complex> ret = B.C;
+               
+                complex[] retArr = ret.GetArrayForWrite();
+                // solve using Lapack
+                unsafe {
+                    fixed ( complex* ptrA = A.GetArrayForRead())
+                    fixed ( complex* ptrB = ret.GetArrayForWrite()) {
+                       
+                        Lapack.ztrtrs('L', 'N', 'N', A.Size[0], B.Size[1], (IntPtr)ptrA, A.Size[0], (IntPtr)ptrB, B.Size[0], ref info);
+                    }
+                }
+                if (info < 0)
+                    throw new ILArgumentException("error inside Lapack function ?trtrs for argument: " + (-info));
+                if (info > 0) {
+                    singularityDetect = info - 1;
+                    for (m = 0; m < ret.Size[1]; m++) {
+                        info = m * n + singularityDetect;
+                        for (int i = singularityDetect; i < n; i++) {
+                            retArr[info++] =  new complex(double.NaN,double.NaN);
+                        }
+                    }
+                } else {
+                    singularityDetect = -1;
+                }
+                return ret;
+            }
+        }
+
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/sort.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/sort.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/sort.cs	(revision 9102)
@@ -0,0 +1,2037 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Algorithms; 
+using ILNumerics.Exceptions; 
+using ILNumerics.Data; 
+using ILNumerics.Misc; 
+
+
+namespace ILNumerics {
+    public partial class ILMath {
+
+
+        /// <summary>
+        /// Sort data in A along first non singleton dimension
+        /// </summary>
+        /// <param name="A">Input array, n-dimensional</param>
+        /// <returns>Sorted array of the same size as A</returns>
+        /// <remarks>The data in A will be sorted in ascending order using a non-recursive quick sort algorithm. 
+        /// Elements along the columns of A will get sorted independently from each other. A is not altered.
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have 
+        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
+        /// </remarks>
+        public static ILRetArray< double > sort (ILInArray< double > A) {
+            using (ILScope.Enter(A)) {
+                int fnsd = A.Size.WorkingDimension();
+                if (fnsd < 0) return A.C;
+                return sort(A, fnsd, false);
+            }
+        }
+        /// <summary>
+        /// Sort data in A along first non singleton dimension
+        /// </summary>
+        /// <param name="A">Input array, n-dimensional</param>
+        /// <param name="descending">Determine the direction of sorting (ascending/ descending)</param>
+        /// <returns>Sorted array of the same size as A</returns>
+        /// <remarks>The data in A will be sorted using the quick sort algorithm. Data 
+        /// along the first non singleton dimension will get sorted independently from data 
+        /// in the next row/column.
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have 
+        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
+        /// </remarks>
+        public static ILRetArray< double > sort (ILInArray< double > A, bool descending) {
+            using (ILScope.Enter(A)) {
+                int fnsd = A.Size.WorkingDimension();
+                if (fnsd < 0) return A.C;
+                return sort(A, fnsd, descending);
+            }
+        }
+        /// <summary>
+        /// Sort data in A along dimension 'dim'
+        /// </summary>
+        /// <param name="A">Input array, n-dimensional</param>
+        /// <param name="descending">Direction of sorting</param>
+        /// <param name="dim">Dimension index to sort along</param>
+        /// <returns>Sorted array of the same size as A</returns>
+        /// <remarks>The data in A will be sorted along the dimension <paramref name="dim"/> using a non-recursive quicksort 
+        /// algorithm.  
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>Properties of sorting can be tuned by the settings of <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/> 
+        /// and <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/>.</para>
+        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have 
+        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
+        /// </remarks>
+        public static ILRetArray< double > sort (ILInArray< double > A, int dim, bool descending) {
+            if (object.Equals (A,null)) 
+                throw new Exception("parameter A must not be null");
+            using (ILScope.Enter(A)) {
+                if (dim < 0) // || dim >= A.Dimensions.NumberOfDimensions)
+                    throw new ILArgumentException("invalid dimension argument");
+                if (dim >= A.Size.NumberOfDimensions)
+                    return A.C;
+                // early exit: scalar/ empty
+                if (A.IsEmpty || A.IsScalar)
+                    return A.C;
+                ILArray< double> ret = A.C; // new ILArray<double>(new Storage.ILDenseStorage<double>(ILMemoryPool.Pool.New<double>(A.Dimensions.NumberOfElements), A.Dimensions));
+                int inc = ret.Size.SequentialIndexDistance(dim);
+                int dimLen = A.Size[dim];
+                int maxRuns = A.Size.NumberOfElements / dimLen;
+                int posInArr = 0;
+                if (descending) {
+                    if (maxRuns == 1) {
+                        ILQuickSort.QuickSortDescMT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
+                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
+                        
+                        double[] retArr = ret.GetArrayForWrite();
+                        System.Threading.Tasks.Parallel.For(0, maxRuns,
+                            (c) => {
+                                int pos = (int)(((long)dimLen * c * inc) % (A.Size.NumberOfElements - 1));
+                                ILQuickSort.QuickSortDescST(retArr, pos, pos + (dimLen - 1) * inc, inc);
+                            });
+                    } else {
+                        
+					    double[] retArr = ret.GetArrayForWrite();
+                        for (int c = 0; c < maxRuns; c++) {
+                            if (posInArr >= A.Size.NumberOfElements)
+                                posInArr -= (A.Size.NumberOfElements - 1);
+                            ILQuickSort.QuickSortDescST(retArr, posInArr, posInArr + (dimLen - 1) * inc, inc);
+                            posInArr += dimLen * inc;
+                        }
+                    }
+                } else {
+                    // ascending
+                    if (maxRuns == 1) {
+                        ILQuickSort.QuickSortAscMT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
+                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
+                         
+                        double[] retArr = ret.GetArrayForWrite();
+                        System.Threading.Tasks.Parallel.For(0, maxRuns,
+                            (c) => {
+                                int pos = (dimLen * c * inc) % (A.Size.NumberOfElements - 1);
+                                ILQuickSort.QuickSortAscST(retArr, pos, pos + (dimLen - 1) * inc, inc);
+                            });
+                    } else {
+                        
+                        double[] retArr = ret.GetArrayForWrite();
+                        for (int c = 0; c < maxRuns; c++) {
+                            if (posInArr >= A.Size.NumberOfElements)
+                                posInArr -= (A.Size.NumberOfElements - 1);
+                            ILQuickSort.QuickSortAscST(retArr, posInArr, posInArr + (dimLen - 1) * inc, inc);
+                            posInArr += dimLen * inc;
+                        }
+                    }
+                }
+                //if (descending) {
+                //    for (int c = 0; c < maxRuns; c++) {
+                //        if (posInArr >= A.Dimensions.NumberOfElements)
+                //            posInArr -= (A.Dimensions.NumberOfElements - 1);
+                //        ILQuickSort.QuickSortDescSolid_IT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc, false);
+                //        posInArr += dimLen * inc;
+                //    }
+                //} else {
+                //    // ascending
+                //    for (int c = 0; c < maxRuns; c++) {
+                //        if (posInArr >= A.Dimensions.NumberOfElements)
+                //            posInArr -= (A.Dimensions.NumberOfElements - 1);
+                //        ILQuickSort.QuickSortAscSolid_IT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc, false);
+                //        posInArr += dimLen * inc;
+                //    }
+                //}
+                return ret;
+            }
+        }
+        /// <summary>
+        /// Sort data in A along dimension 'dim'
+        /// </summary>
+        /// <param name="A">Input array, n-dimensional</param>
+        /// <param name="descending">Direction of sorting</param>
+        /// <param name="dim">Dimension index to sort along</param>
+        /// <param name="Indices">[Output] Returns permutation matrix</param>
+        /// <returns>Sorted array of the same size as A</returns>
+        /// <remarks>The data in A will be sorted along the dimension <paramref name="dim"/> using a non-recursive quicksort 
+        /// algorithm.  
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>Properties of sorting can be tuned by the settings of <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/> 
+        /// and <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/>.</para>
+        /// <para>This overload also returns an array 'Indices' which will hold the indices into the original 
+        /// elements <b>after sorting</b>. Elements of 'Indices' are of type double.</para>
+        /// <example><code>ILArray&lt;double&gt; A = ILMath.rand(1,5); 
+        /// //A: 
+        /// // 0.4324  0.9231  0.1231  0.1423  0.2991
+        /// ILArray&lt;double&gt; I; 
+        /// ILArray&lt;double&gt; R = ILMath.sort(A, out I, 1, false);
+        /// //R: 
+        /// // 0.1231  0.1423  0.2991  0.4324  0.9231  
+        /// //I: 
+        /// // 2  3  4  0  1
+        /// </code>
+        /// </example>
+        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have 
+        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
+        /// </remarks>
+        public static ILRetArray< double> sort( ILInArray< double> A, ILOutArray<double> Indices = null, int dim = -1, bool descending = false ) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A, null))
+                    throw new Exception("parameter A must not be null");
+                if (object.Equals(Indices, null)) {
+                    return sort(A,dim,descending); 
+                }
+                if (dim >= A.Size.NumberOfDimensions)
+                    throw new ILArgumentException("invalid dimension argument");
+                // early exit: scalar/ empty
+                if (A.IsEmpty) {
+                    Indices.a = empty<double>(ILSize.Empty00);
+                    return empty< double>(ILSize.Empty00);
+                }
+                if (A.IsScalar) {
+                    Indices.a = 0;
+                    return A.C;
+                }
+                if (dim < 0) {
+                    dim = A.S.WorkingDimension(); 
+                }
+                int[] tmpDims = A.Size.ToIntArray();
+                for (int i = 0; i < A.Size.NumberOfDimensions; i++) {
+                    if (i == dim)
+                        tmpDims[i] = A.Size[dim];
+                    else
+                        tmpDims[i] = 1;
+                }
+                //if (Indices.IsEmpty || !Indices.D.IsSameSize(A.D)) {
+                Indices.a = reshape(counter(0.0, 1.0, 1, A.Size[dim]), tmpDims);
+                tmpDims = A.Size.ToIntArray();
+                tmpDims[dim] = 1;
+                Indices.a = repmat(Indices, tmpDims);
+                //}
+                ILArray<double> ret = A.C;
+                int inc = ret.Size.SequentialIndexDistance(dim);
+                int dimLen = A.Size[dim];
+                int maxRuns = A.Size.NumberOfElements / dimLen;
+                int posInArr = 0;
+                if (descending) {
+                    if (maxRuns == 1) {
+                        ILQuickSort.QuickSortDescIDXMT(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
+                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
+                        double [] retArr = ret.GetArrayForWrite(); 
+                        double[] indArr = Indices.GetArrayForRead(); 
+                        System.Threading.Tasks.Parallel.For(0, maxRuns,
+                            (c) => {
+                                int pos = (dimLen * c * inc) % (A.Size.NumberOfElements-1);
+                                ILQuickSort.QuickSortDescIDXST(retArr, indArr, pos, pos + (dimLen - 1) * inc, inc);
+                        }); 
+                    } else {
+                        for (int c = 0; c < maxRuns; c++) {
+                            if (posInArr >= A.Size.NumberOfElements)
+                                posInArr -= (A.Size.NumberOfElements - 1);
+                            ILQuickSort.QuickSortDescIDXST(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
+                            posInArr += dimLen * inc;
+                        }
+                    }
+                } else {
+                    // ascending
+                    if (maxRuns == 1) {
+                        ILQuickSort.QuickSortAscIDXMT(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
+                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
+                        
+                        double[] retArr = ret.GetArrayForWrite();
+                        double[] indArr = Indices.GetArrayForRead();
+                        System.Threading.Tasks.Parallel.For(0, maxRuns,
+                            (c) => {
+                                int pos = (dimLen * c * inc) % (A.Size.NumberOfElements - 1);
+                                ILQuickSort.QuickSortAscIDXST(retArr, indArr, pos, pos + (dimLen - 1) * inc, inc);
+                            });
+                    } else {
+                        for (int c = 0; c < maxRuns; c++) {
+                            if (posInArr >= A.Size.NumberOfElements)
+                                posInArr -= (A.Size.NumberOfElements - 1);
+                            ILQuickSort.QuickSortAscIDXST(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
+                            posInArr += dimLen * inc;
+                        }
+                    }
+                }
+                return ret;
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// Sort data in A along first non singleton dimension
+        /// </summary>
+        /// <param name="A">Input array, n-dimensional</param>
+        /// <returns>Sorted array of the same size as A</returns>
+        /// <remarks>The data in A will be sorted in ascending order using a non-recursive quick sort algorithm. 
+        /// Elements along the columns of A will get sorted independently from each other. A is not altered.
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have 
+        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
+        /// </remarks>
+        public static ILRetArray< Int64 > sort (ILInArray< Int64 > A) {
+            using (ILScope.Enter(A)) {
+                int fnsd = A.Size.WorkingDimension();
+                if (fnsd < 0) return A.C;
+                return sort(A, fnsd, false);
+            }
+        }
+        /// <summary>
+        /// Sort data in A along first non singleton dimension
+        /// </summary>
+        /// <param name="A">Input array, n-dimensional</param>
+        /// <param name="descending">Determine the direction of sorting (ascending/ descending)</param>
+        /// <returns>Sorted array of the same size as A</returns>
+        /// <remarks>The data in A will be sorted using the quick sort algorithm. Data 
+        /// along the first non singleton dimension will get sorted independently from data 
+        /// in the next row/column.
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have 
+        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
+        /// </remarks>
+        public static ILRetArray< Int64 > sort (ILInArray< Int64 > A, bool descending) {
+            using (ILScope.Enter(A)) {
+                int fnsd = A.Size.WorkingDimension();
+                if (fnsd < 0) return A.C;
+                return sort(A, fnsd, descending);
+            }
+        }
+        /// <summary>
+        /// Sort data in A along dimension 'dim'
+        /// </summary>
+        /// <param name="A">Input array, n-dimensional</param>
+        /// <param name="descending">Direction of sorting</param>
+        /// <param name="dim">Dimension index to sort along</param>
+        /// <returns>Sorted array of the same size as A</returns>
+        /// <remarks>The data in A will be sorted along the dimension <paramref name="dim"/> using a non-recursive quicksort 
+        /// algorithm.  
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>Properties of sorting can be tuned by the settings of <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/> 
+        /// and <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/>.</para>
+        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have 
+        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
+        /// </remarks>
+        public static ILRetArray< Int64 > sort (ILInArray< Int64 > A, int dim, bool descending) {
+            if (object.Equals (A,null)) 
+                throw new Exception("parameter A must not be null");
+            using (ILScope.Enter(A)) {
+                if (dim < 0) // || dim >= A.Dimensions.NumberOfDimensions)
+                    throw new ILArgumentException("invalid dimension argument");
+                if (dim >= A.Size.NumberOfDimensions)
+                    return A.C;
+                // early exit: scalar/ empty
+                if (A.IsEmpty || A.IsScalar)
+                    return A.C;
+                ILArray< Int64> ret = A.C; // new ILArray<double>(new Storage.ILDenseStorage<double>(ILMemoryPool.Pool.New<double>(A.Dimensions.NumberOfElements), A.Dimensions));
+                int inc = ret.Size.SequentialIndexDistance(dim);
+                int dimLen = A.Size[dim];
+                int maxRuns = A.Size.NumberOfElements / dimLen;
+                int posInArr = 0;
+                if (descending) {
+                    if (maxRuns == 1) {
+                        ILQuickSort.QuickSortDescMT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
+                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
+                       
+                        Int64[] retArr = ret.GetArrayForWrite();
+                        System.Threading.Tasks.Parallel.For(0, maxRuns,
+                            (c) => {
+                                int pos = (int)(((long)dimLen * c * inc) % (A.Size.NumberOfElements - 1));
+                                ILQuickSort.QuickSortDescST(retArr, pos, pos + (dimLen - 1) * inc, inc);
+                            });
+                    } else {
+                       
+					    Int64[] retArr = ret.GetArrayForWrite();
+                        for (int c = 0; c < maxRuns; c++) {
+                            if (posInArr >= A.Size.NumberOfElements)
+                                posInArr -= (A.Size.NumberOfElements - 1);
+                            ILQuickSort.QuickSortDescST(retArr, posInArr, posInArr + (dimLen - 1) * inc, inc);
+                            posInArr += dimLen * inc;
+                        }
+                    }
+                } else {
+                    // ascending
+                    if (maxRuns == 1) {
+                        ILQuickSort.QuickSortAscMT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
+                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
+                        
+                        Int64[] retArr = ret.GetArrayForWrite();
+                        System.Threading.Tasks.Parallel.For(0, maxRuns,
+                            (c) => {
+                                int pos = (dimLen * c * inc) % (A.Size.NumberOfElements - 1);
+                                ILQuickSort.QuickSortAscST(retArr, pos, pos + (dimLen - 1) * inc, inc);
+                            });
+                    } else {
+                       
+                        Int64[] retArr = ret.GetArrayForWrite();
+                        for (int c = 0; c < maxRuns; c++) {
+                            if (posInArr >= A.Size.NumberOfElements)
+                                posInArr -= (A.Size.NumberOfElements - 1);
+                            ILQuickSort.QuickSortAscST(retArr, posInArr, posInArr + (dimLen - 1) * inc, inc);
+                            posInArr += dimLen * inc;
+                        }
+                    }
+                }
+                //if (descending) {
+                //    for (int c = 0; c < maxRuns; c++) {
+                //        if (posInArr >= A.Dimensions.NumberOfElements)
+                //            posInArr -= (A.Dimensions.NumberOfElements - 1);
+                //        ILQuickSort.QuickSortDescSolid_IT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc, false);
+                //        posInArr += dimLen * inc;
+                //    }
+                //} else {
+                //    // ascending
+                //    for (int c = 0; c < maxRuns; c++) {
+                //        if (posInArr >= A.Dimensions.NumberOfElements)
+                //            posInArr -= (A.Dimensions.NumberOfElements - 1);
+                //        ILQuickSort.QuickSortAscSolid_IT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc, false);
+                //        posInArr += dimLen * inc;
+                //    }
+                //}
+                return ret;
+            }
+        }
+        /// <summary>
+        /// Sort data in A along dimension 'dim'
+        /// </summary>
+        /// <param name="A">Input array, n-dimensional</param>
+        /// <param name="descending">Direction of sorting</param>
+        /// <param name="dim">Dimension index to sort along</param>
+        /// <param name="Indices">[Output] Returns permutation matrix</param>
+        /// <returns>Sorted array of the same size as A</returns>
+        /// <remarks>The data in A will be sorted along the dimension <paramref name="dim"/> using a non-recursive quicksort 
+        /// algorithm.  
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>Properties of sorting can be tuned by the settings of <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/> 
+        /// and <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/>.</para>
+        /// <para>This overload also returns an array 'Indices' which will hold the indices into the original 
+        /// elements <b>after sorting</b>. Elements of 'Indices' are of type double.</para>
+        /// <example><code>ILArray&lt;double&gt; A = ILMath.rand(1,5); 
+        /// //A: 
+        /// // 0.4324  0.9231  0.1231  0.1423  0.2991
+        /// ILArray&lt;double&gt; I; 
+        /// ILArray&lt;double&gt; R = ILMath.sort(A, out I, 1, false);
+        /// //R: 
+        /// // 0.1231  0.1423  0.2991  0.4324  0.9231  
+        /// //I: 
+        /// // 2  3  4  0  1
+        /// </code>
+        /// </example>
+        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have 
+        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
+        /// </remarks>
+        public static ILRetArray< Int64> sort( ILInArray< Int64> A, ILOutArray<double> Indices = null, int dim = -1, bool descending = false ) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A, null))
+                    throw new Exception("parameter A must not be null");
+                if (object.Equals(Indices, null)) {
+                    return sort(A,dim,descending); 
+                }
+                if (dim >= A.Size.NumberOfDimensions)
+                    throw new ILArgumentException("invalid dimension argument");
+                // early exit: scalar/ empty
+                if (A.IsEmpty) {
+                    Indices.a = empty<double>(ILSize.Empty00);
+                    return empty< Int64>(ILSize.Empty00);
+                }
+                if (A.IsScalar) {
+                    Indices.a = 0;
+                    return A.C;
+                }
+                if (dim < 0) {
+                    dim = A.S.WorkingDimension(); 
+                }
+                int[] tmpDims = A.Size.ToIntArray();
+                for (int i = 0; i < A.Size.NumberOfDimensions; i++) {
+                    if (i == dim)
+                        tmpDims[i] = A.Size[dim];
+                    else
+                        tmpDims[i] = 1;
+                }
+                //if (Indices.IsEmpty || !Indices.D.IsSameSize(A.D)) {
+                Indices.a = reshape(counter(0.0, 1.0, 1, A.Size[dim]), tmpDims);
+                tmpDims = A.Size.ToIntArray();
+                tmpDims[dim] = 1;
+                Indices.a = repmat(Indices, tmpDims);
+                //}
+                ILArray<Int64> ret = A.C;
+                int inc = ret.Size.SequentialIndexDistance(dim);
+                int dimLen = A.Size[dim];
+                int maxRuns = A.Size.NumberOfElements / dimLen;
+                int posInArr = 0;
+                if (descending) {
+                    if (maxRuns == 1) {
+                        ILQuickSort.QuickSortDescIDXMT(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
+                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
+                       Int64 [] retArr = ret.GetArrayForWrite(); 
+                        double[] indArr = Indices.GetArrayForRead(); 
+                        System.Threading.Tasks.Parallel.For(0, maxRuns,
+                            (c) => {
+                                int pos = (dimLen * c * inc) % (A.Size.NumberOfElements-1);
+                                ILQuickSort.QuickSortDescIDXST(retArr, indArr, pos, pos + (dimLen - 1) * inc, inc);
+                        }); 
+                    } else {
+                        for (int c = 0; c < maxRuns; c++) {
+                            if (posInArr >= A.Size.NumberOfElements)
+                                posInArr -= (A.Size.NumberOfElements - 1);
+                            ILQuickSort.QuickSortDescIDXST(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
+                            posInArr += dimLen * inc;
+                        }
+                    }
+                } else {
+                    // ascending
+                    if (maxRuns == 1) {
+                        ILQuickSort.QuickSortAscIDXMT(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
+                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
+                       
+                        Int64[] retArr = ret.GetArrayForWrite();
+                        double[] indArr = Indices.GetArrayForRead();
+                        System.Threading.Tasks.Parallel.For(0, maxRuns,
+                            (c) => {
+                                int pos = (dimLen * c * inc) % (A.Size.NumberOfElements - 1);
+                                ILQuickSort.QuickSortAscIDXST(retArr, indArr, pos, pos + (dimLen - 1) * inc, inc);
+                            });
+                    } else {
+                        for (int c = 0; c < maxRuns; c++) {
+                            if (posInArr >= A.Size.NumberOfElements)
+                                posInArr -= (A.Size.NumberOfElements - 1);
+                            ILQuickSort.QuickSortAscIDXST(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
+                            posInArr += dimLen * inc;
+                        }
+                    }
+                }
+                return ret;
+            }
+        }
+        /// <summary>
+        /// Sort data in A along first non singleton dimension
+        /// </summary>
+        /// <param name="A">Input array, n-dimensional</param>
+        /// <returns>Sorted array of the same size as A</returns>
+        /// <remarks>The data in A will be sorted in ascending order using a non-recursive quick sort algorithm. 
+        /// Elements along the columns of A will get sorted independently from each other. A is not altered.
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have 
+        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
+        /// </remarks>
+        public static ILRetArray< Int32 > sort (ILInArray< Int32 > A) {
+            using (ILScope.Enter(A)) {
+                int fnsd = A.Size.WorkingDimension();
+                if (fnsd < 0) return A.C;
+                return sort(A, fnsd, false);
+            }
+        }
+        /// <summary>
+        /// Sort data in A along first non singleton dimension
+        /// </summary>
+        /// <param name="A">Input array, n-dimensional</param>
+        /// <param name="descending">Determine the direction of sorting (ascending/ descending)</param>
+        /// <returns>Sorted array of the same size as A</returns>
+        /// <remarks>The data in A will be sorted using the quick sort algorithm. Data 
+        /// along the first non singleton dimension will get sorted independently from data 
+        /// in the next row/column.
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have 
+        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
+        /// </remarks>
+        public static ILRetArray< Int32 > sort (ILInArray< Int32 > A, bool descending) {
+            using (ILScope.Enter(A)) {
+                int fnsd = A.Size.WorkingDimension();
+                if (fnsd < 0) return A.C;
+                return sort(A, fnsd, descending);
+            }
+        }
+        /// <summary>
+        /// Sort data in A along dimension 'dim'
+        /// </summary>
+        /// <param name="A">Input array, n-dimensional</param>
+        /// <param name="descending">Direction of sorting</param>
+        /// <param name="dim">Dimension index to sort along</param>
+        /// <returns>Sorted array of the same size as A</returns>
+        /// <remarks>The data in A will be sorted along the dimension <paramref name="dim"/> using a non-recursive quicksort 
+        /// algorithm.  
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>Properties of sorting can be tuned by the settings of <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/> 
+        /// and <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/>.</para>
+        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have 
+        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
+        /// </remarks>
+        public static ILRetArray< Int32 > sort (ILInArray< Int32 > A, int dim, bool descending) {
+            if (object.Equals (A,null)) 
+                throw new Exception("parameter A must not be null");
+            using (ILScope.Enter(A)) {
+                if (dim < 0) // || dim >= A.Dimensions.NumberOfDimensions)
+                    throw new ILArgumentException("invalid dimension argument");
+                if (dim >= A.Size.NumberOfDimensions)
+                    return A.C;
+                // early exit: scalar/ empty
+                if (A.IsEmpty || A.IsScalar)
+                    return A.C;
+                ILArray< Int32> ret = A.C; // new ILArray<double>(new Storage.ILDenseStorage<double>(ILMemoryPool.Pool.New<double>(A.Dimensions.NumberOfElements), A.Dimensions));
+                int inc = ret.Size.SequentialIndexDistance(dim);
+                int dimLen = A.Size[dim];
+                int maxRuns = A.Size.NumberOfElements / dimLen;
+                int posInArr = 0;
+                if (descending) {
+                    if (maxRuns == 1) {
+                        ILQuickSort.QuickSortDescMT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
+                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
+                       
+                        Int32[] retArr = ret.GetArrayForWrite();
+                        System.Threading.Tasks.Parallel.For(0, maxRuns,
+                            (c) => {
+                                int pos = (int)(((long)dimLen * c * inc) % (A.Size.NumberOfElements - 1));
+                                ILQuickSort.QuickSortDescST(retArr, pos, pos + (dimLen - 1) * inc, inc);
+                            });
+                    } else {
+                       
+					    Int32[] retArr = ret.GetArrayForWrite();
+                        for (int c = 0; c < maxRuns; c++) {
+                            if (posInArr >= A.Size.NumberOfElements)
+                                posInArr -= (A.Size.NumberOfElements - 1);
+                            ILQuickSort.QuickSortDescST(retArr, posInArr, posInArr + (dimLen - 1) * inc, inc);
+                            posInArr += dimLen * inc;
+                        }
+                    }
+                } else {
+                    // ascending
+                    if (maxRuns == 1) {
+                        ILQuickSort.QuickSortAscMT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
+                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
+                        
+                        Int32[] retArr = ret.GetArrayForWrite();
+                        System.Threading.Tasks.Parallel.For(0, maxRuns,
+                            (c) => {
+                                int pos = (dimLen * c * inc) % (A.Size.NumberOfElements - 1);
+                                ILQuickSort.QuickSortAscST(retArr, pos, pos + (dimLen - 1) * inc, inc);
+                            });
+                    } else {
+                       
+                        Int32[] retArr = ret.GetArrayForWrite();
+                        for (int c = 0; c < maxRuns; c++) {
+                            if (posInArr >= A.Size.NumberOfElements)
+                                posInArr -= (A.Size.NumberOfElements - 1);
+                            ILQuickSort.QuickSortAscST(retArr, posInArr, posInArr + (dimLen - 1) * inc, inc);
+                            posInArr += dimLen * inc;
+                        }
+                    }
+                }
+                //if (descending) {
+                //    for (int c = 0; c < maxRuns; c++) {
+                //        if (posInArr >= A.Dimensions.NumberOfElements)
+                //            posInArr -= (A.Dimensions.NumberOfElements - 1);
+                //        ILQuickSort.QuickSortDescSolid_IT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc, false);
+                //        posInArr += dimLen * inc;
+                //    }
+                //} else {
+                //    // ascending
+                //    for (int c = 0; c < maxRuns; c++) {
+                //        if (posInArr >= A.Dimensions.NumberOfElements)
+                //            posInArr -= (A.Dimensions.NumberOfElements - 1);
+                //        ILQuickSort.QuickSortAscSolid_IT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc, false);
+                //        posInArr += dimLen * inc;
+                //    }
+                //}
+                return ret;
+            }
+        }
+        /// <summary>
+        /// Sort data in A along dimension 'dim'
+        /// </summary>
+        /// <param name="A">Input array, n-dimensional</param>
+        /// <param name="descending">Direction of sorting</param>
+        /// <param name="dim">Dimension index to sort along</param>
+        /// <param name="Indices">[Output] Returns permutation matrix</param>
+        /// <returns>Sorted array of the same size as A</returns>
+        /// <remarks>The data in A will be sorted along the dimension <paramref name="dim"/> using a non-recursive quicksort 
+        /// algorithm.  
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>Properties of sorting can be tuned by the settings of <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/> 
+        /// and <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/>.</para>
+        /// <para>This overload also returns an array 'Indices' which will hold the indices into the original 
+        /// elements <b>after sorting</b>. Elements of 'Indices' are of type double.</para>
+        /// <example><code>ILArray&lt;double&gt; A = ILMath.rand(1,5); 
+        /// //A: 
+        /// // 0.4324  0.9231  0.1231  0.1423  0.2991
+        /// ILArray&lt;double&gt; I; 
+        /// ILArray&lt;double&gt; R = ILMath.sort(A, out I, 1, false);
+        /// //R: 
+        /// // 0.1231  0.1423  0.2991  0.4324  0.9231  
+        /// //I: 
+        /// // 2  3  4  0  1
+        /// </code>
+        /// </example>
+        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have 
+        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
+        /// </remarks>
+        public static ILRetArray< Int32> sort( ILInArray< Int32> A, ILOutArray<double> Indices = null, int dim = -1, bool descending = false ) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A, null))
+                    throw new Exception("parameter A must not be null");
+                if (object.Equals(Indices, null)) {
+                    return sort(A,dim,descending); 
+                }
+                if (dim >= A.Size.NumberOfDimensions)
+                    throw new ILArgumentException("invalid dimension argument");
+                // early exit: scalar/ empty
+                if (A.IsEmpty) {
+                    Indices.a = empty<double>(ILSize.Empty00);
+                    return empty< Int32>(ILSize.Empty00);
+                }
+                if (A.IsScalar) {
+                    Indices.a = 0;
+                    return A.C;
+                }
+                if (dim < 0) {
+                    dim = A.S.WorkingDimension(); 
+                }
+                int[] tmpDims = A.Size.ToIntArray();
+                for (int i = 0; i < A.Size.NumberOfDimensions; i++) {
+                    if (i == dim)
+                        tmpDims[i] = A.Size[dim];
+                    else
+                        tmpDims[i] = 1;
+                }
+                //if (Indices.IsEmpty || !Indices.D.IsSameSize(A.D)) {
+                Indices.a = reshape(counter(0.0, 1.0, 1, A.Size[dim]), tmpDims);
+                tmpDims = A.Size.ToIntArray();
+                tmpDims[dim] = 1;
+                Indices.a = repmat(Indices, tmpDims);
+                //}
+                ILArray<Int32> ret = A.C;
+                int inc = ret.Size.SequentialIndexDistance(dim);
+                int dimLen = A.Size[dim];
+                int maxRuns = A.Size.NumberOfElements / dimLen;
+                int posInArr = 0;
+                if (descending) {
+                    if (maxRuns == 1) {
+                        ILQuickSort.QuickSortDescIDXMT(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
+                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
+                       Int32 [] retArr = ret.GetArrayForWrite(); 
+                        double[] indArr = Indices.GetArrayForRead(); 
+                        System.Threading.Tasks.Parallel.For(0, maxRuns,
+                            (c) => {
+                                int pos = (dimLen * c * inc) % (A.Size.NumberOfElements-1);
+                                ILQuickSort.QuickSortDescIDXST(retArr, indArr, pos, pos + (dimLen - 1) * inc, inc);
+                        }); 
+                    } else {
+                        for (int c = 0; c < maxRuns; c++) {
+                            if (posInArr >= A.Size.NumberOfElements)
+                                posInArr -= (A.Size.NumberOfElements - 1);
+                            ILQuickSort.QuickSortDescIDXST(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
+                            posInArr += dimLen * inc;
+                        }
+                    }
+                } else {
+                    // ascending
+                    if (maxRuns == 1) {
+                        ILQuickSort.QuickSortAscIDXMT(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
+                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
+                       
+                        Int32[] retArr = ret.GetArrayForWrite();
+                        double[] indArr = Indices.GetArrayForRead();
+                        System.Threading.Tasks.Parallel.For(0, maxRuns,
+                            (c) => {
+                                int pos = (dimLen * c * inc) % (A.Size.NumberOfElements - 1);
+                                ILQuickSort.QuickSortAscIDXST(retArr, indArr, pos, pos + (dimLen - 1) * inc, inc);
+                            });
+                    } else {
+                        for (int c = 0; c < maxRuns; c++) {
+                            if (posInArr >= A.Size.NumberOfElements)
+                                posInArr -= (A.Size.NumberOfElements - 1);
+                            ILQuickSort.QuickSortAscIDXST(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
+                            posInArr += dimLen * inc;
+                        }
+                    }
+                }
+                return ret;
+            }
+        }
+        /// <summary>
+        /// Sort data in A along first non singleton dimension
+        /// </summary>
+        /// <param name="A">Input array, n-dimensional</param>
+        /// <returns>Sorted array of the same size as A</returns>
+        /// <remarks>The data in A will be sorted in ascending order using a non-recursive quick sort algorithm. 
+        /// Elements along the columns of A will get sorted independently from each other. A is not altered.
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have 
+        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
+        /// </remarks>
+        public static ILRetArray< float > sort (ILInArray< float > A) {
+            using (ILScope.Enter(A)) {
+                int fnsd = A.Size.WorkingDimension();
+                if (fnsd < 0) return A.C;
+                return sort(A, fnsd, false);
+            }
+        }
+        /// <summary>
+        /// Sort data in A along first non singleton dimension
+        /// </summary>
+        /// <param name="A">Input array, n-dimensional</param>
+        /// <param name="descending">Determine the direction of sorting (ascending/ descending)</param>
+        /// <returns>Sorted array of the same size as A</returns>
+        /// <remarks>The data in A will be sorted using the quick sort algorithm. Data 
+        /// along the first non singleton dimension will get sorted independently from data 
+        /// in the next row/column.
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have 
+        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
+        /// </remarks>
+        public static ILRetArray< float > sort (ILInArray< float > A, bool descending) {
+            using (ILScope.Enter(A)) {
+                int fnsd = A.Size.WorkingDimension();
+                if (fnsd < 0) return A.C;
+                return sort(A, fnsd, descending);
+            }
+        }
+        /// <summary>
+        /// Sort data in A along dimension 'dim'
+        /// </summary>
+        /// <param name="A">Input array, n-dimensional</param>
+        /// <param name="descending">Direction of sorting</param>
+        /// <param name="dim">Dimension index to sort along</param>
+        /// <returns>Sorted array of the same size as A</returns>
+        /// <remarks>The data in A will be sorted along the dimension <paramref name="dim"/> using a non-recursive quicksort 
+        /// algorithm.  
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>Properties of sorting can be tuned by the settings of <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/> 
+        /// and <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/>.</para>
+        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have 
+        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
+        /// </remarks>
+        public static ILRetArray< float > sort (ILInArray< float > A, int dim, bool descending) {
+            if (object.Equals (A,null)) 
+                throw new Exception("parameter A must not be null");
+            using (ILScope.Enter(A)) {
+                if (dim < 0) // || dim >= A.Dimensions.NumberOfDimensions)
+                    throw new ILArgumentException("invalid dimension argument");
+                if (dim >= A.Size.NumberOfDimensions)
+                    return A.C;
+                // early exit: scalar/ empty
+                if (A.IsEmpty || A.IsScalar)
+                    return A.C;
+                ILArray< float> ret = A.C; // new ILArray<double>(new Storage.ILDenseStorage<double>(ILMemoryPool.Pool.New<double>(A.Dimensions.NumberOfElements), A.Dimensions));
+                int inc = ret.Size.SequentialIndexDistance(dim);
+                int dimLen = A.Size[dim];
+                int maxRuns = A.Size.NumberOfElements / dimLen;
+                int posInArr = 0;
+                if (descending) {
+                    if (maxRuns == 1) {
+                        ILQuickSort.QuickSortDescMT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
+                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
+                       
+                        float[] retArr = ret.GetArrayForWrite();
+                        System.Threading.Tasks.Parallel.For(0, maxRuns,
+                            (c) => {
+                                int pos = (int)(((long)dimLen * c * inc) % (A.Size.NumberOfElements - 1));
+                                ILQuickSort.QuickSortDescST(retArr, pos, pos + (dimLen - 1) * inc, inc);
+                            });
+                    } else {
+                       
+					    float[] retArr = ret.GetArrayForWrite();
+                        for (int c = 0; c < maxRuns; c++) {
+                            if (posInArr >= A.Size.NumberOfElements)
+                                posInArr -= (A.Size.NumberOfElements - 1);
+                            ILQuickSort.QuickSortDescST(retArr, posInArr, posInArr + (dimLen - 1) * inc, inc);
+                            posInArr += dimLen * inc;
+                        }
+                    }
+                } else {
+                    // ascending
+                    if (maxRuns == 1) {
+                        ILQuickSort.QuickSortAscMT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
+                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
+                        
+                        float[] retArr = ret.GetArrayForWrite();
+                        System.Threading.Tasks.Parallel.For(0, maxRuns,
+                            (c) => {
+                                int pos = (dimLen * c * inc) % (A.Size.NumberOfElements - 1);
+                                ILQuickSort.QuickSortAscST(retArr, pos, pos + (dimLen - 1) * inc, inc);
+                            });
+                    } else {
+                       
+                        float[] retArr = ret.GetArrayForWrite();
+                        for (int c = 0; c < maxRuns; c++) {
+                            if (posInArr >= A.Size.NumberOfElements)
+                                posInArr -= (A.Size.NumberOfElements - 1);
+                            ILQuickSort.QuickSortAscST(retArr, posInArr, posInArr + (dimLen - 1) * inc, inc);
+                            posInArr += dimLen * inc;
+                        }
+                    }
+                }
+                //if (descending) {
+                //    for (int c = 0; c < maxRuns; c++) {
+                //        if (posInArr >= A.Dimensions.NumberOfElements)
+                //            posInArr -= (A.Dimensions.NumberOfElements - 1);
+                //        ILQuickSort.QuickSortDescSolid_IT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc, false);
+                //        posInArr += dimLen * inc;
+                //    }
+                //} else {
+                //    // ascending
+                //    for (int c = 0; c < maxRuns; c++) {
+                //        if (posInArr >= A.Dimensions.NumberOfElements)
+                //            posInArr -= (A.Dimensions.NumberOfElements - 1);
+                //        ILQuickSort.QuickSortAscSolid_IT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc, false);
+                //        posInArr += dimLen * inc;
+                //    }
+                //}
+                return ret;
+            }
+        }
+        /// <summary>
+        /// Sort data in A along dimension 'dim'
+        /// </summary>
+        /// <param name="A">Input array, n-dimensional</param>
+        /// <param name="descending">Direction of sorting</param>
+        /// <param name="dim">Dimension index to sort along</param>
+        /// <param name="Indices">[Output] Returns permutation matrix</param>
+        /// <returns>Sorted array of the same size as A</returns>
+        /// <remarks>The data in A will be sorted along the dimension <paramref name="dim"/> using a non-recursive quicksort 
+        /// algorithm.  
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>Properties of sorting can be tuned by the settings of <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/> 
+        /// and <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/>.</para>
+        /// <para>This overload also returns an array 'Indices' which will hold the indices into the original 
+        /// elements <b>after sorting</b>. Elements of 'Indices' are of type double.</para>
+        /// <example><code>ILArray&lt;double&gt; A = ILMath.rand(1,5); 
+        /// //A: 
+        /// // 0.4324  0.9231  0.1231  0.1423  0.2991
+        /// ILArray&lt;double&gt; I; 
+        /// ILArray&lt;double&gt; R = ILMath.sort(A, out I, 1, false);
+        /// //R: 
+        /// // 0.1231  0.1423  0.2991  0.4324  0.9231  
+        /// //I: 
+        /// // 2  3  4  0  1
+        /// </code>
+        /// </example>
+        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have 
+        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
+        /// </remarks>
+        public static ILRetArray< float> sort( ILInArray< float> A, ILOutArray<double> Indices = null, int dim = -1, bool descending = false ) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A, null))
+                    throw new Exception("parameter A must not be null");
+                if (object.Equals(Indices, null)) {
+                    return sort(A,dim,descending); 
+                }
+                if (dim >= A.Size.NumberOfDimensions)
+                    throw new ILArgumentException("invalid dimension argument");
+                // early exit: scalar/ empty
+                if (A.IsEmpty) {
+                    Indices.a = empty<double>(ILSize.Empty00);
+                    return empty< float>(ILSize.Empty00);
+                }
+                if (A.IsScalar) {
+                    Indices.a = 0;
+                    return A.C;
+                }
+                if (dim < 0) {
+                    dim = A.S.WorkingDimension(); 
+                }
+                int[] tmpDims = A.Size.ToIntArray();
+                for (int i = 0; i < A.Size.NumberOfDimensions; i++) {
+                    if (i == dim)
+                        tmpDims[i] = A.Size[dim];
+                    else
+                        tmpDims[i] = 1;
+                }
+                //if (Indices.IsEmpty || !Indices.D.IsSameSize(A.D)) {
+                Indices.a = reshape(counter(0.0, 1.0, 1, A.Size[dim]), tmpDims);
+                tmpDims = A.Size.ToIntArray();
+                tmpDims[dim] = 1;
+                Indices.a = repmat(Indices, tmpDims);
+                //}
+                ILArray<float> ret = A.C;
+                int inc = ret.Size.SequentialIndexDistance(dim);
+                int dimLen = A.Size[dim];
+                int maxRuns = A.Size.NumberOfElements / dimLen;
+                int posInArr = 0;
+                if (descending) {
+                    if (maxRuns == 1) {
+                        ILQuickSort.QuickSortDescIDXMT(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
+                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
+                       float [] retArr = ret.GetArrayForWrite(); 
+                        double[] indArr = Indices.GetArrayForRead(); 
+                        System.Threading.Tasks.Parallel.For(0, maxRuns,
+                            (c) => {
+                                int pos = (dimLen * c * inc) % (A.Size.NumberOfElements-1);
+                                ILQuickSort.QuickSortDescIDXST(retArr, indArr, pos, pos + (dimLen - 1) * inc, inc);
+                        }); 
+                    } else {
+                        for (int c = 0; c < maxRuns; c++) {
+                            if (posInArr >= A.Size.NumberOfElements)
+                                posInArr -= (A.Size.NumberOfElements - 1);
+                            ILQuickSort.QuickSortDescIDXST(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
+                            posInArr += dimLen * inc;
+                        }
+                    }
+                } else {
+                    // ascending
+                    if (maxRuns == 1) {
+                        ILQuickSort.QuickSortAscIDXMT(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
+                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
+                       
+                        float[] retArr = ret.GetArrayForWrite();
+                        double[] indArr = Indices.GetArrayForRead();
+                        System.Threading.Tasks.Parallel.For(0, maxRuns,
+                            (c) => {
+                                int pos = (dimLen * c * inc) % (A.Size.NumberOfElements - 1);
+                                ILQuickSort.QuickSortAscIDXST(retArr, indArr, pos, pos + (dimLen - 1) * inc, inc);
+                            });
+                    } else {
+                        for (int c = 0; c < maxRuns; c++) {
+                            if (posInArr >= A.Size.NumberOfElements)
+                                posInArr -= (A.Size.NumberOfElements - 1);
+                            ILQuickSort.QuickSortAscIDXST(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
+                            posInArr += dimLen * inc;
+                        }
+                    }
+                }
+                return ret;
+            }
+        }
+        /// <summary>
+        /// Sort data in A along first non singleton dimension
+        /// </summary>
+        /// <param name="A">Input array, n-dimensional</param>
+        /// <returns>Sorted array of the same size as A</returns>
+        /// <remarks>The data in A will be sorted in ascending order using a non-recursive quick sort algorithm. 
+        /// Elements along the columns of A will get sorted independently from each other. A is not altered.
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have 
+        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
+        /// </remarks>
+        public static ILRetArray< fcomplex > sort (ILInArray< fcomplex > A) {
+            using (ILScope.Enter(A)) {
+                int fnsd = A.Size.WorkingDimension();
+                if (fnsd < 0) return A.C;
+                return sort(A, fnsd, false);
+            }
+        }
+        /// <summary>
+        /// Sort data in A along first non singleton dimension
+        /// </summary>
+        /// <param name="A">Input array, n-dimensional</param>
+        /// <param name="descending">Determine the direction of sorting (ascending/ descending)</param>
+        /// <returns>Sorted array of the same size as A</returns>
+        /// <remarks>The data in A will be sorted using the quick sort algorithm. Data 
+        /// along the first non singleton dimension will get sorted independently from data 
+        /// in the next row/column.
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have 
+        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
+        /// </remarks>
+        public static ILRetArray< fcomplex > sort (ILInArray< fcomplex > A, bool descending) {
+            using (ILScope.Enter(A)) {
+                int fnsd = A.Size.WorkingDimension();
+                if (fnsd < 0) return A.C;
+                return sort(A, fnsd, descending);
+            }
+        }
+        /// <summary>
+        /// Sort data in A along dimension 'dim'
+        /// </summary>
+        /// <param name="A">Input array, n-dimensional</param>
+        /// <param name="descending">Direction of sorting</param>
+        /// <param name="dim">Dimension index to sort along</param>
+        /// <returns>Sorted array of the same size as A</returns>
+        /// <remarks>The data in A will be sorted along the dimension <paramref name="dim"/> using a non-recursive quicksort 
+        /// algorithm.  
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>Properties of sorting can be tuned by the settings of <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/> 
+        /// and <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/>.</para>
+        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have 
+        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
+        /// </remarks>
+        public static ILRetArray< fcomplex > sort (ILInArray< fcomplex > A, int dim, bool descending) {
+            if (object.Equals (A,null)) 
+                throw new Exception("parameter A must not be null");
+            using (ILScope.Enter(A)) {
+                if (dim < 0) // || dim >= A.Dimensions.NumberOfDimensions)
+                    throw new ILArgumentException("invalid dimension argument");
+                if (dim >= A.Size.NumberOfDimensions)
+                    return A.C;
+                // early exit: scalar/ empty
+                if (A.IsEmpty || A.IsScalar)
+                    return A.C;
+                ILArray< fcomplex> ret = A.C; // new ILArray<double>(new Storage.ILDenseStorage<double>(ILMemoryPool.Pool.New<double>(A.Dimensions.NumberOfElements), A.Dimensions));
+                int inc = ret.Size.SequentialIndexDistance(dim);
+                int dimLen = A.Size[dim];
+                int maxRuns = A.Size.NumberOfElements / dimLen;
+                int posInArr = 0;
+                if (descending) {
+                    if (maxRuns == 1) {
+                        ILQuickSort.QuickSortDescMT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
+                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
+                       
+                        fcomplex[] retArr = ret.GetArrayForWrite();
+                        System.Threading.Tasks.Parallel.For(0, maxRuns,
+                            (c) => {
+                                int pos = (int)(((long)dimLen * c * inc) % (A.Size.NumberOfElements - 1));
+                                ILQuickSort.QuickSortDescST(retArr, pos, pos + (dimLen - 1) * inc, inc);
+                            });
+                    } else {
+                       
+					    fcomplex[] retArr = ret.GetArrayForWrite();
+                        for (int c = 0; c < maxRuns; c++) {
+                            if (posInArr >= A.Size.NumberOfElements)
+                                posInArr -= (A.Size.NumberOfElements - 1);
+                            ILQuickSort.QuickSortDescST(retArr, posInArr, posInArr + (dimLen - 1) * inc, inc);
+                            posInArr += dimLen * inc;
+                        }
+                    }
+                } else {
+                    // ascending
+                    if (maxRuns == 1) {
+                        ILQuickSort.QuickSortAscMT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
+                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
+                        
+                        fcomplex[] retArr = ret.GetArrayForWrite();
+                        System.Threading.Tasks.Parallel.For(0, maxRuns,
+                            (c) => {
+                                int pos = (dimLen * c * inc) % (A.Size.NumberOfElements - 1);
+                                ILQuickSort.QuickSortAscST(retArr, pos, pos + (dimLen - 1) * inc, inc);
+                            });
+                    } else {
+                       
+                        fcomplex[] retArr = ret.GetArrayForWrite();
+                        for (int c = 0; c < maxRuns; c++) {
+                            if (posInArr >= A.Size.NumberOfElements)
+                                posInArr -= (A.Size.NumberOfElements - 1);
+                            ILQuickSort.QuickSortAscST(retArr, posInArr, posInArr + (dimLen - 1) * inc, inc);
+                            posInArr += dimLen * inc;
+                        }
+                    }
+                }
+                //if (descending) {
+                //    for (int c = 0; c < maxRuns; c++) {
+                //        if (posInArr >= A.Dimensions.NumberOfElements)
+                //            posInArr -= (A.Dimensions.NumberOfElements - 1);
+                //        ILQuickSort.QuickSortDescSolid_IT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc, false);
+                //        posInArr += dimLen * inc;
+                //    }
+                //} else {
+                //    // ascending
+                //    for (int c = 0; c < maxRuns; c++) {
+                //        if (posInArr >= A.Dimensions.NumberOfElements)
+                //            posInArr -= (A.Dimensions.NumberOfElements - 1);
+                //        ILQuickSort.QuickSortAscSolid_IT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc, false);
+                //        posInArr += dimLen * inc;
+                //    }
+                //}
+                return ret;
+            }
+        }
+        /// <summary>
+        /// Sort data in A along dimension 'dim'
+        /// </summary>
+        /// <param name="A">Input array, n-dimensional</param>
+        /// <param name="descending">Direction of sorting</param>
+        /// <param name="dim">Dimension index to sort along</param>
+        /// <param name="Indices">[Output] Returns permutation matrix</param>
+        /// <returns>Sorted array of the same size as A</returns>
+        /// <remarks>The data in A will be sorted along the dimension <paramref name="dim"/> using a non-recursive quicksort 
+        /// algorithm.  
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>Properties of sorting can be tuned by the settings of <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/> 
+        /// and <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/>.</para>
+        /// <para>This overload also returns an array 'Indices' which will hold the indices into the original 
+        /// elements <b>after sorting</b>. Elements of 'Indices' are of type double.</para>
+        /// <example><code>ILArray&lt;double&gt; A = ILMath.rand(1,5); 
+        /// //A: 
+        /// // 0.4324  0.9231  0.1231  0.1423  0.2991
+        /// ILArray&lt;double&gt; I; 
+        /// ILArray&lt;double&gt; R = ILMath.sort(A, out I, 1, false);
+        /// //R: 
+        /// // 0.1231  0.1423  0.2991  0.4324  0.9231  
+        /// //I: 
+        /// // 2  3  4  0  1
+        /// </code>
+        /// </example>
+        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have 
+        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
+        /// </remarks>
+        public static ILRetArray< fcomplex> sort( ILInArray< fcomplex> A, ILOutArray<double> Indices = null, int dim = -1, bool descending = false ) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A, null))
+                    throw new Exception("parameter A must not be null");
+                if (object.Equals(Indices, null)) {
+                    return sort(A,dim,descending); 
+                }
+                if (dim >= A.Size.NumberOfDimensions)
+                    throw new ILArgumentException("invalid dimension argument");
+                // early exit: scalar/ empty
+                if (A.IsEmpty) {
+                    Indices.a = empty<double>(ILSize.Empty00);
+                    return empty< fcomplex>(ILSize.Empty00);
+                }
+                if (A.IsScalar) {
+                    Indices.a = 0;
+                    return A.C;
+                }
+                if (dim < 0) {
+                    dim = A.S.WorkingDimension(); 
+                }
+                int[] tmpDims = A.Size.ToIntArray();
+                for (int i = 0; i < A.Size.NumberOfDimensions; i++) {
+                    if (i == dim)
+                        tmpDims[i] = A.Size[dim];
+                    else
+                        tmpDims[i] = 1;
+                }
+                //if (Indices.IsEmpty || !Indices.D.IsSameSize(A.D)) {
+                Indices.a = reshape(counter(0.0, 1.0, 1, A.Size[dim]), tmpDims);
+                tmpDims = A.Size.ToIntArray();
+                tmpDims[dim] = 1;
+                Indices.a = repmat(Indices, tmpDims);
+                //}
+                ILArray<fcomplex> ret = A.C;
+                int inc = ret.Size.SequentialIndexDistance(dim);
+                int dimLen = A.Size[dim];
+                int maxRuns = A.Size.NumberOfElements / dimLen;
+                int posInArr = 0;
+                if (descending) {
+                    if (maxRuns == 1) {
+                        ILQuickSort.QuickSortDescIDXMT(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
+                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
+                       fcomplex [] retArr = ret.GetArrayForWrite(); 
+                        double[] indArr = Indices.GetArrayForRead(); 
+                        System.Threading.Tasks.Parallel.For(0, maxRuns,
+                            (c) => {
+                                int pos = (dimLen * c * inc) % (A.Size.NumberOfElements-1);
+                                ILQuickSort.QuickSortDescIDXST(retArr, indArr, pos, pos + (dimLen - 1) * inc, inc);
+                        }); 
+                    } else {
+                        for (int c = 0; c < maxRuns; c++) {
+                            if (posInArr >= A.Size.NumberOfElements)
+                                posInArr -= (A.Size.NumberOfElements - 1);
+                            ILQuickSort.QuickSortDescIDXST(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
+                            posInArr += dimLen * inc;
+                        }
+                    }
+                } else {
+                    // ascending
+                    if (maxRuns == 1) {
+                        ILQuickSort.QuickSortAscIDXMT(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
+                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
+                       
+                        fcomplex[] retArr = ret.GetArrayForWrite();
+                        double[] indArr = Indices.GetArrayForRead();
+                        System.Threading.Tasks.Parallel.For(0, maxRuns,
+                            (c) => {
+                                int pos = (dimLen * c * inc) % (A.Size.NumberOfElements - 1);
+                                ILQuickSort.QuickSortAscIDXST(retArr, indArr, pos, pos + (dimLen - 1) * inc, inc);
+                            });
+                    } else {
+                        for (int c = 0; c < maxRuns; c++) {
+                            if (posInArr >= A.Size.NumberOfElements)
+                                posInArr -= (A.Size.NumberOfElements - 1);
+                            ILQuickSort.QuickSortAscIDXST(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
+                            posInArr += dimLen * inc;
+                        }
+                    }
+                }
+                return ret;
+            }
+        }
+        /// <summary>
+        /// Sort data in A along first non singleton dimension
+        /// </summary>
+        /// <param name="A">Input array, n-dimensional</param>
+        /// <returns>Sorted array of the same size as A</returns>
+        /// <remarks>The data in A will be sorted in ascending order using a non-recursive quick sort algorithm. 
+        /// Elements along the columns of A will get sorted independently from each other. A is not altered.
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have 
+        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
+        /// </remarks>
+        public static ILRetArray< complex > sort (ILInArray< complex > A) {
+            using (ILScope.Enter(A)) {
+                int fnsd = A.Size.WorkingDimension();
+                if (fnsd < 0) return A.C;
+                return sort(A, fnsd, false);
+            }
+        }
+        /// <summary>
+        /// Sort data in A along first non singleton dimension
+        /// </summary>
+        /// <param name="A">Input array, n-dimensional</param>
+        /// <param name="descending">Determine the direction of sorting (ascending/ descending)</param>
+        /// <returns>Sorted array of the same size as A</returns>
+        /// <remarks>The data in A will be sorted using the quick sort algorithm. Data 
+        /// along the first non singleton dimension will get sorted independently from data 
+        /// in the next row/column.
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have 
+        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
+        /// </remarks>
+        public static ILRetArray< complex > sort (ILInArray< complex > A, bool descending) {
+            using (ILScope.Enter(A)) {
+                int fnsd = A.Size.WorkingDimension();
+                if (fnsd < 0) return A.C;
+                return sort(A, fnsd, descending);
+            }
+        }
+        /// <summary>
+        /// Sort data in A along dimension 'dim'
+        /// </summary>
+        /// <param name="A">Input array, n-dimensional</param>
+        /// <param name="descending">Direction of sorting</param>
+        /// <param name="dim">Dimension index to sort along</param>
+        /// <returns>Sorted array of the same size as A</returns>
+        /// <remarks>The data in A will be sorted along the dimension <paramref name="dim"/> using a non-recursive quicksort 
+        /// algorithm.  
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>Properties of sorting can be tuned by the settings of <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/> 
+        /// and <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/>.</para>
+        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have 
+        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
+        /// </remarks>
+        public static ILRetArray< complex > sort (ILInArray< complex > A, int dim, bool descending) {
+            if (object.Equals (A,null)) 
+                throw new Exception("parameter A must not be null");
+            using (ILScope.Enter(A)) {
+                if (dim < 0) // || dim >= A.Dimensions.NumberOfDimensions)
+                    throw new ILArgumentException("invalid dimension argument");
+                if (dim >= A.Size.NumberOfDimensions)
+                    return A.C;
+                // early exit: scalar/ empty
+                if (A.IsEmpty || A.IsScalar)
+                    return A.C;
+                ILArray< complex> ret = A.C; // new ILArray<double>(new Storage.ILDenseStorage<double>(ILMemoryPool.Pool.New<double>(A.Dimensions.NumberOfElements), A.Dimensions));
+                int inc = ret.Size.SequentialIndexDistance(dim);
+                int dimLen = A.Size[dim];
+                int maxRuns = A.Size.NumberOfElements / dimLen;
+                int posInArr = 0;
+                if (descending) {
+                    if (maxRuns == 1) {
+                        ILQuickSort.QuickSortDescMT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
+                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
+                       
+                        complex[] retArr = ret.GetArrayForWrite();
+                        System.Threading.Tasks.Parallel.For(0, maxRuns,
+                            (c) => {
+                                int pos = (int)(((long)dimLen * c * inc) % (A.Size.NumberOfElements - 1));
+                                ILQuickSort.QuickSortDescST(retArr, pos, pos + (dimLen - 1) * inc, inc);
+                            });
+                    } else {
+                       
+					    complex[] retArr = ret.GetArrayForWrite();
+                        for (int c = 0; c < maxRuns; c++) {
+                            if (posInArr >= A.Size.NumberOfElements)
+                                posInArr -= (A.Size.NumberOfElements - 1);
+                            ILQuickSort.QuickSortDescST(retArr, posInArr, posInArr + (dimLen - 1) * inc, inc);
+                            posInArr += dimLen * inc;
+                        }
+                    }
+                } else {
+                    // ascending
+                    if (maxRuns == 1) {
+                        ILQuickSort.QuickSortAscMT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
+                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
+                        
+                        complex[] retArr = ret.GetArrayForWrite();
+                        System.Threading.Tasks.Parallel.For(0, maxRuns,
+                            (c) => {
+                                int pos = (dimLen * c * inc) % (A.Size.NumberOfElements - 1);
+                                ILQuickSort.QuickSortAscST(retArr, pos, pos + (dimLen - 1) * inc, inc);
+                            });
+                    } else {
+                       
+                        complex[] retArr = ret.GetArrayForWrite();
+                        for (int c = 0; c < maxRuns; c++) {
+                            if (posInArr >= A.Size.NumberOfElements)
+                                posInArr -= (A.Size.NumberOfElements - 1);
+                            ILQuickSort.QuickSortAscST(retArr, posInArr, posInArr + (dimLen - 1) * inc, inc);
+                            posInArr += dimLen * inc;
+                        }
+                    }
+                }
+                //if (descending) {
+                //    for (int c = 0; c < maxRuns; c++) {
+                //        if (posInArr >= A.Dimensions.NumberOfElements)
+                //            posInArr -= (A.Dimensions.NumberOfElements - 1);
+                //        ILQuickSort.QuickSortDescSolid_IT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc, false);
+                //        posInArr += dimLen * inc;
+                //    }
+                //} else {
+                //    // ascending
+                //    for (int c = 0; c < maxRuns; c++) {
+                //        if (posInArr >= A.Dimensions.NumberOfElements)
+                //            posInArr -= (A.Dimensions.NumberOfElements - 1);
+                //        ILQuickSort.QuickSortAscSolid_IT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc, false);
+                //        posInArr += dimLen * inc;
+                //    }
+                //}
+                return ret;
+            }
+        }
+        /// <summary>
+        /// Sort data in A along dimension 'dim'
+        /// </summary>
+        /// <param name="A">Input array, n-dimensional</param>
+        /// <param name="descending">Direction of sorting</param>
+        /// <param name="dim">Dimension index to sort along</param>
+        /// <param name="Indices">[Output] Returns permutation matrix</param>
+        /// <returns>Sorted array of the same size as A</returns>
+        /// <remarks>The data in A will be sorted along the dimension <paramref name="dim"/> using a non-recursive quicksort 
+        /// algorithm.  
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>Properties of sorting can be tuned by the settings of <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/> 
+        /// and <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/>.</para>
+        /// <para>This overload also returns an array 'Indices' which will hold the indices into the original 
+        /// elements <b>after sorting</b>. Elements of 'Indices' are of type double.</para>
+        /// <example><code>ILArray&lt;double&gt; A = ILMath.rand(1,5); 
+        /// //A: 
+        /// // 0.4324  0.9231  0.1231  0.1423  0.2991
+        /// ILArray&lt;double&gt; I; 
+        /// ILArray&lt;double&gt; R = ILMath.sort(A, out I, 1, false);
+        /// //R: 
+        /// // 0.1231  0.1423  0.2991  0.4324  0.9231  
+        /// //I: 
+        /// // 2  3  4  0  1
+        /// </code>
+        /// </example>
+        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have 
+        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
+        /// </remarks>
+        public static ILRetArray< complex> sort( ILInArray< complex> A, ILOutArray<double> Indices = null, int dim = -1, bool descending = false ) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A, null))
+                    throw new Exception("parameter A must not be null");
+                if (object.Equals(Indices, null)) {
+                    return sort(A,dim,descending); 
+                }
+                if (dim >= A.Size.NumberOfDimensions)
+                    throw new ILArgumentException("invalid dimension argument");
+                // early exit: scalar/ empty
+                if (A.IsEmpty) {
+                    Indices.a = empty<double>(ILSize.Empty00);
+                    return empty< complex>(ILSize.Empty00);
+                }
+                if (A.IsScalar) {
+                    Indices.a = 0;
+                    return A.C;
+                }
+                if (dim < 0) {
+                    dim = A.S.WorkingDimension(); 
+                }
+                int[] tmpDims = A.Size.ToIntArray();
+                for (int i = 0; i < A.Size.NumberOfDimensions; i++) {
+                    if (i == dim)
+                        tmpDims[i] = A.Size[dim];
+                    else
+                        tmpDims[i] = 1;
+                }
+                //if (Indices.IsEmpty || !Indices.D.IsSameSize(A.D)) {
+                Indices.a = reshape(counter(0.0, 1.0, 1, A.Size[dim]), tmpDims);
+                tmpDims = A.Size.ToIntArray();
+                tmpDims[dim] = 1;
+                Indices.a = repmat(Indices, tmpDims);
+                //}
+                ILArray<complex> ret = A.C;
+                int inc = ret.Size.SequentialIndexDistance(dim);
+                int dimLen = A.Size[dim];
+                int maxRuns = A.Size.NumberOfElements / dimLen;
+                int posInArr = 0;
+                if (descending) {
+                    if (maxRuns == 1) {
+                        ILQuickSort.QuickSortDescIDXMT(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
+                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
+                       complex [] retArr = ret.GetArrayForWrite(); 
+                        double[] indArr = Indices.GetArrayForRead(); 
+                        System.Threading.Tasks.Parallel.For(0, maxRuns,
+                            (c) => {
+                                int pos = (dimLen * c * inc) % (A.Size.NumberOfElements-1);
+                                ILQuickSort.QuickSortDescIDXST(retArr, indArr, pos, pos + (dimLen - 1) * inc, inc);
+                        }); 
+                    } else {
+                        for (int c = 0; c < maxRuns; c++) {
+                            if (posInArr >= A.Size.NumberOfElements)
+                                posInArr -= (A.Size.NumberOfElements - 1);
+                            ILQuickSort.QuickSortDescIDXST(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
+                            posInArr += dimLen * inc;
+                        }
+                    }
+                } else {
+                    // ascending
+                    if (maxRuns == 1) {
+                        ILQuickSort.QuickSortAscIDXMT(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
+                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
+                       
+                        complex[] retArr = ret.GetArrayForWrite();
+                        double[] indArr = Indices.GetArrayForRead();
+                        System.Threading.Tasks.Parallel.For(0, maxRuns,
+                            (c) => {
+                                int pos = (dimLen * c * inc) % (A.Size.NumberOfElements - 1);
+                                ILQuickSort.QuickSortAscIDXST(retArr, indArr, pos, pos + (dimLen - 1) * inc, inc);
+                            });
+                    } else {
+                        for (int c = 0; c < maxRuns; c++) {
+                            if (posInArr >= A.Size.NumberOfElements)
+                                posInArr -= (A.Size.NumberOfElements - 1);
+                            ILQuickSort.QuickSortAscIDXST(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
+                            posInArr += dimLen * inc;
+                        }
+                    }
+                }
+                return ret;
+            }
+        }
+        /// <summary>
+        /// Sort data in A along first non singleton dimension
+        /// </summary>
+        /// <param name="A">Input array, n-dimensional</param>
+        /// <returns>Sorted array of the same size as A</returns>
+        /// <remarks>The data in A will be sorted in ascending order using a non-recursive quick sort algorithm. 
+        /// Elements along the columns of A will get sorted independently from each other. A is not altered.
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have 
+        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
+        /// </remarks>
+        public static ILRetArray< byte > sort (ILInArray< byte > A) {
+            using (ILScope.Enter(A)) {
+                int fnsd = A.Size.WorkingDimension();
+                if (fnsd < 0) return A.C;
+                return sort(A, fnsd, false);
+            }
+        }
+        /// <summary>
+        /// Sort data in A along first non singleton dimension
+        /// </summary>
+        /// <param name="A">Input array, n-dimensional</param>
+        /// <param name="descending">Determine the direction of sorting (ascending/ descending)</param>
+        /// <returns>Sorted array of the same size as A</returns>
+        /// <remarks>The data in A will be sorted using the quick sort algorithm. Data 
+        /// along the first non singleton dimension will get sorted independently from data 
+        /// in the next row/column.
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have 
+        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
+        /// </remarks>
+        public static ILRetArray< byte > sort (ILInArray< byte > A, bool descending) {
+            using (ILScope.Enter(A)) {
+                int fnsd = A.Size.WorkingDimension();
+                if (fnsd < 0) return A.C;
+                return sort(A, fnsd, descending);
+            }
+        }
+        /// <summary>
+        /// Sort data in A along dimension 'dim'
+        /// </summary>
+        /// <param name="A">Input array, n-dimensional</param>
+        /// <param name="descending">Direction of sorting</param>
+        /// <param name="dim">Dimension index to sort along</param>
+        /// <returns>Sorted array of the same size as A</returns>
+        /// <remarks>The data in A will be sorted along the dimension <paramref name="dim"/> using a non-recursive quicksort 
+        /// algorithm.  
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>Properties of sorting can be tuned by the settings of <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/> 
+        /// and <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/>.</para>
+        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have 
+        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
+        /// </remarks>
+        public static ILRetArray< byte > sort (ILInArray< byte > A, int dim, bool descending) {
+            if (object.Equals (A,null)) 
+                throw new Exception("parameter A must not be null");
+            using (ILScope.Enter(A)) {
+                if (dim < 0) // || dim >= A.Dimensions.NumberOfDimensions)
+                    throw new ILArgumentException("invalid dimension argument");
+                if (dim >= A.Size.NumberOfDimensions)
+                    return A.C;
+                // early exit: scalar/ empty
+                if (A.IsEmpty || A.IsScalar)
+                    return A.C;
+                ILArray< byte> ret = A.C; // new ILArray<double>(new Storage.ILDenseStorage<double>(ILMemoryPool.Pool.New<double>(A.Dimensions.NumberOfElements), A.Dimensions));
+                int inc = ret.Size.SequentialIndexDistance(dim);
+                int dimLen = A.Size[dim];
+                int maxRuns = A.Size.NumberOfElements / dimLen;
+                int posInArr = 0;
+                if (descending) {
+                    if (maxRuns == 1) {
+                        ILQuickSort.QuickSortDescMT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
+                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
+                       
+                        byte[] retArr = ret.GetArrayForWrite();
+                        System.Threading.Tasks.Parallel.For(0, maxRuns,
+                            (c) => {
+                                int pos = (int)(((long)dimLen * c * inc) % (A.Size.NumberOfElements - 1));
+                                ILQuickSort.QuickSortDescST(retArr, pos, pos + (dimLen - 1) * inc, inc);
+                            });
+                    } else {
+                       
+					    byte[] retArr = ret.GetArrayForWrite();
+                        for (int c = 0; c < maxRuns; c++) {
+                            if (posInArr >= A.Size.NumberOfElements)
+                                posInArr -= (A.Size.NumberOfElements - 1);
+                            ILQuickSort.QuickSortDescST(retArr, posInArr, posInArr + (dimLen - 1) * inc, inc);
+                            posInArr += dimLen * inc;
+                        }
+                    }
+                } else {
+                    // ascending
+                    if (maxRuns == 1) {
+                        ILQuickSort.QuickSortAscMT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
+                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
+                        
+                        byte[] retArr = ret.GetArrayForWrite();
+                        System.Threading.Tasks.Parallel.For(0, maxRuns,
+                            (c) => {
+                                int pos = (dimLen * c * inc) % (A.Size.NumberOfElements - 1);
+                                ILQuickSort.QuickSortAscST(retArr, pos, pos + (dimLen - 1) * inc, inc);
+                            });
+                    } else {
+                       
+                        byte[] retArr = ret.GetArrayForWrite();
+                        for (int c = 0; c < maxRuns; c++) {
+                            if (posInArr >= A.Size.NumberOfElements)
+                                posInArr -= (A.Size.NumberOfElements - 1);
+                            ILQuickSort.QuickSortAscST(retArr, posInArr, posInArr + (dimLen - 1) * inc, inc);
+                            posInArr += dimLen * inc;
+                        }
+                    }
+                }
+                //if (descending) {
+                //    for (int c = 0; c < maxRuns; c++) {
+                //        if (posInArr >= A.Dimensions.NumberOfElements)
+                //            posInArr -= (A.Dimensions.NumberOfElements - 1);
+                //        ILQuickSort.QuickSortDescSolid_IT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc, false);
+                //        posInArr += dimLen * inc;
+                //    }
+                //} else {
+                //    // ascending
+                //    for (int c = 0; c < maxRuns; c++) {
+                //        if (posInArr >= A.Dimensions.NumberOfElements)
+                //            posInArr -= (A.Dimensions.NumberOfElements - 1);
+                //        ILQuickSort.QuickSortAscSolid_IT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc, false);
+                //        posInArr += dimLen * inc;
+                //    }
+                //}
+                return ret;
+            }
+        }
+        /// <summary>
+        /// Sort data in A along dimension 'dim'
+        /// </summary>
+        /// <param name="A">Input array, n-dimensional</param>
+        /// <param name="descending">Direction of sorting</param>
+        /// <param name="dim">Dimension index to sort along</param>
+        /// <param name="Indices">[Output] Returns permutation matrix</param>
+        /// <returns>Sorted array of the same size as A</returns>
+        /// <remarks>The data in A will be sorted along the dimension <paramref name="dim"/> using a non-recursive quicksort 
+        /// algorithm.  
+        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b> 
+        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
+        /// <para>Properties of sorting can be tuned by the settings of <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/> 
+        /// and <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/>.</para>
+        /// <para>This overload also returns an array 'Indices' which will hold the indices into the original 
+        /// elements <b>after sorting</b>. Elements of 'Indices' are of type double.</para>
+        /// <example><code>ILArray&lt;double&gt; A = ILMath.rand(1,5); 
+        /// //A: 
+        /// // 0.4324  0.9231  0.1231  0.1423  0.2991
+        /// ILArray&lt;double&gt; I; 
+        /// ILArray&lt;double&gt; R = ILMath.sort(A, out I, 1, false);
+        /// //R: 
+        /// // 0.1231  0.1423  0.2991  0.4324  0.9231  
+        /// //I: 
+        /// // 2  3  4  0  1
+        /// </code>
+        /// </example>
+        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have 
+        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
+        /// </remarks>
+        public static ILRetArray< byte> sort( ILInArray< byte> A, ILOutArray<double> Indices = null, int dim = -1, bool descending = false ) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A, null))
+                    throw new Exception("parameter A must not be null");
+                if (object.Equals(Indices, null)) {
+                    return sort(A,dim,descending); 
+                }
+                if (dim >= A.Size.NumberOfDimensions)
+                    throw new ILArgumentException("invalid dimension argument");
+                // early exit: scalar/ empty
+                if (A.IsEmpty) {
+                    Indices.a = empty<double>(ILSize.Empty00);
+                    return empty< byte>(ILSize.Empty00);
+                }
+                if (A.IsScalar) {
+                    Indices.a = 0;
+                    return A.C;
+                }
+                if (dim < 0) {
+                    dim = A.S.WorkingDimension(); 
+                }
+                int[] tmpDims = A.Size.ToIntArray();
+                for (int i = 0; i < A.Size.NumberOfDimensions; i++) {
+                    if (i == dim)
+                        tmpDims[i] = A.Size[dim];
+                    else
+                        tmpDims[i] = 1;
+                }
+                //if (Indices.IsEmpty || !Indices.D.IsSameSize(A.D)) {
+                Indices.a = reshape(counter(0.0, 1.0, 1, A.Size[dim]), tmpDims);
+                tmpDims = A.Size.ToIntArray();
+                tmpDims[dim] = 1;
+                Indices.a = repmat(Indices, tmpDims);
+                //}
+                ILArray<byte> ret = A.C;
+                int inc = ret.Size.SequentialIndexDistance(dim);
+                int dimLen = A.Size[dim];
+                int maxRuns = A.Size.NumberOfElements / dimLen;
+                int posInArr = 0;
+                if (descending) {
+                    if (maxRuns == 1) {
+                        ILQuickSort.QuickSortDescIDXMT(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
+                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
+                       byte [] retArr = ret.GetArrayForWrite(); 
+                        double[] indArr = Indices.GetArrayForRead(); 
+                        System.Threading.Tasks.Parallel.For(0, maxRuns,
+                            (c) => {
+                                int pos = (dimLen * c * inc) % (A.Size.NumberOfElements-1);
+                                ILQuickSort.QuickSortDescIDXST(retArr, indArr, pos, pos + (dimLen - 1) * inc, inc);
+                        }); 
+                    } else {
+                        for (int c = 0; c < maxRuns; c++) {
+                            if (posInArr >= A.Size.NumberOfElements)
+                                posInArr -= (A.Size.NumberOfElements - 1);
+                            ILQuickSort.QuickSortDescIDXST(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
+                            posInArr += dimLen * inc;
+                        }
+                    }
+                } else {
+                    // ascending
+                    if (maxRuns == 1) {
+                        ILQuickSort.QuickSortAscIDXMT(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
+                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
+                       
+                        byte[] retArr = ret.GetArrayForWrite();
+                        double[] indArr = Indices.GetArrayForRead();
+                        System.Threading.Tasks.Parallel.For(0, maxRuns,
+                            (c) => {
+                                int pos = (dimLen * c * inc) % (A.Size.NumberOfElements - 1);
+                                ILQuickSort.QuickSortAscIDXST(retArr, indArr, pos, pos + (dimLen - 1) * inc, inc);
+                            });
+                    } else {
+                        for (int c = 0; c < maxRuns; c++) {
+                            if (posInArr >= A.Size.NumberOfElements)
+                                posInArr -= (A.Size.NumberOfElements - 1);
+                            ILQuickSort.QuickSortAscIDXST(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
+                            posInArr += dimLen * inc;
+                        }
+                    }
+                }
+                return ret;
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+#region bucket sort - string
+        /// <summary>
+        /// Sort strings in A along first non singleton dimension ascending
+        /// </summary>
+        /// <param name="A">Input array. A may be an empty, scalar, vector or matrix.</param>
+        /// <returns>Sorted array of the same size/shape as A</returns>
+        /// <remarks><para>The strings in A will be sorted lexicographically in ascending order using the bucket sort algorithm. Data 
+        /// along the first non singleton dimension will get sorted independently from data 
+        /// in the other rows/columns.</para>
+        /// <para>The sorting order of strings is determined char-wise by comparing the ASCII codes of the characters.</para></remarks>
+        public static ILRetArray<string> sort (ILInArray<string> A) {
+            using (ILScope.Enter(A)) {
+                int fnsd = A.Size.WorkingDimension();
+                if (fnsd < 0) return A.C;
+                return sort(A, fnsd, false);
+            }
+        }
+        /// <summary>
+        /// Sort strings in A along first non singleton dimension
+        /// </summary>
+        /// <param name="A">Input array. A may be an empty, scalar, vector or matrix.</param>
+        /// <param name="descending">Specifies the direction of sorting: true: descending sort direction; false: ascending</param>
+        /// <returns>Sorted array of the same size/shape as A</returns>
+        /// <remarks><para>The strings in A will be sorted lexicographically in ascending order using the bucket sort algorithm. Data 
+        /// along the first non singleton dimension will get sorted independently from data 
+        /// in the other rows/columns.</para>
+        /// <para>The sorting order of strings is determined char-wise by comparing the ASCII codes of the characters.</para></remarks>
+        public static ILRetArray<string> sort (ILInArray<string> A, bool descending) {
+            using (ILScope.Enter(A)) {
+                int fnsd = A.Size.WorkingDimension();
+                if (fnsd < 0) return A.C;
+                return sort(A, fnsd, descending);
+            }
+        }
+        /// <summary>
+        /// Sort strings in A along dimension 'dim'
+        /// </summary>
+        /// <param name="A">Input array. A may be an empty, scalar, vector or matrix.</param>
+        /// <param name="dim">Dimension to sort along</param>
+        /// <param name="descending">Specifies the direction of sorting: true: descending sort direction; false: ascending</param>
+        /// <returns>Sorted array of the same size/shape as A</returns>
+        /// <remarks><para>The strings in A will be sorted lexicographically in ascending order using the bucket sort algorithm. Data 
+        /// along the first non singleton dimension will get sorted independently from data 
+        /// in the other rows/columns.</para>
+        /// <para>The sorting order of strings is determined char-wise by comparing the ASCII codes of the characters.</para></remarks>
+        public static ILRetArray<string> sort (ILInArray<string> A, int dim, bool descending) {
+            if (object.Equals (A,null)) 
+                throw new Exception("parameter A must not be null");
+            using (ILScope.Enter(A)) {
+                if (A.Size.NumberOfDimensions > 2)
+                    throw new ILArgumentException("for element type string only matrices are supported!");
+                if (dim < 0 || dim >= A.Size.NumberOfDimensions)
+                    throw new ILArgumentException("invalid dimension argument");
+                // early exit: scalar/ empty
+                if (A.IsEmpty || A.IsScalar)
+                    return A.C;
+                ILArray<string> ret =zeros<string>(A.Size);
+                int dim1 = dim % A.Size.NumberOfDimensions;
+                int dim2 = (dim1 + 1) % A.Size.NumberOfDimensions;
+                int maxRuns = A.Size[dim2];
+                ILQueueList<string, byte> ql;
+                ILArray<int>[] ind = new ILArray<int>[2];
+                int[] indI = new int[2];
+                ILASCIIKeyMapper km = new ILASCIIKeyMapper();
+                for (int c = 0; c < maxRuns; c++) {
+                    ind[dim2] = c;
+                    ind[dim1] = null;
+                    ql = ILBucketSort.BucketSort<string, char, byte>(A[ind], null, km, ILBucketSort.SortMethod.ConstantLength);
+                    indI[dim2] = c;
+                    if (descending) {
+                        for (int i = ql.Count; i-- > 0; ) {
+                            indI[dim1] = i;
+                            ret.SetValue(ql.Dequeue().Data, indI);
+                        }
+                    } else {
+                        for (int i = 0; ql.Count > 0; i++) {
+                            indI[dim1] = i;
+                            ret.SetValue(ql.Dequeue().Data, indI);
+                        }
+                    }
+                }
+                return ret;
+            }
+        }
+        /// <summary>
+        /// Sort data in A along dimension 'dim'
+        /// </summary>
+        /// <param name="A">Input array: empty, scalar, vector or matrix</param>
+        /// <param name="descending">Specifies the direction of sorting</param>
+        /// <param name="dim">Dimension to sort along</param>
+        /// <param name="Indices">[Output] Returns permutation matrix also</param>
+        /// <returns>Sorted array of the same size as A</returns>
+        /// <remarks><para>The data in A will be sorted using the quick sort algorithm. Data 
+        /// along the dimension <paramref name="dim"/> will get sorted independently from data 
+        /// in the next row/column.</para>
+        /// <para>This overload also returns an array 'Indices' which will hold the indices into the original 
+        /// elements <b>after sorting</b>. Elements of 'Indices' are of type double.</para>
+        ///</remarks>
+        public static ILRetArray<string> sort (ILInArray<string> A, ILOutArray<double> Indices, int dim, bool descending) {
+            if (object.Equals (A,null)) 
+                throw new Exception("parameter A must not be null");
+            using (ILScope.Enter(A)) {
+                if (A.Size.NumberOfDimensions > 2)
+                    throw new ILArgumentException("for element type string only matrices are supported!");
+                if (dim < 0 || dim >= A.Size.NumberOfDimensions)
+                    throw new ILArgumentException("invalid dimension argument");
+                // early exit: scalar/ empty
+                if (A.IsEmpty || A.IsScalar) {
+                    Indices.a = 0.0;
+                    return A.C;
+                }
+                ILArray<string> ret = zeros<string>(A.Size);
+                int dim1 = dim % A.Size.NumberOfDimensions;
+                int dim2 = (dim1 + 1) % A.Size.NumberOfDimensions;
+                int maxRuns = A.Size[dim2];
+                ILQueueList<string, double> ql;
+                ILBaseArray[] ind = new ILBaseArray[2];
+                int[] indI = new int[2];
+                ILASCIIKeyMapper km = new ILASCIIKeyMapper();
+                Indices.a = ILMath.counter<double>(0.0, 1.0, A.Size);
+                for (int c = 0; c < maxRuns; c++) {
+                    ind[dim2] = (ILArray<int>)c;
+                    ind[dim1] = ILMath.full;
+                    ql = ILBucketSort.BucketSort<string, char, double>(A[ind], Indices[ind], km, ILBucketSort.SortMethod.ConstantLength);
+                    indI[dim2] = c;
+                    if (descending) {
+                        for (int i = ql.Count; i-- > 0; ) {
+                            indI[dim1] = i;
+                            ILListItem<string, double> item = ql.Dequeue();
+                            ret.SetValue(item.Data, indI);
+                            Indices.SetValue(item.m_index, indI);
+                        }
+                    } else {
+                        for (int i = 0; ql.Count > 0; i++) {
+                            indI[dim1] = i;
+                            ILListItem<string, double> item = ql.Dequeue();
+                            ret.SetValue(item.Data, indI);
+                            Indices.SetValue(item.m_index, indI);
+                        }
+                    }
+                }
+                return ret;
+            }
+        }
+        /// <summary>
+        /// Generic sort algorithm in A along dimension 'dim' 
+        /// </summary>
+        /// <param name="A">Input array: empty, scalar, vector or matrix</param>
+        /// <param name="descending">Specifies the direction of sorting</param>
+        /// <param name="dim">Dimension to sort along</param>
+        /// <param name="Indices">[Input/Output] The values in Indices will be returned in the same sorted order as the elements 
+        /// in A. This can be used to derive a permutation matrix of the sorting process.</param>
+        /// <typeparam name="T">Element type of values of A</typeparam>
+        /// <typeparam name="S">Subelement type. For element type of string this would be 'char'</typeparam>
+        /// <typeparam name="I">Element type of indices</typeparam>
+        /// <param name="keymapper">Instancce of an object of type ILKeyMapper. This object must 
+        /// be derived from ILKeyMapper&lt;T,SubelementType&gt; and match the generic argument <typeparamref name="T"/>. It will be 
+        /// used to split single elements into its subelements and map their content into bucket numbers. For all 
+        /// reference types except those of type string you will have to write your own ILKeyMapper class for that purpose.</param>
+        /// <returns>Sorted array of the same size as A</returns>
+        /// <remarks><para>The data in A will be sorted using the quick sort algorithm. Data 
+        /// along the dimension <paramref name="dim"/> will therefore get sorted independently from data 
+        /// in the next row/column.</para>
+        /// <para>This overload also returns an array 'Indices' which will hold the indices into the original 
+        /// elements <b>after sorting</b>. Therefore, the unsorted indices must be provided by the user on entry. Indices must not be null.</para>
+        /// <para>This generic version is able to sort arbitrary element types. Even user defined reference types can be sorted 
+        /// by specifying a user defined ILKeyMapper class instance. Also the type of Indices may be arbitrarily choosen. In difference 
+        /// to the regular sort function overload, Indices must manually be given to the function on entry. Elements in 'Indices'
+        /// are sorted in the same order as the elements of A.</para>
+        /// <para>By using this overload you may use the same permutation matrix several times to reflect the 
+        /// manipulations done to A due multiple sort processes. The Indices given will directly be used for the sorting 
+        /// disregarding initial order.</para>
+        /// </remarks>
+        internal static ILRetArray<T> sort<T, S, I>( ILInArray<T> A, ILOutArray<I> Indices, int dim, bool descending, ILKeyMapper<T, S> keymapper ) {
+            if (object.Equals(A, null))
+                throw new Exception("parameter A must not be null");
+            if (object.Equals(Indices, null))
+                throw new Exception("parameter 'Indices' must not be null");
+            using (ILScope.Enter(A)) {
+                if (!A.IsMatrix)
+                    throw new ILArgumentException("for generic element type - only matrices are supported");
+                if (dim < 0 || dim >= A.Size.NumberOfDimensions)
+                    throw new ILArgumentException("invalid dimension argument");
+                if (keymapper == null)
+                    throw new ILArgumentException("the keymapper argument must not be null");
+                if (object.Equals(Indices, null) || !Indices.Size.IsSameSize(A.Size))
+                    throw new ILArgumentException("indices argument must have same size/shape as input A");
+                // early exit: scalar/ empty
+                if (A.IsEmpty || A.IsScalar) {
+                    Indices.a = default(I);
+                    return A.C;
+                }
+                ILArray<T> ret = zeros<T>(A.Size);
+                int dim1 = dim % A.Size.NumberOfDimensions;
+                int dim2 = (dim1 + 1) % A.Size.NumberOfDimensions;
+                int maxRuns = A.Size[dim2];
+                ILQueueList<T, I> ql;
+                ILBaseArray[] ind = new ILBaseArray[2];
+                int[] indI = new int[2];
+                for (int c = 0; c < maxRuns; c++) {
+                    ind[dim2] = (ILArray<int>)c;
+                    ind[dim1] = full;
+                    ql = ILBucketSort.BucketSort<T, S, I>(A[ind], Indices[ind], keymapper, ILBucketSort.SortMethod.ConstantLength);
+                    indI[dim2] = c;
+                    if (descending) {
+                        for (int i = ql.Count; i-- > 0; ) {
+                            indI[dim1] = i;
+                            ILListItem<T, I> item = ql.Dequeue();
+                            ret.SetValue(item.Data, indI);
+                            Indices.SetValue(item.m_index, indI);
+                        }
+                    } else {
+                        for (int i = 0; ql.Count > 0; i++) {
+                            indI[dim1] = i;
+                            ILListItem<T, I> item = ql.Dequeue();
+                            ret.SetValue(item.Data, indI);
+                            Indices.SetValue(item.m_index, indI);
+                        }
+                    }
+                }
+                return ret;
+            }
+        }
+#endregion 
+
+
+        internal static bool IsSorted (double[] vec,int length, bool descending) {
+            if (descending) {
+                for (int i = 1; i < length; i++) {
+                    if (vec[i] > vec[i-1])
+                        return false; 
+                }
+            } else {
+                for (int i = 1; i < length; i++) {
+                    if (vec[i] < vec[i-1])
+                        return false; 
+                }
+            }
+            return true;
+        }
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/sqrt.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/sqrt.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/sqrt.cs	(revision 9102)
@@ -0,0 +1,804 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics;
+using ILNumerics.Exceptions;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+
+
+namespace ILNumerics {
+    public partial class ILMath {
+
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>Square root of array elements - complex output</summary>
+        /// <param name="A">Input array - positive and negative values allowed</param>
+        /// <returns>Square root of elements of A - complex output</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<fcomplex>  sqrtc (ILInArray< float > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<fcomplex>(A.Size); 
+                ILSize inDim = A.Size;
+                float[] arrA = A.GetArrayForRead(); 
+                fcomplex [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (true) {
+                    retArr = ILMemoryPool.Pool.New<fcomplex>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<fcomplex> retStorage = new ILDenseStorage<fcomplex>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    fcomplex* cp = ((fcomplex*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  fcomplex.Sqrt(cp[0]  )  /*dummy*/;
+                            cp[1] =  fcomplex.Sqrt(cp[1]  )  /*dummy*/;
+                            cp[2] =  fcomplex.Sqrt(cp[2]  )  /*dummy*/;
+                            cp[3] =  fcomplex.Sqrt(cp[3]  )  /*dummy*/;
+                            cp[4] =  fcomplex.Sqrt(cp[4]  )  /*dummy*/;
+                            cp[5] =  fcomplex.Sqrt(cp[5]  )  /*dummy*/;
+                            cp[6] =  fcomplex.Sqrt(cp[6]  )  /*dummy*/;
+                            cp[7] =  fcomplex.Sqrt(cp[7]  )  /*dummy*/;
+                            cp[8] =  fcomplex.Sqrt(cp[8]  )  /*dummy*/;
+                            cp[9] =  fcomplex.Sqrt(cp[9]  )  /*dummy*/;
+                            cp[10] =  fcomplex.Sqrt(cp[10]  )  /*dummy*/;
+                            cp[11] =  fcomplex.Sqrt(cp[11]  )  /*dummy*/;
+                            cp[12] =  fcomplex.Sqrt(cp[12]  )  /*dummy*/;
+                            cp[13] =  fcomplex.Sqrt(cp[13]  )  /*dummy*/;
+                            cp[14] =  fcomplex.Sqrt(cp[14]  )  /*dummy*/;
+                            cp[15] =  fcomplex.Sqrt(cp[15]  )  /*dummy*/;
+                            cp[16] =  fcomplex.Sqrt(cp[16]  )  /*dummy*/;
+                            cp[17] =  fcomplex.Sqrt(cp[17]  )  /*dummy*/;
+                            cp[18] =  fcomplex.Sqrt(cp[18]  )  /*dummy*/;
+                            cp[19] =  fcomplex.Sqrt(cp[19]  )  /*dummy*/;
+                            cp[20] =  fcomplex.Sqrt(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.Sqrt(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        float* ap = ((float*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  fcomplex.Sqrt(ap[0]  )  /*dummy*/;
+                            cp[1] =  fcomplex.Sqrt(ap[1]  )  /*dummy*/;
+                            cp[2] =  fcomplex.Sqrt(ap[2]  )  /*dummy*/;
+                            cp[3] =  fcomplex.Sqrt(ap[3]  )  /*dummy*/;
+                            cp[4] =  fcomplex.Sqrt(ap[4]  )  /*dummy*/;
+                            cp[5] =  fcomplex.Sqrt(ap[5]  )  /*dummy*/;
+                            cp[6] =  fcomplex.Sqrt(ap[6]  )  /*dummy*/;
+                            cp[7] =  fcomplex.Sqrt(ap[7]  )  /*dummy*/;
+                            cp[8] =  fcomplex.Sqrt(ap[8]  )  /*dummy*/;
+                            cp[9] =  fcomplex.Sqrt(ap[9]  )  /*dummy*/;
+                            cp[10] =  fcomplex.Sqrt(ap[10]  )  /*dummy*/;
+                            cp[11] =  fcomplex.Sqrt(ap[11]  )  /*dummy*/;
+                            cp[12] =  fcomplex.Sqrt(ap[12]  )  /*dummy*/;
+                            cp[13] =  fcomplex.Sqrt(ap[13]  )  /*dummy*/;
+                            cp[14] =  fcomplex.Sqrt(ap[14]  )  /*dummy*/;
+                            cp[15] =  fcomplex.Sqrt(ap[15]  )  /*dummy*/;
+                            cp[16] =  fcomplex.Sqrt(ap[16]  )  /*dummy*/;
+                            cp[17] =  fcomplex.Sqrt(ap[17]  )  /*dummy*/;
+                            cp[18] =  fcomplex.Sqrt(ap[18]  )  /*dummy*/;
+                            cp[19] =  fcomplex.Sqrt(ap[19]  )  /*dummy*/;
+                            cp[20] =  fcomplex.Sqrt(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.Sqrt(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( float* arrAP = arrA)
+                fixed ( fcomplex* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<fcomplex>(retStorage);
+            }
+        }
+        /// <summary>Square root of array elements - complex output</summary>
+        /// <param name="A">Input array - positive and negative values allowed</param>
+        /// <returns>Square root of elements of A - complex output</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<complex>  sqrtc (ILInArray< double > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<complex>(A.Size); 
+                ILSize inDim = A.Size;
+                double[] arrA = A.GetArrayForRead(); 
+                complex [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (true) {
+                    retArr = ILMemoryPool.Pool.New<complex>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<complex> retStorage = new ILDenseStorage<complex>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    complex* cp = ((complex*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  complex.Sqrt(cp[0]  )  /*dummy*/;
+                            cp[1] =  complex.Sqrt(cp[1]  )  /*dummy*/;
+                            cp[2] =  complex.Sqrt(cp[2]  )  /*dummy*/;
+                            cp[3] =  complex.Sqrt(cp[3]  )  /*dummy*/;
+                            cp[4] =  complex.Sqrt(cp[4]  )  /*dummy*/;
+                            cp[5] =  complex.Sqrt(cp[5]  )  /*dummy*/;
+                            cp[6] =  complex.Sqrt(cp[6]  )  /*dummy*/;
+                            cp[7] =  complex.Sqrt(cp[7]  )  /*dummy*/;
+                            cp[8] =  complex.Sqrt(cp[8]  )  /*dummy*/;
+                            cp[9] =  complex.Sqrt(cp[9]  )  /*dummy*/;
+                            cp[10] =  complex.Sqrt(cp[10]  )  /*dummy*/;
+                            cp[11] =  complex.Sqrt(cp[11]  )  /*dummy*/;
+                            cp[12] =  complex.Sqrt(cp[12]  )  /*dummy*/;
+                            cp[13] =  complex.Sqrt(cp[13]  )  /*dummy*/;
+                            cp[14] =  complex.Sqrt(cp[14]  )  /*dummy*/;
+                            cp[15] =  complex.Sqrt(cp[15]  )  /*dummy*/;
+                            cp[16] =  complex.Sqrt(cp[16]  )  /*dummy*/;
+                            cp[17] =  complex.Sqrt(cp[17]  )  /*dummy*/;
+                            cp[18] =  complex.Sqrt(cp[18]  )  /*dummy*/;
+                            cp[19] =  complex.Sqrt(cp[19]  )  /*dummy*/;
+                            cp[20] =  complex.Sqrt(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.Sqrt(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        double* ap = ((double*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  complex.Sqrt(ap[0]  )  /*dummy*/;
+                            cp[1] =  complex.Sqrt(ap[1]  )  /*dummy*/;
+                            cp[2] =  complex.Sqrt(ap[2]  )  /*dummy*/;
+                            cp[3] =  complex.Sqrt(ap[3]  )  /*dummy*/;
+                            cp[4] =  complex.Sqrt(ap[4]  )  /*dummy*/;
+                            cp[5] =  complex.Sqrt(ap[5]  )  /*dummy*/;
+                            cp[6] =  complex.Sqrt(ap[6]  )  /*dummy*/;
+                            cp[7] =  complex.Sqrt(ap[7]  )  /*dummy*/;
+                            cp[8] =  complex.Sqrt(ap[8]  )  /*dummy*/;
+                            cp[9] =  complex.Sqrt(ap[9]  )  /*dummy*/;
+                            cp[10] =  complex.Sqrt(ap[10]  )  /*dummy*/;
+                            cp[11] =  complex.Sqrt(ap[11]  )  /*dummy*/;
+                            cp[12] =  complex.Sqrt(ap[12]  )  /*dummy*/;
+                            cp[13] =  complex.Sqrt(ap[13]  )  /*dummy*/;
+                            cp[14] =  complex.Sqrt(ap[14]  )  /*dummy*/;
+                            cp[15] =  complex.Sqrt(ap[15]  )  /*dummy*/;
+                            cp[16] =  complex.Sqrt(ap[16]  )  /*dummy*/;
+                            cp[17] =  complex.Sqrt(ap[17]  )  /*dummy*/;
+                            cp[18] =  complex.Sqrt(ap[18]  )  /*dummy*/;
+                            cp[19] =  complex.Sqrt(ap[19]  )  /*dummy*/;
+                            cp[20] =  complex.Sqrt(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.Sqrt(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( double* arrAP = arrA)
+                fixed ( complex* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<complex>(retStorage);
+            }
+        }
+        /// <summary>Square root of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Square root of elements of A </returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<complex>  sqrt (ILInArray< complex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<complex>(A.Size); 
+                ILSize inDim = A.Size;
+                complex[] arrA = A.GetArrayForRead(); 
+                complex [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (true) {
+                    retArr = ILMemoryPool.Pool.New<complex>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<complex> retStorage = new ILDenseStorage<complex>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    complex* cp = ((complex*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  complex.Sqrt(cp[0]  )  /*dummy*/;
+                            cp[1] =  complex.Sqrt(cp[1]  )  /*dummy*/;
+                            cp[2] =  complex.Sqrt(cp[2]  )  /*dummy*/;
+                            cp[3] =  complex.Sqrt(cp[3]  )  /*dummy*/;
+                            cp[4] =  complex.Sqrt(cp[4]  )  /*dummy*/;
+                            cp[5] =  complex.Sqrt(cp[5]  )  /*dummy*/;
+                            cp[6] =  complex.Sqrt(cp[6]  )  /*dummy*/;
+                            cp[7] =  complex.Sqrt(cp[7]  )  /*dummy*/;
+                            cp[8] =  complex.Sqrt(cp[8]  )  /*dummy*/;
+                            cp[9] =  complex.Sqrt(cp[9]  )  /*dummy*/;
+                            cp[10] =  complex.Sqrt(cp[10]  )  /*dummy*/;
+                            cp[11] =  complex.Sqrt(cp[11]  )  /*dummy*/;
+                            cp[12] =  complex.Sqrt(cp[12]  )  /*dummy*/;
+                            cp[13] =  complex.Sqrt(cp[13]  )  /*dummy*/;
+                            cp[14] =  complex.Sqrt(cp[14]  )  /*dummy*/;
+                            cp[15] =  complex.Sqrt(cp[15]  )  /*dummy*/;
+                            cp[16] =  complex.Sqrt(cp[16]  )  /*dummy*/;
+                            cp[17] =  complex.Sqrt(cp[17]  )  /*dummy*/;
+                            cp[18] =  complex.Sqrt(cp[18]  )  /*dummy*/;
+                            cp[19] =  complex.Sqrt(cp[19]  )  /*dummy*/;
+                            cp[20] =  complex.Sqrt(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.Sqrt(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        complex* ap = ((complex*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  complex.Sqrt(ap[0]  )  /*dummy*/;
+                            cp[1] =  complex.Sqrt(ap[1]  )  /*dummy*/;
+                            cp[2] =  complex.Sqrt(ap[2]  )  /*dummy*/;
+                            cp[3] =  complex.Sqrt(ap[3]  )  /*dummy*/;
+                            cp[4] =  complex.Sqrt(ap[4]  )  /*dummy*/;
+                            cp[5] =  complex.Sqrt(ap[5]  )  /*dummy*/;
+                            cp[6] =  complex.Sqrt(ap[6]  )  /*dummy*/;
+                            cp[7] =  complex.Sqrt(ap[7]  )  /*dummy*/;
+                            cp[8] =  complex.Sqrt(ap[8]  )  /*dummy*/;
+                            cp[9] =  complex.Sqrt(ap[9]  )  /*dummy*/;
+                            cp[10] =  complex.Sqrt(ap[10]  )  /*dummy*/;
+                            cp[11] =  complex.Sqrt(ap[11]  )  /*dummy*/;
+                            cp[12] =  complex.Sqrt(ap[12]  )  /*dummy*/;
+                            cp[13] =  complex.Sqrt(ap[13]  )  /*dummy*/;
+                            cp[14] =  complex.Sqrt(ap[14]  )  /*dummy*/;
+                            cp[15] =  complex.Sqrt(ap[15]  )  /*dummy*/;
+                            cp[16] =  complex.Sqrt(ap[16]  )  /*dummy*/;
+                            cp[17] =  complex.Sqrt(ap[17]  )  /*dummy*/;
+                            cp[18] =  complex.Sqrt(ap[18]  )  /*dummy*/;
+                            cp[19] =  complex.Sqrt(ap[19]  )  /*dummy*/;
+                            cp[20] =  complex.Sqrt(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.Sqrt(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( complex* arrAP = arrA)
+                fixed ( complex* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<complex>(retStorage);
+            }
+        }
+        /// <summary>Square root of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Square root of elements of A </returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<fcomplex>  sqrt (ILInArray< fcomplex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<fcomplex>(A.Size); 
+                ILSize inDim = A.Size;
+                fcomplex[] arrA = A.GetArrayForRead(); 
+                fcomplex [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (true) {
+                    retArr = ILMemoryPool.Pool.New<fcomplex>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<fcomplex> retStorage = new ILDenseStorage<fcomplex>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    fcomplex* cp = ((fcomplex*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  fcomplex.Sqrt(cp[0]  )  /*dummy*/;
+                            cp[1] =  fcomplex.Sqrt(cp[1]  )  /*dummy*/;
+                            cp[2] =  fcomplex.Sqrt(cp[2]  )  /*dummy*/;
+                            cp[3] =  fcomplex.Sqrt(cp[3]  )  /*dummy*/;
+                            cp[4] =  fcomplex.Sqrt(cp[4]  )  /*dummy*/;
+                            cp[5] =  fcomplex.Sqrt(cp[5]  )  /*dummy*/;
+                            cp[6] =  fcomplex.Sqrt(cp[6]  )  /*dummy*/;
+                            cp[7] =  fcomplex.Sqrt(cp[7]  )  /*dummy*/;
+                            cp[8] =  fcomplex.Sqrt(cp[8]  )  /*dummy*/;
+                            cp[9] =  fcomplex.Sqrt(cp[9]  )  /*dummy*/;
+                            cp[10] =  fcomplex.Sqrt(cp[10]  )  /*dummy*/;
+                            cp[11] =  fcomplex.Sqrt(cp[11]  )  /*dummy*/;
+                            cp[12] =  fcomplex.Sqrt(cp[12]  )  /*dummy*/;
+                            cp[13] =  fcomplex.Sqrt(cp[13]  )  /*dummy*/;
+                            cp[14] =  fcomplex.Sqrt(cp[14]  )  /*dummy*/;
+                            cp[15] =  fcomplex.Sqrt(cp[15]  )  /*dummy*/;
+                            cp[16] =  fcomplex.Sqrt(cp[16]  )  /*dummy*/;
+                            cp[17] =  fcomplex.Sqrt(cp[17]  )  /*dummy*/;
+                            cp[18] =  fcomplex.Sqrt(cp[18]  )  /*dummy*/;
+                            cp[19] =  fcomplex.Sqrt(cp[19]  )  /*dummy*/;
+                            cp[20] =  fcomplex.Sqrt(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.Sqrt(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        fcomplex* ap = ((fcomplex*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  fcomplex.Sqrt(ap[0]  )  /*dummy*/;
+                            cp[1] =  fcomplex.Sqrt(ap[1]  )  /*dummy*/;
+                            cp[2] =  fcomplex.Sqrt(ap[2]  )  /*dummy*/;
+                            cp[3] =  fcomplex.Sqrt(ap[3]  )  /*dummy*/;
+                            cp[4] =  fcomplex.Sqrt(ap[4]  )  /*dummy*/;
+                            cp[5] =  fcomplex.Sqrt(ap[5]  )  /*dummy*/;
+                            cp[6] =  fcomplex.Sqrt(ap[6]  )  /*dummy*/;
+                            cp[7] =  fcomplex.Sqrt(ap[7]  )  /*dummy*/;
+                            cp[8] =  fcomplex.Sqrt(ap[8]  )  /*dummy*/;
+                            cp[9] =  fcomplex.Sqrt(ap[9]  )  /*dummy*/;
+                            cp[10] =  fcomplex.Sqrt(ap[10]  )  /*dummy*/;
+                            cp[11] =  fcomplex.Sqrt(ap[11]  )  /*dummy*/;
+                            cp[12] =  fcomplex.Sqrt(ap[12]  )  /*dummy*/;
+                            cp[13] =  fcomplex.Sqrt(ap[13]  )  /*dummy*/;
+                            cp[14] =  fcomplex.Sqrt(ap[14]  )  /*dummy*/;
+                            cp[15] =  fcomplex.Sqrt(ap[15]  )  /*dummy*/;
+                            cp[16] =  fcomplex.Sqrt(ap[16]  )  /*dummy*/;
+                            cp[17] =  fcomplex.Sqrt(ap[17]  )  /*dummy*/;
+                            cp[18] =  fcomplex.Sqrt(ap[18]  )  /*dummy*/;
+                            cp[19] =  fcomplex.Sqrt(ap[19]  )  /*dummy*/;
+                            cp[20] =  fcomplex.Sqrt(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.Sqrt(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( fcomplex* arrAP = arrA)
+                fixed ( fcomplex* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<fcomplex>(retStorage);
+            }
+        }
+        /// <summary>Square root of array elements - real output</summary>
+        /// <param name="A">Input array - only positive values are allowed.</param>
+        /// <returns>Square root of elements of A - real output</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<float>  sqrt (ILInArray< float > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<float>(A.Size); 
+                ILSize inDim = A.Size;
+                float[] arrA = A.GetArrayForRead(); 
+                float [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (true) {
+                    retArr = ILMemoryPool.Pool.New<float>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<float> retStorage = new ILDenseStorage<float>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    float* cp = ((float*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  (float)Math.Sqrt(cp[0]  )  /*dummy*/;
+                            cp[1] =  (float)Math.Sqrt(cp[1]  )  /*dummy*/;
+                            cp[2] =  (float)Math.Sqrt(cp[2]  )  /*dummy*/;
+                            cp[3] =  (float)Math.Sqrt(cp[3]  )  /*dummy*/;
+                            cp[4] =  (float)Math.Sqrt(cp[4]  )  /*dummy*/;
+                            cp[5] =  (float)Math.Sqrt(cp[5]  )  /*dummy*/;
+                            cp[6] =  (float)Math.Sqrt(cp[6]  )  /*dummy*/;
+                            cp[7] =  (float)Math.Sqrt(cp[7]  )  /*dummy*/;
+                            cp[8] =  (float)Math.Sqrt(cp[8]  )  /*dummy*/;
+                            cp[9] =  (float)Math.Sqrt(cp[9]  )  /*dummy*/;
+                            cp[10] =  (float)Math.Sqrt(cp[10]  )  /*dummy*/;
+                            cp[11] =  (float)Math.Sqrt(cp[11]  )  /*dummy*/;
+                            cp[12] =  (float)Math.Sqrt(cp[12]  )  /*dummy*/;
+                            cp[13] =  (float)Math.Sqrt(cp[13]  )  /*dummy*/;
+                            cp[14] =  (float)Math.Sqrt(cp[14]  )  /*dummy*/;
+                            cp[15] =  (float)Math.Sqrt(cp[15]  )  /*dummy*/;
+                            cp[16] =  (float)Math.Sqrt(cp[16]  )  /*dummy*/;
+                            cp[17] =  (float)Math.Sqrt(cp[17]  )  /*dummy*/;
+                            cp[18] =  (float)Math.Sqrt(cp[18]  )  /*dummy*/;
+                            cp[19] =  (float)Math.Sqrt(cp[19]  )  /*dummy*/;
+                            cp[20] =  (float)Math.Sqrt(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  (float)Math.Sqrt(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        float* ap = ((float*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  (float)Math.Sqrt(ap[0]  )  /*dummy*/;
+                            cp[1] =  (float)Math.Sqrt(ap[1]  )  /*dummy*/;
+                            cp[2] =  (float)Math.Sqrt(ap[2]  )  /*dummy*/;
+                            cp[3] =  (float)Math.Sqrt(ap[3]  )  /*dummy*/;
+                            cp[4] =  (float)Math.Sqrt(ap[4]  )  /*dummy*/;
+                            cp[5] =  (float)Math.Sqrt(ap[5]  )  /*dummy*/;
+                            cp[6] =  (float)Math.Sqrt(ap[6]  )  /*dummy*/;
+                            cp[7] =  (float)Math.Sqrt(ap[7]  )  /*dummy*/;
+                            cp[8] =  (float)Math.Sqrt(ap[8]  )  /*dummy*/;
+                            cp[9] =  (float)Math.Sqrt(ap[9]  )  /*dummy*/;
+                            cp[10] =  (float)Math.Sqrt(ap[10]  )  /*dummy*/;
+                            cp[11] =  (float)Math.Sqrt(ap[11]  )  /*dummy*/;
+                            cp[12] =  (float)Math.Sqrt(ap[12]  )  /*dummy*/;
+                            cp[13] =  (float)Math.Sqrt(ap[13]  )  /*dummy*/;
+                            cp[14] =  (float)Math.Sqrt(ap[14]  )  /*dummy*/;
+                            cp[15] =  (float)Math.Sqrt(ap[15]  )  /*dummy*/;
+                            cp[16] =  (float)Math.Sqrt(ap[16]  )  /*dummy*/;
+                            cp[17] =  (float)Math.Sqrt(ap[17]  )  /*dummy*/;
+                            cp[18] =  (float)Math.Sqrt(ap[18]  )  /*dummy*/;
+                            cp[19] =  (float)Math.Sqrt(ap[19]  )  /*dummy*/;
+                            cp[20] =  (float)Math.Sqrt(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  (float)Math.Sqrt(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( float* arrAP = arrA)
+                fixed ( float* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<float>(retStorage);
+            }
+        }
+        /// <summary>Square root of array elements - real output</summary>
+        /// <param name="A">Input array - only positive values are allowed.</param>
+        /// <returns>Square root of elements of A - real output</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<double>  sqrt (ILInArray< double > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<double>(A.Size); 
+                ILSize inDim = A.Size;
+                double[] arrA = A.GetArrayForRead(); 
+                double [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (true) {
+                    retArr = ILMemoryPool.Pool.New<double>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<double> retStorage = new ILDenseStorage<double>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    double* cp = ((double*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  Math.Sqrt(cp[0]  )  /*dummy*/;
+                            cp[1] =  Math.Sqrt(cp[1]  )  /*dummy*/;
+                            cp[2] =  Math.Sqrt(cp[2]  )  /*dummy*/;
+                            cp[3] =  Math.Sqrt(cp[3]  )  /*dummy*/;
+                            cp[4] =  Math.Sqrt(cp[4]  )  /*dummy*/;
+                            cp[5] =  Math.Sqrt(cp[5]  )  /*dummy*/;
+                            cp[6] =  Math.Sqrt(cp[6]  )  /*dummy*/;
+                            cp[7] =  Math.Sqrt(cp[7]  )  /*dummy*/;
+                            cp[8] =  Math.Sqrt(cp[8]  )  /*dummy*/;
+                            cp[9] =  Math.Sqrt(cp[9]  )  /*dummy*/;
+                            cp[10] =  Math.Sqrt(cp[10]  )  /*dummy*/;
+                            cp[11] =  Math.Sqrt(cp[11]  )  /*dummy*/;
+                            cp[12] =  Math.Sqrt(cp[12]  )  /*dummy*/;
+                            cp[13] =  Math.Sqrt(cp[13]  )  /*dummy*/;
+                            cp[14] =  Math.Sqrt(cp[14]  )  /*dummy*/;
+                            cp[15] =  Math.Sqrt(cp[15]  )  /*dummy*/;
+                            cp[16] =  Math.Sqrt(cp[16]  )  /*dummy*/;
+                            cp[17] =  Math.Sqrt(cp[17]  )  /*dummy*/;
+                            cp[18] =  Math.Sqrt(cp[18]  )  /*dummy*/;
+                            cp[19] =  Math.Sqrt(cp[19]  )  /*dummy*/;
+                            cp[20] =  Math.Sqrt(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Math.Sqrt(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        double* ap = ((double*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  Math.Sqrt(ap[0]  )  /*dummy*/;
+                            cp[1] =  Math.Sqrt(ap[1]  )  /*dummy*/;
+                            cp[2] =  Math.Sqrt(ap[2]  )  /*dummy*/;
+                            cp[3] =  Math.Sqrt(ap[3]  )  /*dummy*/;
+                            cp[4] =  Math.Sqrt(ap[4]  )  /*dummy*/;
+                            cp[5] =  Math.Sqrt(ap[5]  )  /*dummy*/;
+                            cp[6] =  Math.Sqrt(ap[6]  )  /*dummy*/;
+                            cp[7] =  Math.Sqrt(ap[7]  )  /*dummy*/;
+                            cp[8] =  Math.Sqrt(ap[8]  )  /*dummy*/;
+                            cp[9] =  Math.Sqrt(ap[9]  )  /*dummy*/;
+                            cp[10] =  Math.Sqrt(ap[10]  )  /*dummy*/;
+                            cp[11] =  Math.Sqrt(ap[11]  )  /*dummy*/;
+                            cp[12] =  Math.Sqrt(ap[12]  )  /*dummy*/;
+                            cp[13] =  Math.Sqrt(ap[13]  )  /*dummy*/;
+                            cp[14] =  Math.Sqrt(ap[14]  )  /*dummy*/;
+                            cp[15] =  Math.Sqrt(ap[15]  )  /*dummy*/;
+                            cp[16] =  Math.Sqrt(ap[16]  )  /*dummy*/;
+                            cp[17] =  Math.Sqrt(ap[17]  )  /*dummy*/;
+                            cp[18] =  Math.Sqrt(ap[18]  )  /*dummy*/;
+                            cp[19] =  Math.Sqrt(ap[19]  )  /*dummy*/;
+                            cp[20] =  Math.Sqrt(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Math.Sqrt(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( double* arrAP = arrA)
+                fixed ( double* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<double>(retStorage);
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/std.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/std.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/std.cs	(revision 9102)
@@ -0,0 +1,103 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics;
+using ILNumerics.Exceptions;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+
+
+
+namespace ILNumerics {
+
+    public partial class ILMath {
+
+
+        /// <summary>
+        /// Standard deviation for values in A
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="Weights">Vector of scaling factors, same length as working dimension of A, default: no scaling</param>
+        /// <param name="biased">[Optional] true: apply biased normalization to result, default: false (non-biased)</param>
+        /// <param name="dim">[Optional] Dimension index of A to operate along, default: first non singleton dimension</param>
+        /// <returns>Variances</returns>
+        /// <remarks><para>On scalar A a scalar 0 of the same shape as A is returned.</para>
+        /// <para>On empty A an empty array is returned, having the dimension to operate along reduced to length 1.</para>
+        /// <para>The parameters <paramref name="Weights"/>, <paramref name="biased"/> and <paramref name="dim"/> are optional. 
+        /// Ommiting either one will choose its respective default value.</para>
+        /// <para>The standard deviation is computed by the formula 
+        /// <c>std = sqrt(var(A,...))</c>. For further details on given parameters, see 
+        /// <see cref="M:ILNumerics.ILMath.var(ILNumerics.ILInArray{T},ILNumerics.ILInArray{T},bool,false);"/>.</para>
+        /// </remarks>
+        public static ILRetArray<double> std(ILInArray<double> A, 
+                                                            ILInArray<double> Weights = null, 
+                                                            bool biased = false, int dim = -1) {
+            return sqrt(var(A,Weights,biased,dim)); 
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// Standard deviation for values in A
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="Weights">Vector of scaling factors, same length as working dimension of A, default: no scaling</param>
+        /// <param name="biased">[Optional] true: apply biased normalization to result, default: false (non-biased)</param>
+        /// <param name="dim">[Optional] Dimension index of A to operate along, default: first non singleton dimension</param>
+        /// <returns>Variances</returns>
+        /// <remarks><para>On scalar A a scalar 0 of the same shape as A is returned.</para>
+        /// <para>On empty A an empty array is returned, having the dimension to operate along reduced to length 1.</para>
+        /// <para>The parameters <paramref name="Weights"/>, <paramref name="biased"/> and <paramref name="dim"/> are optional. 
+        /// Ommiting either one will choose its respective default value.</para>
+        /// <para>The standard deviation is computed by the formula 
+        /// <c>std = sqrt(var(A,...))</c>. For further details on given parameters, see 
+        /// <see cref="M:ILNumerics.ILMath.var(ILNumerics.ILInArray{T},ILNumerics.ILInArray{T},bool,false);"/>.</para>
+        /// </remarks>
+        public static ILRetArray<float> std(ILInArray<float> A, 
+                                                            ILInArray<float> Weights = null, 
+                                                            bool biased = false, int dim = -1) {
+            return sqrt(var(A,Weights,biased,dim)); 
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+   }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/sub2ind.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/sub2ind.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/sub2ind.cs	(revision 9102)
@@ -0,0 +1,66 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics;
+using ILNumerics.Exceptions;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+
+namespace ILNumerics {
+
+    public partial class ILMath {
+        /// <summary>
+        /// Convert subscript indices to sequential index
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="subscripts">Subscripts</param>
+        /// <returns>Sequential index for subscript indices</returns>
+        /// <remarks>The function returns the sequential index i into A referencing the same element as would be referenced by the subscript indices.</remarks>
+        public static int sub2ind( ILBaseArray A, int[] subscripts ) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A, null) || A.IsEmpty || subscripts == null || subscripts.Length == 0)
+                    throw new ILArgumentException("sub2ind: both, A and subscripts must be non-empty!");
+                return A.Size.IndexFromArray(subscripts);
+            }
+        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/sumall.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/sumall.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/sumall.cs	(revision 9102)
@@ -0,0 +1,276 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions; 
+
+namespace ILNumerics  {
+    
+    public partial class ILMath {
+
+
+        /// <summary>
+        /// Sum all elements of array A 
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns><para>Scalar sum of all elements of A.</para>
+        /// <para>If A is empty, an empty array will be returned.</para></returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If A was null.</exception>
+        /// <seealso cref="ILNumerics.ILMath.sum(ILInArray&lt;double&gt;,int)"/>
+        public static ILRetArray<double> sumall( ILInArray<double> A ) {
+            if (object.Equals(A, null))
+                throw new ILArgumentException("sumall: argument must not be null!");
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    return empty<double>(ILSize.Empty00);
+                }
+                
+                double retArr =  0;
+                unsafe {
+                    fixed ( double* inArrStart = A.GetArrayForRead()) {
+                        
+                        double* inArrWalk = inArrStart;
+                        
+                        double* inArrEnd = inArrStart + A.Size.NumberOfElements;
+                        while (inArrWalk < inArrEnd) {
+                            retArr += *inArrWalk++;
+                        }
+                    }
+                }
+                return array<double>(retArr, 1, 1);
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// Sum all elements of array A 
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns><para>Scalar sum of all elements of A.</para>
+        /// <para>If A is empty, an empty array will be returned.</para></returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If A was null.</exception>
+        /// <seealso cref="ILNumerics.ILMath.sum(ILInArray&lt;double&gt;,int)"/>
+        public static ILRetArray<Int64> sumall( ILInArray<Int64> A ) {
+            if (object.Equals(A, null))
+                throw new ILArgumentException("sumall: argument must not be null!");
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    return empty<Int64>(ILSize.Empty00);
+                }
+               
+                Int64 retArr =  0;
+                unsafe {
+                    fixed ( Int64* inArrStart = A.GetArrayForRead()) {
+                       
+                        Int64* inArrWalk = inArrStart;
+                       
+                        Int64* inArrEnd = inArrStart + A.Size.NumberOfElements;
+                        while (inArrWalk < inArrEnd) {
+                            retArr += *inArrWalk++;
+                        }
+                    }
+                }
+                return array<Int64>(retArr, 1, 1);
+            }
+        }
+        /// <summary>
+        /// Sum all elements of array A 
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns><para>Scalar sum of all elements of A.</para>
+        /// <para>If A is empty, an empty array will be returned.</para></returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If A was null.</exception>
+        /// <seealso cref="ILNumerics.ILMath.sum(ILInArray&lt;double&gt;,int)"/>
+        public static ILRetArray<Int32> sumall( ILInArray<Int32> A ) {
+            if (object.Equals(A, null))
+                throw new ILArgumentException("sumall: argument must not be null!");
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    return empty<Int32>(ILSize.Empty00);
+                }
+               
+                Int32 retArr =  0;
+                unsafe {
+                    fixed ( Int32* inArrStart = A.GetArrayForRead()) {
+                       
+                        Int32* inArrWalk = inArrStart;
+                       
+                        Int32* inArrEnd = inArrStart + A.Size.NumberOfElements;
+                        while (inArrWalk < inArrEnd) {
+                            retArr += *inArrWalk++;
+                        }
+                    }
+                }
+                return array<Int32>(retArr, 1, 1);
+            }
+        }
+        /// <summary>
+        /// Sum all elements of array A 
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns><para>Scalar sum of all elements of A.</para>
+        /// <para>If A is empty, an empty array will be returned.</para></returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If A was null.</exception>
+        /// <seealso cref="ILNumerics.ILMath.sum(ILInArray&lt;double&gt;,int)"/>
+        public static ILRetArray<byte> sumall( ILInArray<byte> A ) {
+            if (object.Equals(A, null))
+                throw new ILArgumentException("sumall: argument must not be null!");
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    return empty<byte>(ILSize.Empty00);
+                }
+               
+                byte retArr =  0;
+                unsafe {
+                    fixed ( byte* inArrStart = A.GetArrayForRead()) {
+                       
+                        byte* inArrWalk = inArrStart;
+                       
+                        byte* inArrEnd = inArrStart + A.Size.NumberOfElements;
+                        while (inArrWalk < inArrEnd) {
+                            retArr += *inArrWalk++;
+                        }
+                    }
+                }
+                return array<byte>(retArr, 1, 1);
+            }
+        }
+        /// <summary>
+        /// Sum all elements of array A 
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns><para>Scalar sum of all elements of A.</para>
+        /// <para>If A is empty, an empty array will be returned.</para></returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If A was null.</exception>
+        /// <seealso cref="ILNumerics.ILMath.sum(ILInArray&lt;double&gt;,int)"/>
+        public static ILRetArray<fcomplex> sumall( ILInArray<fcomplex> A ) {
+            if (object.Equals(A, null))
+                throw new ILArgumentException("sumall: argument must not be null!");
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    return empty<fcomplex>(ILSize.Empty00);
+                }
+               
+                fcomplex retArr =  new fcomplex(0.0f,0.0f);
+                unsafe {
+                    fixed ( fcomplex* inArrStart = A.GetArrayForRead()) {
+                       
+                        fcomplex* inArrWalk = inArrStart;
+                       
+                        fcomplex* inArrEnd = inArrStart + A.Size.NumberOfElements;
+                        while (inArrWalk < inArrEnd) {
+                            retArr += *inArrWalk++;
+                        }
+                    }
+                }
+                return array<fcomplex>(retArr, 1, 1);
+            }
+        }
+        /// <summary>
+        /// Sum all elements of array A 
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns><para>Scalar sum of all elements of A.</para>
+        /// <para>If A is empty, an empty array will be returned.</para></returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If A was null.</exception>
+        /// <seealso cref="ILNumerics.ILMath.sum(ILInArray&lt;double&gt;,int)"/>
+        public static ILRetArray<float> sumall( ILInArray<float> A ) {
+            if (object.Equals(A, null))
+                throw new ILArgumentException("sumall: argument must not be null!");
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    return empty<float>(ILSize.Empty00);
+                }
+               
+                float retArr =  0.0f;
+                unsafe {
+                    fixed ( float* inArrStart = A.GetArrayForRead()) {
+                       
+                        float* inArrWalk = inArrStart;
+                       
+                        float* inArrEnd = inArrStart + A.Size.NumberOfElements;
+                        while (inArrWalk < inArrEnd) {
+                            retArr += *inArrWalk++;
+                        }
+                    }
+                }
+                return array<float>(retArr, 1, 1);
+            }
+        }
+        /// <summary>
+        /// Sum all elements of array A 
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <returns><para>Scalar sum of all elements of A.</para>
+        /// <para>If A is empty, an empty array will be returned.</para></returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If A was null.</exception>
+        /// <seealso cref="ILNumerics.ILMath.sum(ILInArray&lt;double&gt;,int)"/>
+        public static ILRetArray<complex> sumall( ILInArray<complex> A ) {
+            if (object.Equals(A, null))
+                throw new ILArgumentException("sumall: argument must not be null!");
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    return empty<complex>(ILSize.Empty00);
+                }
+               
+                complex retArr =  new complex(0.0,0.0);
+                unsafe {
+                    fixed ( complex* inArrStart = A.GetArrayForRead()) {
+                       
+                        complex* inArrWalk = inArrStart;
+                       
+                        complex* inArrEnd = inArrStart + A.Size.NumberOfElements;
+                        while (inArrWalk < inArrEnd) {
+                            retArr += *inArrWalk++;
+                        }
+                    }
+                }
+                return array<complex>(retArr, 1, 1);
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/tan.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/tan.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/tan.cs	(revision 9102)
@@ -0,0 +1,559 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics;
+using ILNumerics.Exceptions; 
+using ILNumerics.Storage; 
+using ILNumerics.Misc; 
+
+
+
+namespace ILNumerics {
+
+    public partial class ILMath {
+
+
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>Tangens of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Tangens of array elements</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<complex>  tan (ILInArray< complex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<complex>(A.Size); 
+                ILSize inDim = A.Size;
+                complex[] arrA = A.GetArrayForRead(); 
+                complex [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<complex>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<complex> retStorage = new ILDenseStorage<complex>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    complex* cp = ((complex*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  complex.Tan(cp[0]  )  /*dummy*/;
+                            cp[1] =  complex.Tan(cp[1]  )  /*dummy*/;
+                            cp[2] =  complex.Tan(cp[2]  )  /*dummy*/;
+                            cp[3] =  complex.Tan(cp[3]  )  /*dummy*/;
+                            cp[4] =  complex.Tan(cp[4]  )  /*dummy*/;
+                            cp[5] =  complex.Tan(cp[5]  )  /*dummy*/;
+                            cp[6] =  complex.Tan(cp[6]  )  /*dummy*/;
+                            cp[7] =  complex.Tan(cp[7]  )  /*dummy*/;
+                            cp[8] =  complex.Tan(cp[8]  )  /*dummy*/;
+                            cp[9] =  complex.Tan(cp[9]  )  /*dummy*/;
+                            cp[10] =  complex.Tan(cp[10]  )  /*dummy*/;
+                            cp[11] =  complex.Tan(cp[11]  )  /*dummy*/;
+                            cp[12] =  complex.Tan(cp[12]  )  /*dummy*/;
+                            cp[13] =  complex.Tan(cp[13]  )  /*dummy*/;
+                            cp[14] =  complex.Tan(cp[14]  )  /*dummy*/;
+                            cp[15] =  complex.Tan(cp[15]  )  /*dummy*/;
+                            cp[16] =  complex.Tan(cp[16]  )  /*dummy*/;
+                            cp[17] =  complex.Tan(cp[17]  )  /*dummy*/;
+                            cp[18] =  complex.Tan(cp[18]  )  /*dummy*/;
+                            cp[19] =  complex.Tan(cp[19]  )  /*dummy*/;
+                            cp[20] =  complex.Tan(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.Tan(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        complex* ap = ((complex*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  complex.Tan(ap[0]  )  /*dummy*/;
+                            cp[1] =  complex.Tan(ap[1]  )  /*dummy*/;
+                            cp[2] =  complex.Tan(ap[2]  )  /*dummy*/;
+                            cp[3] =  complex.Tan(ap[3]  )  /*dummy*/;
+                            cp[4] =  complex.Tan(ap[4]  )  /*dummy*/;
+                            cp[5] =  complex.Tan(ap[5]  )  /*dummy*/;
+                            cp[6] =  complex.Tan(ap[6]  )  /*dummy*/;
+                            cp[7] =  complex.Tan(ap[7]  )  /*dummy*/;
+                            cp[8] =  complex.Tan(ap[8]  )  /*dummy*/;
+                            cp[9] =  complex.Tan(ap[9]  )  /*dummy*/;
+                            cp[10] =  complex.Tan(ap[10]  )  /*dummy*/;
+                            cp[11] =  complex.Tan(ap[11]  )  /*dummy*/;
+                            cp[12] =  complex.Tan(ap[12]  )  /*dummy*/;
+                            cp[13] =  complex.Tan(ap[13]  )  /*dummy*/;
+                            cp[14] =  complex.Tan(ap[14]  )  /*dummy*/;
+                            cp[15] =  complex.Tan(ap[15]  )  /*dummy*/;
+                            cp[16] =  complex.Tan(ap[16]  )  /*dummy*/;
+                            cp[17] =  complex.Tan(ap[17]  )  /*dummy*/;
+                            cp[18] =  complex.Tan(ap[18]  )  /*dummy*/;
+                            cp[19] =  complex.Tan(ap[19]  )  /*dummy*/;
+                            cp[20] =  complex.Tan(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.Tan(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( complex* arrAP = arrA)
+                fixed ( complex* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<complex>(retStorage);
+            }
+        }
+        /// <summary>Tangens of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Tangens of array elements</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<fcomplex>  tan (ILInArray< fcomplex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<fcomplex>(A.Size); 
+                ILSize inDim = A.Size;
+                fcomplex[] arrA = A.GetArrayForRead(); 
+                fcomplex [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<fcomplex>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<fcomplex> retStorage = new ILDenseStorage<fcomplex>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    fcomplex* cp = ((fcomplex*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  fcomplex.Tan(cp[0]  )  /*dummy*/;
+                            cp[1] =  fcomplex.Tan(cp[1]  )  /*dummy*/;
+                            cp[2] =  fcomplex.Tan(cp[2]  )  /*dummy*/;
+                            cp[3] =  fcomplex.Tan(cp[3]  )  /*dummy*/;
+                            cp[4] =  fcomplex.Tan(cp[4]  )  /*dummy*/;
+                            cp[5] =  fcomplex.Tan(cp[5]  )  /*dummy*/;
+                            cp[6] =  fcomplex.Tan(cp[6]  )  /*dummy*/;
+                            cp[7] =  fcomplex.Tan(cp[7]  )  /*dummy*/;
+                            cp[8] =  fcomplex.Tan(cp[8]  )  /*dummy*/;
+                            cp[9] =  fcomplex.Tan(cp[9]  )  /*dummy*/;
+                            cp[10] =  fcomplex.Tan(cp[10]  )  /*dummy*/;
+                            cp[11] =  fcomplex.Tan(cp[11]  )  /*dummy*/;
+                            cp[12] =  fcomplex.Tan(cp[12]  )  /*dummy*/;
+                            cp[13] =  fcomplex.Tan(cp[13]  )  /*dummy*/;
+                            cp[14] =  fcomplex.Tan(cp[14]  )  /*dummy*/;
+                            cp[15] =  fcomplex.Tan(cp[15]  )  /*dummy*/;
+                            cp[16] =  fcomplex.Tan(cp[16]  )  /*dummy*/;
+                            cp[17] =  fcomplex.Tan(cp[17]  )  /*dummy*/;
+                            cp[18] =  fcomplex.Tan(cp[18]  )  /*dummy*/;
+                            cp[19] =  fcomplex.Tan(cp[19]  )  /*dummy*/;
+                            cp[20] =  fcomplex.Tan(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.Tan(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        fcomplex* ap = ((fcomplex*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  fcomplex.Tan(ap[0]  )  /*dummy*/;
+                            cp[1] =  fcomplex.Tan(ap[1]  )  /*dummy*/;
+                            cp[2] =  fcomplex.Tan(ap[2]  )  /*dummy*/;
+                            cp[3] =  fcomplex.Tan(ap[3]  )  /*dummy*/;
+                            cp[4] =  fcomplex.Tan(ap[4]  )  /*dummy*/;
+                            cp[5] =  fcomplex.Tan(ap[5]  )  /*dummy*/;
+                            cp[6] =  fcomplex.Tan(ap[6]  )  /*dummy*/;
+                            cp[7] =  fcomplex.Tan(ap[7]  )  /*dummy*/;
+                            cp[8] =  fcomplex.Tan(ap[8]  )  /*dummy*/;
+                            cp[9] =  fcomplex.Tan(ap[9]  )  /*dummy*/;
+                            cp[10] =  fcomplex.Tan(ap[10]  )  /*dummy*/;
+                            cp[11] =  fcomplex.Tan(ap[11]  )  /*dummy*/;
+                            cp[12] =  fcomplex.Tan(ap[12]  )  /*dummy*/;
+                            cp[13] =  fcomplex.Tan(ap[13]  )  /*dummy*/;
+                            cp[14] =  fcomplex.Tan(ap[14]  )  /*dummy*/;
+                            cp[15] =  fcomplex.Tan(ap[15]  )  /*dummy*/;
+                            cp[16] =  fcomplex.Tan(ap[16]  )  /*dummy*/;
+                            cp[17] =  fcomplex.Tan(ap[17]  )  /*dummy*/;
+                            cp[18] =  fcomplex.Tan(ap[18]  )  /*dummy*/;
+                            cp[19] =  fcomplex.Tan(ap[19]  )  /*dummy*/;
+                            cp[20] =  fcomplex.Tan(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.Tan(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( fcomplex* arrAP = arrA)
+                fixed ( fcomplex* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<fcomplex>(retStorage);
+            }
+        }
+        /// <summary>Tangens of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Tangens of array elements</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<float>  tan (ILInArray< float > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<float>(A.Size); 
+                ILSize inDim = A.Size;
+                float[] arrA = A.GetArrayForRead(); 
+                float [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<float>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<float> retStorage = new ILDenseStorage<float>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    float* cp = ((float*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  (float)Math.Tan(cp[0]  )  /*dummy*/;
+                            cp[1] =  (float)Math.Tan(cp[1]  )  /*dummy*/;
+                            cp[2] =  (float)Math.Tan(cp[2]  )  /*dummy*/;
+                            cp[3] =  (float)Math.Tan(cp[3]  )  /*dummy*/;
+                            cp[4] =  (float)Math.Tan(cp[4]  )  /*dummy*/;
+                            cp[5] =  (float)Math.Tan(cp[5]  )  /*dummy*/;
+                            cp[6] =  (float)Math.Tan(cp[6]  )  /*dummy*/;
+                            cp[7] =  (float)Math.Tan(cp[7]  )  /*dummy*/;
+                            cp[8] =  (float)Math.Tan(cp[8]  )  /*dummy*/;
+                            cp[9] =  (float)Math.Tan(cp[9]  )  /*dummy*/;
+                            cp[10] =  (float)Math.Tan(cp[10]  )  /*dummy*/;
+                            cp[11] =  (float)Math.Tan(cp[11]  )  /*dummy*/;
+                            cp[12] =  (float)Math.Tan(cp[12]  )  /*dummy*/;
+                            cp[13] =  (float)Math.Tan(cp[13]  )  /*dummy*/;
+                            cp[14] =  (float)Math.Tan(cp[14]  )  /*dummy*/;
+                            cp[15] =  (float)Math.Tan(cp[15]  )  /*dummy*/;
+                            cp[16] =  (float)Math.Tan(cp[16]  )  /*dummy*/;
+                            cp[17] =  (float)Math.Tan(cp[17]  )  /*dummy*/;
+                            cp[18] =  (float)Math.Tan(cp[18]  )  /*dummy*/;
+                            cp[19] =  (float)Math.Tan(cp[19]  )  /*dummy*/;
+                            cp[20] =  (float)Math.Tan(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  (float)Math.Tan(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        float* ap = ((float*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  (float)Math.Tan(ap[0]  )  /*dummy*/;
+                            cp[1] =  (float)Math.Tan(ap[1]  )  /*dummy*/;
+                            cp[2] =  (float)Math.Tan(ap[2]  )  /*dummy*/;
+                            cp[3] =  (float)Math.Tan(ap[3]  )  /*dummy*/;
+                            cp[4] =  (float)Math.Tan(ap[4]  )  /*dummy*/;
+                            cp[5] =  (float)Math.Tan(ap[5]  )  /*dummy*/;
+                            cp[6] =  (float)Math.Tan(ap[6]  )  /*dummy*/;
+                            cp[7] =  (float)Math.Tan(ap[7]  )  /*dummy*/;
+                            cp[8] =  (float)Math.Tan(ap[8]  )  /*dummy*/;
+                            cp[9] =  (float)Math.Tan(ap[9]  )  /*dummy*/;
+                            cp[10] =  (float)Math.Tan(ap[10]  )  /*dummy*/;
+                            cp[11] =  (float)Math.Tan(ap[11]  )  /*dummy*/;
+                            cp[12] =  (float)Math.Tan(ap[12]  )  /*dummy*/;
+                            cp[13] =  (float)Math.Tan(ap[13]  )  /*dummy*/;
+                            cp[14] =  (float)Math.Tan(ap[14]  )  /*dummy*/;
+                            cp[15] =  (float)Math.Tan(ap[15]  )  /*dummy*/;
+                            cp[16] =  (float)Math.Tan(ap[16]  )  /*dummy*/;
+                            cp[17] =  (float)Math.Tan(ap[17]  )  /*dummy*/;
+                            cp[18] =  (float)Math.Tan(ap[18]  )  /*dummy*/;
+                            cp[19] =  (float)Math.Tan(ap[19]  )  /*dummy*/;
+                            cp[20] =  (float)Math.Tan(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  (float)Math.Tan(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( float* arrAP = arrA)
+                fixed ( float* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<float>(retStorage);
+            }
+        }
+        /// <summary>Tangens of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Tangens of array elements</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<double>  tan (ILInArray< double > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<double>(A.Size); 
+                ILSize inDim = A.Size;
+                double[] arrA = A.GetArrayForRead(); 
+                double [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<double>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<double> retStorage = new ILDenseStorage<double>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    double* cp = ((double*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  Math.Tan(cp[0]  )  /*dummy*/;
+                            cp[1] =  Math.Tan(cp[1]  )  /*dummy*/;
+                            cp[2] =  Math.Tan(cp[2]  )  /*dummy*/;
+                            cp[3] =  Math.Tan(cp[3]  )  /*dummy*/;
+                            cp[4] =  Math.Tan(cp[4]  )  /*dummy*/;
+                            cp[5] =  Math.Tan(cp[5]  )  /*dummy*/;
+                            cp[6] =  Math.Tan(cp[6]  )  /*dummy*/;
+                            cp[7] =  Math.Tan(cp[7]  )  /*dummy*/;
+                            cp[8] =  Math.Tan(cp[8]  )  /*dummy*/;
+                            cp[9] =  Math.Tan(cp[9]  )  /*dummy*/;
+                            cp[10] =  Math.Tan(cp[10]  )  /*dummy*/;
+                            cp[11] =  Math.Tan(cp[11]  )  /*dummy*/;
+                            cp[12] =  Math.Tan(cp[12]  )  /*dummy*/;
+                            cp[13] =  Math.Tan(cp[13]  )  /*dummy*/;
+                            cp[14] =  Math.Tan(cp[14]  )  /*dummy*/;
+                            cp[15] =  Math.Tan(cp[15]  )  /*dummy*/;
+                            cp[16] =  Math.Tan(cp[16]  )  /*dummy*/;
+                            cp[17] =  Math.Tan(cp[17]  )  /*dummy*/;
+                            cp[18] =  Math.Tan(cp[18]  )  /*dummy*/;
+                            cp[19] =  Math.Tan(cp[19]  )  /*dummy*/;
+                            cp[20] =  Math.Tan(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Math.Tan(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        double* ap = ((double*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  Math.Tan(ap[0]  )  /*dummy*/;
+                            cp[1] =  Math.Tan(ap[1]  )  /*dummy*/;
+                            cp[2] =  Math.Tan(ap[2]  )  /*dummy*/;
+                            cp[3] =  Math.Tan(ap[3]  )  /*dummy*/;
+                            cp[4] =  Math.Tan(ap[4]  )  /*dummy*/;
+                            cp[5] =  Math.Tan(ap[5]  )  /*dummy*/;
+                            cp[6] =  Math.Tan(ap[6]  )  /*dummy*/;
+                            cp[7] =  Math.Tan(ap[7]  )  /*dummy*/;
+                            cp[8] =  Math.Tan(ap[8]  )  /*dummy*/;
+                            cp[9] =  Math.Tan(ap[9]  )  /*dummy*/;
+                            cp[10] =  Math.Tan(ap[10]  )  /*dummy*/;
+                            cp[11] =  Math.Tan(ap[11]  )  /*dummy*/;
+                            cp[12] =  Math.Tan(ap[12]  )  /*dummy*/;
+                            cp[13] =  Math.Tan(ap[13]  )  /*dummy*/;
+                            cp[14] =  Math.Tan(ap[14]  )  /*dummy*/;
+                            cp[15] =  Math.Tan(ap[15]  )  /*dummy*/;
+                            cp[16] =  Math.Tan(ap[16]  )  /*dummy*/;
+                            cp[17] =  Math.Tan(ap[17]  )  /*dummy*/;
+                            cp[18] =  Math.Tan(ap[18]  )  /*dummy*/;
+                            cp[19] =  Math.Tan(ap[19]  )  /*dummy*/;
+                            cp[20] =  Math.Tan(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Math.Tan(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( double* arrAP = arrA)
+                fixed ( double* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<double>(retStorage);
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/tanh.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/tanh.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/tanh.cs	(revision 9102)
@@ -0,0 +1,558 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics;
+using ILNumerics.Exceptions; 
+using ILNumerics.Storage; 
+using ILNumerics.Misc; 
+
+
+
+namespace ILNumerics {
+    
+    public partial class ILMath {
+
+
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>Hyperbolic tangent of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Hyperbolic tangent of array elements</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<complex>  tanh (ILInArray< complex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<complex>(A.Size); 
+                ILSize inDim = A.Size;
+                complex[] arrA = A.GetArrayForRead(); 
+                complex [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<complex>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<complex> retStorage = new ILDenseStorage<complex>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    complex* cp = ((complex*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  complex.Tanh(cp[0]  )  /*dummy*/;
+                            cp[1] =  complex.Tanh(cp[1]  )  /*dummy*/;
+                            cp[2] =  complex.Tanh(cp[2]  )  /*dummy*/;
+                            cp[3] =  complex.Tanh(cp[3]  )  /*dummy*/;
+                            cp[4] =  complex.Tanh(cp[4]  )  /*dummy*/;
+                            cp[5] =  complex.Tanh(cp[5]  )  /*dummy*/;
+                            cp[6] =  complex.Tanh(cp[6]  )  /*dummy*/;
+                            cp[7] =  complex.Tanh(cp[7]  )  /*dummy*/;
+                            cp[8] =  complex.Tanh(cp[8]  )  /*dummy*/;
+                            cp[9] =  complex.Tanh(cp[9]  )  /*dummy*/;
+                            cp[10] =  complex.Tanh(cp[10]  )  /*dummy*/;
+                            cp[11] =  complex.Tanh(cp[11]  )  /*dummy*/;
+                            cp[12] =  complex.Tanh(cp[12]  )  /*dummy*/;
+                            cp[13] =  complex.Tanh(cp[13]  )  /*dummy*/;
+                            cp[14] =  complex.Tanh(cp[14]  )  /*dummy*/;
+                            cp[15] =  complex.Tanh(cp[15]  )  /*dummy*/;
+                            cp[16] =  complex.Tanh(cp[16]  )  /*dummy*/;
+                            cp[17] =  complex.Tanh(cp[17]  )  /*dummy*/;
+                            cp[18] =  complex.Tanh(cp[18]  )  /*dummy*/;
+                            cp[19] =  complex.Tanh(cp[19]  )  /*dummy*/;
+                            cp[20] =  complex.Tanh(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.Tanh(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        complex* ap = ((complex*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  complex.Tanh(ap[0]  )  /*dummy*/;
+                            cp[1] =  complex.Tanh(ap[1]  )  /*dummy*/;
+                            cp[2] =  complex.Tanh(ap[2]  )  /*dummy*/;
+                            cp[3] =  complex.Tanh(ap[3]  )  /*dummy*/;
+                            cp[4] =  complex.Tanh(ap[4]  )  /*dummy*/;
+                            cp[5] =  complex.Tanh(ap[5]  )  /*dummy*/;
+                            cp[6] =  complex.Tanh(ap[6]  )  /*dummy*/;
+                            cp[7] =  complex.Tanh(ap[7]  )  /*dummy*/;
+                            cp[8] =  complex.Tanh(ap[8]  )  /*dummy*/;
+                            cp[9] =  complex.Tanh(ap[9]  )  /*dummy*/;
+                            cp[10] =  complex.Tanh(ap[10]  )  /*dummy*/;
+                            cp[11] =  complex.Tanh(ap[11]  )  /*dummy*/;
+                            cp[12] =  complex.Tanh(ap[12]  )  /*dummy*/;
+                            cp[13] =  complex.Tanh(ap[13]  )  /*dummy*/;
+                            cp[14] =  complex.Tanh(ap[14]  )  /*dummy*/;
+                            cp[15] =  complex.Tanh(ap[15]  )  /*dummy*/;
+                            cp[16] =  complex.Tanh(ap[16]  )  /*dummy*/;
+                            cp[17] =  complex.Tanh(ap[17]  )  /*dummy*/;
+                            cp[18] =  complex.Tanh(ap[18]  )  /*dummy*/;
+                            cp[19] =  complex.Tanh(ap[19]  )  /*dummy*/;
+                            cp[20] =  complex.Tanh(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  complex.Tanh(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( complex* arrAP = arrA)
+                fixed ( complex* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<complex>(retStorage);
+            }
+        }
+        /// <summary>Hyperbolic tangent of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Hyperbolic tangent of array elements</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<fcomplex>  tanh (ILInArray< fcomplex > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<fcomplex>(A.Size); 
+                ILSize inDim = A.Size;
+                fcomplex[] arrA = A.GetArrayForRead(); 
+                fcomplex [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<fcomplex>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<fcomplex> retStorage = new ILDenseStorage<fcomplex>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    fcomplex* cp = ((fcomplex*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  fcomplex.Tanh(cp[0]  )  /*dummy*/;
+                            cp[1] =  fcomplex.Tanh(cp[1]  )  /*dummy*/;
+                            cp[2] =  fcomplex.Tanh(cp[2]  )  /*dummy*/;
+                            cp[3] =  fcomplex.Tanh(cp[3]  )  /*dummy*/;
+                            cp[4] =  fcomplex.Tanh(cp[4]  )  /*dummy*/;
+                            cp[5] =  fcomplex.Tanh(cp[5]  )  /*dummy*/;
+                            cp[6] =  fcomplex.Tanh(cp[6]  )  /*dummy*/;
+                            cp[7] =  fcomplex.Tanh(cp[7]  )  /*dummy*/;
+                            cp[8] =  fcomplex.Tanh(cp[8]  )  /*dummy*/;
+                            cp[9] =  fcomplex.Tanh(cp[9]  )  /*dummy*/;
+                            cp[10] =  fcomplex.Tanh(cp[10]  )  /*dummy*/;
+                            cp[11] =  fcomplex.Tanh(cp[11]  )  /*dummy*/;
+                            cp[12] =  fcomplex.Tanh(cp[12]  )  /*dummy*/;
+                            cp[13] =  fcomplex.Tanh(cp[13]  )  /*dummy*/;
+                            cp[14] =  fcomplex.Tanh(cp[14]  )  /*dummy*/;
+                            cp[15] =  fcomplex.Tanh(cp[15]  )  /*dummy*/;
+                            cp[16] =  fcomplex.Tanh(cp[16]  )  /*dummy*/;
+                            cp[17] =  fcomplex.Tanh(cp[17]  )  /*dummy*/;
+                            cp[18] =  fcomplex.Tanh(cp[18]  )  /*dummy*/;
+                            cp[19] =  fcomplex.Tanh(cp[19]  )  /*dummy*/;
+                            cp[20] =  fcomplex.Tanh(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.Tanh(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        fcomplex* ap = ((fcomplex*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  fcomplex.Tanh(ap[0]  )  /*dummy*/;
+                            cp[1] =  fcomplex.Tanh(ap[1]  )  /*dummy*/;
+                            cp[2] =  fcomplex.Tanh(ap[2]  )  /*dummy*/;
+                            cp[3] =  fcomplex.Tanh(ap[3]  )  /*dummy*/;
+                            cp[4] =  fcomplex.Tanh(ap[4]  )  /*dummy*/;
+                            cp[5] =  fcomplex.Tanh(ap[5]  )  /*dummy*/;
+                            cp[6] =  fcomplex.Tanh(ap[6]  )  /*dummy*/;
+                            cp[7] =  fcomplex.Tanh(ap[7]  )  /*dummy*/;
+                            cp[8] =  fcomplex.Tanh(ap[8]  )  /*dummy*/;
+                            cp[9] =  fcomplex.Tanh(ap[9]  )  /*dummy*/;
+                            cp[10] =  fcomplex.Tanh(ap[10]  )  /*dummy*/;
+                            cp[11] =  fcomplex.Tanh(ap[11]  )  /*dummy*/;
+                            cp[12] =  fcomplex.Tanh(ap[12]  )  /*dummy*/;
+                            cp[13] =  fcomplex.Tanh(ap[13]  )  /*dummy*/;
+                            cp[14] =  fcomplex.Tanh(ap[14]  )  /*dummy*/;
+                            cp[15] =  fcomplex.Tanh(ap[15]  )  /*dummy*/;
+                            cp[16] =  fcomplex.Tanh(ap[16]  )  /*dummy*/;
+                            cp[17] =  fcomplex.Tanh(ap[17]  )  /*dummy*/;
+                            cp[18] =  fcomplex.Tanh(ap[18]  )  /*dummy*/;
+                            cp[19] =  fcomplex.Tanh(ap[19]  )  /*dummy*/;
+                            cp[20] =  fcomplex.Tanh(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  fcomplex.Tanh(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( fcomplex* arrAP = arrA)
+                fixed ( fcomplex* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<fcomplex>(retStorage);
+            }
+        }
+        /// <summary>Hyperbolic tangent of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Hyperbolic tangent of array elements</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<float>  tanh (ILInArray< float > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<float>(A.Size); 
+                ILSize inDim = A.Size;
+                float[] arrA = A.GetArrayForRead(); 
+                float [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<float>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<float> retStorage = new ILDenseStorage<float>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    float* cp = ((float*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  (float)Math.Tanh(cp[0]  )  /*dummy*/;
+                            cp[1] =  (float)Math.Tanh(cp[1]  )  /*dummy*/;
+                            cp[2] =  (float)Math.Tanh(cp[2]  )  /*dummy*/;
+                            cp[3] =  (float)Math.Tanh(cp[3]  )  /*dummy*/;
+                            cp[4] =  (float)Math.Tanh(cp[4]  )  /*dummy*/;
+                            cp[5] =  (float)Math.Tanh(cp[5]  )  /*dummy*/;
+                            cp[6] =  (float)Math.Tanh(cp[6]  )  /*dummy*/;
+                            cp[7] =  (float)Math.Tanh(cp[7]  )  /*dummy*/;
+                            cp[8] =  (float)Math.Tanh(cp[8]  )  /*dummy*/;
+                            cp[9] =  (float)Math.Tanh(cp[9]  )  /*dummy*/;
+                            cp[10] =  (float)Math.Tanh(cp[10]  )  /*dummy*/;
+                            cp[11] =  (float)Math.Tanh(cp[11]  )  /*dummy*/;
+                            cp[12] =  (float)Math.Tanh(cp[12]  )  /*dummy*/;
+                            cp[13] =  (float)Math.Tanh(cp[13]  )  /*dummy*/;
+                            cp[14] =  (float)Math.Tanh(cp[14]  )  /*dummy*/;
+                            cp[15] =  (float)Math.Tanh(cp[15]  )  /*dummy*/;
+                            cp[16] =  (float)Math.Tanh(cp[16]  )  /*dummy*/;
+                            cp[17] =  (float)Math.Tanh(cp[17]  )  /*dummy*/;
+                            cp[18] =  (float)Math.Tanh(cp[18]  )  /*dummy*/;
+                            cp[19] =  (float)Math.Tanh(cp[19]  )  /*dummy*/;
+                            cp[20] =  (float)Math.Tanh(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  (float)Math.Tanh(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        float* ap = ((float*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  (float)Math.Tanh(ap[0]  )  /*dummy*/;
+                            cp[1] =  (float)Math.Tanh(ap[1]  )  /*dummy*/;
+                            cp[2] =  (float)Math.Tanh(ap[2]  )  /*dummy*/;
+                            cp[3] =  (float)Math.Tanh(ap[3]  )  /*dummy*/;
+                            cp[4] =  (float)Math.Tanh(ap[4]  )  /*dummy*/;
+                            cp[5] =  (float)Math.Tanh(ap[5]  )  /*dummy*/;
+                            cp[6] =  (float)Math.Tanh(ap[6]  )  /*dummy*/;
+                            cp[7] =  (float)Math.Tanh(ap[7]  )  /*dummy*/;
+                            cp[8] =  (float)Math.Tanh(ap[8]  )  /*dummy*/;
+                            cp[9] =  (float)Math.Tanh(ap[9]  )  /*dummy*/;
+                            cp[10] =  (float)Math.Tanh(ap[10]  )  /*dummy*/;
+                            cp[11] =  (float)Math.Tanh(ap[11]  )  /*dummy*/;
+                            cp[12] =  (float)Math.Tanh(ap[12]  )  /*dummy*/;
+                            cp[13] =  (float)Math.Tanh(ap[13]  )  /*dummy*/;
+                            cp[14] =  (float)Math.Tanh(ap[14]  )  /*dummy*/;
+                            cp[15] =  (float)Math.Tanh(ap[15]  )  /*dummy*/;
+                            cp[16] =  (float)Math.Tanh(ap[16]  )  /*dummy*/;
+                            cp[17] =  (float)Math.Tanh(ap[17]  )  /*dummy*/;
+                            cp[18] =  (float)Math.Tanh(ap[18]  )  /*dummy*/;
+                            cp[19] =  (float)Math.Tanh(ap[19]  )  /*dummy*/;
+                            cp[20] =  (float)Math.Tanh(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  (float)Math.Tanh(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( float* arrAP = arrA)
+                fixed ( float* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<float>(retStorage);
+            }
+        }
+        /// <summary>Hyperbolic tangent of array elements</summary>
+        /// <param name="A">Input array</param>
+        /// <returns>Hyperbolic tangent of array elements</returns>
+        /// <remarks><para>If the input array is empty, an empty array will be returned.</para>
+        /// <para>The array returned will be a dense array.</para></remarks>
+        public unsafe static  ILRetArray<double>  tanh (ILInArray< double > A) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return new  ILRetArray<double>(A.Size); 
+                ILSize inDim = A.Size;
+                double[] arrA = A.GetArrayForRead(); 
+                double [] retArr;
+                int outLen = inDim.NumberOfElements;
+                bool inplace = true;
+               
+                if (!A.TryGetStorage4InplaceOp(out retArr)) {
+                    retArr = ILMemoryPool.Pool.New<double>(outLen);
+                    inplace = false; 
+                }
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen;
+                    workItemCount = 1;
+                }
+                ILDenseStorage<double> retStorage = new ILDenseStorage<double>(retArr, inDim);
+                
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, bool> range = (Tuple<int, int, IntPtr, IntPtr, bool>)data;
+                   
+                    double* cp = ((double*)range.Item4 + range.Item1);
+                    int len = range.Item2; 
+                    if (range.Item5) { 
+                        // inplace
+                        while (len > 20) {
+                            cp[0] =  Math.Tanh(cp[0]  )  /*dummy*/;
+                            cp[1] =  Math.Tanh(cp[1]  )  /*dummy*/;
+                            cp[2] =  Math.Tanh(cp[2]  )  /*dummy*/;
+                            cp[3] =  Math.Tanh(cp[3]  )  /*dummy*/;
+                            cp[4] =  Math.Tanh(cp[4]  )  /*dummy*/;
+                            cp[5] =  Math.Tanh(cp[5]  )  /*dummy*/;
+                            cp[6] =  Math.Tanh(cp[6]  )  /*dummy*/;
+                            cp[7] =  Math.Tanh(cp[7]  )  /*dummy*/;
+                            cp[8] =  Math.Tanh(cp[8]  )  /*dummy*/;
+                            cp[9] =  Math.Tanh(cp[9]  )  /*dummy*/;
+                            cp[10] =  Math.Tanh(cp[10]  )  /*dummy*/;
+                            cp[11] =  Math.Tanh(cp[11]  )  /*dummy*/;
+                            cp[12] =  Math.Tanh(cp[12]  )  /*dummy*/;
+                            cp[13] =  Math.Tanh(cp[13]  )  /*dummy*/;
+                            cp[14] =  Math.Tanh(cp[14]  )  /*dummy*/;
+                            cp[15] =  Math.Tanh(cp[15]  )  /*dummy*/;
+                            cp[16] =  Math.Tanh(cp[16]  )  /*dummy*/;
+                            cp[17] =  Math.Tanh(cp[17]  )  /*dummy*/;
+                            cp[18] =  Math.Tanh(cp[18]  )  /*dummy*/;
+                            cp[19] =  Math.Tanh(cp[19]  )  /*dummy*/;
+                            cp[20] =  Math.Tanh(cp[20]  )  /*dummy*/;
+                            cp+=21; len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Math.Tanh(*cp  )  /*dummy*/;
+                            cp++;
+                        }
+                    } else {
+                        double* ap = ((double*)range.Item3 + range.Item1);
+                        while (len > 20) {
+                            cp[0] =  Math.Tanh(ap[0]  )  /*dummy*/;
+                            cp[1] =  Math.Tanh(ap[1]  )  /*dummy*/;
+                            cp[2] =  Math.Tanh(ap[2]  )  /*dummy*/;
+                            cp[3] =  Math.Tanh(ap[3]  )  /*dummy*/;
+                            cp[4] =  Math.Tanh(ap[4]  )  /*dummy*/;
+                            cp[5] =  Math.Tanh(ap[5]  )  /*dummy*/;
+                            cp[6] =  Math.Tanh(ap[6]  )  /*dummy*/;
+                            cp[7] =  Math.Tanh(ap[7]  )  /*dummy*/;
+                            cp[8] =  Math.Tanh(ap[8]  )  /*dummy*/;
+                            cp[9] =  Math.Tanh(ap[9]  )  /*dummy*/;
+                            cp[10] =  Math.Tanh(ap[10]  )  /*dummy*/;
+                            cp[11] =  Math.Tanh(ap[11]  )  /*dummy*/;
+                            cp[12] =  Math.Tanh(ap[12]  )  /*dummy*/;
+                            cp[13] =  Math.Tanh(ap[13]  )  /*dummy*/;
+                            cp[14] =  Math.Tanh(ap[14]  )  /*dummy*/;
+                            cp[15] =  Math.Tanh(ap[15]  )  /*dummy*/;
+                            cp[16] =  Math.Tanh(ap[16]  )  /*dummy*/;
+                            cp[17] =  Math.Tanh(ap[17]  )  /*dummy*/;
+                            cp[18] =  Math.Tanh(ap[18]  )  /*dummy*/;
+                            cp[19] =  Math.Tanh(ap[19]  )  /*dummy*/;
+                            cp[20] =  Math.Tanh(ap[20]  )  /*dummy*/;
+                            ap += 21;
+                            cp += 21;
+                            len -= 21; 
+                        }
+                        while (len-- > 0) {
+                            *cp =  Math.Tanh(*ap  )  /*dummy*/;
+                            ap++;
+                            cp++;
+                        }
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                fixed ( double* arrAP = arrA)
+                fixed ( double* retArrP = retArr) {
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, bool> range
+                            = new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, bool>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                return new  ILRetArray<double>(retStorage);
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+   }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/trace.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/trace.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/trace.cs	(revision 9102)
@@ -0,0 +1,157 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions;
+
+
+namespace ILNumerics {
+    public partial class ILMath {
+
+
+        /// <summary>
+        /// Trace of matrix
+        /// </summary>
+        /// <param name="A">Input matrix, size [m x n]</param>
+        /// <returns>Scalar of same type as A with the sum of diagonal elements of A.</returns>
+        public static ILRetArray< double> trace( ILInArray< double> A ) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return empty< double>(A.Size);
+                if (A.IsVector || A.IsScalar)
+                    return A[0];
+                return sum(diag(A));
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// Trace of matrix
+        /// </summary>
+        /// <param name="A">Input matrix, size [m x n]</param>
+        /// <returns>Scalar of same type as A with the sum of diagonal elements of A.</returns>
+        public static ILRetArray< Int64> trace( ILInArray< Int64> A ) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return empty< Int64>(A.Size);
+                if (A.IsVector || A.IsScalar)
+                    return A[0];
+                return sum(diag(A));
+            }
+        }
+        /// <summary>
+        /// Trace of matrix
+        /// </summary>
+        /// <param name="A">Input matrix, size [m x n]</param>
+        /// <returns>Scalar of same type as A with the sum of diagonal elements of A.</returns>
+        public static ILRetArray< Int32> trace( ILInArray< Int32> A ) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return empty< Int32>(A.Size);
+                if (A.IsVector || A.IsScalar)
+                    return A[0];
+                return sum(diag(A));
+            }
+        }
+        /// <summary>
+        /// Trace of matrix
+        /// </summary>
+        /// <param name="A">Input matrix, size [m x n]</param>
+        /// <returns>Scalar of same type as A with the sum of diagonal elements of A.</returns>
+        public static ILRetArray< float> trace( ILInArray< float> A ) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return empty< float>(A.Size);
+                if (A.IsVector || A.IsScalar)
+                    return A[0];
+                return sum(diag(A));
+            }
+        }
+        /// <summary>
+        /// Trace of matrix
+        /// </summary>
+        /// <param name="A">Input matrix, size [m x n]</param>
+        /// <returns>Scalar of same type as A with the sum of diagonal elements of A.</returns>
+        public static ILRetArray< fcomplex> trace( ILInArray< fcomplex> A ) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return empty< fcomplex>(A.Size);
+                if (A.IsVector || A.IsScalar)
+                    return A[0];
+                return sum(diag(A));
+            }
+        }
+        /// <summary>
+        /// Trace of matrix
+        /// </summary>
+        /// <param name="A">Input matrix, size [m x n]</param>
+        /// <returns>Scalar of same type as A with the sum of diagonal elements of A.</returns>
+        public static ILRetArray< complex> trace( ILInArray< complex> A ) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return empty< complex>(A.Size);
+                if (A.IsVector || A.IsScalar)
+                    return A[0];
+                return sum(diag(A));
+            }
+        }
+        /// <summary>
+        /// Trace of matrix
+        /// </summary>
+        /// <param name="A">Input matrix, size [m x n]</param>
+        /// <returns>Scalar of same type as A with the sum of diagonal elements of A.</returns>
+        public static ILRetArray< byte> trace( ILInArray< byte> A ) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty)
+                    return empty< byte>(A.Size);
+                if (A.IsVector || A.IsScalar)
+                    return A[0];
+                return sum(diag(A));
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/tril_u.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/tril_u.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/tril_u.cs	(revision 9102)
@@ -0,0 +1,79 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions;
+
+namespace ILNumerics  {
+    public partial class ILMath {
+
+        /// <summary>
+        /// Upper triangular part of matrix
+        /// </summary>
+        /// <typeparam name="T">Inner type of matrix</typeparam>
+        /// <param name="A">Input matrix, size [m x n]</param>
+        /// <returns>Array of size [m x n], holding upper triangular part of A</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If A has more than 2 dimensions.</exception>
+        public static ILRetArray<T> triu <T>(ILInArray<T> A) {
+            using (ILScope.Enter(A)) {
+                if (A.Size.NumberOfDimensions > 2)
+                    throw new ILArgumentException("input argument must be matrix");
+                return new ILRetArray<T>(A.Storage.copyUpperTriangle(A.Size[0]));
+            }
+        }
+        /// <summary>
+        /// Lower triangular part of matrix
+        /// </summary>
+        /// <typeparam name="T">Inner type of matrix</typeparam>
+        /// <param name="A">Input matrix, size [m x n]</param>
+        /// <returns>Array of size [m x n], holding lower triangular part of A</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If A has more than 2 dimensions.</exception>
+        public static ILRetArray<T> tril <T>(ILInArray<T> A) {
+            using (ILScope.Enter(A)) {
+                if (A.Size.NumberOfDimensions > 2)
+                    throw new ILArgumentException("input argument must be matrix!");
+                return new ILRetArray<T>(A.Storage.copyLowerTriangle());
+            }
+        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/var.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/var.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/var.cs	(revision 9102)
@@ -0,0 +1,213 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics;
+using ILNumerics.Exceptions;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+
+
+
+namespace ILNumerics {
+
+    public partial class ILMath {
+
+
+        /// <summary>
+        /// Variance along dimension of A
+        /// </summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="Weights">[Optional] Vector of scaling factors, same length as working dimension of A, default: no scaling</param>
+        /// <param name="biased">[Optional] true: apply biased normalization to result, default: false (non-biased)</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns>Variances</returns>
+        /// <remarks><para>On scalar A a scalar 0 of the same shape as A is returned.</para>
+        /// <para>On empty A an empty array is returned, having the dimension to operate along reduced to length 1.</para>
+        /// <para>The parameters <paramref name="Weights"/>, <paramref name="biased"/> and <paramref name="dim"/> are optional. 
+        /// Ommiting either one will choose its respective default value.</para>
+        /// <para> The result for <paramref name="biased"/> = true is computed by the following formula: 
+        /// <code>r = (A - mean(A)); 
+        /// var = sum(r * r) / A.D[dim];</code>
+        /// If <paramref name="biased"/> is false (default) the normalization is done with the length of the working dimension of A as follows: 
+        /// <code>r = (A - mean(A)); 
+        /// var = sum(r * r) / (A.D[dim] - 1); </code>
+        /// If <paramref name="Weights"/> is given, the parameter <paramref name="biased"/> is ignored.</para>
+        /// <para>If <paramref name="Weights"/> is given, the normalization is applied to r as follows: 
+        /// <code>w = w / sum(w); 
+        /// r = A - sum(w * A);
+        /// var = sum(w * (r * r)); 
+        /// </code></para></remarks>
+        public static ILRetArray<double> var(ILInArray<double> A, 
+                                                            ILInArray<double> Weights = null, 
+                                                            bool biased = false, int dim = -1) {
+            using (ILScope.Enter(A, Weights)) {
+                if (isnull(A)) 
+                    throw new ILArgumentException("input parameter A must not be null");
+                if (A.IsScalar) {
+                    return zeros<double>(A.S); 
+                }
+                if (dim == -1) {
+                    dim = A.S.WorkingDimension(); 
+                    if (dim < 0) 
+                        dim = 0; 
+                }
+                if (A.IsEmpty) {
+                    int[] dims = A.S.ToIntArray(); 
+                    dims[dim] = 1;
+                    return zeros<double>(dims); 
+                }
+                int n = A.S[dim]; 
+                if (isnull(Weights)) {
+                    // unweighted
+                    ILArray<double> tmp = n; 
+                    if (!biased && n > 1) {
+                        tmp.a = tmp - 1; 
+                    }
+                    ILArray<double> tmpM = sum(A, dim) / n;
+                    ILArray<double> AminTmpM = A - tmpM;
+                    return sum(AminTmpM * AminTmpM, dim) / tmp; 
+                } else {
+                    // weighted 
+                    if (!Weights.IsVector || Weights.S.NumberOfElements != n) {
+                        throw new ILArgumentException("Weights parameter must be a vector of the length of the working dimension of A"); 
+                    }
+                    if (any(Weights < 0)) {
+                        throw new ILArgumentException("values of Weights parameter must all be positive");
+                    }
+                    ILArray<double> locWeights; 
+                    if (!A.IsMatrix) {
+                        // vector expansion currently only works for vectors on matrices
+                        ILArray<int> wdims = ones<int>(Math.Max(dim, ndims(A))); 
+                        wdims[dim] = Weights.Length;
+                        locWeights = reshape(Weights, new ILSize(wdims)) / sumall(Weights);
+                        int[] repDims = A.S.ToIntArray(); 
+                        repDims[dim] = 1;
+                        locWeights = repmat(locWeights, repDims); 
+                    }
+                    ILArray<double> r = A - sum(Weights * A, dim);
+                    return sum(Weights * (r * r), dim);
+                }
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// Variance along dimension of A
+        /// </summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="Weights">[Optional] Vector of scaling factors, same length as working dimension of A, default: no scaling</param>
+        /// <param name="biased">[Optional] true: apply biased normalization to result, default: false (non-biased)</param>
+        /// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns>Variances</returns>
+        /// <remarks><para>On scalar A a scalar 0 of the same shape as A is returned.</para>
+        /// <para>On empty A an empty array is returned, having the dimension to operate along reduced to length 1.</para>
+        /// <para>The parameters <paramref name="Weights"/>, <paramref name="biased"/> and <paramref name="dim"/> are optional. 
+        /// Ommiting either one will choose its respective default value.</para>
+        /// <para> The result for <paramref name="biased"/> = true is computed by the following formula: 
+        /// <code>r = (A - mean(A)); 
+        /// var = sum(r * r) / A.D[dim];</code>
+        /// If <paramref name="biased"/> is false (default) the normalization is done with the length of the working dimension of A as follows: 
+        /// <code>r = (A - mean(A)); 
+        /// var = sum(r * r) / (A.D[dim] - 1); </code>
+        /// If <paramref name="Weights"/> is given, the parameter <paramref name="biased"/> is ignored.</para>
+        /// <para>If <paramref name="Weights"/> is given, the normalization is applied to r as follows: 
+        /// <code>w = w / sum(w); 
+        /// r = A - sum(w * A);
+        /// var = sum(w * (r * r)); 
+        /// </code></para></remarks>
+        public static ILRetArray<float> var(ILInArray<float> A, 
+                                                            ILInArray<float> Weights = null, 
+                                                            bool biased = false, int dim = -1) {
+            using (ILScope.Enter(A, Weights)) {
+                if (isnull(A)) 
+                    throw new ILArgumentException("input parameter A must not be null");
+                if (A.IsScalar) {
+                    return zeros<float>(A.S); 
+                }
+                if (dim == -1) {
+                    dim = A.S.WorkingDimension(); 
+                    if (dim < 0) 
+                        dim = 0; 
+                }
+                if (A.IsEmpty) {
+                    int[] dims = A.S.ToIntArray(); 
+                    dims[dim] = 1;
+                    return zeros<float>(dims); 
+                }
+                int n = A.S[dim]; 
+                if (isnull(Weights)) {
+                    // unweighted
+                    ILArray<float> tmp = n; 
+                    if (!biased && n > 1) {
+                        tmp.a = tmp - 1; 
+                    }
+                    ILArray<float> tmpM = sum(A, dim) / n;
+                    ILArray<float> AminTmpM = A - tmpM;
+                    return sum(AminTmpM * AminTmpM, dim) / tmp; 
+                } else {
+                    // weighted 
+                    if (!Weights.IsVector || Weights.S.NumberOfElements != n) {
+                        throw new ILArgumentException("Weights parameter must be a vector of the length of the working dimension of A"); 
+                    }
+                    if (any(Weights < 0)) {
+                        throw new ILArgumentException("values of Weights parameter must all be positive");
+                    }
+                    ILArray<float> locWeights; 
+                    if (!A.IsMatrix) {
+                        // vector expansion currently only works for vectors on matrices
+                        ILArray<int> wdims = ones<int>(Math.Max(dim, ndims(A))); 
+                        wdims[dim] = Weights.Length;
+                        locWeights = reshape(Weights, new ILSize(wdims)) / sumall(Weights);
+                        int[] repDims = A.S.ToIntArray(); 
+                        repDims[dim] = 1;
+                        locWeights = repmat(locWeights, repDims); 
+                    }
+                    ILArray<float> r = A - sum(Weights * A, dim);
+                    return sum(Weights * (r * r), dim);
+                }
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+   }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/vec.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/vec.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/vec.cs	(revision 9102)
@@ -0,0 +1,240 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.InteropServices; 
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Native;
+using ILNumerics.Exceptions;
+
+namespace ILNumerics {
+
+	public partial class ILMath {
+
+        /// <summary>
+        /// Regulary spaced vector
+        /// </summary>
+        /// <param name="start">Start value</param>
+        /// <param name="end">End value</param>
+        /// <returns>Row vector of size 1xN, where N is the number of elements 
+        /// between start and end, all equally spaced with interval 1. The last element 
+        /// of the returned vector will be less than or equal to end, if start <![CDATA[<]]> end.</returns>
+        /// <remarks>This is the same as vector (start,1,end).</remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If start <![CDATA[>]]> end</exception>
+        public static ILRetArray<double> vec(ILBaseArray start, ILBaseArray end) {
+            return vec<double>(start, 1, end);
+        }
+
+        /// <summary>
+        /// Regularly spaced vector, spacing 1
+        /// </summary>
+        /// <param name="start">Start value</param>
+        /// <param name="end">End value</param>
+        /// <returns>Row vector of size 1xN, where N is the number of elements 
+        /// between start and end, all equally spaced with stepsize of 1. The last element 
+        /// of the returned vector will be less than or equal to end, if start &lt; end. </returns>
+        public static ILRetArray<T> vec<T>(ILBaseArray start, ILBaseArray end) {
+            return vec<T>(start, 1, end);
+        }
+
+        /// <summary>
+        /// Regulary spaced column vector
+        /// </summary>
+        /// <param name="start">Start value</param>
+        /// <param name="step">Step size</param>
+        /// <param name="end">End value</param>
+        /// <returns>Column vector of length N, where N is the number of elements 
+        /// between start and end, all equally spaced with stepsize of 'step'. The last element 
+        /// of the returned vector will be less than or equal to end, if start &lt; end. If start 
+        /// &gt; end, the elements in the vector will linearly decrease from 
+        /// start to end. In this case, step must be negative.</returns>
+        /// <remarks><para>The shape of the vector created is controlled by the setting switch <see cref="ILNumerics.Settings.CreateRowVectorsByDefault"/>.
+        /// This setting defaults to 'false' which will cause the creation of a column vector. </para></remarks>
+        public static ILRetArray<T> vec<T>(ILBaseArray start, ILBaseArray step, ILBaseArray end) {
+            using (ILScope.Enter(start, step, end)) {
+                if (object.Equals(start, null) || !start.IsNumeric || !start.IsScalar) throw new ILArgumentException("start must be numeric scalar");
+                if (object.Equals(step, null) || !step.IsNumeric || !step.IsScalar) throw new ILArgumentException("step must be numeric scalar");
+                if (object.Equals(end, null) || !end.IsNumeric || !end.IsScalar) throw new ILArgumentException("end must be numeric scalar");
+                double dStart = todouble(start).GetValue(0);
+                double dStep = todouble(step).GetValue(0);
+                double dEnd = todouble(end).GetValue(0);
+
+                if (dStep == 0)
+                    throw new ILArgumentException("step must not be 0");
+                if (dStart > dEnd && dStep > 0)
+                    throw new ILArgumentException("if start > end, step must be negativ");
+                if (dStart < dEnd && dStep < 0)
+                    throw new ILArgumentException("if start < end, step must be positiv");
+                int nrElements = (int)Math.Floor((dEnd - dStart) / dStep) + 1;
+                T[] data = ILMemoryPool.Pool.New<T>(nrElements);
+                if (false) {
+
+                    
+                } else if (data is  double[]) {
+                    unsafe {
+                        
+                        double val = ( double)dStart;
+                        fixed ( double* pDataConst = (data as  double[])) {
+                            
+                            double* pData = pDataConst;
+                            
+                            double* lastElement = pDataConst + nrElements;
+                            while (pData < lastElement) {
+                                *pData++ = val;
+                                val = ( double)(val + dStep);
+                            }
+                        }
+                    }
+
+#region HYCALPER AUTO GENERATED CODE
+
+                   
+                } else if (data is  byte[]) {
+                    unsafe {
+                       
+                        byte val = ( byte)dStart;
+                        fixed ( byte* pDataConst = (data as  byte[])) {
+                           
+                            byte* pData = pDataConst;
+                           
+                            byte* lastElement = pDataConst + nrElements;
+                            while (pData < lastElement) {
+                                *pData++ = val;
+                                val = ( byte)(val + dStep);
+                            }
+                        }
+                    }
+                   
+                } else if (data is  Int64[]) {
+                    unsafe {
+                       
+                        Int64 val = ( Int64)dStart;
+                        fixed ( Int64* pDataConst = (data as  Int64[])) {
+                           
+                            Int64* pData = pDataConst;
+                           
+                            Int64* lastElement = pDataConst + nrElements;
+                            while (pData < lastElement) {
+                                *pData++ = val;
+                                val = ( Int64)(val + dStep);
+                            }
+                        }
+                    }
+                   
+                } else if (data is  complex[]) {
+                    unsafe {
+                       
+                        complex val = ( complex)dStart;
+                        fixed ( complex* pDataConst = (data as  complex[])) {
+                           
+                            complex* pData = pDataConst;
+                           
+                            complex* lastElement = pDataConst + nrElements;
+                            while (pData < lastElement) {
+                                *pData++ = val;
+                                val = ( complex)(val + dStep);
+                            }
+                        }
+                    }
+                   
+                } else if (data is  fcomplex[]) {
+                    unsafe {
+                       
+                        fcomplex val = ( fcomplex)dStart;
+                        fixed ( fcomplex* pDataConst = (data as  fcomplex[])) {
+                           
+                            fcomplex* pData = pDataConst;
+                           
+                            fcomplex* lastElement = pDataConst + nrElements;
+                            while (pData < lastElement) {
+                                *pData++ = val;
+                                val = ( fcomplex)(val + dStep);
+                            }
+                        }
+                    }
+                   
+                } else if (data is  Int32[]) {
+                    unsafe {
+                       
+                        Int32 val = ( Int32)dStart;
+                        fixed ( Int32* pDataConst = (data as  Int32[])) {
+                           
+                            Int32* pData = pDataConst;
+                           
+                            Int32* lastElement = pDataConst + nrElements;
+                            while (pData < lastElement) {
+                                *pData++ = val;
+                                val = ( Int32)(val + dStep);
+                            }
+                        }
+                    }
+                   
+                } else if (data is  float[]) {
+                    unsafe {
+                       
+                        float val = ( float)dStart;
+                        fixed ( float* pDataConst = (data as  float[])) {
+                           
+                            float* pData = pDataConst;
+                           
+                            float* lastElement = pDataConst + nrElements;
+                            while (pData < lastElement) {
+                                *pData++ = val;
+                                val = ( float)(val + dStep);
+                            }
+                        }
+                    }
+
+#endregion HYCALPER AUTO GENERATED CODE
+               } else {
+                    throw new ILArgumentException(String.Format("vec is not defined for arrays of inner type '{0}'", typeof(T).Name));
+                }
+                if (Settings.CreateRowVectorsByDefault) {
+                    return new ILRetArray<T>(data, 1, nrElements);
+                } else {
+                    return new ILRetArray<T>(data, nrElements, 1);
+                }
+            }
+        }
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/xor.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/xor.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/xor.cs	(revision 9102)
@@ -0,0 +1,1912 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.InteropServices;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Native;
+using ILNumerics.Exceptions;
+
+
+
+namespace ILNumerics {
+
+    public partial class ILMath {
+
+
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>Elementwise logical 'xor' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array with the elementwise result of logical 'xor' for all elements in A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  xor(ILInArray<Int64> A, ILInArray<Int64> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                Int64[] arrA = A.GetArrayForRead();
+               
+                Int64[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0) != 0 ^ B.GetValue(0) != 0) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  xorEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    Int64 scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            Int64* ap = ((Int64*)range.Item3 + range.Item1);
+                            Int64* bp = ((Int64*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                                *cp = (*ap != 0 ^ *bp != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((Int64*)range.Item3 + range.Item1);
+                            scalar = *((Int64*)range.Item4);
+                            while (cp < cLast) {
+                                *cp = (scalar != 0 ^ *ap != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((Int64*)range.Item3);
+                            bp = ((Int64*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                                *cp = (scalar != 0 ^ *bp != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (Int64* arrAP = arrA)
+                fixed (Int64* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  xorEx(ILInArray<Int64> A, ILInArray<Int64> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                Int64[] arrA = A.GetArrayForRead();
+               
+                Int64[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    Int64* ap;
+                   
+                    Int64* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (Int64*)range.Item3;
+                                bp = (Int64*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap != 0 ^ *bp != 0) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (Int64*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (Int64*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap != 0 ^ *bp != 0) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( Int64* arrAP = arrA)
+                fixed ( Int64* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'xor' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array with the elementwise result of logical 'xor' for all elements in A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  xor(ILInArray<Int32> A, ILInArray<Int32> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                Int32[] arrA = A.GetArrayForRead();
+               
+                Int32[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0) != 0 ^ B.GetValue(0) != 0) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  xorEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    Int32 scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            Int32* ap = ((Int32*)range.Item3 + range.Item1);
+                            Int32* bp = ((Int32*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                                *cp = (*ap != 0 ^ *bp != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((Int32*)range.Item3 + range.Item1);
+                            scalar = *((Int32*)range.Item4);
+                            while (cp < cLast) {
+                                *cp = (scalar != 0 ^ *ap != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((Int32*)range.Item3);
+                            bp = ((Int32*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                                *cp = (scalar != 0 ^ *bp != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (Int32* arrAP = arrA)
+                fixed (Int32* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  xorEx(ILInArray<Int32> A, ILInArray<Int32> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                Int32[] arrA = A.GetArrayForRead();
+               
+                Int32[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    Int32* ap;
+                   
+                    Int32* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (Int32*)range.Item3;
+                                bp = (Int32*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap != 0 ^ *bp != 0) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (Int32*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (Int32*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap != 0 ^ *bp != 0) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( Int32* arrAP = arrA)
+                fixed ( Int32* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'xor' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array with the elementwise result of logical 'xor' for all elements in A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  xor(ILInArray<float> A, ILInArray<float> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                float[] arrA = A.GetArrayForRead();
+               
+                float[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0) != 0 ^ B.GetValue(0) != 0) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  xorEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    float scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            float* ap = ((float*)range.Item3 + range.Item1);
+                            float* bp = ((float*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                                *cp = (*ap != 0 ^ *bp != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((float*)range.Item3 + range.Item1);
+                            scalar = *((float*)range.Item4);
+                            while (cp < cLast) {
+                                *cp = (scalar != 0 ^ *ap != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((float*)range.Item3);
+                            bp = ((float*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                                *cp = (scalar != 0 ^ *bp != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (float* arrAP = arrA)
+                fixed (float* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  xorEx(ILInArray<float> A, ILInArray<float> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                float[] arrA = A.GetArrayForRead();
+               
+                float[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    float* ap;
+                   
+                    float* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (float*)range.Item3;
+                                bp = (float*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap != 0 ^ *bp != 0) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (float*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (float*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap != 0 ^ *bp != 0) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( float* arrAP = arrA)
+                fixed ( float* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'xor' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array with the elementwise result of logical 'xor' for all elements in A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  xor(ILInArray<fcomplex> A, ILInArray<fcomplex> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                fcomplex[] arrA = A.GetArrayForRead();
+               
+                fcomplex[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0) != 0 ^ B.GetValue(0) != 0) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  xorEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    fcomplex scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            fcomplex* ap = ((fcomplex*)range.Item3 + range.Item1);
+                            fcomplex* bp = ((fcomplex*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                                *cp = (*ap != 0 ^ *bp != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((fcomplex*)range.Item3 + range.Item1);
+                            scalar = *((fcomplex*)range.Item4);
+                            while (cp < cLast) {
+                                *cp = (scalar != 0 ^ *ap != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((fcomplex*)range.Item3);
+                            bp = ((fcomplex*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                                *cp = (scalar != 0 ^ *bp != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (fcomplex* arrAP = arrA)
+                fixed (fcomplex* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  xorEx(ILInArray<fcomplex> A, ILInArray<fcomplex> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                fcomplex[] arrA = A.GetArrayForRead();
+               
+                fcomplex[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    fcomplex* ap;
+                   
+                    fcomplex* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (fcomplex*)range.Item3;
+                                bp = (fcomplex*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap != 0 ^ *bp != 0) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (fcomplex*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (fcomplex*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap != 0 ^ *bp != 0) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( fcomplex* arrAP = arrA)
+                fixed ( fcomplex* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'xor' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array with the elementwise result of logical 'xor' for all elements in A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  xor(ILInArray<complex> A, ILInArray<complex> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                complex[] arrA = A.GetArrayForRead();
+               
+                complex[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0) != 0 ^ B.GetValue(0) != 0) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  xorEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    complex scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            complex* ap = ((complex*)range.Item3 + range.Item1);
+                            complex* bp = ((complex*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                                *cp = (*ap != 0 ^ *bp != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((complex*)range.Item3 + range.Item1);
+                            scalar = *((complex*)range.Item4);
+                            while (cp < cLast) {
+                                *cp = (scalar != 0 ^ *ap != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((complex*)range.Item3);
+                            bp = ((complex*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                                *cp = (scalar != 0 ^ *bp != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (complex* arrAP = arrA)
+                fixed (complex* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  xorEx(ILInArray<complex> A, ILInArray<complex> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                complex[] arrA = A.GetArrayForRead();
+               
+                complex[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    complex* ap;
+                   
+                    complex* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (complex*)range.Item3;
+                                bp = (complex*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap != 0 ^ *bp != 0) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (complex*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (complex*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap != 0 ^ *bp != 0) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( complex* arrAP = arrA)
+                fixed ( complex* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'xor' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array with the elementwise result of logical 'xor' for all elements in A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  xor(ILInArray<byte> A, ILInArray<byte> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                byte[] arrA = A.GetArrayForRead();
+               
+                byte[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0) != 0 ^ B.GetValue(0) != 0) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  xorEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    byte scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            byte* ap = ((byte*)range.Item3 + range.Item1);
+                            byte* bp = ((byte*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                                *cp = (*ap != 0 ^ *bp != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((byte*)range.Item3 + range.Item1);
+                            scalar = *((byte*)range.Item4);
+                            while (cp < cLast) {
+                                *cp = (scalar != 0 ^ *ap != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((byte*)range.Item3);
+                            bp = ((byte*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                                *cp = (scalar != 0 ^ *bp != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (byte* arrAP = arrA)
+                fixed (byte* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  xorEx(ILInArray<byte> A, ILInArray<byte> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                byte[] arrA = A.GetArrayForRead();
+               
+                byte[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    byte* ap;
+                   
+                    byte* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (byte*)range.Item3;
+                                bp = (byte*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap != 0 ^ *bp != 0) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (byte*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (byte*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap != 0 ^ *bp != 0) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( byte* arrAP = arrA)
+                fixed ( byte* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+        /// <summary>Elementwise logical 'xor' operator</summary>
+        /// <param name="A">Input array A</param>
+        /// <param name="B">Input array B</param>
+        /// <returns>Logical array with the elementwise result of logical 'xor' for all elements in A and B</returns>
+        /// <remarks><para>On empty input an empty array will be returned.</para>
+        /// <para>A and/or B may be scalar. The scalar value will be applied on all elements of the other array.</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If neither A nor B is scalar or empty, the dimensions of both arrays must match.</exception>
+        public unsafe static ILRetLogical  xor(ILInArray<double> A, ILInArray<double> B) {
+            using (ILScope.Enter(A, B)) {
+                int outLen;
+                BinOpItMode mode;
+                byte[] retArr;
+               
+                double[] arrA = A.GetArrayForRead();
+               
+                double[] arrB = B.GetArrayForRead(); 
+                ILSize outDims;
+                if (A.IsScalar) {
+                    if (B.IsScalar) {
+                        return new ILRetLogical(new byte[1] { (A.GetValue(0) != 0 ^ B.GetValue(0) != 0) ? (byte)1 : (byte)0 });
+                    } else if (B.IsEmpty) {
+                        return new ILRetLogical(B.Size);
+                    } else {
+                        outLen = B.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.SAN;
+                    }
+                    outDims = B.Size;
+                } else {
+                    outDims = A.Size;
+                    if (B.IsScalar) {
+                        if (A.IsEmpty) {
+                            return new ILRetLogical(A.Size);
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.ASN;
+                    } else {
+                        // array + array 
+                        if (!A.Size.IsSameSize(B.Size)) {
+                            return  xorEx(A,B); 
+                        }
+                        outLen = A.S.NumberOfElements;
+                        retArr = ILMemoryPool.Pool.New<byte>(outLen);
+                        mode = BinOpItMode.AAN;
+                    }
+                }
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = (Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>)data;
+                    byte* cLast, cp = (byte*)range.Item5 + range.Item1;
+                    double scalar;
+                    cLast = cp + range.Item2;
+                    #region loops
+                    switch (mode) {
+                        case BinOpItMode.AAN:
+                            double* ap = ((double*)range.Item3 + range.Item1);
+                            double* bp = ((double*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                                *cp = (*ap != 0 ^ *bp != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                ap++; 
+                                bp++; 
+                            }
+                            break;
+                        case BinOpItMode.ASN:
+                            ap = ((double*)range.Item3 + range.Item1);
+                            scalar = *((double*)range.Item4);
+                            while (cp < cLast) {
+                                *cp = (scalar != 0 ^ *ap != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                ap++;
+
+                            }
+                            break;
+                        case BinOpItMode.SAN:
+                            scalar = *((double*)range.Item3);
+                            bp = ((double*)range.Item4 + range.Item1);
+                            while (cp < cLast) {
+                                *cp = (scalar != 0 ^ *bp != 0) ? (byte)1 : (byte)0;
+                                cp++; 
+                                bp++; 
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                    #endregion
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+
+                #region do the work
+                fixed (double* arrAP = arrA)
+                fixed (double* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                    if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) {
+                        if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                            workItemLength = outLen / workItemCount;
+                        } else {
+                            workItemLength = outLen / 2;
+                            workItemCount = 2;
+                        }
+                    } else {
+                        workItemLength = outLen;
+                        workItemCount = 1;
+                    }
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr, BinOpItMode>
+                                (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP, mode));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                }
+
+                #endregion
+                return new ILRetLogical(retArr, outDims);
+            }
+        }
+
+        private static unsafe ILRetLogical  xorEx(ILInArray<double> A, ILInArray<double> B) {
+            using (ILScope.Enter(A, B)) {
+                #region parameter checking
+                if (isnull(A) || isnull(B))
+                    return new ILRetLogical(ILSize.Empty00);
+                if (A.IsEmpty) {
+                    return new ILRetLogical(B.S);
+                } else if (B.IsEmpty) {
+                    return new ILRetLogical(A.S);
+                }
+                //if (A.IsScalar || B.IsScalar || A.D.IsSameSize(B.D)) 
+                //    return add(A,B);
+                int dim = -1;
+                for (int l = 0; l < Math.Max(A.S.NumberOfDimensions, B.S.NumberOfDimensions); l++) {
+                    if (A.S[l] != B.S[l]) {
+                        if (dim >= 0 || (A.S[l] != 1 && B.S[l] != 1)) {
+                            throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                        }
+                        dim = l;
+                    }
+                }
+                if (dim > 1)
+                    throw new ILArgumentException("singleton dimension expansion currently is only supported for colum- and row vectors");
+                #endregion
+
+                #region parameter preparation
+                byte[] retArr;
+               
+                double[] arrA = A.GetArrayForRead();
+               
+                double[] arrB = B.GetArrayForRead();
+                ILSize outDims;
+                BinOptItExMode mode;
+                int arrInc = 0;
+                int arrStepInc = 0;
+                int dimLen = 0;
+                if (A.IsVector) {
+                    outDims = B.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.VAN;
+                    dimLen = A.Length;
+                } else if (B.IsVector) {
+                    outDims = A.S;
+                    retArr = ILMemoryPool.Pool.New<byte>(outDims.NumberOfElements);
+                    mode = BinOptItExMode.AVN;
+                    dimLen = B.Length;
+                } else {
+                    throw new ILArgumentException("A and B must have the same size except for one simgleton dimension in A or B");
+                }
+                arrInc = (dim == 0) ? outDims.SequentialIndexDistance(1) : outDims.SequentialIndexDistance(0);
+                arrStepInc = outDims.SequentialIndexDistance(dim);
+                #endregion
+
+                #region worker loops definition
+                ILLogicalStorage retStorage = new ILLogicalStorage(retArr, outDims);
+                int workerCount = 1;
+                Action<object> worker = data => {
+                    // expects: iStart, iLen, ap, bp, cp
+                    Tuple<int, int, IntPtr, IntPtr, IntPtr> range =
+                        (Tuple<int, int, IntPtr, IntPtr, IntPtr>)data;
+                   
+                    double* ap;
+                   
+                    double* bp;
+                    byte* cp;
+                    switch (mode) {
+                        case BinOptItExMode.VAN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (double*)range.Item3;
+                                bp = (double*)range.Item4 + range.Item1 + s * arrStepInc; ;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap != 0 ^ *bp != 0) ? (byte)1 : (byte)0;
+                                    ap++;
+                                    bp += arrInc;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                        case BinOptItExMode.AVN:
+                            for (int s = 0; s < range.Item2; s++) {
+                                ap = (double*)range.Item3 + range.Item1 + s * arrStepInc;
+                                bp = (double*)range.Item4;
+                                cp = (byte*)range.Item5 + range.Item1 + s * arrStepInc;
+                                for (int l = 0; l < dimLen; l++) {
+                                    *cp = (*ap != 0 ^ *bp != 0) ? (byte)1 : (byte)0;
+                                    ap += arrInc;
+                                    bp++;
+                                    cp += arrInc;
+                                }
+                            }
+                            break;
+                    }
+                    System.Threading.Interlocked.Decrement(ref workerCount);
+                };
+                #endregion
+
+                #region work distribution
+                int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength;
+                int outLen = outDims.NumberOfElements;
+                if (Settings.s_maxNumberThreads > 1 && outLen / 2 >= Settings.s_minParallelElement1Count) {
+                    if (outLen / workItemCount > Settings.s_minParallelElement1Count) {
+                        workItemLength = outLen / dimLen / workItemCount;
+                        //workItemLength = (int)((double)outLen / workItemCount * 1.05);
+                    } else {
+                        workItemLength = outLen / dimLen / 2;
+                        workItemCount = 2;
+                    }
+                } else {
+                    workItemLength = outLen / dimLen;
+                    workItemCount = 1;
+                }
+
+                fixed ( double* arrAP = arrA)
+                fixed ( double* arrBP = arrB)
+                fixed (byte* retArrP = retArr) {
+
+                    for (; i < workItemCount - 1; i++) {
+                        Tuple<int, int, IntPtr, IntPtr, IntPtr> range
+                            = new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                               (i * workItemLength * arrStepInc, workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP);
+                        System.Threading.Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i, worker, range);
+                    }
+                    // the last (or may the only) chunk is done right here
+                    //System.Threading.Interlocked.Increment(ref retStorage.PendingTasks);
+                    worker(new Tuple<int, int, IntPtr, IntPtr, IntPtr>
+                                (i * workItemLength * arrStepInc, (outLen / dimLen) - i * workItemLength, (IntPtr)arrAP, (IntPtr)arrBP, (IntPtr)retArrP));
+
+                    ILThreadPool.Wait4Workers(ref workerCount);
+                }
+                #endregion
+
+                return new ILRetLogical(retStorage);
+            }
+        }
+
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/zeros.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/zeros.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/zeros.cs	(revision 9102)
@@ -0,0 +1,144 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.InteropServices; 
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Native;
+using ILNumerics.Exceptions;
+
+namespace ILNumerics {
+
+	public partial class ILMath {
+
+        /// <summary>
+        /// Create double array with all elements initialized to 0
+        /// </summary>
+        /// <param name="size">Size description</param>
+        /// <returns>Zeros-filled array.</returns>
+        public static ILRetArray<double> zeros(params int[] size) {
+            return (ILRetArray<double>)zeros(NumericType.Double, new ILSize(size));
+        }
+        /// <summary>
+        /// Create double array with all elements initialized to 0
+        /// </summary>
+        /// <param name="size">Size descriptor</param>
+        /// <returns>Zeros-filled array.</returns>
+        public static ILRetArray<double> zeros(ILSize size) {
+            return (ILRetArray<double>)zeros(NumericType.Double, size);
+        }
+        /// <summary>
+        /// Create array with all elements initialized to default(T)
+        /// </summary>
+        /// <typeparam name="T">Element type</typeparam>
+        /// <param name="size">Size descriptor</param>
+        /// <returns>New array, initialized to default(T)</returns>
+        public static ILRetArray<T> zeros<T>(ILSize size) {
+            return array<T>(default(T), size);
+        }
+        /// <summary>
+        /// Create new array of arbitrary element type, initialized to '0'
+        /// </summary>
+        /// <typeparam name="T">Element type</typeparam>
+        /// <param name="size">Size description</param>
+        /// <returns>New array having the size determined by 'dims', initialized to '0'</returns>
+        /// <remarks>For T deriving from Sytem.ValueType elements will be '0'. All other element types
+        /// will be initialized to default(T).</remarks>
+        public static ILRetArray<T> zeros<T>(params int[] size) {
+            return array<T>(default(T), new ILSize(size));
+        }
+        /// <summary>
+        /// Create array initialized with all elements set to zero
+        /// </summary>
+        /// <param name="type">Numeric type specification. One value out of the types listed in the <see cred="ILNumerics.NumericType"/>
+        /// enum.</param>
+        /// <param name="size">Size descriptor</param>
+        /// <returns>Array of inner type corresponding to <paramref name="type"/> argument.</returns>
+        /// <remarks>The array returned may be casted to the appropriate actual type afterwards. 
+        /// <para>
+        /// <list type="number"> 
+        /// <listheader>The following types are supported: </listheader>
+        /// <item>Double</item>
+        /// <item>Single</item>
+        /// <item>Complex</item>
+        /// <item>FComplex</item>
+        /// <item>Byte</item>
+        /// <item>Int32</item>
+        /// <item>Int64</item>
+        /// </list>
+        /// </para>
+        /// <para>This function is provided for downward compatibility reasons only and will be removed in a future update. It is recommended to use the <see cref="zeros{T}(ILSize)"/> or <see cref="zeros{T}(int[])"/> overloads instead.</para>
+        /// <para>The interface of this function does not confirm to the rules of functions in ILNumerics. Therefore, in order to prevent for potential memory issues, the return value should be converted to 
+        /// a concrete array type explicitely: </para>
+        /// <example>
+        /// <code>
+        /// ILArray&lt;double> A = todouble(zeros(NumericType.double, size(10,20))); 
+        /// 
+        /// // better and easier would be: 
+        /// ILArray&lt;double> B = zeros&lt;double>(10,20); 
+        /// </code>
+        /// </example>
+        /// </remarks>
+        [Obsolete("Use overload ILMath.zeros<T> instead!")]
+        public static ILBaseArray zeros(NumericType type, ILSize size) {
+            switch (type) {
+                case NumericType.Double:
+                    return zeros<double>(size);
+                case NumericType.Single:
+                    return zeros<float>(size);
+                case NumericType.Complex:
+                    return zeros<complex>(size);
+                case NumericType.FComplex:
+                    return zeros<fcomplex>(size);
+                case NumericType.Byte:
+                    return zeros<byte>(size);
+                case NumericType.Int32:
+                    return zeros<int>(size);
+                case NumericType.Int64:
+                    return zeros<Int64>(size);
+                default:
+                    return zeros<double>(size);
+            }
+        }
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/statistics/median.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/statistics/median.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/statistics/median.cs	(revision 9102)
@@ -0,0 +1,957 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading; 
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions;
+using System.Linq;
+
+
+namespace ILNumerics  {
+    public partial class ILMath {
+
+        /// <summary>
+        /// Calculate median along the specified dimension
+        /// </summary>
+        /// <param name="A">Input Array</param>
+        /// <returns><para>Array having the specified dimension reduced to the length 1 with the median of 
+        /// all elements along that dimension.</para>
+        /// <param name="dim">[Optional] Index of dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <para>The result will have the same number of dimensions as A, but the specified dimension will have the 
+        /// size 1.</para><para>If the specified dimension of A is empty, the median along that dimension will be NaN and that dimension will be 1.</para></returns>
+        public static ILRetArray<double>  median(ILInArray<double> A, int dim = -1)
+        {
+           
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+
+                if (dim >= A.Size.NumberOfDimensions)
+                    return   A.C;
+               
+                if (A.IsScalar) {
+                    
+                    return array<double>(new double[] { A.GetValue(0) }, 1, 1);
+                }
+
+                if (A.S[dim] == 1)
+                    return  A.C;
+
+                int[] newDims = A.S.ToIntArray();
+                newDims[dim] = 1;
+                ILSize retDimension = new ILSize(newDims);
+
+                if (A.IsEmpty)
+                    return array<double>(double.NaN,retDimension);
+
+                 double[] retArr = ILMemoryPool.Pool.New< double>(retDimension.NumberOfElements);
+
+                int maxRuns = retDimension.NumberOfElements;
+                
+                double[] aArray = null;
+                if (maxRuns == 1) {
+                    // ho: easier would be to use a new local array: 
+                    // ILArray<double> aClone = A.C; 
+                    // aArray = aClone.GetArrayForWrite();  here... (but the implemented way works just as well) 
+                    aArray = ILMemoryPool.Pool.New< double>(A.S[dim]);
+                    A.ExportValues(ref aArray);
+                    retArr[0] = median_worker(aArray, A.S[dim]);
+                    ILMemoryPool.Pool.Free(aArray);
+                } else
+                {
+                    #region may run parallel
+                    aArray = A.GetArrayForRead();
+                    int inc = A.Size.SequentialIndexDistance(dim);
+                    int dimLen = A.Size[dim];
+                    int modHelp = A.Size.NumberOfElements - 1;
+                    int modOut = retDimension.NumberOfElements - 1;
+                    int incOut = retDimension.SequentialIndexDistance(dim);
+                    int numelA = A.S.NumberOfElements;
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                    if (Settings.s_maxNumberThreads > 1 && maxRuns > 1 
+                        && numelA / 2 >= Settings.s_minParallelElement1Count) {
+
+                        if (maxRuns >= Settings.s_maxNumberThreads
+                            && numelA / Settings.s_maxNumberThreads > Settings.s_minParallelElement1Count) {
+                            workItemLength = maxRuns / workItemCount;
+                        } else {
+                            workItemLength = maxRuns / 2;
+                            workItemCount = 2;
+                        }
+                        
+                    } else {
+                        workItemLength = maxRuns;
+                        workItemCount = 1;
+                    }
+                    Action<object> action = (data) => {
+                        Tuple<int, int> range = (Tuple<int, int>)data;
+                        int from = range.Item1, to = range.Item2;
+                        
+                        double[] tmpArr = ILMemoryPool.Pool.New< double>(dimLen);
+                        for (int c = from; c < to; c++)
+                        {
+                            int pos = (int)(((long)dimLen * c * inc) % modHelp);
+
+                            long posOut = ((long)c * incOut);
+                            if (posOut > modOut)
+                                posOut = ((posOut - 1) % modOut) + 1;
+                            int end = pos + dimLen * inc;
+                            int k = 0;
+                            // ho: TODO: probably faster if operating on a full clone of A. median_worker would handle LDA, start, end than ... 
+                            for (int j = pos; j < end; j += inc)
+                                tmpArr[k++] = aArray[j];
+                            retArr[posOut] = median_worker(tmpArr, dimLen);
+                        }
+                        ILMemoryPool.Pool.Free(tmpArr); 
+                        System.Threading.Interlocked.Decrement(ref workerCount);
+                    };
+                    for (; i < workItemCount - 1; i++) {
+                        Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,action, Tuple.Create(i * workItemLength, (i + 1) * workItemLength));
+                    }
+                    action(Tuple.Create(i * workItemLength, maxRuns));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                    #endregion
+                }
+                return array(retArr, newDims);
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// Calculate median along the specified dimension
+        /// </summary>
+        /// <param name="A">Input Array</param>
+        /// <returns><para>Array having the specified dimension reduced to the length 1 with the median of 
+        /// all elements along that dimension.</para>
+        /// <param name="dim">[Optional] Index of dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <para>The result will have the same number of dimensions as A, but the specified dimension will have the 
+        /// size 1.</para><para>If the specified dimension of A is empty, the median along that dimension will be NaN and that dimension will be 1.</para></returns>
+        public static ILRetArray<double>  median(ILInArray<Int64> A, int dim = -1)
+        {
+           
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+
+                if (dim >= A.Size.NumberOfDimensions)
+                    return  todouble(A.C);
+               
+                if (A.IsScalar) {
+                    
+                    return array<double>(new double[] { A.GetValue(0) }, 1, 1);
+                }
+
+                if (A.S[dim] == 1)
+                    return  todouble(A.C);
+
+                int[] newDims = A.S.ToIntArray();
+                newDims[dim] = 1;
+                ILSize retDimension = new ILSize(newDims);
+
+                if (A.IsEmpty)
+                    return array<double>(double.NaN,retDimension);
+
+                double[] retArr = ILMemoryPool.Pool.New< double>(retDimension.NumberOfElements);
+
+                int maxRuns = retDimension.NumberOfElements;
+               
+                Int64[] aArray = null;
+                if (maxRuns == 1) {
+                    // ho: easier would be to use a new local array: 
+                    // ILArray<double> aClone = A.C; 
+                    // aArray = aClone.GetArrayForWrite();  here... (but the implemented way works just as well) 
+                    aArray = ILMemoryPool.Pool.New< Int64>(A.S[dim]);
+                    A.ExportValues(ref aArray);
+                    retArr[0] = median_worker(aArray, A.S[dim]);
+                    ILMemoryPool.Pool.Free(aArray);
+                } else
+                {
+                    #region may run parallel
+                    aArray = A.GetArrayForRead();
+                    int inc = A.Size.SequentialIndexDistance(dim);
+                    int dimLen = A.Size[dim];
+                    int modHelp = A.Size.NumberOfElements - 1;
+                    int modOut = retDimension.NumberOfElements - 1;
+                    int incOut = retDimension.SequentialIndexDistance(dim);
+                    int numelA = A.S.NumberOfElements;
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                    if (Settings.s_maxNumberThreads > 1 && maxRuns > 1 
+                        && numelA / 2 >= Settings.s_minParallelElement1Count) {
+
+                        if (maxRuns >= Settings.s_maxNumberThreads
+                            && numelA / Settings.s_maxNumberThreads > Settings.s_minParallelElement1Count) {
+                            workItemLength = maxRuns / workItemCount;
+                        } else {
+                            workItemLength = maxRuns / 2;
+                            workItemCount = 2;
+                        }
+                        
+                    } else {
+                        workItemLength = maxRuns;
+                        workItemCount = 1;
+                    }
+                    Action<object> action = (data) => {
+                        Tuple<int, int> range = (Tuple<int, int>)data;
+                        int from = range.Item1, to = range.Item2;
+                       
+                        Int64[] tmpArr = ILMemoryPool.Pool.New< Int64>(dimLen);
+                        for (int c = from; c < to; c++)
+                        {
+                            int pos = (int)(((long)dimLen * c * inc) % modHelp);
+
+                            long posOut = ((long)c * incOut);
+                            if (posOut > modOut)
+                                posOut = ((posOut - 1) % modOut) + 1;
+                            int end = pos + dimLen * inc;
+                            int k = 0;
+                            // ho: TODO: probably faster if operating on a full clone of A. median_worker would handle LDA, start, end than ... 
+                            for (int j = pos; j < end; j += inc)
+                                tmpArr[k++] = aArray[j];
+                            retArr[posOut] = median_worker(tmpArr, dimLen);
+                        }
+                        ILMemoryPool.Pool.Free(tmpArr); 
+                        System.Threading.Interlocked.Decrement(ref workerCount);
+                    };
+                    for (; i < workItemCount - 1; i++) {
+                        Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,action, Tuple.Create(i * workItemLength, (i + 1) * workItemLength));
+                    }
+                    action(Tuple.Create(i * workItemLength, maxRuns));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                    #endregion
+                }
+                return array(retArr, newDims);
+            }
+        }
+        /// <summary>
+        /// Calculate median along the specified dimension
+        /// </summary>
+        /// <param name="A">Input Array</param>
+        /// <returns><para>Array having the specified dimension reduced to the length 1 with the median of 
+        /// all elements along that dimension.</para>
+        /// <param name="dim">[Optional] Index of dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <para>The result will have the same number of dimensions as A, but the specified dimension will have the 
+        /// size 1.</para><para>If the specified dimension of A is empty, the median along that dimension will be NaN and that dimension will be 1.</para></returns>
+        public static ILRetArray<double>  median(ILInArray<Int32> A, int dim = -1)
+        {
+           
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+
+                if (dim >= A.Size.NumberOfDimensions)
+                    return  todouble(A.C);
+               
+                if (A.IsScalar) {
+                    
+                    return array<double>(new double[] { A.GetValue(0) }, 1, 1);
+                }
+
+                if (A.S[dim] == 1)
+                    return  todouble(A.C);
+
+                int[] newDims = A.S.ToIntArray();
+                newDims[dim] = 1;
+                ILSize retDimension = new ILSize(newDims);
+
+                if (A.IsEmpty)
+                    return array<double>(double.NaN,retDimension);
+
+                double[] retArr = ILMemoryPool.Pool.New< double>(retDimension.NumberOfElements);
+
+                int maxRuns = retDimension.NumberOfElements;
+               
+                Int32[] aArray = null;
+                if (maxRuns == 1) {
+                    // ho: easier would be to use a new local array: 
+                    // ILArray<double> aClone = A.C; 
+                    // aArray = aClone.GetArrayForWrite();  here... (but the implemented way works just as well) 
+                    aArray = ILMemoryPool.Pool.New< Int32>(A.S[dim]);
+                    A.ExportValues(ref aArray);
+                    retArr[0] = median_worker(aArray, A.S[dim]);
+                    ILMemoryPool.Pool.Free(aArray);
+                } else
+                {
+                    #region may run parallel
+                    aArray = A.GetArrayForRead();
+                    int inc = A.Size.SequentialIndexDistance(dim);
+                    int dimLen = A.Size[dim];
+                    int modHelp = A.Size.NumberOfElements - 1;
+                    int modOut = retDimension.NumberOfElements - 1;
+                    int incOut = retDimension.SequentialIndexDistance(dim);
+                    int numelA = A.S.NumberOfElements;
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                    if (Settings.s_maxNumberThreads > 1 && maxRuns > 1 
+                        && numelA / 2 >= Settings.s_minParallelElement1Count) {
+
+                        if (maxRuns >= Settings.s_maxNumberThreads
+                            && numelA / Settings.s_maxNumberThreads > Settings.s_minParallelElement1Count) {
+                            workItemLength = maxRuns / workItemCount;
+                        } else {
+                            workItemLength = maxRuns / 2;
+                            workItemCount = 2;
+                        }
+                        
+                    } else {
+                        workItemLength = maxRuns;
+                        workItemCount = 1;
+                    }
+                    Action<object> action = (data) => {
+                        Tuple<int, int> range = (Tuple<int, int>)data;
+                        int from = range.Item1, to = range.Item2;
+                       
+                        Int32[] tmpArr = ILMemoryPool.Pool.New< Int32>(dimLen);
+                        for (int c = from; c < to; c++)
+                        {
+                            int pos = (int)(((long)dimLen * c * inc) % modHelp);
+
+                            long posOut = ((long)c * incOut);
+                            if (posOut > modOut)
+                                posOut = ((posOut - 1) % modOut) + 1;
+                            int end = pos + dimLen * inc;
+                            int k = 0;
+                            // ho: TODO: probably faster if operating on a full clone of A. median_worker would handle LDA, start, end than ... 
+                            for (int j = pos; j < end; j += inc)
+                                tmpArr[k++] = aArray[j];
+                            retArr[posOut] = median_worker(tmpArr, dimLen);
+                        }
+                        ILMemoryPool.Pool.Free(tmpArr); 
+                        System.Threading.Interlocked.Decrement(ref workerCount);
+                    };
+                    for (; i < workItemCount - 1; i++) {
+                        Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,action, Tuple.Create(i * workItemLength, (i + 1) * workItemLength));
+                    }
+                    action(Tuple.Create(i * workItemLength, maxRuns));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                    #endregion
+                }
+                return array(retArr, newDims);
+            }
+        }
+        /// <summary>
+        /// Calculate median along the specified dimension
+        /// </summary>
+        /// <param name="A">Input Array</param>
+        /// <returns><para>Array having the specified dimension reduced to the length 1 with the median of 
+        /// all elements along that dimension.</para>
+        /// <param name="dim">[Optional] Index of dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <para>The result will have the same number of dimensions as A, but the specified dimension will have the 
+        /// size 1.</para><para>If the specified dimension of A is empty, the median along that dimension will be NaN and that dimension will be 1.</para></returns>
+        public static ILRetArray<double>  median(ILInArray<byte> A, int dim = -1)
+        {
+           
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+
+                if (dim >= A.Size.NumberOfDimensions)
+                    return  todouble(A.C);
+               
+                if (A.IsScalar) {
+                    
+                    return array<double>(new double[] { A.GetValue(0) }, 1, 1);
+                }
+
+                if (A.S[dim] == 1)
+                    return  todouble(A.C);
+
+                int[] newDims = A.S.ToIntArray();
+                newDims[dim] = 1;
+                ILSize retDimension = new ILSize(newDims);
+
+                if (A.IsEmpty)
+                    return array<double>(double.NaN,retDimension);
+
+                double[] retArr = ILMemoryPool.Pool.New< double>(retDimension.NumberOfElements);
+
+                int maxRuns = retDimension.NumberOfElements;
+               
+                byte[] aArray = null;
+                if (maxRuns == 1) {
+                    // ho: easier would be to use a new local array: 
+                    // ILArray<double> aClone = A.C; 
+                    // aArray = aClone.GetArrayForWrite();  here... (but the implemented way works just as well) 
+                    aArray = ILMemoryPool.Pool.New< byte>(A.S[dim]);
+                    A.ExportValues(ref aArray);
+                    retArr[0] = median_worker(aArray, A.S[dim]);
+                    ILMemoryPool.Pool.Free(aArray);
+                } else
+                {
+                    #region may run parallel
+                    aArray = A.GetArrayForRead();
+                    int inc = A.Size.SequentialIndexDistance(dim);
+                    int dimLen = A.Size[dim];
+                    int modHelp = A.Size.NumberOfElements - 1;
+                    int modOut = retDimension.NumberOfElements - 1;
+                    int incOut = retDimension.SequentialIndexDistance(dim);
+                    int numelA = A.S.NumberOfElements;
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                    if (Settings.s_maxNumberThreads > 1 && maxRuns > 1 
+                        && numelA / 2 >= Settings.s_minParallelElement1Count) {
+
+                        if (maxRuns >= Settings.s_maxNumberThreads
+                            && numelA / Settings.s_maxNumberThreads > Settings.s_minParallelElement1Count) {
+                            workItemLength = maxRuns / workItemCount;
+                        } else {
+                            workItemLength = maxRuns / 2;
+                            workItemCount = 2;
+                        }
+                        
+                    } else {
+                        workItemLength = maxRuns;
+                        workItemCount = 1;
+                    }
+                    Action<object> action = (data) => {
+                        Tuple<int, int> range = (Tuple<int, int>)data;
+                        int from = range.Item1, to = range.Item2;
+                       
+                        byte[] tmpArr = ILMemoryPool.Pool.New< byte>(dimLen);
+                        for (int c = from; c < to; c++)
+                        {
+                            int pos = (int)(((long)dimLen * c * inc) % modHelp);
+
+                            long posOut = ((long)c * incOut);
+                            if (posOut > modOut)
+                                posOut = ((posOut - 1) % modOut) + 1;
+                            int end = pos + dimLen * inc;
+                            int k = 0;
+                            // ho: TODO: probably faster if operating on a full clone of A. median_worker would handle LDA, start, end than ... 
+                            for (int j = pos; j < end; j += inc)
+                                tmpArr[k++] = aArray[j];
+                            retArr[posOut] = median_worker(tmpArr, dimLen);
+                        }
+                        ILMemoryPool.Pool.Free(tmpArr); 
+                        System.Threading.Interlocked.Decrement(ref workerCount);
+                    };
+                    for (; i < workItemCount - 1; i++) {
+                        Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,action, Tuple.Create(i * workItemLength, (i + 1) * workItemLength));
+                    }
+                    action(Tuple.Create(i * workItemLength, maxRuns));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                    #endregion
+                }
+                return array(retArr, newDims);
+            }
+        }
+        /// <summary>
+        /// Calculate median along the specified dimension
+        /// </summary>
+        /// <param name="A">Input Array</param>
+        /// <returns><para>Array having the specified dimension reduced to the length 1 with the median of 
+        /// all elements along that dimension.</para>
+        /// <param name="dim">[Optional] Index of dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <para>The result will have the same number of dimensions as A, but the specified dimension will have the 
+        /// size 1.</para><para>If the specified dimension of A is empty, the median along that dimension will be NaN and that dimension will be 1.</para></returns>
+        public static ILRetArray<fcomplex>  median(ILInArray<fcomplex> A, int dim = -1)
+        {
+           
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+
+                if (dim >= A.Size.NumberOfDimensions)
+                    return  A.C;
+               
+                if (A.IsScalar) {
+                    
+                    return array<fcomplex>(new fcomplex[] { A.GetValue(0) }, 1, 1);
+                }
+
+                if (A.S[dim] == 1)
+                    return  A.C;
+
+                int[] newDims = A.S.ToIntArray();
+                newDims[dim] = 1;
+                ILSize retDimension = new ILSize(newDims);
+
+                if (A.IsEmpty)
+                    return array<fcomplex>(fcomplex.NaN,retDimension);
+
+                fcomplex[] retArr = ILMemoryPool.Pool.New< fcomplex>(retDimension.NumberOfElements);
+
+                int maxRuns = retDimension.NumberOfElements;
+               
+                fcomplex[] aArray = null;
+                if (maxRuns == 1) {
+                    // ho: easier would be to use a new local array: 
+                    // ILArray<double> aClone = A.C; 
+                    // aArray = aClone.GetArrayForWrite();  here... (but the implemented way works just as well) 
+                    aArray = ILMemoryPool.Pool.New< fcomplex>(A.S[dim]);
+                    A.ExportValues(ref aArray);
+                    retArr[0] = median_worker(aArray, A.S[dim]);
+                    ILMemoryPool.Pool.Free(aArray);
+                } else
+                {
+                    #region may run parallel
+                    aArray = A.GetArrayForRead();
+                    int inc = A.Size.SequentialIndexDistance(dim);
+                    int dimLen = A.Size[dim];
+                    int modHelp = A.Size.NumberOfElements - 1;
+                    int modOut = retDimension.NumberOfElements - 1;
+                    int incOut = retDimension.SequentialIndexDistance(dim);
+                    int numelA = A.S.NumberOfElements;
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                    if (Settings.s_maxNumberThreads > 1 && maxRuns > 1 
+                        && numelA / 2 >= Settings.s_minParallelElement1Count) {
+
+                        if (maxRuns >= Settings.s_maxNumberThreads
+                            && numelA / Settings.s_maxNumberThreads > Settings.s_minParallelElement1Count) {
+                            workItemLength = maxRuns / workItemCount;
+                        } else {
+                            workItemLength = maxRuns / 2;
+                            workItemCount = 2;
+                        }
+                        
+                    } else {
+                        workItemLength = maxRuns;
+                        workItemCount = 1;
+                    }
+                    Action<object> action = (data) => {
+                        Tuple<int, int> range = (Tuple<int, int>)data;
+                        int from = range.Item1, to = range.Item2;
+                       
+                        fcomplex[] tmpArr = ILMemoryPool.Pool.New< fcomplex>(dimLen);
+                        for (int c = from; c < to; c++)
+                        {
+                            int pos = (int)(((long)dimLen * c * inc) % modHelp);
+
+                            long posOut = ((long)c * incOut);
+                            if (posOut > modOut)
+                                posOut = ((posOut - 1) % modOut) + 1;
+                            int end = pos + dimLen * inc;
+                            int k = 0;
+                            // ho: TODO: probably faster if operating on a full clone of A. median_worker would handle LDA, start, end than ... 
+                            for (int j = pos; j < end; j += inc)
+                                tmpArr[k++] = aArray[j];
+                            retArr[posOut] = median_worker(tmpArr, dimLen);
+                        }
+                        ILMemoryPool.Pool.Free(tmpArr); 
+                        System.Threading.Interlocked.Decrement(ref workerCount);
+                    };
+                    for (; i < workItemCount - 1; i++) {
+                        Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,action, Tuple.Create(i * workItemLength, (i + 1) * workItemLength));
+                    }
+                    action(Tuple.Create(i * workItemLength, maxRuns));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                    #endregion
+                }
+                return array(retArr, newDims);
+            }
+        }
+        /// <summary>
+        /// Calculate median along the specified dimension
+        /// </summary>
+        /// <param name="A">Input Array</param>
+        /// <returns><para>Array having the specified dimension reduced to the length 1 with the median of 
+        /// all elements along that dimension.</para>
+        /// <param name="dim">[Optional] Index of dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <para>The result will have the same number of dimensions as A, but the specified dimension will have the 
+        /// size 1.</para><para>If the specified dimension of A is empty, the median along that dimension will be NaN and that dimension will be 1.</para></returns>
+        public static ILRetArray<float>  median(ILInArray<float> A, int dim = -1)
+        {
+           
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+
+                if (dim >= A.Size.NumberOfDimensions)
+                    return  A.C;
+               
+                if (A.IsScalar) {
+                    
+                    return array<float>(new float[] { A.GetValue(0) }, 1, 1);
+                }
+
+                if (A.S[dim] == 1)
+                    return  A.C;
+
+                int[] newDims = A.S.ToIntArray();
+                newDims[dim] = 1;
+                ILSize retDimension = new ILSize(newDims);
+
+                if (A.IsEmpty)
+                    return array<float>(float.NaN,retDimension);
+
+                float[] retArr = ILMemoryPool.Pool.New< float>(retDimension.NumberOfElements);
+
+                int maxRuns = retDimension.NumberOfElements;
+               
+                float[] aArray = null;
+                if (maxRuns == 1) {
+                    // ho: easier would be to use a new local array: 
+                    // ILArray<double> aClone = A.C; 
+                    // aArray = aClone.GetArrayForWrite();  here... (but the implemented way works just as well) 
+                    aArray = ILMemoryPool.Pool.New< float>(A.S[dim]);
+                    A.ExportValues(ref aArray);
+                    retArr[0] = median_worker(aArray, A.S[dim]);
+                    ILMemoryPool.Pool.Free(aArray);
+                } else
+                {
+                    #region may run parallel
+                    aArray = A.GetArrayForRead();
+                    int inc = A.Size.SequentialIndexDistance(dim);
+                    int dimLen = A.Size[dim];
+                    int modHelp = A.Size.NumberOfElements - 1;
+                    int modOut = retDimension.NumberOfElements - 1;
+                    int incOut = retDimension.SequentialIndexDistance(dim);
+                    int numelA = A.S.NumberOfElements;
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                    if (Settings.s_maxNumberThreads > 1 && maxRuns > 1 
+                        && numelA / 2 >= Settings.s_minParallelElement1Count) {
+
+                        if (maxRuns >= Settings.s_maxNumberThreads
+                            && numelA / Settings.s_maxNumberThreads > Settings.s_minParallelElement1Count) {
+                            workItemLength = maxRuns / workItemCount;
+                        } else {
+                            workItemLength = maxRuns / 2;
+                            workItemCount = 2;
+                        }
+                        
+                    } else {
+                        workItemLength = maxRuns;
+                        workItemCount = 1;
+                    }
+                    Action<object> action = (data) => {
+                        Tuple<int, int> range = (Tuple<int, int>)data;
+                        int from = range.Item1, to = range.Item2;
+                       
+                        float[] tmpArr = ILMemoryPool.Pool.New< float>(dimLen);
+                        for (int c = from; c < to; c++)
+                        {
+                            int pos = (int)(((long)dimLen * c * inc) % modHelp);
+
+                            long posOut = ((long)c * incOut);
+                            if (posOut > modOut)
+                                posOut = ((posOut - 1) % modOut) + 1;
+                            int end = pos + dimLen * inc;
+                            int k = 0;
+                            // ho: TODO: probably faster if operating on a full clone of A. median_worker would handle LDA, start, end than ... 
+                            for (int j = pos; j < end; j += inc)
+                                tmpArr[k++] = aArray[j];
+                            retArr[posOut] = median_worker(tmpArr, dimLen);
+                        }
+                        ILMemoryPool.Pool.Free(tmpArr); 
+                        System.Threading.Interlocked.Decrement(ref workerCount);
+                    };
+                    for (; i < workItemCount - 1; i++) {
+                        Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,action, Tuple.Create(i * workItemLength, (i + 1) * workItemLength));
+                    }
+                    action(Tuple.Create(i * workItemLength, maxRuns));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                    #endregion
+                }
+                return array(retArr, newDims);
+            }
+        }
+        /// <summary>
+        /// Calculate median along the specified dimension
+        /// </summary>
+        /// <param name="A">Input Array</param>
+        /// <returns><para>Array having the specified dimension reduced to the length 1 with the median of 
+        /// all elements along that dimension.</para>
+        /// <param name="dim">[Optional] Index of dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <para>The result will have the same number of dimensions as A, but the specified dimension will have the 
+        /// size 1.</para><para>If the specified dimension of A is empty, the median along that dimension will be NaN and that dimension will be 1.</para></returns>
+        public static ILRetArray<complex>  median(ILInArray<complex> A, int dim = -1)
+        {
+           
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+
+                if (dim >= A.Size.NumberOfDimensions)
+                    return  A.C;
+               
+                if (A.IsScalar) {
+                    
+                    return array<complex>(new complex[] { A.GetValue(0) }, 1, 1);
+                }
+
+                if (A.S[dim] == 1)
+                    return  A.C;
+
+                int[] newDims = A.S.ToIntArray();
+                newDims[dim] = 1;
+                ILSize retDimension = new ILSize(newDims);
+
+                if (A.IsEmpty)
+                    return array<complex>(complex.NaN,retDimension);
+
+                complex[] retArr = ILMemoryPool.Pool.New< complex>(retDimension.NumberOfElements);
+
+                int maxRuns = retDimension.NumberOfElements;
+               
+                complex[] aArray = null;
+                if (maxRuns == 1) {
+                    // ho: easier would be to use a new local array: 
+                    // ILArray<double> aClone = A.C; 
+                    // aArray = aClone.GetArrayForWrite();  here... (but the implemented way works just as well) 
+                    aArray = ILMemoryPool.Pool.New< complex>(A.S[dim]);
+                    A.ExportValues(ref aArray);
+                    retArr[0] = median_worker(aArray, A.S[dim]);
+                    ILMemoryPool.Pool.Free(aArray);
+                } else
+                {
+                    #region may run parallel
+                    aArray = A.GetArrayForRead();
+                    int inc = A.Size.SequentialIndexDistance(dim);
+                    int dimLen = A.Size[dim];
+                    int modHelp = A.Size.NumberOfElements - 1;
+                    int modOut = retDimension.NumberOfElements - 1;
+                    int incOut = retDimension.SequentialIndexDistance(dim);
+                    int numelA = A.S.NumberOfElements;
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                    if (Settings.s_maxNumberThreads > 1 && maxRuns > 1 
+                        && numelA / 2 >= Settings.s_minParallelElement1Count) {
+
+                        if (maxRuns >= Settings.s_maxNumberThreads
+                            && numelA / Settings.s_maxNumberThreads > Settings.s_minParallelElement1Count) {
+                            workItemLength = maxRuns / workItemCount;
+                        } else {
+                            workItemLength = maxRuns / 2;
+                            workItemCount = 2;
+                        }
+                        
+                    } else {
+                        workItemLength = maxRuns;
+                        workItemCount = 1;
+                    }
+                    Action<object> action = (data) => {
+                        Tuple<int, int> range = (Tuple<int, int>)data;
+                        int from = range.Item1, to = range.Item2;
+                       
+                        complex[] tmpArr = ILMemoryPool.Pool.New< complex>(dimLen);
+                        for (int c = from; c < to; c++)
+                        {
+                            int pos = (int)(((long)dimLen * c * inc) % modHelp);
+
+                            long posOut = ((long)c * incOut);
+                            if (posOut > modOut)
+                                posOut = ((posOut - 1) % modOut) + 1;
+                            int end = pos + dimLen * inc;
+                            int k = 0;
+                            // ho: TODO: probably faster if operating on a full clone of A. median_worker would handle LDA, start, end than ... 
+                            for (int j = pos; j < end; j += inc)
+                                tmpArr[k++] = aArray[j];
+                            retArr[posOut] = median_worker(tmpArr, dimLen);
+                        }
+                        ILMemoryPool.Pool.Free(tmpArr); 
+                        System.Threading.Interlocked.Decrement(ref workerCount);
+                    };
+                    for (; i < workItemCount - 1; i++) {
+                        Interlocked.Increment(ref workerCount);
+                        ILThreadPool.QueueUserWorkItem(i,action, Tuple.Create(i * workItemLength, (i + 1) * workItemLength));
+                    }
+                    action(Tuple.Create(i * workItemLength, maxRuns));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                    #endregion
+                }
+                return array(retArr, newDims);
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+        #region private helpers
+
+        static double median_worker(double[] list, int length)
+        {
+            // ATTENTION: list will be changed in here!!!
+            if (length % 2 == 0)
+            {
+                // even number of elements
+                int newRight;
+                
+                double a = (double)quickselect_worker(list, 0, length - 1, length / 2, out newRight);
+                
+                
+                double b = (double)quickselect_worker(list, newRight + 1, length - 1, 1, out newRight);
+                return b - (b - a) / (double) 2.0; // SMA: Reduces rounding errors...apparently.
+            }
+            else
+            {
+                // odd number of elements
+                int dummy;
+                return (double) quickselect_worker(list, 0, length - 1, (length - 1) / 2 + 1, out dummy);
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+        static double median_worker(Int64[] list, int length)
+        {
+            // ATTENTION: list will be changed in here!!!
+            if (length % 2 == 0)
+            {
+                // even number of elements
+                int newRight;
+               
+                double a = (double)quickselect_worker(list, 0, length - 1, length / 2, out newRight);
+                
+               
+                double b = (double)quickselect_worker(list, newRight + 1, length - 1, 1, out newRight);
+                return b - (b - a) / (double) 2.0; // SMA: Reduces rounding errors...apparently.
+            }
+            else
+            {
+                // odd number of elements
+                int dummy;
+                return (double) quickselect_worker(list, 0, length - 1, (length - 1) / 2 + 1, out dummy);
+            }
+        }
+        static double median_worker(Int32[] list, int length)
+        {
+            // ATTENTION: list will be changed in here!!!
+            if (length % 2 == 0)
+            {
+                // even number of elements
+                int newRight;
+               
+                double a = (double)quickselect_worker(list, 0, length - 1, length / 2, out newRight);
+                
+               
+                double b = (double)quickselect_worker(list, newRight + 1, length - 1, 1, out newRight);
+                return b - (b - a) / (double) 2.0; // SMA: Reduces rounding errors...apparently.
+            }
+            else
+            {
+                // odd number of elements
+                int dummy;
+                return (double) quickselect_worker(list, 0, length - 1, (length - 1) / 2 + 1, out dummy);
+            }
+        }
+        static double median_worker(byte[] list, int length)
+        {
+            // ATTENTION: list will be changed in here!!!
+            if (length % 2 == 0)
+            {
+                // even number of elements
+                int newRight;
+               
+                double a = (double)quickselect_worker(list, 0, length - 1, length / 2, out newRight);
+                
+               
+                double b = (double)quickselect_worker(list, newRight + 1, length - 1, 1, out newRight);
+                return b - (b - a) / (double) 2.0; // SMA: Reduces rounding errors...apparently.
+            }
+            else
+            {
+                // odd number of elements
+                int dummy;
+                return (double) quickselect_worker(list, 0, length - 1, (length - 1) / 2 + 1, out dummy);
+            }
+        }
+        static fcomplex median_worker(fcomplex[] list, int length)
+        {
+            // ATTENTION: list will be changed in here!!!
+            if (length % 2 == 0)
+            {
+                // even number of elements
+                int newRight;
+               
+                fcomplex a = (fcomplex)quickselect_worker(list, 0, length - 1, length / 2, out newRight);
+                
+               
+                fcomplex b = (fcomplex)quickselect_worker(list, newRight + 1, length - 1, 1, out newRight);
+                return b - (b - a) / (fcomplex) 2.0; // SMA: Reduces rounding errors...apparently.
+            }
+            else
+            {
+                // odd number of elements
+                int dummy;
+                return (fcomplex) quickselect_worker(list, 0, length - 1, (length - 1) / 2 + 1, out dummy);
+            }
+        }
+        static float median_worker(float[] list, int length)
+        {
+            // ATTENTION: list will be changed in here!!!
+            if (length % 2 == 0)
+            {
+                // even number of elements
+                int newRight;
+               
+                float a = (float)quickselect_worker(list, 0, length - 1, length / 2, out newRight);
+                
+               
+                float b = (float)quickselect_worker(list, newRight + 1, length - 1, 1, out newRight);
+                return b - (b - a) / (float) 2.0; // SMA: Reduces rounding errors...apparently.
+            }
+            else
+            {
+                // odd number of elements
+                int dummy;
+                return (float) quickselect_worker(list, 0, length - 1, (length - 1) / 2 + 1, out dummy);
+            }
+        }
+        static complex median_worker(complex[] list, int length)
+        {
+            // ATTENTION: list will be changed in here!!!
+            if (length % 2 == 0)
+            {
+                // even number of elements
+                int newRight;
+               
+                complex a = (complex)quickselect_worker(list, 0, length - 1, length / 2, out newRight);
+                
+               
+                complex b = (complex)quickselect_worker(list, newRight + 1, length - 1, 1, out newRight);
+                return b - (b - a) / (complex) 2.0; // SMA: Reduces rounding errors...apparently.
+            }
+            else
+            {
+                // odd number of elements
+                int dummy;
+                return (complex) quickselect_worker(list, 0, length - 1, (length - 1) / 2 + 1, out dummy);
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+       #endregion
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/statistics/nanmean.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/statistics/nanmean.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/statistics/nanmean.cs	(revision 9102)
@@ -0,0 +1,126 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions;
+
+
+
+namespace ILNumerics  {
+	public partial class ILMath {
+
+		/// <summary>
+		/// Mean of array along specified dimension ignoring NaN values
+		/// </summary>
+		/// <param name="A">Input array</param>
+        /// <param name="dim">[Optional] Index of the dimension to work along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+		/// <returns>Mean of non-NaN elements along specified dimension</returns>
+		/// <remarks><para>The return array has the same shape as A, but the selected dimension is reduced 
+		/// to length 1. If A is scalar, an scalar array will be returned. On empty input, the output will be empty.
+		/// </para><para>If A contains an all NaN vector along the specified dimension the resulting value will by NaN
+		/// (as the nansum of these elements is 0 divided by 0 elements)</para></remarks>
+		public static ILRetArray<double> nanmean( ILInArray<double> A, int dim = -1) {
+			using (ILScope.Enter(A)) {
+				if (dim < 0)
+					dim = A.Size.WorkingDimension();
+				return nansum_internal(A, dim, true);
+			}
+		}
+
+#region HYCALPER AUTO GENERATED CODE
+
+		/// <summary>
+		/// Mean of array along specified dimension ignoring NaN values
+		/// </summary>
+		/// <param name="A">Input array</param>
+        /// <param name="dim">[Optional] Index of the dimension to work along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+		/// <returns>Mean of non-NaN elements along specified dimension</returns>
+		/// <remarks><para>The return array has the same shape as A, but the selected dimension is reduced 
+		/// to length 1. If A is scalar, an scalar array will be returned. On empty input, the output will be empty.
+		/// </para><para>If A contains an all NaN vector along the specified dimension the resulting value will by NaN
+		/// (as the nansum of these elements is 0 divided by 0 elements)</para></remarks>
+		public static ILRetArray<fcomplex> nanmean( ILInArray<fcomplex> A, int dim = -1) {
+			using (ILScope.Enter(A)) {
+				if (dim < 0)
+					dim = A.Size.WorkingDimension();
+				return nansum_internal(A, dim, true);
+			}
+		}
+		/// <summary>
+		/// Mean of array along specified dimension ignoring NaN values
+		/// </summary>
+		/// <param name="A">Input array</param>
+        /// <param name="dim">[Optional] Index of the dimension to work along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+		/// <returns>Mean of non-NaN elements along specified dimension</returns>
+		/// <remarks><para>The return array has the same shape as A, but the selected dimension is reduced 
+		/// to length 1. If A is scalar, an scalar array will be returned. On empty input, the output will be empty.
+		/// </para><para>If A contains an all NaN vector along the specified dimension the resulting value will by NaN
+		/// (as the nansum of these elements is 0 divided by 0 elements)</para></remarks>
+		public static ILRetArray<float> nanmean( ILInArray<float> A, int dim = -1) {
+			using (ILScope.Enter(A)) {
+				if (dim < 0)
+					dim = A.Size.WorkingDimension();
+				return nansum_internal(A, dim, true);
+			}
+		}
+		/// <summary>
+		/// Mean of array along specified dimension ignoring NaN values
+		/// </summary>
+		/// <param name="A">Input array</param>
+        /// <param name="dim">[Optional] Index of the dimension to work along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+		/// <returns>Mean of non-NaN elements along specified dimension</returns>
+		/// <remarks><para>The return array has the same shape as A, but the selected dimension is reduced 
+		/// to length 1. If A is scalar, an scalar array will be returned. On empty input, the output will be empty.
+		/// </para><para>If A contains an all NaN vector along the specified dimension the resulting value will by NaN
+		/// (as the nansum of these elements is 0 divided by 0 elements)</para></remarks>
+		public static ILRetArray<complex> nanmean( ILInArray<complex> A, int dim = -1) {
+			using (ILScope.Enter(A)) {
+				if (dim < 0)
+					dim = A.Size.WorkingDimension();
+				return nansum_internal(A, dim, true);
+			}
+		}
+
+#endregion HYCALPER AUTO GENERATED CODE
+}
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/statistics/nansum.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/statistics/nansum.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/statistics/nansum.cs	(revision 9102)
@@ -0,0 +1,647 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading; 
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions;
+
+
+
+namespace ILNumerics  {
+	public partial class ILMath {
+
+		/// <summary>
+		/// Sum elements along first non singleton dimension ignoring NaN values
+		/// </summary>
+		/// <param name="A">Input array</param>
+		/// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+		/// <returns>Sum of elements along specified of first non singleton dimension, ignoring nan values</returns>
+		/// <remarks><para>The array returned will have the same size as <paramref name="A"/>, with the specified or first non singleton dimension 
+		/// reduced to the length 1. It will contain the sum of all elements along that dimension after removing NaN values respectively. </para>
+		/// <para>If A contains an all NaN vector along <paramref name="dim"/> , 
+		/// the resulting sum will be 0 - not NaN! This corresponds to the sum of an empty vector.</para></remarks> 
+		public static ILRetArray<double> nansum(ILInArray<double> A, int dim = -1)
+		{
+			if (dim < 0)
+				dim = A.Size.WorkingDimension();
+			return nansum_internal(A, dim, false);
+		}
+		
+		/// <summary>
+		/// Depending on settings, calculate nansum or nanmean
+		/// </summary>
+		private static ILRetArray<double> nansum_internal (ILInArray<double> A, int dim, bool computeMean) {
+			using (ILScope.Enter(A)) {
+				if (dim >= A.Size.NumberOfDimensions)
+				   return A.C;
+				
+				if (A.IsScalar) {
+					return array<double>(new double[1] { A.GetValue(0) }, 1, 1);
+				}
+				
+				if (A.S[dim] == 1) return A.C;
+
+				int[] newDims = A.S.ToIntArray();
+				newDims[dim] = 1; 
+				ILSize retDimension = new ILSize(newDims);
+
+				if (A.IsEmpty)
+					return empty<double>(retDimension);
+
+				double[] retArr = ILMemoryPool.Pool.New<double>(retDimension.NumberOfElements);
+
+				int inc = A.Size.SequentialIndexDistance(dim);
+				int dimLen = A.Size[dim];
+				int maxRuns = retDimension.NumberOfElements;
+				int modHelp = A.Size.NumberOfElements - 1;
+				int modOut = retDimension.NumberOfElements - 1;
+				int incOut = retDimension.SequentialIndexDistance(dim); 
+				int numelA = A.S.NumberOfElements;
+				
+				double[] aArray = A.GetArrayForRead();
+				if (maxRuns == 1) {
+					
+					double tmp = 0;
+					if (computeMean)
+					{
+						int cnt = 0;
+						for (int j = 0; j < dimLen; j++)
+						{
+							if (!/*HC:inArr1*/double.IsNaN(aArray[j]))
+							{
+								tmp += aArray[j];
+								cnt++;
+							}
+						}
+						if (cnt == 0)
+							retArr[0] = double.NaN;
+						else
+							retArr[0] = tmp / cnt;
+					}
+					else
+					{
+						for (int j = 0; j < dimLen; j++)
+						{
+							if (!/*HC:inArr1*/double.IsNaN(aArray[j]))
+								tmp += aArray[j];
+						}
+						retArr[0] = tmp;
+					}
+				} else {
+					#region may run parallel 
+					int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+					if (Settings.s_maxNumberThreads > 1 && maxRuns > 1 
+						&& numelA / 2 >= Settings.s_minParallelElement1Count) {
+
+						if (maxRuns >= Settings.s_maxNumberThreads
+							&& numelA / Settings.s_maxNumberThreads > Settings.s_minParallelElement1Count) {
+							workItemLength = maxRuns / workItemCount;
+						} else {
+							workItemLength = maxRuns / 2;
+							workItemCount = 2;
+						}
+						
+					} else {
+						workItemLength = maxRuns;
+						workItemCount = 1;
+					}
+					Action<object> action = (data) => {
+						Tuple<int, int> range = (Tuple<int, int>)data;
+						int from = range.Item1, to = range.Item2;
+						for (int c = from; c < to; c++) {
+							int pos = (int)(((long)dimLen * c * inc) % modHelp);
+							long posOut = ((long)c * incOut);
+							if (posOut > modOut)
+								posOut = ((posOut - 1) % modOut) + 1;
+							
+							double tmp = 0;
+							int end = pos + dimLen * inc;
+							if (computeMean)
+							{
+								int cnt = 0;
+								for (int j = pos; j < end; j += inc)
+								{
+									if (!/*HC:inArr1*/double.IsNaN(aArray[j]))
+									{ 
+										tmp += aArray[j];
+										cnt++;
+									}
+								}
+								if (cnt == 0)
+									retArr[posOut] = double.NaN;
+								else
+									retArr[posOut] = tmp / cnt;
+							}
+							else
+							{
+							   
+								for (int j = pos; j < end; j += inc)
+								{
+									if (!/*HC:inArr1*/double.IsNaN(aArray[j]))
+										tmp += aArray[j];
+								}
+								retArr[posOut] = tmp;
+							}
+						}
+						System.Threading.Interlocked.Decrement(ref workerCount);
+					};
+					for (; i < workItemCount - 1; i++) {
+						Interlocked.Increment(ref workerCount);
+
+						ILThreadPool.QueueUserWorkItem(i,action, Tuple.Create(i * workItemLength, (i + 1) * workItemLength));
+					}
+					action(Tuple.Create(i * workItemLength, maxRuns));
+					ILThreadPool.Wait4Workers(ref workerCount); 
+					#endregion
+				}
+				return array(retArr, newDims);
+			}
+		}
+
+#region HYCALPER AUTO GENERATED CODE
+
+		/// <summary>
+		/// Sum elements along first non singleton dimension ignoring NaN values
+		/// </summary>
+		/// <param name="A">Input array</param>
+		/// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+		/// <returns>Sum of elements along specified of first non singleton dimension, ignoring nan values</returns>
+		/// <remarks><para>The array returned will have the same size as <paramref name="A"/>, with the specified or first non singleton dimension 
+		/// reduced to the length 1. It will contain the sum of all elements along that dimension after removing NaN values respectively. </para>
+		/// <para>If A contains an all NaN vector along <paramref name="dim"/> , 
+		/// the resulting sum will be 0 - not NaN! This corresponds to the sum of an empty vector.</para></remarks> 
+		public static ILRetArray<fcomplex> nansum(ILInArray<fcomplex> A, int dim = -1)
+		{
+			if (dim < 0)
+				dim = A.Size.WorkingDimension();
+			return nansum_internal(A, dim, false);
+		}
+		
+		/// <summary>
+		/// Depending on settings, calculate nansum or nanmean
+		/// </summary>
+		private static ILRetArray<fcomplex> nansum_internal (ILInArray<fcomplex> A, int dim, bool computeMean) {
+			using (ILScope.Enter(A)) {
+				if (dim >= A.Size.NumberOfDimensions)
+				   return A.C;
+				
+				if (A.IsScalar) {
+					return array<fcomplex>(new fcomplex[1] { A.GetValue(0) }, 1, 1);
+				}
+				
+				if (A.S[dim] == 1) return A.C;
+
+				int[] newDims = A.S.ToIntArray();
+				newDims[dim] = 1; 
+				ILSize retDimension = new ILSize(newDims);
+
+				if (A.IsEmpty)
+					return empty<fcomplex>(retDimension);
+
+				fcomplex[] retArr = ILMemoryPool.Pool.New<fcomplex>(retDimension.NumberOfElements);
+
+				int inc = A.Size.SequentialIndexDistance(dim);
+				int dimLen = A.Size[dim];
+				int maxRuns = retDimension.NumberOfElements;
+				int modHelp = A.Size.NumberOfElements - 1;
+				int modOut = retDimension.NumberOfElements - 1;
+				int incOut = retDimension.SequentialIndexDistance(dim); 
+				int numelA = A.S.NumberOfElements;
+				
+				fcomplex[] aArray = A.GetArrayForRead();
+				if (maxRuns == 1) {
+					
+					fcomplex tmp = 0;
+					if (computeMean)
+					{
+						int cnt = 0;
+						for (int j = 0; j < dimLen; j++)
+						{
+							if (!/*HC:*/fcomplex.IsNaN(aArray[j]))
+							{
+								tmp += aArray[j];
+								cnt++;
+							}
+						}
+						if (cnt == 0)
+							retArr[0] = fcomplex.NaN;
+						else
+							retArr[0] = tmp / cnt;
+					}
+					else
+					{
+						for (int j = 0; j < dimLen; j++)
+						{
+							if (!/*HC:*/fcomplex.IsNaN(aArray[j]))
+								tmp += aArray[j];
+						}
+						retArr[0] = tmp;
+					}
+				} else {
+					#region may run parallel 
+					int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+					if (Settings.s_maxNumberThreads > 1 && maxRuns > 1 
+						&& numelA / 2 >= Settings.s_minParallelElement1Count) {
+
+						if (maxRuns >= Settings.s_maxNumberThreads
+							&& numelA / Settings.s_maxNumberThreads > Settings.s_minParallelElement1Count) {
+							workItemLength = maxRuns / workItemCount;
+						} else {
+							workItemLength = maxRuns / 2;
+							workItemCount = 2;
+						}
+						
+					} else {
+						workItemLength = maxRuns;
+						workItemCount = 1;
+					}
+					Action<object> action = (data) => {
+						Tuple<int, int> range = (Tuple<int, int>)data;
+						int from = range.Item1, to = range.Item2;
+						for (int c = from; c < to; c++) {
+							int pos = (int)(((long)dimLen * c * inc) % modHelp);
+							long posOut = ((long)c * incOut);
+							if (posOut > modOut)
+								posOut = ((posOut - 1) % modOut) + 1;
+							
+							fcomplex tmp = 0;
+							int end = pos + dimLen * inc;
+							if (computeMean)
+							{
+								int cnt = 0;
+								for (int j = pos; j < end; j += inc)
+								{
+									if (!/*HC:*/fcomplex.IsNaN(aArray[j]))
+									{ 
+										tmp += aArray[j];
+										cnt++;
+									}
+								}
+								if (cnt == 0)
+									retArr[posOut] = fcomplex.NaN;
+								else
+									retArr[posOut] = tmp / cnt;
+							}
+							else
+							{
+							   
+								for (int j = pos; j < end; j += inc)
+								{
+									if (!/*HC:*/fcomplex.IsNaN(aArray[j]))
+										tmp += aArray[j];
+								}
+								retArr[posOut] = tmp;
+							}
+						}
+						System.Threading.Interlocked.Decrement(ref workerCount);
+					};
+					for (; i < workItemCount - 1; i++) {
+						Interlocked.Increment(ref workerCount);
+
+						ILThreadPool.QueueUserWorkItem(i,action, Tuple.Create(i * workItemLength, (i + 1) * workItemLength));
+					}
+					action(Tuple.Create(i * workItemLength, maxRuns));
+					ILThreadPool.Wait4Workers(ref workerCount); 
+					#endregion
+				}
+				return array(retArr, newDims);
+			}
+		}
+		/// <summary>
+		/// Sum elements along first non singleton dimension ignoring NaN values
+		/// </summary>
+		/// <param name="A">Input array</param>
+		/// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+		/// <returns>Sum of elements along specified of first non singleton dimension, ignoring nan values</returns>
+		/// <remarks><para>The array returned will have the same size as <paramref name="A"/>, with the specified or first non singleton dimension 
+		/// reduced to the length 1. It will contain the sum of all elements along that dimension after removing NaN values respectively. </para>
+		/// <para>If A contains an all NaN vector along <paramref name="dim"/> , 
+		/// the resulting sum will be 0 - not NaN! This corresponds to the sum of an empty vector.</para></remarks> 
+		public static ILRetArray<float> nansum(ILInArray<float> A, int dim = -1)
+		{
+			if (dim < 0)
+				dim = A.Size.WorkingDimension();
+			return nansum_internal(A, dim, false);
+		}
+		
+		/// <summary>
+		/// Depending on settings, calculate nansum or nanmean
+		/// </summary>
+		private static ILRetArray<float> nansum_internal (ILInArray<float> A, int dim, bool computeMean) {
+			using (ILScope.Enter(A)) {
+				if (dim >= A.Size.NumberOfDimensions)
+				   return A.C;
+				
+				if (A.IsScalar) {
+					return array<float>(new float[1] { A.GetValue(0) }, 1, 1);
+				}
+				
+				if (A.S[dim] == 1) return A.C;
+
+				int[] newDims = A.S.ToIntArray();
+				newDims[dim] = 1; 
+				ILSize retDimension = new ILSize(newDims);
+
+				if (A.IsEmpty)
+					return empty<float>(retDimension);
+
+				float[] retArr = ILMemoryPool.Pool.New<float>(retDimension.NumberOfElements);
+
+				int inc = A.Size.SequentialIndexDistance(dim);
+				int dimLen = A.Size[dim];
+				int maxRuns = retDimension.NumberOfElements;
+				int modHelp = A.Size.NumberOfElements - 1;
+				int modOut = retDimension.NumberOfElements - 1;
+				int incOut = retDimension.SequentialIndexDistance(dim); 
+				int numelA = A.S.NumberOfElements;
+				
+				float[] aArray = A.GetArrayForRead();
+				if (maxRuns == 1) {
+					
+					float tmp = 0;
+					if (computeMean)
+					{
+						int cnt = 0;
+						for (int j = 0; j < dimLen; j++)
+						{
+							if (!/*HC:*/float.IsNaN(aArray[j]))
+							{
+								tmp += aArray[j];
+								cnt++;
+							}
+						}
+						if (cnt == 0)
+							retArr[0] = float.NaN;
+						else
+							retArr[0] = tmp / cnt;
+					}
+					else
+					{
+						for (int j = 0; j < dimLen; j++)
+						{
+							if (!/*HC:*/float.IsNaN(aArray[j]))
+								tmp += aArray[j];
+						}
+						retArr[0] = tmp;
+					}
+				} else {
+					#region may run parallel 
+					int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+					if (Settings.s_maxNumberThreads > 1 && maxRuns > 1 
+						&& numelA / 2 >= Settings.s_minParallelElement1Count) {
+
+						if (maxRuns >= Settings.s_maxNumberThreads
+							&& numelA / Settings.s_maxNumberThreads > Settings.s_minParallelElement1Count) {
+							workItemLength = maxRuns / workItemCount;
+						} else {
+							workItemLength = maxRuns / 2;
+							workItemCount = 2;
+						}
+						
+					} else {
+						workItemLength = maxRuns;
+						workItemCount = 1;
+					}
+					Action<object> action = (data) => {
+						Tuple<int, int> range = (Tuple<int, int>)data;
+						int from = range.Item1, to = range.Item2;
+						for (int c = from; c < to; c++) {
+							int pos = (int)(((long)dimLen * c * inc) % modHelp);
+							long posOut = ((long)c * incOut);
+							if (posOut > modOut)
+								posOut = ((posOut - 1) % modOut) + 1;
+							
+							float tmp = 0;
+							int end = pos + dimLen * inc;
+							if (computeMean)
+							{
+								int cnt = 0;
+								for (int j = pos; j < end; j += inc)
+								{
+									if (!/*HC:*/float.IsNaN(aArray[j]))
+									{ 
+										tmp += aArray[j];
+										cnt++;
+									}
+								}
+								if (cnt == 0)
+									retArr[posOut] = float.NaN;
+								else
+									retArr[posOut] = tmp / cnt;
+							}
+							else
+							{
+							   
+								for (int j = pos; j < end; j += inc)
+								{
+									if (!/*HC:*/float.IsNaN(aArray[j]))
+										tmp += aArray[j];
+								}
+								retArr[posOut] = tmp;
+							}
+						}
+						System.Threading.Interlocked.Decrement(ref workerCount);
+					};
+					for (; i < workItemCount - 1; i++) {
+						Interlocked.Increment(ref workerCount);
+
+						ILThreadPool.QueueUserWorkItem(i,action, Tuple.Create(i * workItemLength, (i + 1) * workItemLength));
+					}
+					action(Tuple.Create(i * workItemLength, maxRuns));
+					ILThreadPool.Wait4Workers(ref workerCount); 
+					#endregion
+				}
+				return array(retArr, newDims);
+			}
+		}
+		/// <summary>
+		/// Sum elements along first non singleton dimension ignoring NaN values
+		/// </summary>
+		/// <param name="A">Input array</param>
+		/// <param name="dim">[Optional] Index of the dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+		/// <returns>Sum of elements along specified of first non singleton dimension, ignoring nan values</returns>
+		/// <remarks><para>The array returned will have the same size as <paramref name="A"/>, with the specified or first non singleton dimension 
+		/// reduced to the length 1. It will contain the sum of all elements along that dimension after removing NaN values respectively. </para>
+		/// <para>If A contains an all NaN vector along <paramref name="dim"/> , 
+		/// the resulting sum will be 0 - not NaN! This corresponds to the sum of an empty vector.</para></remarks> 
+		public static ILRetArray<complex> nansum(ILInArray<complex> A, int dim = -1)
+		{
+			if (dim < 0)
+				dim = A.Size.WorkingDimension();
+			return nansum_internal(A, dim, false);
+		}
+		
+		/// <summary>
+		/// Depending on settings, calculate nansum or nanmean
+		/// </summary>
+		private static ILRetArray<complex> nansum_internal (ILInArray<complex> A, int dim, bool computeMean) {
+			using (ILScope.Enter(A)) {
+				if (dim >= A.Size.NumberOfDimensions)
+				   return A.C;
+				
+				if (A.IsScalar) {
+					return array<complex>(new complex[1] { A.GetValue(0) }, 1, 1);
+				}
+				
+				if (A.S[dim] == 1) return A.C;
+
+				int[] newDims = A.S.ToIntArray();
+				newDims[dim] = 1; 
+				ILSize retDimension = new ILSize(newDims);
+
+				if (A.IsEmpty)
+					return empty<complex>(retDimension);
+
+				complex[] retArr = ILMemoryPool.Pool.New<complex>(retDimension.NumberOfElements);
+
+				int inc = A.Size.SequentialIndexDistance(dim);
+				int dimLen = A.Size[dim];
+				int maxRuns = retDimension.NumberOfElements;
+				int modHelp = A.Size.NumberOfElements - 1;
+				int modOut = retDimension.NumberOfElements - 1;
+				int incOut = retDimension.SequentialIndexDistance(dim); 
+				int numelA = A.S.NumberOfElements;
+				
+				complex[] aArray = A.GetArrayForRead();
+				if (maxRuns == 1) {
+					
+					complex tmp = 0;
+					if (computeMean)
+					{
+						int cnt = 0;
+						for (int j = 0; j < dimLen; j++)
+						{
+							if (!/*HC:*/complex.IsNaN(aArray[j]))
+							{
+								tmp += aArray[j];
+								cnt++;
+							}
+						}
+						if (cnt == 0)
+							retArr[0] = complex.NaN;
+						else
+							retArr[0] = tmp / cnt;
+					}
+					else
+					{
+						for (int j = 0; j < dimLen; j++)
+						{
+							if (!/*HC:*/complex.IsNaN(aArray[j]))
+								tmp += aArray[j];
+						}
+						retArr[0] = tmp;
+					}
+				} else {
+					#region may run parallel 
+					int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+					if (Settings.s_maxNumberThreads > 1 && maxRuns > 1 
+						&& numelA / 2 >= Settings.s_minParallelElement1Count) {
+
+						if (maxRuns >= Settings.s_maxNumberThreads
+							&& numelA / Settings.s_maxNumberThreads > Settings.s_minParallelElement1Count) {
+							workItemLength = maxRuns / workItemCount;
+						} else {
+							workItemLength = maxRuns / 2;
+							workItemCount = 2;
+						}
+						
+					} else {
+						workItemLength = maxRuns;
+						workItemCount = 1;
+					}
+					Action<object> action = (data) => {
+						Tuple<int, int> range = (Tuple<int, int>)data;
+						int from = range.Item1, to = range.Item2;
+						for (int c = from; c < to; c++) {
+							int pos = (int)(((long)dimLen * c * inc) % modHelp);
+							long posOut = ((long)c * incOut);
+							if (posOut > modOut)
+								posOut = ((posOut - 1) % modOut) + 1;
+							
+							complex tmp = 0;
+							int end = pos + dimLen * inc;
+							if (computeMean)
+							{
+								int cnt = 0;
+								for (int j = pos; j < end; j += inc)
+								{
+									if (!/*HC:*/complex.IsNaN(aArray[j]))
+									{ 
+										tmp += aArray[j];
+										cnt++;
+									}
+								}
+								if (cnt == 0)
+									retArr[posOut] = complex.NaN;
+								else
+									retArr[posOut] = tmp / cnt;
+							}
+							else
+							{
+							   
+								for (int j = pos; j < end; j += inc)
+								{
+									if (!/*HC:*/complex.IsNaN(aArray[j]))
+										tmp += aArray[j];
+								}
+								retArr[posOut] = tmp;
+							}
+						}
+						System.Threading.Interlocked.Decrement(ref workerCount);
+					};
+					for (; i < workItemCount - 1; i++) {
+						Interlocked.Increment(ref workerCount);
+
+						ILThreadPool.QueueUserWorkItem(i,action, Tuple.Create(i * workItemLength, (i + 1) * workItemLength));
+					}
+					action(Tuple.Create(i * workItemLength, maxRuns));
+					ILThreadPool.Wait4Workers(ref workerCount); 
+					#endregion
+				}
+				return array(retArr, newDims);
+			}
+		}
+
+#endregion HYCALPER AUTO GENERATED CODE
+}
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/statistics/select.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/statistics/select.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/statistics/select.cs	(revision 9102)
@@ -0,0 +1,1335 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading; 
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions;
+ 
+
+
+namespace ILNumerics  {
+    public partial class ILMath {
+
+        /// <summary>
+        /// Select the k-th smallest element from an array along a specific dimension
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="k">The element to find. If k is smaller 1 or larger than the number of elements in list, the smallest/largest value will be returned.</param>
+        /// <param name="dim">[Optional] Dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns><para>Array having the specified dimension reduced to the length 1 with the value of the k-the smallest element along that dimension.</para>
+        /// <para>Exception: If the selected dimension is of size 0 it will remain 0 (an empty set).</para></returns>
+        public static ILRetArray<double> select(ILInArray<double> A, int k, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+
+                if (dim >= A.Size.NumberOfDimensions)
+                    return A.C;
+               
+                if (A.IsScalar) {
+                    return new ILRetArray<double>(new double[] { A.GetValue(0) }, 1, 1);
+                }
+               
+                if (A.S[dim] == 1) return A.C;
+
+                int[] newDims = A.S.ToIntArray();
+                if (A.IsEmpty)
+                {
+                    // If the array is empty, check whether it is empty along the chosen dimension
+                    
+                    if (A.S[dim] > 0)
+                        // no there are potential elements in that dimension, hence we reduce it to 1
+                        newDims[dim] = 1;
+                    else
+                        // yes, empty along chosen dimension so the result is empty, i.e. 0 elements in that dimension
+                        newDims[dim] = 0;
+                    return ILRetArray<double>.empty(new ILSize(newDims));
+                }
+
+                newDims[dim] = 1;
+
+                // Check selected element and replace by useful value
+                if (k < 1)
+                    k = 1;
+                if (k > A.S[dim])
+                    k = A.S[dim];
+
+                ILSize retDimension = new ILSize(newDims);
+
+                 double[] retArr = ILMemoryPool.Pool.New< double>(retDimension.NumberOfElements);
+
+                int inc = A.Size.SequentialIndexDistance(dim);
+                int dimLen = A.Size[dim];
+                int maxRuns = retDimension.NumberOfElements;
+                int modHelp = A.Size.NumberOfElements - 1;
+                int modOut = retDimension.NumberOfElements - 1;
+                int incOut = retDimension.SequentialIndexDistance(dim); 
+                int numelA = A.S.NumberOfElements;
+                if (maxRuns == 1) {
+                    int dummy;
+                    retArr[0] = quickselect_worker(A.C.GetArrayForWrite(), 0, A.S[dim] - 1, k, out dummy);
+                } else {
+                    #region may run parallel 
+                    
+                    double[] aArray = A.GetArrayForRead();
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                    if (Settings.s_maxNumberThreads > 1 && maxRuns > 1 
+                        && numelA / 2 >= Settings.s_minParallelElement1Count) {
+
+                        if (maxRuns >= Settings.s_maxNumberThreads
+                            && numelA / Settings.s_maxNumberThreads > Settings.s_minParallelElement1Count) {
+                            workItemLength = maxRuns / workItemCount;
+                        } else {
+                            workItemLength = maxRuns / 2;
+                            workItemCount = 2;
+                        }
+                        
+                    } else {
+                        workItemLength = maxRuns;
+                        workItemCount = 1;
+                    }
+                    Action<object> action = (data) => {
+                        Tuple<int, int> range = (Tuple<int, int>)data;
+                        int from = range.Item1, to = range.Item2;
+                        for (int c = from; c < to; c++) {
+                            int pos = (int)(((long)dimLen * c * inc) % modHelp);
+                            int posOut = (c * incOut);
+                            if (posOut > modOut)
+                                posOut = ((posOut - 1) % modOut) + 1;
+                            
+                            double[] tmp = ILMemoryPool.Pool.New< double>(dimLen);
+                            int locPos = 0;
+                            int end = pos + dimLen * inc;
+                            for (int j = pos; j < end; j += inc)
+                                tmp[locPos++] = aArray[j];
+                            int dummy;
+                            retArr[posOut] = quickselect_worker(tmp, 0, dimLen - 1, k, out dummy);
+                            ILMemoryPool.Pool.Free(tmp);
+                        }
+                        System.Threading.Interlocked.Decrement(ref workerCount);
+                    };
+                    for (; i < workItemCount - 1; i++) {
+                        Interlocked.Increment(ref workerCount);
+
+                        ILThreadPool.QueueUserWorkItem(i,action, Tuple.Create(i * workItemLength, (i + 1) * workItemLength));
+                    }
+                    action(Tuple.Create(i * workItemLength, maxRuns));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                    #endregion
+                }
+                return new ILRetArray<double>(retArr, newDims);
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// Select the k-th smallest element from an array along a specific dimension
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="k">The element to find. If k is smaller 1 or larger than the number of elements in list, the smallest/largest value will be returned.</param>
+        /// <param name="dim">[Optional] Dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns><para>Array having the specified dimension reduced to the length 1 with the value of the k-the smallest element along that dimension.</para>
+        /// <para>Exception: If the selected dimension is of size 0 it will remain 0 (an empty set).</para></returns>
+        public static ILRetArray<Int64> select(ILInArray<Int64> A, int k, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+
+                if (dim >= A.Size.NumberOfDimensions)
+                    return A.C;
+               
+                if (A.IsScalar) {
+                    return new ILRetArray<Int64>(new Int64[] { A.GetValue(0) }, 1, 1);
+                }
+               
+                if (A.S[dim] == 1) return A.C;
+
+                int[] newDims = A.S.ToIntArray();
+                if (A.IsEmpty)
+                {
+                    // If the array is empty, check whether it is empty along the chosen dimension
+                    
+                    if (A.S[dim] > 0)
+                        // no there are potential elements in that dimension, hence we reduce it to 1
+                        newDims[dim] = 1;
+                    else
+                        // yes, empty along chosen dimension so the result is empty, i.e. 0 elements in that dimension
+                        newDims[dim] = 0;
+                    return ILRetArray<Int64>.empty(new ILSize(newDims));
+                }
+
+                newDims[dim] = 1;
+
+                // Check selected element and replace by useful value
+                if (k < 1)
+                    k = 1;
+                if (k > A.S[dim])
+                    k = A.S[dim];
+
+                ILSize retDimension = new ILSize(newDims);
+
+                Int64[] retArr = ILMemoryPool.Pool.New< Int64>(retDimension.NumberOfElements);
+
+                int inc = A.Size.SequentialIndexDistance(dim);
+                int dimLen = A.Size[dim];
+                int maxRuns = retDimension.NumberOfElements;
+                int modHelp = A.Size.NumberOfElements - 1;
+                int modOut = retDimension.NumberOfElements - 1;
+                int incOut = retDimension.SequentialIndexDistance(dim); 
+                int numelA = A.S.NumberOfElements;
+                if (maxRuns == 1) {
+                    int dummy;
+                    retArr[0] = quickselect_worker(A.C.GetArrayForWrite(), 0, A.S[dim] - 1, k, out dummy);
+                } else {
+                    #region may run parallel 
+                   
+                    Int64[] aArray = A.GetArrayForRead();
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                    if (Settings.s_maxNumberThreads > 1 && maxRuns > 1 
+                        && numelA / 2 >= Settings.s_minParallelElement1Count) {
+
+                        if (maxRuns >= Settings.s_maxNumberThreads
+                            && numelA / Settings.s_maxNumberThreads > Settings.s_minParallelElement1Count) {
+                            workItemLength = maxRuns / workItemCount;
+                        } else {
+                            workItemLength = maxRuns / 2;
+                            workItemCount = 2;
+                        }
+                        
+                    } else {
+                        workItemLength = maxRuns;
+                        workItemCount = 1;
+                    }
+                    Action<object> action = (data) => {
+                        Tuple<int, int> range = (Tuple<int, int>)data;
+                        int from = range.Item1, to = range.Item2;
+                        for (int c = from; c < to; c++) {
+                            int pos = (int)(((long)dimLen * c * inc) % modHelp);
+                            int posOut = (c * incOut);
+                            if (posOut > modOut)
+                                posOut = ((posOut - 1) % modOut) + 1;
+                           
+                            Int64[] tmp = ILMemoryPool.Pool.New< Int64>(dimLen);
+                            int locPos = 0;
+                            int end = pos + dimLen * inc;
+                            for (int j = pos; j < end; j += inc)
+                                tmp[locPos++] = aArray[j];
+                            int dummy;
+                            retArr[posOut] = quickselect_worker(tmp, 0, dimLen - 1, k, out dummy);
+                            ILMemoryPool.Pool.Free(tmp);
+                        }
+                        System.Threading.Interlocked.Decrement(ref workerCount);
+                    };
+                    for (; i < workItemCount - 1; i++) {
+                        Interlocked.Increment(ref workerCount);
+
+                        ILThreadPool.QueueUserWorkItem(i,action, Tuple.Create(i * workItemLength, (i + 1) * workItemLength));
+                    }
+                    action(Tuple.Create(i * workItemLength, maxRuns));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                    #endregion
+                }
+                return new ILRetArray<Int64>(retArr, newDims);
+            }
+        }
+        /// <summary>
+        /// Select the k-th smallest element from an array along a specific dimension
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="k">The element to find. If k is smaller 1 or larger than the number of elements in list, the smallest/largest value will be returned.</param>
+        /// <param name="dim">[Optional] Dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns><para>Array having the specified dimension reduced to the length 1 with the value of the k-the smallest element along that dimension.</para>
+        /// <para>Exception: If the selected dimension is of size 0 it will remain 0 (an empty set).</para></returns>
+        public static ILRetArray<Int32> select(ILInArray<Int32> A, int k, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+
+                if (dim >= A.Size.NumberOfDimensions)
+                    return A.C;
+               
+                if (A.IsScalar) {
+                    return new ILRetArray<Int32>(new Int32[] { A.GetValue(0) }, 1, 1);
+                }
+               
+                if (A.S[dim] == 1) return A.C;
+
+                int[] newDims = A.S.ToIntArray();
+                if (A.IsEmpty)
+                {
+                    // If the array is empty, check whether it is empty along the chosen dimension
+                    
+                    if (A.S[dim] > 0)
+                        // no there are potential elements in that dimension, hence we reduce it to 1
+                        newDims[dim] = 1;
+                    else
+                        // yes, empty along chosen dimension so the result is empty, i.e. 0 elements in that dimension
+                        newDims[dim] = 0;
+                    return ILRetArray<Int32>.empty(new ILSize(newDims));
+                }
+
+                newDims[dim] = 1;
+
+                // Check selected element and replace by useful value
+                if (k < 1)
+                    k = 1;
+                if (k > A.S[dim])
+                    k = A.S[dim];
+
+                ILSize retDimension = new ILSize(newDims);
+
+                Int32[] retArr = ILMemoryPool.Pool.New< Int32>(retDimension.NumberOfElements);
+
+                int inc = A.Size.SequentialIndexDistance(dim);
+                int dimLen = A.Size[dim];
+                int maxRuns = retDimension.NumberOfElements;
+                int modHelp = A.Size.NumberOfElements - 1;
+                int modOut = retDimension.NumberOfElements - 1;
+                int incOut = retDimension.SequentialIndexDistance(dim); 
+                int numelA = A.S.NumberOfElements;
+                if (maxRuns == 1) {
+                    int dummy;
+                    retArr[0] = quickselect_worker(A.C.GetArrayForWrite(), 0, A.S[dim] - 1, k, out dummy);
+                } else {
+                    #region may run parallel 
+                   
+                    Int32[] aArray = A.GetArrayForRead();
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                    if (Settings.s_maxNumberThreads > 1 && maxRuns > 1 
+                        && numelA / 2 >= Settings.s_minParallelElement1Count) {
+
+                        if (maxRuns >= Settings.s_maxNumberThreads
+                            && numelA / Settings.s_maxNumberThreads > Settings.s_minParallelElement1Count) {
+                            workItemLength = maxRuns / workItemCount;
+                        } else {
+                            workItemLength = maxRuns / 2;
+                            workItemCount = 2;
+                        }
+                        
+                    } else {
+                        workItemLength = maxRuns;
+                        workItemCount = 1;
+                    }
+                    Action<object> action = (data) => {
+                        Tuple<int, int> range = (Tuple<int, int>)data;
+                        int from = range.Item1, to = range.Item2;
+                        for (int c = from; c < to; c++) {
+                            int pos = (int)(((long)dimLen * c * inc) % modHelp);
+                            int posOut = (c * incOut);
+                            if (posOut > modOut)
+                                posOut = ((posOut - 1) % modOut) + 1;
+                           
+                            Int32[] tmp = ILMemoryPool.Pool.New< Int32>(dimLen);
+                            int locPos = 0;
+                            int end = pos + dimLen * inc;
+                            for (int j = pos; j < end; j += inc)
+                                tmp[locPos++] = aArray[j];
+                            int dummy;
+                            retArr[posOut] = quickselect_worker(tmp, 0, dimLen - 1, k, out dummy);
+                            ILMemoryPool.Pool.Free(tmp);
+                        }
+                        System.Threading.Interlocked.Decrement(ref workerCount);
+                    };
+                    for (; i < workItemCount - 1; i++) {
+                        Interlocked.Increment(ref workerCount);
+
+                        ILThreadPool.QueueUserWorkItem(i,action, Tuple.Create(i * workItemLength, (i + 1) * workItemLength));
+                    }
+                    action(Tuple.Create(i * workItemLength, maxRuns));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                    #endregion
+                }
+                return new ILRetArray<Int32>(retArr, newDims);
+            }
+        }
+        /// <summary>
+        /// Select the k-th smallest element from an array along a specific dimension
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="k">The element to find. If k is smaller 1 or larger than the number of elements in list, the smallest/largest value will be returned.</param>
+        /// <param name="dim">[Optional] Dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns><para>Array having the specified dimension reduced to the length 1 with the value of the k-the smallest element along that dimension.</para>
+        /// <para>Exception: If the selected dimension is of size 0 it will remain 0 (an empty set).</para></returns>
+        public static ILRetArray<byte> select(ILInArray<byte> A, int k, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+
+                if (dim >= A.Size.NumberOfDimensions)
+                    return A.C;
+               
+                if (A.IsScalar) {
+                    return new ILRetArray<byte>(new byte[] { A.GetValue(0) }, 1, 1);
+                }
+               
+                if (A.S[dim] == 1) return A.C;
+
+                int[] newDims = A.S.ToIntArray();
+                if (A.IsEmpty)
+                {
+                    // If the array is empty, check whether it is empty along the chosen dimension
+                    
+                    if (A.S[dim] > 0)
+                        // no there are potential elements in that dimension, hence we reduce it to 1
+                        newDims[dim] = 1;
+                    else
+                        // yes, empty along chosen dimension so the result is empty, i.e. 0 elements in that dimension
+                        newDims[dim] = 0;
+                    return ILRetArray<byte>.empty(new ILSize(newDims));
+                }
+
+                newDims[dim] = 1;
+
+                // Check selected element and replace by useful value
+                if (k < 1)
+                    k = 1;
+                if (k > A.S[dim])
+                    k = A.S[dim];
+
+                ILSize retDimension = new ILSize(newDims);
+
+                byte[] retArr = ILMemoryPool.Pool.New< byte>(retDimension.NumberOfElements);
+
+                int inc = A.Size.SequentialIndexDistance(dim);
+                int dimLen = A.Size[dim];
+                int maxRuns = retDimension.NumberOfElements;
+                int modHelp = A.Size.NumberOfElements - 1;
+                int modOut = retDimension.NumberOfElements - 1;
+                int incOut = retDimension.SequentialIndexDistance(dim); 
+                int numelA = A.S.NumberOfElements;
+                if (maxRuns == 1) {
+                    int dummy;
+                    retArr[0] = quickselect_worker(A.C.GetArrayForWrite(), 0, A.S[dim] - 1, k, out dummy);
+                } else {
+                    #region may run parallel 
+                   
+                    byte[] aArray = A.GetArrayForRead();
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                    if (Settings.s_maxNumberThreads > 1 && maxRuns > 1 
+                        && numelA / 2 >= Settings.s_minParallelElement1Count) {
+
+                        if (maxRuns >= Settings.s_maxNumberThreads
+                            && numelA / Settings.s_maxNumberThreads > Settings.s_minParallelElement1Count) {
+                            workItemLength = maxRuns / workItemCount;
+                        } else {
+                            workItemLength = maxRuns / 2;
+                            workItemCount = 2;
+                        }
+                        
+                    } else {
+                        workItemLength = maxRuns;
+                        workItemCount = 1;
+                    }
+                    Action<object> action = (data) => {
+                        Tuple<int, int> range = (Tuple<int, int>)data;
+                        int from = range.Item1, to = range.Item2;
+                        for (int c = from; c < to; c++) {
+                            int pos = (int)(((long)dimLen * c * inc) % modHelp);
+                            int posOut = (c * incOut);
+                            if (posOut > modOut)
+                                posOut = ((posOut - 1) % modOut) + 1;
+                           
+                            byte[] tmp = ILMemoryPool.Pool.New< byte>(dimLen);
+                            int locPos = 0;
+                            int end = pos + dimLen * inc;
+                            for (int j = pos; j < end; j += inc)
+                                tmp[locPos++] = aArray[j];
+                            int dummy;
+                            retArr[posOut] = quickselect_worker(tmp, 0, dimLen - 1, k, out dummy);
+                            ILMemoryPool.Pool.Free(tmp);
+                        }
+                        System.Threading.Interlocked.Decrement(ref workerCount);
+                    };
+                    for (; i < workItemCount - 1; i++) {
+                        Interlocked.Increment(ref workerCount);
+
+                        ILThreadPool.QueueUserWorkItem(i,action, Tuple.Create(i * workItemLength, (i + 1) * workItemLength));
+                    }
+                    action(Tuple.Create(i * workItemLength, maxRuns));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                    #endregion
+                }
+                return new ILRetArray<byte>(retArr, newDims);
+            }
+        }
+        /// <summary>
+        /// Select the k-th smallest element from an array along a specific dimension
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="k">The element to find. If k is smaller 1 or larger than the number of elements in list, the smallest/largest value will be returned.</param>
+        /// <param name="dim">[Optional] Dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns><para>Array having the specified dimension reduced to the length 1 with the value of the k-the smallest element along that dimension.</para>
+        /// <para>Exception: If the selected dimension is of size 0 it will remain 0 (an empty set).</para></returns>
+        public static ILRetArray<fcomplex> select(ILInArray<fcomplex> A, int k, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+
+                if (dim >= A.Size.NumberOfDimensions)
+                    return A.C;
+               
+                if (A.IsScalar) {
+                    return new ILRetArray<fcomplex>(new fcomplex[] { A.GetValue(0) }, 1, 1);
+                }
+               
+                if (A.S[dim] == 1) return A.C;
+
+                int[] newDims = A.S.ToIntArray();
+                if (A.IsEmpty)
+                {
+                    // If the array is empty, check whether it is empty along the chosen dimension
+                    
+                    if (A.S[dim] > 0)
+                        // no there are potential elements in that dimension, hence we reduce it to 1
+                        newDims[dim] = 1;
+                    else
+                        // yes, empty along chosen dimension so the result is empty, i.e. 0 elements in that dimension
+                        newDims[dim] = 0;
+                    return ILRetArray<fcomplex>.empty(new ILSize(newDims));
+                }
+
+                newDims[dim] = 1;
+
+                // Check selected element and replace by useful value
+                if (k < 1)
+                    k = 1;
+                if (k > A.S[dim])
+                    k = A.S[dim];
+
+                ILSize retDimension = new ILSize(newDims);
+
+                fcomplex[] retArr = ILMemoryPool.Pool.New< fcomplex>(retDimension.NumberOfElements);
+
+                int inc = A.Size.SequentialIndexDistance(dim);
+                int dimLen = A.Size[dim];
+                int maxRuns = retDimension.NumberOfElements;
+                int modHelp = A.Size.NumberOfElements - 1;
+                int modOut = retDimension.NumberOfElements - 1;
+                int incOut = retDimension.SequentialIndexDistance(dim); 
+                int numelA = A.S.NumberOfElements;
+                if (maxRuns == 1) {
+                    int dummy;
+                    retArr[0] = quickselect_worker(A.C.GetArrayForWrite(), 0, A.S[dim] - 1, k, out dummy);
+                } else {
+                    #region may run parallel 
+                   
+                    fcomplex[] aArray = A.GetArrayForRead();
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                    if (Settings.s_maxNumberThreads > 1 && maxRuns > 1 
+                        && numelA / 2 >= Settings.s_minParallelElement1Count) {
+
+                        if (maxRuns >= Settings.s_maxNumberThreads
+                            && numelA / Settings.s_maxNumberThreads > Settings.s_minParallelElement1Count) {
+                            workItemLength = maxRuns / workItemCount;
+                        } else {
+                            workItemLength = maxRuns / 2;
+                            workItemCount = 2;
+                        }
+                        
+                    } else {
+                        workItemLength = maxRuns;
+                        workItemCount = 1;
+                    }
+                    Action<object> action = (data) => {
+                        Tuple<int, int> range = (Tuple<int, int>)data;
+                        int from = range.Item1, to = range.Item2;
+                        for (int c = from; c < to; c++) {
+                            int pos = (int)(((long)dimLen * c * inc) % modHelp);
+                            int posOut = (c * incOut);
+                            if (posOut > modOut)
+                                posOut = ((posOut - 1) % modOut) + 1;
+                           
+                            fcomplex[] tmp = ILMemoryPool.Pool.New< fcomplex>(dimLen);
+                            int locPos = 0;
+                            int end = pos + dimLen * inc;
+                            for (int j = pos; j < end; j += inc)
+                                tmp[locPos++] = aArray[j];
+                            int dummy;
+                            retArr[posOut] = quickselect_worker(tmp, 0, dimLen - 1, k, out dummy);
+                            ILMemoryPool.Pool.Free(tmp);
+                        }
+                        System.Threading.Interlocked.Decrement(ref workerCount);
+                    };
+                    for (; i < workItemCount - 1; i++) {
+                        Interlocked.Increment(ref workerCount);
+
+                        ILThreadPool.QueueUserWorkItem(i,action, Tuple.Create(i * workItemLength, (i + 1) * workItemLength));
+                    }
+                    action(Tuple.Create(i * workItemLength, maxRuns));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                    #endregion
+                }
+                return new ILRetArray<fcomplex>(retArr, newDims);
+            }
+        }
+        /// <summary>
+        /// Select the k-th smallest element from an array along a specific dimension
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="k">The element to find. If k is smaller 1 or larger than the number of elements in list, the smallest/largest value will be returned.</param>
+        /// <param name="dim">[Optional] Dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns><para>Array having the specified dimension reduced to the length 1 with the value of the k-the smallest element along that dimension.</para>
+        /// <para>Exception: If the selected dimension is of size 0 it will remain 0 (an empty set).</para></returns>
+        public static ILRetArray<float> select(ILInArray<float> A, int k, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+
+                if (dim >= A.Size.NumberOfDimensions)
+                    return A.C;
+               
+                if (A.IsScalar) {
+                    return new ILRetArray<float>(new float[] { A.GetValue(0) }, 1, 1);
+                }
+               
+                if (A.S[dim] == 1) return A.C;
+
+                int[] newDims = A.S.ToIntArray();
+                if (A.IsEmpty)
+                {
+                    // If the array is empty, check whether it is empty along the chosen dimension
+                    
+                    if (A.S[dim] > 0)
+                        // no there are potential elements in that dimension, hence we reduce it to 1
+                        newDims[dim] = 1;
+                    else
+                        // yes, empty along chosen dimension so the result is empty, i.e. 0 elements in that dimension
+                        newDims[dim] = 0;
+                    return ILRetArray<float>.empty(new ILSize(newDims));
+                }
+
+                newDims[dim] = 1;
+
+                // Check selected element and replace by useful value
+                if (k < 1)
+                    k = 1;
+                if (k > A.S[dim])
+                    k = A.S[dim];
+
+                ILSize retDimension = new ILSize(newDims);
+
+                float[] retArr = ILMemoryPool.Pool.New< float>(retDimension.NumberOfElements);
+
+                int inc = A.Size.SequentialIndexDistance(dim);
+                int dimLen = A.Size[dim];
+                int maxRuns = retDimension.NumberOfElements;
+                int modHelp = A.Size.NumberOfElements - 1;
+                int modOut = retDimension.NumberOfElements - 1;
+                int incOut = retDimension.SequentialIndexDistance(dim); 
+                int numelA = A.S.NumberOfElements;
+                if (maxRuns == 1) {
+                    int dummy;
+                    retArr[0] = quickselect_worker(A.C.GetArrayForWrite(), 0, A.S[dim] - 1, k, out dummy);
+                } else {
+                    #region may run parallel 
+                   
+                    float[] aArray = A.GetArrayForRead();
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                    if (Settings.s_maxNumberThreads > 1 && maxRuns > 1 
+                        && numelA / 2 >= Settings.s_minParallelElement1Count) {
+
+                        if (maxRuns >= Settings.s_maxNumberThreads
+                            && numelA / Settings.s_maxNumberThreads > Settings.s_minParallelElement1Count) {
+                            workItemLength = maxRuns / workItemCount;
+                        } else {
+                            workItemLength = maxRuns / 2;
+                            workItemCount = 2;
+                        }
+                        
+                    } else {
+                        workItemLength = maxRuns;
+                        workItemCount = 1;
+                    }
+                    Action<object> action = (data) => {
+                        Tuple<int, int> range = (Tuple<int, int>)data;
+                        int from = range.Item1, to = range.Item2;
+                        for (int c = from; c < to; c++) {
+                            int pos = (int)(((long)dimLen * c * inc) % modHelp);
+                            int posOut = (c * incOut);
+                            if (posOut > modOut)
+                                posOut = ((posOut - 1) % modOut) + 1;
+                           
+                            float[] tmp = ILMemoryPool.Pool.New< float>(dimLen);
+                            int locPos = 0;
+                            int end = pos + dimLen * inc;
+                            for (int j = pos; j < end; j += inc)
+                                tmp[locPos++] = aArray[j];
+                            int dummy;
+                            retArr[posOut] = quickselect_worker(tmp, 0, dimLen - 1, k, out dummy);
+                            ILMemoryPool.Pool.Free(tmp);
+                        }
+                        System.Threading.Interlocked.Decrement(ref workerCount);
+                    };
+                    for (; i < workItemCount - 1; i++) {
+                        Interlocked.Increment(ref workerCount);
+
+                        ILThreadPool.QueueUserWorkItem(i,action, Tuple.Create(i * workItemLength, (i + 1) * workItemLength));
+                    }
+                    action(Tuple.Create(i * workItemLength, maxRuns));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                    #endregion
+                }
+                return new ILRetArray<float>(retArr, newDims);
+            }
+        }
+        /// <summary>
+        /// Select the k-th smallest element from an array along a specific dimension
+        /// </summary>
+        /// <param name="A">Input array</param>
+        /// <param name="k">The element to find. If k is smaller 1 or larger than the number of elements in list, the smallest/largest value will be returned.</param>
+        /// <param name="dim">[Optional] Dimension to operate along. If omitted operates along the first non singleton dimension (i.e. != 1).</param>
+        /// <returns><para>Array having the specified dimension reduced to the length 1 with the value of the k-the smallest element along that dimension.</para>
+        /// <para>Exception: If the selected dimension is of size 0 it will remain 0 (an empty set).</para></returns>
+        public static ILRetArray<complex> select(ILInArray<complex> A, int k, int dim = -1) {
+            using (ILScope.Enter(A)) {
+                if (dim < 0)
+                    dim = A.Size.WorkingDimension();
+
+                if (dim >= A.Size.NumberOfDimensions)
+                    return A.C;
+               
+                if (A.IsScalar) {
+                    return new ILRetArray<complex>(new complex[] { A.GetValue(0) }, 1, 1);
+                }
+               
+                if (A.S[dim] == 1) return A.C;
+
+                int[] newDims = A.S.ToIntArray();
+                if (A.IsEmpty)
+                {
+                    // If the array is empty, check whether it is empty along the chosen dimension
+                    
+                    if (A.S[dim] > 0)
+                        // no there are potential elements in that dimension, hence we reduce it to 1
+                        newDims[dim] = 1;
+                    else
+                        // yes, empty along chosen dimension so the result is empty, i.e. 0 elements in that dimension
+                        newDims[dim] = 0;
+                    return ILRetArray<complex>.empty(new ILSize(newDims));
+                }
+
+                newDims[dim] = 1;
+
+                // Check selected element and replace by useful value
+                if (k < 1)
+                    k = 1;
+                if (k > A.S[dim])
+                    k = A.S[dim];
+
+                ILSize retDimension = new ILSize(newDims);
+
+                complex[] retArr = ILMemoryPool.Pool.New< complex>(retDimension.NumberOfElements);
+
+                int inc = A.Size.SequentialIndexDistance(dim);
+                int dimLen = A.Size[dim];
+                int maxRuns = retDimension.NumberOfElements;
+                int modHelp = A.Size.NumberOfElements - 1;
+                int modOut = retDimension.NumberOfElements - 1;
+                int incOut = retDimension.SequentialIndexDistance(dim); 
+                int numelA = A.S.NumberOfElements;
+                if (maxRuns == 1) {
+                    int dummy;
+                    retArr[0] = quickselect_worker(A.C.GetArrayForWrite(), 0, A.S[dim] - 1, k, out dummy);
+                } else {
+                    #region may run parallel 
+                   
+                    complex[] aArray = A.GetArrayForRead();
+                    int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1;
+                    if (Settings.s_maxNumberThreads > 1 && maxRuns > 1 
+                        && numelA / 2 >= Settings.s_minParallelElement1Count) {
+
+                        if (maxRuns >= Settings.s_maxNumberThreads
+                            && numelA / Settings.s_maxNumberThreads > Settings.s_minParallelElement1Count) {
+                            workItemLength = maxRuns / workItemCount;
+                        } else {
+                            workItemLength = maxRuns / 2;
+                            workItemCount = 2;
+                        }
+                        
+                    } else {
+                        workItemLength = maxRuns;
+                        workItemCount = 1;
+                    }
+                    Action<object> action = (data) => {
+                        Tuple<int, int> range = (Tuple<int, int>)data;
+                        int from = range.Item1, to = range.Item2;
+                        for (int c = from; c < to; c++) {
+                            int pos = (int)(((long)dimLen * c * inc) % modHelp);
+                            int posOut = (c * incOut);
+                            if (posOut > modOut)
+                                posOut = ((posOut - 1) % modOut) + 1;
+                           
+                            complex[] tmp = ILMemoryPool.Pool.New< complex>(dimLen);
+                            int locPos = 0;
+                            int end = pos + dimLen * inc;
+                            for (int j = pos; j < end; j += inc)
+                                tmp[locPos++] = aArray[j];
+                            int dummy;
+                            retArr[posOut] = quickselect_worker(tmp, 0, dimLen - 1, k, out dummy);
+                            ILMemoryPool.Pool.Free(tmp);
+                        }
+                        System.Threading.Interlocked.Decrement(ref workerCount);
+                    };
+                    for (; i < workItemCount - 1; i++) {
+                        Interlocked.Increment(ref workerCount);
+
+                        ILThreadPool.QueueUserWorkItem(i,action, Tuple.Create(i * workItemLength, (i + 1) * workItemLength));
+                    }
+                    action(Tuple.Create(i * workItemLength, maxRuns));
+                    ILThreadPool.Wait4Workers(ref workerCount); 
+                    #endregion
+                }
+                return new ILRetArray<complex>(retArr, newDims);
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+        #region private helpers
+
+        private static int partition(double[] list, int left, int right, int pivotIndex)
+        {
+            
+            double pivotValue = list[pivotIndex];
+            
+            double tmp = list[right];
+            list[right] = list[pivotIndex];
+            list[pivotIndex] = tmp; // Move pivot to end
+            int storeIndex = left;
+            for (int i = left; i <= right; i++)
+            {
+                if (list[i] < pivotValue)
+                {
+                    tmp = list[storeIndex];
+                    list[storeIndex] = list[i];
+                    list[i] = tmp;
+                    storeIndex++;
+                }
+            }
+            // Move pivot to its final place
+            tmp = list[right];
+            list[right] = list[storeIndex];
+            list[storeIndex] = tmp;
+
+            return storeIndex;
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+        private static int partition(Int64[] list, int left, int right, int pivotIndex)
+        {
+           
+            Int64 pivotValue = list[pivotIndex];
+           
+            Int64 tmp = list[right];
+            list[right] = list[pivotIndex];
+            list[pivotIndex] = tmp; // Move pivot to end
+            int storeIndex = left;
+            for (int i = left; i <= right; i++)
+            {
+                if (list[i] < pivotValue)
+                {
+                    tmp = list[storeIndex];
+                    list[storeIndex] = list[i];
+                    list[i] = tmp;
+                    storeIndex++;
+                }
+            }
+            // Move pivot to its final place
+            tmp = list[right];
+            list[right] = list[storeIndex];
+            list[storeIndex] = tmp;
+
+            return storeIndex;
+        }
+        private static int partition(Int32[] list, int left, int right, int pivotIndex)
+        {
+           
+            Int32 pivotValue = list[pivotIndex];
+           
+            Int32 tmp = list[right];
+            list[right] = list[pivotIndex];
+            list[pivotIndex] = tmp; // Move pivot to end
+            int storeIndex = left;
+            for (int i = left; i <= right; i++)
+            {
+                if (list[i] < pivotValue)
+                {
+                    tmp = list[storeIndex];
+                    list[storeIndex] = list[i];
+                    list[i] = tmp;
+                    storeIndex++;
+                }
+            }
+            // Move pivot to its final place
+            tmp = list[right];
+            list[right] = list[storeIndex];
+            list[storeIndex] = tmp;
+
+            return storeIndex;
+        }
+        private static int partition(byte[] list, int left, int right, int pivotIndex)
+        {
+           
+            byte pivotValue = list[pivotIndex];
+           
+            byte tmp = list[right];
+            list[right] = list[pivotIndex];
+            list[pivotIndex] = tmp; // Move pivot to end
+            int storeIndex = left;
+            for (int i = left; i <= right; i++)
+            {
+                if (list[i] < pivotValue)
+                {
+                    tmp = list[storeIndex];
+                    list[storeIndex] = list[i];
+                    list[i] = tmp;
+                    storeIndex++;
+                }
+            }
+            // Move pivot to its final place
+            tmp = list[right];
+            list[right] = list[storeIndex];
+            list[storeIndex] = tmp;
+
+            return storeIndex;
+        }
+        private static int partition(fcomplex[] list, int left, int right, int pivotIndex)
+        {
+           
+            fcomplex pivotValue = list[pivotIndex];
+           
+            fcomplex tmp = list[right];
+            list[right] = list[pivotIndex];
+            list[pivotIndex] = tmp; // Move pivot to end
+            int storeIndex = left;
+            for (int i = left; i <= right; i++)
+            {
+                if (list[i] < pivotValue)
+                {
+                    tmp = list[storeIndex];
+                    list[storeIndex] = list[i];
+                    list[i] = tmp;
+                    storeIndex++;
+                }
+            }
+            // Move pivot to its final place
+            tmp = list[right];
+            list[right] = list[storeIndex];
+            list[storeIndex] = tmp;
+
+            return storeIndex;
+        }
+        private static int partition(float[] list, int left, int right, int pivotIndex)
+        {
+           
+            float pivotValue = list[pivotIndex];
+           
+            float tmp = list[right];
+            list[right] = list[pivotIndex];
+            list[pivotIndex] = tmp; // Move pivot to end
+            int storeIndex = left;
+            for (int i = left; i <= right; i++)
+            {
+                if (list[i] < pivotValue)
+                {
+                    tmp = list[storeIndex];
+                    list[storeIndex] = list[i];
+                    list[i] = tmp;
+                    storeIndex++;
+                }
+            }
+            // Move pivot to its final place
+            tmp = list[right];
+            list[right] = list[storeIndex];
+            list[storeIndex] = tmp;
+
+            return storeIndex;
+        }
+        private static int partition(complex[] list, int left, int right, int pivotIndex)
+        {
+           
+            complex pivotValue = list[pivotIndex];
+           
+            complex tmp = list[right];
+            list[right] = list[pivotIndex];
+            list[pivotIndex] = tmp; // Move pivot to end
+            int storeIndex = left;
+            for (int i = left; i <= right; i++)
+            {
+                if (list[i] < pivotValue)
+                {
+                    tmp = list[storeIndex];
+                    list[storeIndex] = list[i];
+                    list[i] = tmp;
+                    storeIndex++;
+                }
+            }
+            // Move pivot to its final place
+            tmp = list[right];
+            list[right] = list[storeIndex];
+            list[storeIndex] = tmp;
+
+            return storeIndex;
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+
+        /// <summary>
+        /// Quick select algorithm: Find the k-th smallest element in list.
+        /// Will change the list parameter!
+        /// </summary>
+        /// <remarks><para>Elements in the array list will be reordered. Make sure to pass a copy if you intend to use that data later</para></remarks>
+        /// <param name="list">The list to search in</param>
+        /// <param name="left">The first index in the list to start the search</param>
+        /// <param name="right">The last index in the list to end the search</param>
+        /// <param name="k">The k-th smallest element to find in list[left:right]. If k is smaller than 1 or larger than the number of elements the smallest/largest value will be returned.</param>
+        /// <param name="position">Returns the index in list where the smallest element was found</param>
+        /// <returns>The k-th smallest element</returns>
+        private static double quickselect_worker(double[] list, int left, int right, int k, out int position)
+        {
+            if ((left < 0) || (right > list.Length - 1))
+                throw new Exception("Arguments out of range. Left and right must be within the array limits");
+            position = -1;
+            while (true)
+            {
+                if (left == right) // If the list contains only one element
+                {
+                    position = left;
+                    return list[left];  // Return that element
+                }
+                // select pivotIndex between left and right
+                int pivotIndex = (left + right) / 2;
+                position = partition(list, left, right, pivotIndex); // = new pivot index
+                int pivotDist = position - left + 1;
+                // The pivot is in its final sorted position, 
+                // so pivotDist reflects its 1-based position if list were sorted
+                if (pivotDist == k)
+                    return list[position];
+                else if (k < pivotDist)
+                {
+                    //return quickselect(list, left, pivotNewIndex - 1, k);
+                    right = position - 1;
+                }
+                else
+                {
+                    //  return quickselect(list, pivotNewIndex + 1, right, k - pivotDist);
+                    left = position + 1;
+                    k = k - pivotDist;
+                }
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// Quick select algorithm: Find the k-th smallest element in list.
+        /// Will change the list parameter!
+        /// </summary>
+        /// <remarks><para>Elements in the array list will be reordered. Make sure to pass a copy if you intend to use that data later</para></remarks>
+        /// <param name="list">The list to search in</param>
+        /// <param name="left">The first index in the list to start the search</param>
+        /// <param name="right">The last index in the list to end the search</param>
+        /// <param name="k">The k-th smallest element to find in list[left:right]. If k is smaller than 1 or larger than the number of elements the smallest/largest value will be returned.</param>
+        /// <param name="position">Returns the index in list where the smallest element was found</param>
+        /// <returns>The k-th smallest element</returns>
+        private static Int64 quickselect_worker(Int64[] list, int left, int right, int k, out int position)
+        {
+            if ((left < 0) || (right > list.Length - 1))
+                throw new Exception("Arguments out of range. Left and right must be within the array limits");
+            position = -1;
+            while (true)
+            {
+                if (left == right) // If the list contains only one element
+                {
+                    position = left;
+                    return list[left];  // Return that element
+                }
+                // select pivotIndex between left and right
+                int pivotIndex = (left + right) / 2;
+                position = partition(list, left, right, pivotIndex); // = new pivot index
+                int pivotDist = position - left + 1;
+                // The pivot is in its final sorted position, 
+                // so pivotDist reflects its 1-based position if list were sorted
+                if (pivotDist == k)
+                    return list[position];
+                else if (k < pivotDist)
+                {
+                    //return quickselect(list, left, pivotNewIndex - 1, k);
+                    right = position - 1;
+                }
+                else
+                {
+                    //  return quickselect(list, pivotNewIndex + 1, right, k - pivotDist);
+                    left = position + 1;
+                    k = k - pivotDist;
+                }
+            }
+        }
+        /// <summary>
+        /// Quick select algorithm: Find the k-th smallest element in list.
+        /// Will change the list parameter!
+        /// </summary>
+        /// <remarks><para>Elements in the array list will be reordered. Make sure to pass a copy if you intend to use that data later</para></remarks>
+        /// <param name="list">The list to search in</param>
+        /// <param name="left">The first index in the list to start the search</param>
+        /// <param name="right">The last index in the list to end the search</param>
+        /// <param name="k">The k-th smallest element to find in list[left:right]. If k is smaller than 1 or larger than the number of elements the smallest/largest value will be returned.</param>
+        /// <param name="position">Returns the index in list where the smallest element was found</param>
+        /// <returns>The k-th smallest element</returns>
+        private static Int32 quickselect_worker(Int32[] list, int left, int right, int k, out int position)
+        {
+            if ((left < 0) || (right > list.Length - 1))
+                throw new Exception("Arguments out of range. Left and right must be within the array limits");
+            position = -1;
+            while (true)
+            {
+                if (left == right) // If the list contains only one element
+                {
+                    position = left;
+                    return list[left];  // Return that element
+                }
+                // select pivotIndex between left and right
+                int pivotIndex = (left + right) / 2;
+                position = partition(list, left, right, pivotIndex); // = new pivot index
+                int pivotDist = position - left + 1;
+                // The pivot is in its final sorted position, 
+                // so pivotDist reflects its 1-based position if list were sorted
+                if (pivotDist == k)
+                    return list[position];
+                else if (k < pivotDist)
+                {
+                    //return quickselect(list, left, pivotNewIndex - 1, k);
+                    right = position - 1;
+                }
+                else
+                {
+                    //  return quickselect(list, pivotNewIndex + 1, right, k - pivotDist);
+                    left = position + 1;
+                    k = k - pivotDist;
+                }
+            }
+        }
+        /// <summary>
+        /// Quick select algorithm: Find the k-th smallest element in list.
+        /// Will change the list parameter!
+        /// </summary>
+        /// <remarks><para>Elements in the array list will be reordered. Make sure to pass a copy if you intend to use that data later</para></remarks>
+        /// <param name="list">The list to search in</param>
+        /// <param name="left">The first index in the list to start the search</param>
+        /// <param name="right">The last index in the list to end the search</param>
+        /// <param name="k">The k-th smallest element to find in list[left:right]. If k is smaller than 1 or larger than the number of elements the smallest/largest value will be returned.</param>
+        /// <param name="position">Returns the index in list where the smallest element was found</param>
+        /// <returns>The k-th smallest element</returns>
+        private static byte quickselect_worker(byte[] list, int left, int right, int k, out int position)
+        {
+            if ((left < 0) || (right > list.Length - 1))
+                throw new Exception("Arguments out of range. Left and right must be within the array limits");
+            position = -1;
+            while (true)
+            {
+                if (left == right) // If the list contains only one element
+                {
+                    position = left;
+                    return list[left];  // Return that element
+                }
+                // select pivotIndex between left and right
+                int pivotIndex = (left + right) / 2;
+                position = partition(list, left, right, pivotIndex); // = new pivot index
+                int pivotDist = position - left + 1;
+                // The pivot is in its final sorted position, 
+                // so pivotDist reflects its 1-based position if list were sorted
+                if (pivotDist == k)
+                    return list[position];
+                else if (k < pivotDist)
+                {
+                    //return quickselect(list, left, pivotNewIndex - 1, k);
+                    right = position - 1;
+                }
+                else
+                {
+                    //  return quickselect(list, pivotNewIndex + 1, right, k - pivotDist);
+                    left = position + 1;
+                    k = k - pivotDist;
+                }
+            }
+        }
+        /// <summary>
+        /// Quick select algorithm: Find the k-th smallest element in list.
+        /// Will change the list parameter!
+        /// </summary>
+        /// <remarks><para>Elements in the array list will be reordered. Make sure to pass a copy if you intend to use that data later</para></remarks>
+        /// <param name="list">The list to search in</param>
+        /// <param name="left">The first index in the list to start the search</param>
+        /// <param name="right">The last index in the list to end the search</param>
+        /// <param name="k">The k-th smallest element to find in list[left:right]. If k is smaller than 1 or larger than the number of elements the smallest/largest value will be returned.</param>
+        /// <param name="position">Returns the index in list where the smallest element was found</param>
+        /// <returns>The k-th smallest element</returns>
+        private static fcomplex quickselect_worker(fcomplex[] list, int left, int right, int k, out int position)
+        {
+            if ((left < 0) || (right > list.Length - 1))
+                throw new Exception("Arguments out of range. Left and right must be within the array limits");
+            position = -1;
+            while (true)
+            {
+                if (left == right) // If the list contains only one element
+                {
+                    position = left;
+                    return list[left];  // Return that element
+                }
+                // select pivotIndex between left and right
+                int pivotIndex = (left + right) / 2;
+                position = partition(list, left, right, pivotIndex); // = new pivot index
+                int pivotDist = position - left + 1;
+                // The pivot is in its final sorted position, 
+                // so pivotDist reflects its 1-based position if list were sorted
+                if (pivotDist == k)
+                    return list[position];
+                else if (k < pivotDist)
+                {
+                    //return quickselect(list, left, pivotNewIndex - 1, k);
+                    right = position - 1;
+                }
+                else
+                {
+                    //  return quickselect(list, pivotNewIndex + 1, right, k - pivotDist);
+                    left = position + 1;
+                    k = k - pivotDist;
+                }
+            }
+        }
+        /// <summary>
+        /// Quick select algorithm: Find the k-th smallest element in list.
+        /// Will change the list parameter!
+        /// </summary>
+        /// <remarks><para>Elements in the array list will be reordered. Make sure to pass a copy if you intend to use that data later</para></remarks>
+        /// <param name="list">The list to search in</param>
+        /// <param name="left">The first index in the list to start the search</param>
+        /// <param name="right">The last index in the list to end the search</param>
+        /// <param name="k">The k-th smallest element to find in list[left:right]. If k is smaller than 1 or larger than the number of elements the smallest/largest value will be returned.</param>
+        /// <param name="position">Returns the index in list where the smallest element was found</param>
+        /// <returns>The k-th smallest element</returns>
+        private static float quickselect_worker(float[] list, int left, int right, int k, out int position)
+        {
+            if ((left < 0) || (right > list.Length - 1))
+                throw new Exception("Arguments out of range. Left and right must be within the array limits");
+            position = -1;
+            while (true)
+            {
+                if (left == right) // If the list contains only one element
+                {
+                    position = left;
+                    return list[left];  // Return that element
+                }
+                // select pivotIndex between left and right
+                int pivotIndex = (left + right) / 2;
+                position = partition(list, left, right, pivotIndex); // = new pivot index
+                int pivotDist = position - left + 1;
+                // The pivot is in its final sorted position, 
+                // so pivotDist reflects its 1-based position if list were sorted
+                if (pivotDist == k)
+                    return list[position];
+                else if (k < pivotDist)
+                {
+                    //return quickselect(list, left, pivotNewIndex - 1, k);
+                    right = position - 1;
+                }
+                else
+                {
+                    //  return quickselect(list, pivotNewIndex + 1, right, k - pivotDist);
+                    left = position + 1;
+                    k = k - pivotDist;
+                }
+            }
+        }
+        /// <summary>
+        /// Quick select algorithm: Find the k-th smallest element in list.
+        /// Will change the list parameter!
+        /// </summary>
+        /// <remarks><para>Elements in the array list will be reordered. Make sure to pass a copy if you intend to use that data later</para></remarks>
+        /// <param name="list">The list to search in</param>
+        /// <param name="left">The first index in the list to start the search</param>
+        /// <param name="right">The last index in the list to end the search</param>
+        /// <param name="k">The k-th smallest element to find in list[left:right]. If k is smaller than 1 or larger than the number of elements the smallest/largest value will be returned.</param>
+        /// <param name="position">Returns the index in list where the smallest element was found</param>
+        /// <returns>The k-th smallest element</returns>
+        private static complex quickselect_worker(complex[] list, int left, int right, int k, out int position)
+        {
+            if ((left < 0) || (right > list.Length - 1))
+                throw new Exception("Arguments out of range. Left and right must be within the array limits");
+            position = -1;
+            while (true)
+            {
+                if (left == right) // If the list contains only one element
+                {
+                    position = left;
+                    return list[left];  // Return that element
+                }
+                // select pivotIndex between left and right
+                int pivotIndex = (left + right) / 2;
+                position = partition(list, left, right, pivotIndex); // = new pivot index
+                int pivotDist = position - left + 1;
+                // The pivot is in its final sorted position, 
+                // so pivotDist reflects its 1-based position if list were sorted
+                if (pivotDist == k)
+                    return list[position];
+                else if (k < pivotDist)
+                {
+                    //return quickselect(list, left, pivotNewIndex - 1, k);
+                    right = position - 1;
+                }
+                else
+                {
+                    //  return quickselect(list, pivotNewIndex + 1, right, k - pivotDist);
+                    left = position + 1;
+                    k = k - pivotDist;
+                }
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+       #endregion
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/ILNumerics.csproj
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/ILNumerics.csproj	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/ILNumerics.csproj	(revision 9102)
@@ -0,0 +1,664 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{93B4A10E-8979-4028-8CCF-49D88D6FAC0C}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>ILNumerics</RootNamespace>
+    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <AssemblyName>ILNumerics</AssemblyName>
+    <MSBuildCommunityTasksPath>$(SolutionDir)\Build</MSBuildCommunityTasksPath>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>..\..\..\trunk\sources\bin\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>..\..\bin\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+    <RunCodeAnalysis>false</RunCodeAnalysis>
+    <CodeAnalysisRuleSet>BasicDesignGuidelineRules.ruleset</CodeAnalysisRuleSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>..\..\..\trunk\sources\bin\</OutputPath>
+    <DefineConstants>TRACE;DEBUG;x64</DefineConstants>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
+    <CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
+    <WarningLevel>4</WarningLevel>
+    <Optimize>false</Optimize>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
+    <OutputPath>..\..\bin\</OutputPath>
+    <DefineConstants>x64 KMEANSVERBOSE_ MKLFFT_VERBOSE</DefineConstants>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
+    <CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
+    <UseVSHostingProcess>false</UseVSHostingProcess>
+    <WarningLevel>4</WarningLevel>
+    <DocumentationFile>..\..\bin\ILNumerics.xml</DocumentationFile>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>..\..\..\trunk\sources\bin\</OutputPath>
+    <DefineConstants>TRACE_ DEBUG VERBOSE_ FINALIZE_DISPOSE_ ILDenseArray_CONSTRUCT_VERBOSE_ KMEANSVERBOSE DRAWPLOTCUBESCREENRECT_ DRAWTEXTURESHEET_</DefineConstants>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
+    <CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
+    <DocumentationFile>..\bin\ILNumerics.xml</DocumentationFile>
+    <Optimize>false</Optimize>
+    <NoWarn>0419</NoWarn>
+    <WarningLevel>4</WarningLevel>
+    <RegisterForComInterop>false</RegisterForComInterop>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
+    <OutputPath>..\..\bin\</OutputPath>
+    <DefineConstants>VERBOSE_ FINALIZE_DISPOSE_ KMEANSVERBOSE_</DefineConstants>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <UseVSHostingProcess>false</UseVSHostingProcess>
+    <DocumentationFile>..\..\bin\ILNumerics.xml</DocumentationFile>
+    <WarningLevel>4</WarningLevel>
+    <DebugSymbols>true</DebugSymbols>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'ReleaseBuild|AnyCPU'">
+    <OutputPath>bin\ReleaseBuild\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <CodeAnalysisLogFile>..\bin\ILNumerics.Server.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+    <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+    <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>BasicDesignGuidelineRules.ruleset</CodeAnalysisRuleSet>
+    <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+    <CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
+    <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+    <CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'ReleaseBuild|x64'">
+    <OutputPath>bin\x64\ReleaseBuild\</OutputPath>
+    <DefineConstants>x64</DefineConstants>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+    <DocumentationFile>..\build\Windows\x64_64bit\ILNumerics.Server.XML</DocumentationFile>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <CodeAnalysisLogFile>..\bin64\ILNumerics.Server.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+    <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+    <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+    <UseVSHostingProcess>false</UseVSHostingProcess>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+    <CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
+    <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+    <CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
+    <CodeAnalysisFailOnMissingRules>false</CodeAnalysisFailOnMissingRules>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'ReleaseBuild|x86'">
+    <OutputPath>bin\x86\ReleaseBuild\</OutputPath>
+    <DefineConstants>VERBOSE_ FINALIZE_DISPOSE_</DefineConstants>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+    <DocumentationFile>..\build\Windows\x64_64bit\ILNumerics.Server.XML</DocumentationFile>
+    <Optimize>true</Optimize>
+    <WarningLevel>1</WarningLevel>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <CodeAnalysisLogFile>..\bin\ILNumerics.Server.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+    <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+    <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+    <UseVSHostingProcess>false</UseVSHostingProcess>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+    <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+  </PropertyGroup>
+  <PropertyGroup>
+    <SignAssembly>true</SignAssembly>
+  </PropertyGroup>
+  <PropertyGroup>
+    <AssemblyOriginatorKeyFile>HeuristicLab.snk</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="OpenTK">
+      <HintPath>bin64\OpenTK.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Numerics" />
+    <Reference Include="System.Windows.Forms" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+    <Reference Include="System.Configuration" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Algorithms\Graphics\Triangularize.cs" />
+    <Compile Include="Algorithms\MachineLearning\ILEM.cs" />
+    <Compile Include="Algorithms\MachineLearning\ILKNN.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Algorithms\MachineLearning\ILKRR.cs" />
+    <Compile Include="Algorithms\MachineLearning\ILOLS.cs" />
+    <Compile Include="Algorithms\MachineLearning\ILPCA.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Algorithms\MachineLearning\ILResult.cs" />
+    <Compile Include="Algorithms\MachineLearning\kmeansclust.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Algorithms\Sorting\ILBucketSort.cs" />
+    <Compile Include="Algorithms\Sorting\ILKeyMapper.cs" />
+    <Compile Include="Algorithms\Sorting\ILQueue.cs" />
+    <Compile Include="Algorithms\Sorting\ILQuickSortST.cs" />
+    <Compile Include="Algorithms\Sorting\ILQuickSortMT.cs" />
+    <Compile Include="Algorithms\Special\ILSpecialData.cs" />
+    <Compile Include="Array\ILArray.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Array\ILBaseArray.cs" />
+    <Compile Include="Array\ILBaseArrayGen.cs" />
+    <Compile Include="Array\ILBaseCell.cs" />
+    <Compile Include="Array\ILBaseLogical.cs" />
+    <Compile Include="Array\ILCell.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Array\ILDenseArray.cs" />
+    <Compile Include="Array\ILFullRange.cs" />
+    <Compile Include="Array\ILInArray.cs" />
+    <Compile Include="Array\ILInCell.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Array\ILInLogical.cs" />
+    <Compile Include="Array\ILLogical.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Array\ILOutArray.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Array\ILOutLogical.cs" />
+    <Compile Include="Array\ILRetArray.cs" />
+    <Compile Include="Array\ILRetCell.cs" />
+    <Compile Include="Array\ILRetLogical.cs" />
+    <Compile Include="Array\ILOutCell.cs" />
+    <Compile Include="Array\ILRegularRange.cs" />
+    <Compile Include="Array\Operator_Overloads.cs" />
+    <Compile Include="Data\ILAVLTree.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Data\ILIntList.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Drawing\Collections\ILAxisCollection.cs" />
+    <Compile Include="Drawing\Collections\ILGraphCollection.cs" />
+    <Compile Include="Drawing\Collections\ILLightCollection.cs" />
+    <Compile Include="Drawing\Collections\ILSubfigureCollection.cs" />
+    <Compile Include="Drawing\Collections\ILTickCollection.cs" />
+    <Compile Include="Drawing\Controls\DummyNamespaceHolders.cs" />
+    <Compile Include="Drawing\Controls\ILBorderFitLabel.cs">
+      <SubType>Component</SubType>
+    </Compile>
+    <Compile Include="Drawing\Controls\ILColorBar.cs">
+      <SubType>Component</SubType>
+    </Compile>
+    <Compile Include="Drawing\Controls\ILMovingDockPanel.cs">
+      <SubType>Component</SubType>
+    </Compile>
+    <Compile Include="Drawing\Controls\ILPanel.cs">
+      <SubType>Component</SubType>
+    </Compile>
+    <Compile Include="Drawing\Controls\ILSubfigure.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="Drawing\Controls\ILTextBoxAutoHide.cs">
+      <SubType>Component</SubType>
+    </Compile>
+    <Compile Include="Drawing\Graphs\ILFilledGraph.cs" />
+    <Compile Include="Drawing\Graphs\ILGraph.cs" />
+    <Compile Include="Drawing\Graphs\ILImageSCGraph.cs" />
+    <Compile Include="Drawing\Graphs\ILPlot2DGraph.cs" />
+    <Compile Include="Drawing\Graphs\ILSceneGraph.cs" />
+    <Compile Include="Drawing\Graphs\ILSceneGraphInnerNode.cs" />
+    <Compile Include="Drawing\Graphs\ILSceneGraphNode.cs" />
+    <Compile Include="Drawing\Graphs\ILSceneGraphRootNode.cs" />
+    <Compile Include="Drawing\Graphs\ILSceneGraphShapedLeaf.cs" />
+    <Compile Include="Drawing\Graphs\ILSurfaceGraph.cs" />
+    <Compile Include="Drawing\Interfaces\IILGraphFactory.cs" />
+    <Compile Include="Drawing\Interfaces\IILLegendRenderer.cs" />
+    <Compile Include="Drawing\Interfaces\IILPanelConfigurator.cs" />
+    <Compile Include="Drawing\Interfaces\IILSupportsLight.cs" />
+    <Compile Include="Drawing\Interfaces\IILTextInterpreter.cs" />
+    <Compile Include="Drawing\Interfaces\IILTextRenderer.cs" />
+    <Compile Include="Drawing\Interfaces\IILVertexDefinition.cs" />
+    <Compile Include="Drawing\Labeling\ILHashCreator.cs" />
+    <Compile Include="Drawing\Labeling\ILLabel.cs" />
+    <Compile Include="Drawing\Labeling\ILLabelingElement.cs" />
+    <Compile Include="Drawing\Labeling\ILRendererAttribute.cs" />
+    <Compile Include="Drawing\Labeling\ILRenderQueue.cs" />
+    <Compile Include="Drawing\Labeling\ILRenderQueueItem.cs" />
+    <Compile Include="Drawing\Labeling\ILShapeLabel.cs" />
+    <Compile Include="Drawing\Labeling\ILSimpleInterpreter.cs" />
+    <Compile Include="Drawing\Labeling\ILSimpleTexInterpreter.cs" />
+    <Compile Include="Drawing\Labeling\ILTextRendererManager.cs" />
+    <Compile Include="Drawing\Labeling\ILTextureData.cs" />
+    <Compile Include="Drawing\Labeling\ILTextureManager.cs" />
+    <Compile Include="Drawing\Labeling\ILTextureStorage.cs" />
+    <Compile Include="Drawing\Labeling\ILWorldLabel.cs" />
+    <Compile Include="Drawing\Lighting\ILLight.cs" />
+    <Compile Include="Drawing\Lighting\ILMaterial.cs" />
+    <Compile Include="Drawing\Marker\ILBitmapMarkerShape.cs" />
+    <Compile Include="Drawing\Marker\ILMarker.cs" />
+    <Compile Include="Drawing\Marker\ILMarkerShape.cs" />
+    <Compile Include="Drawing\Marker\ILMarkerShapeProxy.cs" />
+    <Compile Include="Drawing\Marker\ILStyledMarkerShape.cs" />
+    <Compile Include="Drawing\Marker\ILTexMarkerShape.cs" />
+    <Compile Include="Drawing\Misc\Definitions.cs" />
+    <Compile Include="Drawing\Misc\Events.cs" />
+    <Compile Include="Drawing\Misc\ILAction.cs" />
+    <Compile Include="Drawing\Misc\ILActionRamp.cs" />
+    <Compile Include="Drawing\Misc\ILActionRampElement.cs" />
+    <Compile Include="Drawing\Misc\ILAxis.cs" />
+    <Compile Include="Drawing\Misc\ILCamera.cs" />
+    <Compile Include="Drawing\Misc\ILClippingData.cs" />
+    <Compile Include="Drawing\Misc\ILColorEnumerator.cs" />
+    <Compile Include="Drawing\Misc\ILColormap.cs" />
+    <Compile Include="Drawing\Misc\ILColorProvider.cs" />
+    <Compile Include="Drawing\Misc\ILDrawingException.cs" />
+    <Compile Include="Drawing\Misc\ILGraphComparer.cs" />
+    <Compile Include="Drawing\Misc\ILLegend.cs" />
+    <Compile Include="Drawing\Misc\ILLineProperties.cs" />
+    <Compile Include="Drawing\Misc\ILRenderProperties.cs" />
+    <Compile Include="Drawing\Misc\ILZoomAction.cs" />
+    <Compile Include="Drawing\Platform\OpenGL\ILOGLAxis.cs" />
+    <Compile Include="Drawing\Platform\OpenGL\ILOGLBitmapMarkerShape.cs" />
+    <Compile Include="Drawing\Platform\OpenGL\ILOGLImageSCGraph.cs" />
+    <Compile Include="Drawing\Platform\OpenGL\ILOGLLegend.cs" />
+    <Compile Include="Drawing\Platform\OpenGL\ILOGLLineRendererC4bV3f.cs" />
+    <Compile Include="Drawing\Platform\OpenGL\ILOGLLinesRendererC4bV3f.cs" />
+    <Compile Include="Drawing\Platform\OpenGL\ILOGLPanel.cs">
+      <SubType>Component</SubType>
+    </Compile>
+    <Compile Include="Drawing\Platform\OpenGL\ILOGLPlot2DGraph.cs" />
+    <Compile Include="Drawing\Platform\OpenGL\ILOGLPointsRendererC4bV3f.cs" />
+    <Compile Include="Drawing\Platform\OpenGL\ILOGLRenderer.cs" />
+    <Compile Include="Drawing\Platform\OpenGL\ILOGLStyledMarkerShape.cs" />
+    <Compile Include="Drawing\Platform\OpenGL\ILOGLSurfaceGraph.cs" />
+    <Compile Include="Drawing\Platform\OpenGL\ILOGLTextureStorage.cs" />
+    <Compile Include="Drawing\Platform\OpenGL\ILOGLVertexRendererC4bV3f.cs" />
+    <Compile Include="Drawing\Platform\OpenGL\ILOGLVertexRendererC4fN3fV3f.cs" />
+    <Compile Include="Drawing\Platform\OpenGL\ILOGLWorldRenderer.cs" />
+    <Compile Include="Drawing\Platform\OpenGL\ILOGLXAxis.cs" />
+    <Compile Include="Drawing\Platform\OpenGL\ILOGLYAxis.cs" />
+    <Compile Include="Drawing\Platform\OpenGL\ILOGLZAxis.cs" />
+    <Compile Include="Drawing\Plots\ILBarGraph2D.cs" />
+    <Compile Include="Drawing\Plots\ILBarGraph3d.cs" />
+    <Compile Include="Drawing\Plots\ILLitBox3D.cs" />
+    <Compile Include="Drawing\Plots\ILLitSink.cs" />
+    <Compile Include="Drawing\Plots\ILLitSurface.cs" />
+    <Compile Include="Drawing\Plots\ILPlot.cs" />
+    <Compile Include="Drawing\Plots\ILVectorField2D.cs" />
+    <Compile Include="Drawing\Resources\Images1.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DesignTime>True</DesignTime>
+      <DependentUpon>Images.resx</DependentUpon>
+    </Compile>
+    <Compile Include="Drawing\Resources\Markers1.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DesignTime>True</DesignTime>
+      <DependentUpon>Markers.resx</DependentUpon>
+    </Compile>
+    <Compile Include="Drawing\Shapes\ILBorderedShape.cs" />
+    <Compile Include="Drawing\Shapes\ILCompositeShape.cs" />
+    <Compile Include="Drawing\Shapes\ILLine.cs" />
+    <Compile Include="Drawing\Shapes\ILLines.cs" />
+    <Compile Include="Drawing\Shapes\ILLitBorderedShape.cs" />
+    <Compile Include="Drawing\Shapes\ILLitCompositeShape.cs" />
+    <Compile Include="Drawing\Shapes\ILLitPolygon.cs" />
+    <Compile Include="Drawing\Shapes\ILLitQuad.cs" />
+    <Compile Include="Drawing\Shapes\ILLitQuads.cs" />
+    <Compile Include="Drawing\Shapes\ILLitSphere.cs" />
+    <Compile Include="Drawing\Shapes\ILLitTriangle.cs" />
+    <Compile Include="Drawing\Shapes\ILLitTriangles.cs" />
+    <Compile Include="Drawing\Shapes\ILPoints.cs" />
+    <Compile Include="Drawing\Shapes\ILPolygon.cs" />
+    <Compile Include="Drawing\Shapes\ILQuad.cs" />
+    <Compile Include="Drawing\Shapes\ILQuads.cs" />
+    <Compile Include="Drawing\Shapes\ILShape.cs" />
+    <Compile Include="Drawing\Shapes\ILTriangle.cs" />
+    <Compile Include="Drawing\Shapes\ILTriangles.cs" />
+    <Compile Include="Drawing\Shapes\ILVertexRenderer.cs" />
+    <Compile Include="Drawing\Shapes\VertexDefinitions.cs" />
+    <Compile Include="Functions\builtin\abs.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Functions\builtin\acos.cs" />
+    <Compile Include="Functions\builtin\Add.cs" />
+    <Compile Include="Functions\builtin\all.cs" />
+    <Compile Include="Functions\builtin\allall.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Functions\builtin\and.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Functions\builtin\any.cs" />
+    <Compile Include="Functions\builtin\anyall.cs" />
+    <Compile Include="Functions\builtin\apply.cs" />
+    <Compile Include="Functions\builtin\array.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Functions\builtin\asin.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Functions\builtin\atan.cs" />
+    <Compile Include="Functions\builtin\atan2.cs" />
+    <Compile Include="Functions\builtin\cart2pol.cs" />
+    <Compile Include="Functions\builtin\ccomplex.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Functions\builtin\ceil.cs" />
+    <Compile Include="Functions\builtin\cell.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Functions\builtin\check.cs" />
+    <Compile Include="Functions\builtin\chol.cs" />
+    <Compile Include="Functions\builtin\conj.cs" />
+    <Compile Include="Functions\builtin\convert.cs" />
+    <Compile Include="Functions\builtin\cos.cs" />
+    <Compile Include="Functions\builtin\cosh.cs" />
+    <Compile Include="Functions\builtin\counter.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Functions\builtin\cov.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Functions\builtin\det.cs" />
+    <Compile Include="Functions\builtin\diag.cs" />
+    <Compile Include="Functions\builtin\diff.cs" />
+    <Compile Include="Functions\builtin\dimensionWrapper.cs" />
+    <Compile Include="Functions\builtin\distL1.cs" />
+    <Compile Include="Functions\builtin\DivideElem.cs" />
+    <Compile Include="Functions\builtin\eig.cs" />
+    <Compile Include="Functions\builtin\empty.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Functions\builtin\end.cs" />
+    <Compile Include="Functions\builtin\eps.cs" />
+    <Compile Include="Functions\builtin\eq.cs" />
+    <Compile Include="Functions\builtin\exp.cs" />
+    <Compile Include="Functions\builtin\eye.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Functions\builtin\fft.cs" />
+    <Compile Include="Functions\builtin\Find.cs" />
+    <Compile Include="Functions\builtin\fix.cs" />
+    <Compile Include="Functions\builtin\fliplr.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Functions\builtin\flipud.cs" />
+    <Compile Include="Functions\builtin\floor.cs" />
+    <Compile Include="Functions\builtin\free.cs" />
+    <Compile Include="Functions\builtin\Horzcat.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Functions\builtin\ManMatMult.cs" />
+    <Compile Include="Functions\builtin\mvnpdf.cs" />
+    <Compile Include="Functions\builtin\ge.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Functions\builtin\gt.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Functions\builtin\imag.cs" />
+    <Compile Include="Functions\builtin\ind2sub.cs" />
+    <Compile Include="Functions\builtin\Invert.cs" />
+    <Compile Include="Functions\builtin\isempty.cs" />
+    <Compile Include="Functions\builtin\isequal.cs" />
+    <Compile Include="Functions\builtin\isequalwithequalnans.cs" />
+    <Compile Include="Functions\builtin\isfinite.cs" />
+    <Compile Include="Functions\builtin\isinf.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Functions\builtin\isnan.cs" />
+    <Compile Include="Functions\builtin\isneginf.cs" />
+    <Compile Include="Functions\builtin\isnull.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Functions\builtin\isnullorempty.cs" />
+    <Compile Include="Functions\builtin\isposinf.cs" />
+    <Compile Include="Functions\builtin\le.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Functions\builtin\linspace.cs" />
+    <Compile Include="Functions\builtin\load.cs" />
+    <Compile Include="Functions\builtin\log.cs" />
+    <Compile Include="Functions\builtin\log10.cs" />
+    <Compile Include="Functions\builtin\logspace.cs" />
+    <Compile Include="Functions\builtin\lt.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Functions\builtin\lu.cs" />
+    <Compile Include="Functions\builtin\matrixTest.cs" />
+    <Compile Include="Functions\builtin\Max.cs" />
+    <Compile Include="Functions\builtin\maxall.cs" />
+    <Compile Include="Functions\builtin\mean.cs" />
+    <Compile Include="Functions\builtin\meshgrid.cs" />
+    <Compile Include="Functions\builtin\Min.cs" />
+    <Compile Include="Functions\builtin\minall.cs" />
+    <Compile Include="Functions\builtin\mod.cs" />
+    <Compile Include="Functions\builtin\multiply.cs" />
+    <Compile Include="Functions\builtin\MultiplyElem.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Functions\builtin\mvnrnd.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Functions\builtin\neq.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Functions\builtin\new.cs" />
+    <Compile Include="Functions\builtin\Norm.cs" />
+    <Compile Include="Functions\builtin\ones.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Functions\builtin\or.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Functions\builtin\pinv.cs" />
+    <Compile Include="Functions\builtin\pol2cart.cs" />
+    <Compile Include="Functions\builtin\pow.cs" />
+    <Compile Include="Functions\builtin\prod.cs" />
+    <Compile Include="Functions\builtin\qr.cs" />
+    <Compile Include="Functions\builtin\r.cs" />
+    <Compile Include="Functions\builtin\rand.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Functions\builtin\randn.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Functions\builtin\randperm.cs" />
+    <Compile Include="Functions\builtin\rank.cs" />
+    <Compile Include="Functions\builtin\real.cs" />
+    <Compile Include="Functions\builtin\real2complex.cs" />
+    <Compile Include="Functions\builtin\real2fcomplex.cs" />
+    <Compile Include="Functions\builtin\repmat.cs" />
+    <Compile Include="Functions\builtin\reshape.cs" />
+    <Compile Include="Functions\builtin\round.cs" />
+    <Compile Include="Functions\builtin\set.cs" />
+    <Compile Include="Functions\builtin\sign.cs" />
+    <Compile Include="Functions\builtin\sin.cs" />
+    <Compile Include="Functions\builtin\sinh.cs" />
+    <Compile Include="Functions\builtin\slash.cs" />
+    <Compile Include="Functions\builtin\sort.cs" />
+    <Compile Include="Functions\builtin\sqrt.cs" />
+    <Compile Include="Functions\builtin\std.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Functions\builtin\sub2ind.cs" />
+    <Compile Include="Functions\builtin\Subtract.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Functions\builtin\sumall.cs" />
+    <Compile Include="Functions\builtin\SumMT.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Functions\builtin\Svd.cs" />
+    <Compile Include="Functions\builtin\tan.cs" />
+    <Compile Include="Functions\builtin\tanh.cs" />
+    <Compile Include="Functions\builtin\trace.cs" />
+    <Compile Include="Functions\builtin\tril_u.cs" />
+    <Compile Include="Functions\builtin\var.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Functions\builtin\vec.cs" />
+    <Compile Include="Functions\builtin\Vertcat.cs" />
+    <Compile Include="Functions\builtin\xor.cs" />
+    <Compile Include="Functions\builtin\zeros.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Functions\ILMath_General.cs" />
+    <Compile Include="Functions\statistics\median.cs" />
+    <Compile Include="Functions\statistics\nanmean.cs" />
+    <Compile Include="Functions\statistics\nansum.cs" />
+    <Compile Include="Functions\statistics\select.cs" />
+    <Compile Include="Misc\Enums.cs" />
+    <Compile Include="Misc\IILMemoryPool.cs" />
+    <Compile Include="Misc\ILArrayCache.cs" />
+    <Compile Include="Misc\ILCacheManager.cs" />
+    <Compile Include="Misc\ILComplex.cs" />
+    <Compile Include="Misc\ILExtensionMethods.cs" />
+    <Compile Include="Misc\ILFComplex.cs" />
+    <Compile Include="Misc\ILDebuggerProxy.cs" />
+    <Compile Include="Misc\ILException.cs" />
+    <Compile Include="Misc\ILExpression.cs" />
+    <Compile Include="Misc\ILMatFile5.cs" />
+    <Compile Include="Misc\ILMemoryPool.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Misc\ILMemoryPoolInternal.cs" />
+    <Compile Include="Misc\ILNRandom.cs" />
+    <Compile Include="Misc\ILPerformanceCounterMemoryPool.cs" />
+    <Compile Include="Misc\ILPerformanceCounterThreadPool.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Misc\ILPerformer.cs" />
+    <Compile Include="Misc\ILRand.cs" />
+    <Compile Include="Misc\ILRequestsValueComparer.cs" />
+    <Compile Include="Misc\ILScope.cs" />
+    <Compile Include="Misc\ILScopeList.cs" />
+    <Compile Include="Misc\ILSettings.cs" />
+    <Compile Include="Misc\ILSize.cs" />
+    <Compile Include="Misc\ILThreadConfig.cs" />
+    <Compile Include="Misc\ILThreadPool.cs" />
+    <Compile Include="Native\FFT\IILFFT.cs" />
+    <Compile Include="Native\FFT\ILACMLFFT.cs" />
+    <Compile Include="Native\FFT\ILFFTW3FFT.cs" />
+    <Compile Include="Native\FFT\ILMKLFFT.cs" />
+    <Compile Include="Native\lapack\IILLapack.cs" />
+    <Compile Include="Native\lapack\ILACML4_1.cs" />
+    <Compile Include="Native\lapack\ILLapackGenLinux.cs" />
+    <Compile Include="Native\lapack\ILLapackManaged.cs" />
+    <Compile Include="Native\lapack\ILLapackMKL10.0C.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Storage\ILCellStorage.cs" />
+    <Compile Include="Storage\ILCountableArray.cs" />
+    <Compile Include="Storage\ILDenseStorage.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Storage\ILDenseStorage_Constructors.cs" />
+    <Compile Include="Storage\ILLeftSideRange.cs" />
+    <Compile Include="Storage\ILLogicalStorage.cs" />
+    <Compile Include="Storage\ILRange.cs" />
+    <Compile Include="Storage\ILRightSideRange.cs" />
+    <Compile Include="Storage\ILStorage.cs" />
+    <Compile Include="Storage\ILStorageGeneric.cs" />
+    <Compile Include="Drawing\Platform\OpenGL\ILGLU.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="Drawing\Controls\ILColorBar.resx">
+      <DependentUpon>ILColorBar.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Drawing\Resources\Images.resx">
+      <Generator>ResXFileCodeGenerator</Generator>
+      <LastGenOutput>Images1.Designer.cs</LastGenOutput>
+      <CustomToolNamespace>ILNumerics.Drawing.Resources</CustomToolNamespace>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Drawing\Resources\Markers.resx">
+      <Generator>ResXFileCodeGenerator</Generator>
+      <LastGenOutput>Markers1.Designer.cs</LastGenOutput>
+      <CustomToolNamespace>ILNumerics.Drawing.Resources</CustomToolNamespace>
+    </EmbeddedResource>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="app.config" />
+    <None Include="Drawing\Resources\Circle25x25.png" />
+    <None Include="Drawing\Resources\close.bmp" />
+    <None Include="Drawing\Resources\Cross25x25.png" />
+    <None Include="Drawing\Resources\Diamond25x25.png" />
+    <None Include="Drawing\Resources\ILN20x25.png" />
+    <None Include="Drawing\Resources\Plus25x25.png" />
+    <None Include="Drawing\Resources\Triangle.gif" />
+    <None Include="Drawing\Resources\Triangle.jpg" />
+    <None Include="Drawing\Resources\TriangleDown25x25.png" />
+    <None Include="Drawing\Resources\TriangleLeft25x25.png" />
+    <None Include="Drawing\Resources\TriangleRight25x25.png" />
+    <None Include="Drawing\Resources\TriangleUp25x25.png" />
+    <None Include="Drawing\Resources\TriangleUp25x25A.bmp" />
+    <None Include="Drawing\Resources\TriangleUp25x25A.png" />
+    <Content Include="Native\lapack\link_general\HowToCreate lapack_gen.dll.txt" />
+    <Content Include="Native\lapack\link_general\lapack_gen.def" />
+    <Content Include="Native\lapack\link_general\lapack_gen.dll" />
+    <Content Include="Native\lapack\link_general\Win32sharedDLL.sh.txt" />
+    <None Include="HeuristicLab.snk" />
+    <None Include="packages.config" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Native\lapack\link_general\blas_LINUX.a" />
+    <None Include="Native\lapack\link_general\lapack_gen-gcc.lib" />
+    <None Include="Native\lapack\link_general\lapack_LINUX.a" />
+    <None Include="Native\lapack\link_general\linkAtlasGCC65.bash" />
+  </ItemGroup>
+  <ItemGroup />
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/License.txt
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/License.txt	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/License.txt	(revision 9102)
@@ -0,0 +1,674 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+    <program>  Copyright (C) <year>  <name of author>
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+  The GNU General Public License does not permit incorporating your program
+into proprietary programs.  If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.  But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/Enums.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/Enums.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/Enums.cs	(revision 9102)
@@ -0,0 +1,198 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+namespace ILNumerics {
+
+    /// <summary>
+    /// All toolboxes currently available in ILNumerics 
+    /// </summary>
+    public enum Toolboxes {
+        /// <summary>
+        ///  Machine Learning Toolbox
+        /// </summary>
+        MachineLearning,
+        /// <summary>
+        /// Statistics Toolbox
+        /// </summary>
+        Statistics
+    }
+
+    /// <summary>
+    /// Modes for implicit conversions from logical arrays to System.Boolean 
+    /// </summary>
+    /// <remarks>
+    /// <seealso cref="ILNumerics.Settings.LogicalArrayToBoolConversion"/></remarks>
+    public enum LogicalConversionMode {
+        /// <summary>
+        /// Throw an exception on the attempt to convert a non scaler value to logical/boolean.
+        /// </summary>
+        NonScalarThrowsException,
+        /// <summary>
+        /// Convert non scalar values to logical/boolean by applying the allall() function (i.e. it is true when all elements are non zero).
+        /// </summary>
+        ImplicitAllAll
+    }
+    /// <summary>
+    /// Enumerate all numeric type names used by ILNumerics
+    /// </summary>
+    public enum NumericType {
+        /// <summary>
+        /// double element type.
+        /// </summary>
+        Double,
+        /// <summary>
+        /// float element type.
+        /// </summary>
+        Single,
+        /// <summary>
+        /// complex element type.
+        /// </summary>
+        Complex ,
+        /// <summary>
+        /// fcomplex element type.
+        /// </summary>
+        FComplex,
+        /// <summary>
+        /// byte element type.
+        /// </summary>
+        Byte,
+        /// <summary>
+        /// Int32 element type.
+        /// </summary>
+        Int32,
+        /// <summary>
+        /// Int64 element type.
+        /// </summary>
+        Int64,
+    }
+
+    /// <summary>
+    /// Defines the way ILArrays are serialized to stream.
+    /// </summary>
+    /// <seealso cref="ILNumerics.ILDenseArray&lt;T&gt;.ToStream(System.IO.Stream,string,ILArrayStreamSerializationFlags)"/>
+    public enum ILArrayStreamSerializationFlags {
+        /// <summary>
+        /// Print values 'vectorized': one value after each other. The true dimension configuration 
+        /// of the array will be lost in the result. 
+        /// </summary>
+        Serial,
+        /// <summary>
+        /// Print values 'matrixwise'. The real dimensions configuration for the array are kept 
+        /// in the result. The array will be printed by pages, consisting out of the 1st and 2nd 
+        /// leading dimnsion. A dimension tag will prefix each page. The format can be used as 
+        /// fancier output version for human reading as well as human readable serialization 
+        /// format. ILArray's are capable of constructing from streams containing this type of 
+        /// output. 
+        /// </summary>
+        Formatted, 
+        /// <summary>
+        /// Export whole array instance to matlab 5.0 format
+        /// </summary>
+        Matlab
+    }
+    /// <summary>
+    /// Possible properties for matrices 
+    /// </summary>
+    /// <remarks><para>These properties may be returned by function overloads receiving a MatrixProperties 
+    /// parameter by reference. </para>
+    /// <para><![CDATA[This enum is a bitflag'ed enum! You may query for any combination via the bitwise operators | and &. ]]></para></remarks>
+    public enum MatrixProperties : int {
+        /// <summary>
+        /// Hermitian matrix 
+        /// </summary>
+        Hermitian = 1,
+        /// <summary>
+        /// Positive definite
+        /// </summary>
+        PositivDefinite = 2 ,
+        /// <summary>
+        /// Upper triangular matrix
+        /// </summary>
+        UpperTriangular = 4,
+        /// <summary>
+        /// Lower triangular matrix
+        /// </summary>
+        LowerTriangular = 8,
+        /// <summary>
+        /// Square matrix
+        /// </summary>
+        Square = 16,
+        /// <summary>
+        /// Diagonal matrix
+        /// </summary>
+        Diagonal = 32,
+        /// <summary>
+        /// The matrix is singular 
+        /// </summary>
+        Singular = 64,
+        /// <summary>
+        /// Hessenberg matrix
+        /// </summary>
+        Hessenberg = 128,
+        /// <summary>
+        /// Householder matrix
+        /// </summary>
+        Householder = 256,
+        /// <summary>
+        /// Unitary matrix
+        /// </summary>
+        Unitary = 512,
+        /// <summary>
+        /// Orthogonal matrix
+        /// </summary>
+        Orthogonal = 1024,
+        /// <summary>
+        /// Orthonormal matrix
+        /// </summary>
+        Orthonormal = 2048,
+        /// <summary>
+        /// The matrix has deficient rank
+        /// </summary>
+        RankDeficient = 4096,
+        /// <summary>
+        /// The matrix has no special properties
+        /// </summary>
+        None = 8192,
+        /// <summary>
+        /// No specific properties known (default)
+        /// </summary>
+        Unknown = 0
+    }
+}
+
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/IILMemoryPool.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/IILMemoryPool.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/IILMemoryPool.cs	(revision 9102)
@@ -0,0 +1,51 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace ILNumerics.Misc {
+    internal interface IILMemoryPool {
+
+        string Info(); 
+        string Info(bool generateShortInfo); 
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILArrayCache.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILArrayCache.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILArrayCache.cs	(revision 9102)
@@ -0,0 +1,101 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace ILNumerics.Misc {
+    // ToDo: DOKU Missing for complete class
+    public class ILArrayCache : IDisposable {
+
+        int m_hashKey; 
+        ILCell m_cache;
+        bool m_hasValue = false;
+
+        internal ILArrayCache() {
+            m_hasValue = false;  
+            m_cache = new ILCell(1,1);
+        }
+
+        public bool IsCached(params ILBaseArray[] keys) {
+            return hash(keys) == m_hashKey;
+        }
+
+        private int hash(ILBaseArray[] keys) {
+            if (keys == null) return 0; 
+            using (ILScope.Enter(keys)) {
+                int ret = keys.Length; 
+                foreach (ILBaseArray a in keys) {
+                    ret = unchecked(ret * 17) + a.GetHashCode(); 
+                }
+                return ret; 
+            }
+        }
+
+        public void Cache<T>(ILInArray<T> array, params ILBaseArray[] keys) {
+            using (ILScope.Enter(array)) {
+                m_hashKey = hash(keys); 
+                m_cache[0] = array;
+            }
+        }
+        public bool TryGetArray<T>(ILOutArray<T> cache, params ILBaseArray[] keys) {
+            if (object.Equals(cache,null)) 
+                return false; 
+            int curKey = hash(keys);
+            if (curKey == m_hashKey) {
+                cache.a = m_cache.GetArray<T>(0);
+                return true;
+            } 
+            return false;            
+        }
+
+        #region IDisposable Members
+
+        public void Dispose() {
+            if (! object.Equals( m_cache, null) )
+                m_cache.Dispose(); 
+            m_hasValue = false; 
+            m_hashKey = -1; 
+        }
+
+        #endregion
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILCPUID.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILCPUID.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILCPUID.cs	(revision 9102)
@@ -0,0 +1,210 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Diagnostics; 
+using System.Threading; 
+using System.Runtime.InteropServices; 
+using System.Reflection; 
+using ILNumerics;
+
+namespace ILNumerics.Misc {
+    /// <summary>
+    /// This class will support the runtime evaluation of the current processort. This is preliminary work and not used by the current ILNumerics release.
+    /// </summary>
+    public class ILCPUID {
+
+        #region attributes
+        bool? m_supportsCPUID = null; 
+        #endregion
+
+        #region properties
+        public bool Supported {
+            get {
+                if (!m_supportsCPUID.HasValue) {
+                    checkSupport();
+                }
+                return m_supportsCPUID.Value; }
+        }
+        #endregion
+        delegate uint cpuid_support_delegate();
+        static uint cpuid_support_dummy() {
+            return 0;
+        }
+
+        //[UnmanagedFunctionPointer(System.Runtime.InteropServices.CallingConvention.Cdecl)]
+        delegate void cpuid_delegate(int[] buffer);
+        static void cpuid_dummy(int[] buffer) {
+        }
+
+        static byte[] cpuid_asmprog = new byte[]{
+0x53,                 // push        ebx  
+0x56,                 // push        esi  
+0x8B, 0xF2,              // mov         esi,edx  
+0x83, 0xC6, 0x08,           // add         esi,8  
+0x8B, 0x06,              // mov         eax,dword ptr [esi]  
+0x0F, 0xA2,              // cpuid  
+0x89, 0x06,              // mov         dword ptr [esi],eax  
+0x89, 0x5E, 0x04,           // mov         dword ptr [esi+4],ebx  
+0x89, 0x4E, 0x08,           // mov         dword ptr [esi+8],ecx  
+0x89, 0x56, 0x0C,           // mov         dword ptr [esi+0Ch],edx  
+0x5E,                 // pop         esi  
+0x5B,                 // pop         ebx  
+0xC3
+
+//0x55,                  // push        ebp  
+//0x8B, 0xEC,               // mov         ebp,esp  
+//0x50,                  // push        eax  
+//0x56,                  // push        esi  
+//0x8B, 0x75, 0x08,            // mov         esi,dword ptr [ebp+8]  
+//0x8B, 0x06,               // mov         eax,dword ptr [esi]  
+//0x0F, 0xA2,               // cpuid  
+//0x89, 0x06,               // mov         dword ptr [esi],eax  
+//0x89, 0x5E, 0x04,            // mov         dword ptr [esi+4],ebx  
+//0x89, 0x4E, 0x08,            // mov         dword ptr [esi+8],ecx  
+//0x89, 0x56, 0x0C,            // mov         dword ptr [esi+0Ch],edx  
+//0x5E,                  // pop         esi  
+//0x58,                  // pop         eax  
+//0x8B, 0xE5,               // mov         esp,ebp  
+//0x5D,                  // pop         ebp 
+//0xC3
+};
+
+        static byte[] support_cpuid_asmprog = new byte[]{
+ 0x9C,                // pushfd  
+ 0x58,                // pop         eax  
+ 0x8B, 0xC8,             // mov         ecx,eax  
+ 0x35, 0x00, 0x00, 0x20, 0x00,    // xor         eax,200000h  
+ 0x50,                // push        eax  
+ 0x9D,                // popfd  
+ 0x9C,                // pushfd  
+ 0x58,                // pop         eax  
+ 0x33, 0xC1,             // xor         eax,ecx  
+ 0xC3
+    };
+
+        [DllImport("kernel32.dll", SetLastError = true)]
+        static extern IntPtr VirtualAlloc(IntPtr lpAddress, UIntPtr dwSize, AllocationType flAllocationType, MemoryProtection flProtect);
+        [DllImport("kernel32")]
+        private static extern bool VirtualFree(IntPtr lpAddress, UInt32 dwSize, UInt32 dwFreeType);
+
+        [Flags()]
+        public enum AllocationType : uint {
+            COMMIT = 0x1000,
+            RESERVE = 0x2000,
+            RESET = 0x80000,
+            LARGE_PAGES = 0x20000000,
+            PHYSICAL = 0x400000,
+            TOP_DOWN = 0x100000,
+            WRITE_WATCH = 0x200000
+        }
+
+        [Flags()]
+        public enum MemoryProtection : uint {
+            EXECUTE = 0x10,
+            EXECUTE_READ = 0x20,
+            EXECUTE_READWRITE = 0x40,
+            EXECUTE_WRITECOPY = 0x80,
+            NOACCESS = 0x01,
+            READONLY = 0x02,
+            READWRITE = 0x04,
+            WRITECOPY = 0x08,
+            GUARD_Modifierflag = 0x100,
+            NOCACHE_Modifierflag = 0x200,
+            WRITECOMBINE_Modifierflag = 0x400
+        }
+
+        unsafe public ILCPUID() {
+        }
+
+        unsafe public void Query(int[] buffer) {
+            // the actual cpuid request
+            if (buffer == null || buffer.Length < 4) 
+                throw new Exception("argument 'buffer' must have length >= 4"); 
+            IntPtr instructions = default(IntPtr); 
+            try {
+                instructions = VirtualAlloc(IntPtr.Zero, new UIntPtr((uint)cpuid_asmprog.Length), AllocationType.COMMIT | AllocationType.RESERVE, MemoryProtection.EXECUTE_READWRITE);
+                Marshal.Copy(cpuid_asmprog,0,instructions,cpuid_asmprog.Length); 
+                
+                cpuid_delegate cpuid = new cpuid_delegate(cpuid_dummy);
+                Type funcType = typeof(Delegate);
+                FieldInfo funcPointer = funcType.GetField("_methodPtr", BindingFlags.NonPublic | BindingFlags.Instance);
+                funcPointer.SetValue(cpuid,instructions); 
+                //fixed (int* buffer_fixed = buffer) {
+                    cpuid(buffer); 
+                //}
+
+            } finally {
+                if (instructions != IntPtr.Zero) {
+                    VirtualFree(instructions, 0, 0x8000); // MEM_RELEASE
+                    instructions = IntPtr.Zero;
+                }
+            }
+        }
+
+        unsafe private IntPtr checkSupport() {
+            IntPtr instructions = IntPtr.Zero;
+            try {
+                //'write' the asm - must be in an instruction section! (data area would not work)
+
+                instructions = VirtualAlloc(IntPtr.Zero, new UIntPtr((ulong)support_cpuid_asmprog.Length), AllocationType.COMMIT | AllocationType.RESERVE, MemoryProtection.EXECUTE_READWRITE);
+                Marshal.Copy(support_cpuid_asmprog,0,instructions,support_cpuid_asmprog.Length); 
+
+                Type funcType = typeof(Delegate);
+                FieldInfo funcPointer = funcType.GetField("_methodPtr", BindingFlags.NonPublic | BindingFlags.Instance);
+
+                // setup test for cpuid support
+                cpuid_support_delegate natcpuid_support = new cpuid_support_delegate(cpuid_support_dummy);
+                funcPointer.SetValue(natcpuid_support, instructions);
+                if (natcpuid_support() == 0) {
+                    Console.WriteLine("No support for cpuid!");
+                    m_supportsCPUID = false;
+                } else {
+                    m_supportsCPUID = true;
+                }
+            } finally {
+                if (instructions != IntPtr.Zero) {
+                    VirtualFree(instructions, 0, 0x8000); // MEM_RELEASE
+                    instructions = IntPtr.Zero;
+                }
+            }
+            return instructions;
+        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILCacheManager.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILCacheManager.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILCacheManager.cs	(revision 9102)
@@ -0,0 +1,94 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace ILNumerics.Misc {
+    /// <summary>
+    /// Manages local array caches, singleton instance is accessed via: ILNumerics.ILArrayCache&lt;T;gt;.Manager
+    /// </summary>
+    public class ILCacheManager {
+
+        private static ILCacheManager s_manager;
+        /// <summary>
+        /// Singleton instance of a cache manager, used to retrieve local array caches 
+        /// </summary>
+        public static ILCacheManager Manager {
+            get {
+                if (s_manager == null) {
+                    s_manager = new ILCacheManager();
+                }
+                return s_manager;
+            }
+        }
+
+        IList<IDisposable> m_caches = new List<IDisposable>(); 
+
+        internal ILCacheManager() {
+
+        }
+
+        /// <summary>
+        /// Create a new ILArrayCache and add to managed caches
+        /// </summary>
+        /// <returns>The new cache</returns>
+        public ILArrayCache GetCache() {
+            ILArrayCache ret = new ILArrayCache(); 
+            m_caches.Add(ret); 
+            return ret; 
+        }
+
+        /// <summary>
+        /// Dispose all managed caches
+        /// </summary>
+        public void FreeAllCaches() {
+            foreach (IDisposable d in m_caches) {
+                if (d != null) {
+                    d.Dispose(); 
+                }
+            }
+        }
+
+
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILComplex.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILComplex.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILComplex.cs	(revision 9102)
@@ -0,0 +1,2427 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+#pragma warning disable 162 
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.InteropServices;
+ 
+
+
+namespace ILNumerics {
+    /// <summary>
+    /// Floating point complex value data type of double precision
+    /// </summary>
+    /// <remarks>This class extends the system value types for real numbers to complex double 
+    /// values. Besides the publicly available members 'real' and 'imag' it provides all the 
+    /// basis functionality the floating point system.double brings (abs, log, sqrt, tan etc.),
+    /// as well as it overrides the basic unary and binary operators for all common system value 
+    /// types including rarely used types (e.g. UInt16). This includes the basic numerical operations 
+    /// like '+','-','/','*' and the relational operators: '==','>','>=' etc. Also there are some 
+    /// explicit and some implicit casting operators from / to complex value into system 
+    /// value types.</remarks>
+    [Serializable]
+    [StructLayout(LayoutKind.Sequential)]
+    public struct complex : IEquatable<complex> {
+        /// <summary>
+        /// Real part of this complex number
+        /// </summary>
+        public double real;
+        /// <summary>
+        /// Imaginary part of this complex number
+        /// </summary>
+        public double imag;
+        /// <summary>
+        /// Imaginary unit 
+        /// </summary>
+        public static readonly complex i = new complex(0.0f,1.0f); 
+
+        /// <summary>
+        /// Constructor creating a new complex value
+        /// </summary>
+        /// <param name="real">Real part</param>
+        /// <param name="imag">Imaginary part</param>
+        public complex(double real, double imag) {
+            this.real = real; 
+            this.imag = imag; 
+        }
+        /// <summary>
+        /// Complex conjugate 
+        /// </summary>
+        public complex conj {
+            get{
+                return new complex(real,-imag);
+            }
+        }
+
+        /// <summary>
+        /// Positive infinity for real and imag part of complex value
+        /// </summary>
+       public static complex INF {
+            get {
+                return new complex(
+                    double.PositiveInfinity,
+                    double.PositiveInfinity
+                );
+            }
+        }
+
+        /// <summary>
+        /// New complex, real and imaginary parts are zero
+        /// </summary>
+       public static complex Zero {
+            get {
+                return new complex(0.0,0.0);
+            }
+        }
+
+        /// <summary>
+        /// Complex quantity, marked as being "not a number"
+        /// </summary>
+        public static complex NaN {
+            get {
+                return new complex(double.NaN,double.NaN); 
+            }
+        }
+
+        /// <summary>
+        /// Are obj's real and imaginary part identical to the real and imaginary parts of this fcomplex
+        /// </summary>
+        /// <param name="obj">fcomplex object to determine the equality for</param>
+        /// <returns>true if obj is of fcomplex type and its real and imag part has the same 
+        /// values as the real and imaginary part of this array.</returns>
+        public override bool Equals(object obj) {
+            if (obj is complex && ((complex)obj) == this)
+                return true; 
+            return false; 
+        }
+        /// <summary>
+        /// Check if a complex number equals this complex number
+        /// </summary>
+        /// <param name="other">other complex number</param>
+        /// <returns>true if both, real and imaginary parts of both complex number are (binary) equal, false otherwise</returns>
+        public bool Equals(complex other) {
+            return real.Equals(other.real) && imag.Equals(other.imag); 
+        }
+        /// <summary>
+        /// Hash code of this comples
+        /// </summary>
+        /// <returns>Hash code of this complex</returns>
+        public override int GetHashCode() {
+            return 77101 * real.GetHashCode() + imag.GetHashCode();
+        }
+
+
+        
+        /// <summary>
+        /// Add two complex numbers
+        /// </summary>
+        /// <param name="A">First summand</param>
+        /// <param name="B">Second summand</param>
+        /// <returns>result</returns>
+        public static  complex operator +( complex A,  complex B) {
+             complex ret; 
+             ret.real =   (double) (A.real + B.real );
+             ret.imag =   (double) (A.imag + B.imag );
+            return ret;
+        }
+        /// <summary>
+        /// Subtract two complex values
+        /// </summary>
+        /// <param name="A">Minuend</param>
+        /// <param name="B">Subtrahend</param>
+        /// <returns>result</returns>
+        public static  complex operator -( complex A,  complex B) {
+             complex ret; 
+            ret.real =  (double) (A.real  - B.real );
+            ret.imag =  (double) (A.imag - B.imag );
+            return ret;
+        }
+        /// <summary>
+        /// Multiply two complex values
+        /// </summary>
+        /// <param name="A">First factor</param>
+        /// <param name="B">Second factor</param>
+        /// <returns>result</returns>
+        public static  complex operator *( complex A,  complex B) {
+             complex ret;
+            ret.real =  (double) ((A.real * B.real ) - (A.imag * B.imag ));
+            ret.imag =  (double) ((A.real * B.imag ) + (A.imag * B.real ));
+            return ret; 
+        }
+        /// <summary>
+        /// Divide two numbers
+        /// </summary>
+        /// <param name="A">Divident</param>
+        /// <param name="B">Divisor</param>
+        /// <returns>Result</returns>
+        /// <remarks><para>Unless the operator must handle special inputs (Inf or 0 values), 
+        /// the algorithm described in [1] is used for division. This is considered to be 
+        /// more robust against floating point overflow than the naive approach of simple 
+        /// cartesian division.</para>
+        /// <para>References: [1]: Smith, R.L., Algorithm 116: Complex division. Commun.ACM 5,8 (1962),435 <br />
+        /// [2]: Stewart, G.W., A note on complex division, ACM trans.on math software, Vol.11, N.3 (1985)</para></remarks>
+        public static  complex operator /( complex A,  complex B) {
+            if (B.imag == 0) return A / B.real; 
+            return A * (1 / B); 
+            if (IsNaN(A) ||  complex .IsNaN(B)) return NaN;
+            //if ( complex .IsInfinity(B)) return NaN;            
+            //if (A.real == 0 && A.imag == 0) return ( complex )0;
+             complex ret;
+            if (B.real == 0) {
+                ret.imag =  (double) -(A.real / B.imag); 
+                ret.real =  (double) (A.imag / B.imag); 
+                return ret; 
+            }
+            // this would be the naive approach. But it come with to little robustness against overflow
+            //double norm2 = B.real * B.real + B.imag * B.imag;
+            //if (norm2 == 0) return INF;    // this may be removed, since division by 0 results in inf anyway ? 
+            //ret.real =  (double) (((A.real  * B.real ) + (A.imag  * B.imag )) / norm2);
+            //ret.imag =  (double) (((A.imag  * B.real ) - (A.real  * B.imag )) / norm2); 
+            
+            // this algorithm is taken from [1]. The one described in [2] was not taken. Tests 
+            // did not show any advantage when using double precision floating point arithmetic.
+             double tmp1, tmp2; 
+            if (Math.Abs(B.real) >= Math.Abs(B.imag)) {
+                tmp1 =  (double) (B.imag * (1/B.real)); 
+                tmp2 =  (double) (B.real + B.imag*tmp1); 
+                ret.real =  (double) (A.real + A.imag*tmp1)/tmp2; 
+                ret.imag =  (double) (A.imag - A.real*tmp1)/tmp2; 
+            } else {
+                tmp1 =  (double) (B.real * (1/B.imag));
+                tmp2 =  (double) (B.imag + B.real*tmp1); 
+                ret.real =  (double) (A.imag + A.real*tmp1)/tmp2; 
+                ret.imag = -  (double) (A.real - A.imag*tmp1)/tmp2; 
+            }
+            return ret;                                            
+        }
+        /// <summary>
+        /// Equality comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true, if real and imaginary part are identical</returns>
+        public static bool operator ==( complex A,  complex B) {
+            return (A.imag  == B.imag ) && (A.real  == B.real );
+        }
+        /// <summary>
+        /// Unequality comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real and imaginary parts of A and B are not equal, false otherwise</returns>
+        public static bool operator !=( complex A,  complex B) {
+            return (A.imag  != B.imag ) || (A.real  != B.real );
+        }
+        /// <summary>
+        /// Greater than comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is greater than real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator > ( complex A,  complex B) {
+            return (A.real > B.real );
+        }
+        /// <summary>
+        /// Lower than comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is lower then real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator < ( complex A,  complex B) {
+            return (A.real < B.real );
+        }
+        /// <summary>
+        /// Greater than or equal to comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is greater than real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator >=( complex A,  complex B) {
+            return (A.real >= B.real );
+        }
+        /// <summary>
+        /// Lower than or equal to comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is lower then real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator <=( complex A,  complex B) { 
+            return (A.real <= B.real );
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+       
+        /// <summary>
+        /// Add two complex numbers
+        /// </summary>
+        /// <param name="A">First summand</param>
+        /// <param name="B">Second summand</param>
+        /// <returns>result</returns>
+        public static  complex operator +( complex A,  fcomplex B) {
+            complex ret; 
+             ret.real =  (double) (A.real + B.real );
+             ret.imag =  (double) (A.imag + B.imag );
+            return ret;
+        }
+        /// <summary>
+        /// Subtract two complex values
+        /// </summary>
+        /// <param name="A">Minuend</param>
+        /// <param name="B">Subtrahend</param>
+        /// <returns>result</returns>
+        public static  complex operator -( complex A,  fcomplex B) {
+            complex ret; 
+            ret.real =  (double) (A.real  - B.real );
+            ret.imag =  (double) (A.imag - B.imag );
+            return ret;
+        }
+        /// <summary>
+        /// Multiply two complex values
+        /// </summary>
+        /// <param name="A">First factor</param>
+        /// <param name="B">Second factor</param>
+        /// <returns>result</returns>
+        public static  complex operator *( complex A,  fcomplex B) {
+            complex ret;
+            ret.real =  (double) ((A.real * B.real ) - (A.imag * B.imag ));
+            ret.imag =  (double) ((A.real * B.imag ) + (A.imag * B.real ));
+            return ret; 
+        }
+        /// <summary>
+        /// Divide two numbers
+        /// </summary>
+        /// <param name="A">Divident</param>
+        /// <param name="B">Divisor</param>
+        /// <returns>Result</returns>
+        /// <remarks><para>Unless the operator must handle special inputs (Inf or 0 values), 
+        /// the algorithm described in [1] is used for division. This is considered to be 
+        /// more robust against floating point overflow than the naive approach of simple 
+        /// cartesian division.</para>
+        /// <para>References: [1]: Smith, R.L., Algorithm 116: Complex division. Commun.ACM 5,8 (1962),435 <br />
+        /// [2]: Stewart, G.W., A note on complex division, ACM trans.on math software, Vol.11, N.3 (1985)</para></remarks>
+        public static  complex operator /( complex A,  fcomplex B) {
+            if (B.imag == 0) return A / B.real; 
+            return A * (1 / B); 
+            if (IsNaN(A) ||  fcomplex .IsNaN(B)) return NaN;
+            //if ( fcomplex .IsInfinity(B)) return NaN;            
+            //if (A.real == 0 && A.imag == 0) return ( complex )0;
+            complex ret;
+            if (B.real == 0) {
+                ret.imag =  (double) -(A.real / B.imag); 
+                ret.real =  (double) (A.imag / B.imag); 
+                return ret; 
+            }
+            // this would be the naive approach. But it come with to little robustness against overflow
+            //double norm2 = B.real * B.real + B.imag * B.imag;
+            //if (norm2 == 0) return INF;    // this may be removed, since division by 0 results in inf anyway ? 
+            //ret.real =  (double) (((A.real  * B.real ) + (A.imag  * B.imag )) / norm2);
+            //ret.imag =  (double) (((A.imag  * B.real ) - (A.real  * B.imag )) / norm2); 
+            
+            // this algorithm is taken from [1]. The one described in [2] was not taken. Tests 
+            // did not show any advantage when using double precision floating point arithmetic.
+            double tmp1, tmp2; 
+            if (Math.Abs(B.real) >= Math.Abs(B.imag)) {
+                tmp1 =  (double) (B.imag * (1/B.real)); 
+                tmp2 =  (double) (B.real + B.imag*tmp1); 
+                ret.real =  (double) (A.real + A.imag*tmp1)/tmp2; 
+                ret.imag =  (double) (A.imag - A.real*tmp1)/tmp2; 
+            } else {
+                tmp1 =  (double) (B.real * (1/B.imag));
+                tmp2 =  (double) (B.imag + B.real*tmp1); 
+                ret.real =  (double) (A.imag + A.real*tmp1)/tmp2; 
+                ret.imag = -  (double) (A.real - A.imag*tmp1)/tmp2; 
+            }
+            return ret;                                            
+        }
+        /// <summary>
+        /// Equality comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true, if real and imaginary part are identical</returns>
+        public static bool operator ==( complex A,  fcomplex B) {
+            return (A.imag  == B.imag ) && (A.real  == B.real );
+        }
+        /// <summary>
+        /// Unequality comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real and imaginary parts of A and B are not equal, false otherwise</returns>
+        public static bool operator !=( complex A,  fcomplex B) {
+            return (A.imag  != B.imag ) || (A.real  != B.real );
+        }
+        /// <summary>
+        /// Greater than comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is greater than real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator > ( complex A,  fcomplex B) {
+            return (A.real > B.real );
+        }
+        /// <summary>
+        /// Lower than comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is lower then real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator < ( complex A,  fcomplex B) {
+            return (A.real < B.real );
+        }
+        /// <summary>
+        /// Greater than or equal to comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is greater than real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator >=( complex A,  fcomplex B) {
+            return (A.real >= B.real );
+        }
+        /// <summary>
+        /// Lower than or equal to comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is lower then real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator <=( complex A,  fcomplex B) { 
+            return (A.real <= B.real );
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+
+        
+        /// <summary>
+        /// Add two complex numbers
+        /// </summary>
+        /// <param name="A">First summand</param>
+        /// <param name="B">Second summand</param>
+        /// <returns>Result</returns>
+        public static  complex operator +( complex A,  double B) {
+             complex ret;
+            ret.real =  (double) (A.real + B);
+            ret.imag =  (double) A.imag;
+            return ret;
+        }
+        /// <summary>
+        /// Subtract two values
+        /// </summary>
+        /// <param name="A">Minuend</param>
+        /// <param name="B">Subtrahend</param>
+        /// <returns>result</returns>
+        public static  complex operator -( complex A,  double B) {
+             complex ret;
+            ret.real =  (double) (A.real - B);
+            ret.imag =  (double) A.imag;
+            return ret;
+        }
+        /// <summary>
+        /// Multiply two values
+        /// </summary>
+        /// <param name="A">First factor</param>
+        /// <param name="B">Second factor</param>
+        /// <returns>result</returns>
+        public static  complex operator *( complex A,  double B) {
+             complex ret;
+            ret.real =  (double) (A.real * B);
+            ret.imag =  (double) (A.imag * B);
+            return ret;
+        }
+        /// <summary>
+        /// Divide two numbers
+        /// </summary>
+        /// <param name="A">Divident</param>
+        /// <param name="B">Divisor</param>
+        /// <returns>result</returns>
+        public static  complex operator /( complex A,  double B) {
+            if (IsNaN(A)) return NaN;
+            
+            if (double.IsNaN(B)) return NaN; 
+            if (A.real == 0 && A.imag == 0) {
+                if (B == 0) return NaN; 
+                return ( complex )0;
+            } else {
+                
+                if (double .IsInfinity(B)) 
+                {
+                    if (IsInfinity(A)) {
+                        return NaN; 
+                    } else {
+                        return ( complex )0;
+                    }
+                }
+            }
+             complex ret;
+            if (B == 0) return INF ;
+            ret.real =  (double) (A.real / B);
+            ret.imag =  (double) (A.imag / B);
+            return ret;
+        }
+        /// <summary>
+        /// Equality comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>result</returns>
+        /// <remarks>Real inputs are converted to a complex number and the result is compared to the complex input.</remarks>
+        public static bool operator ==( complex A,  double B) {
+            return (A.real == B && A.imag == 0.0);
+        }
+        /// <summary>
+        /// Unequality comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real and imaginary parts of A and B are not equal, false otherwise</returns>
+        /// <remarks>Real inputs are converted to a complex number and the result is compared to the complex input.</remarks>
+        public static bool operator !=( complex A,  double B) {
+            return (A.imag != 0.0) || (A.real != B);
+        }
+        /// <summary>
+        /// Freater than comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is greater than real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator > ( complex A,  double B) {
+            return (A.real > B);
+        }
+        /// <summary>
+        /// Lower than comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is lower then real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator <(  complex A,  double B) {
+            return (A.real < B);
+        }
+        /// <summary>
+        /// Greater than or equal to comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is greater than real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator >=( complex A,  double B) {
+            return (A.real >= B);
+        }
+        /// <summary>
+        /// Lower than or equal to comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is lower then real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator <=( complex A,  double B) {
+            return (A.real <= B);
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+       
+        /// <summary>
+        /// Add two complex numbers
+        /// </summary>
+        /// <param name="A">First summand</param>
+        /// <param name="B">Second summand</param>
+        /// <returns>Result</returns>
+        public static  complex operator +( complex A,  Int64 B) {
+            complex ret;
+            ret.real =  (double) (A.real + B);
+            ret.imag =  (double) A.imag;
+            return ret;
+        }
+        /// <summary>
+        /// Subtract two values
+        /// </summary>
+        /// <param name="A">Minuend</param>
+        /// <param name="B">Subtrahend</param>
+        /// <returns>result</returns>
+        public static  complex operator -( complex A,  Int64 B) {
+            complex ret;
+            ret.real =  (double) (A.real - B);
+            ret.imag =  (double) A.imag;
+            return ret;
+        }
+        /// <summary>
+        /// Multiply two values
+        /// </summary>
+        /// <param name="A">First factor</param>
+        /// <param name="B">Second factor</param>
+        /// <returns>result</returns>
+        public static  complex operator *( complex A,  Int64 B) {
+            complex ret;
+            ret.real =  (double) (A.real * B);
+            ret.imag =  (double) (A.imag * B);
+            return ret;
+        }
+        /// <summary>
+        /// Divide two numbers
+        /// </summary>
+        /// <param name="A">Divident</param>
+        /// <param name="B">Divisor</param>
+        /// <returns>result</returns>
+        public static  complex operator /( complex A,  Int64 B) {
+            if (IsNaN(A)) return NaN;
+            
+            if (A.real == 0 && A.imag == 0) {
+                if (B == 0) return NaN; 
+                return ( complex )0;
+            } else {
+                if (false)
+                {
+                    if (IsInfinity(A)) {
+                        return NaN; 
+                    } else {
+                        return ( complex )0;
+                    }
+                }
+            }
+            complex ret;
+            if (B == 0) return INF ;
+            ret.real =  (double) (A.real / B);
+            ret.imag =  (double) (A.imag / B);
+            return ret;
+        }
+        /// <summary>
+        /// Equality comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>result</returns>
+        /// <remarks>Real inputs are converted to a complex number and the result is compared to the complex input.</remarks>
+        public static bool operator ==( complex A,  Int64 B) {
+            return (A.real == B && A.imag == 0.0);
+        }
+        /// <summary>
+        /// Unequality comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real and imaginary parts of A and B are not equal, false otherwise</returns>
+        /// <remarks>Real inputs are converted to a complex number and the result is compared to the complex input.</remarks>
+        public static bool operator !=( complex A,  Int64 B) {
+            return (A.imag != 0.0) || (A.real != B);
+        }
+        /// <summary>
+        /// Freater than comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is greater than real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator > ( complex A,  Int64 B) {
+            return (A.real > B);
+        }
+        /// <summary>
+        /// Lower than comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is lower then real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator <(  complex A,  Int64 B) {
+            return (A.real < B);
+        }
+        /// <summary>
+        /// Greater than or equal to comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is greater than real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator >=( complex A,  Int64 B) {
+            return (A.real >= B);
+        }
+        /// <summary>
+        /// Lower than or equal to comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is lower then real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator <=( complex A,  Int64 B) {
+            return (A.real <= B);
+        }
+       
+        /// <summary>
+        /// Add two complex numbers
+        /// </summary>
+        /// <param name="A">First summand</param>
+        /// <param name="B">Second summand</param>
+        /// <returns>Result</returns>
+        public static  complex operator +( complex A,  Int32 B) {
+            complex ret;
+            ret.real =  (double) (A.real + B);
+            ret.imag =  (double) A.imag;
+            return ret;
+        }
+        /// <summary>
+        /// Subtract two values
+        /// </summary>
+        /// <param name="A">Minuend</param>
+        /// <param name="B">Subtrahend</param>
+        /// <returns>result</returns>
+        public static  complex operator -( complex A,  Int32 B) {
+            complex ret;
+            ret.real =  (double) (A.real - B);
+            ret.imag =  (double) A.imag;
+            return ret;
+        }
+        /// <summary>
+        /// Multiply two values
+        /// </summary>
+        /// <param name="A">First factor</param>
+        /// <param name="B">Second factor</param>
+        /// <returns>result</returns>
+        public static  complex operator *( complex A,  Int32 B) {
+            complex ret;
+            ret.real =  (double) (A.real * B);
+            ret.imag =  (double) (A.imag * B);
+            return ret;
+        }
+        /// <summary>
+        /// Divide two numbers
+        /// </summary>
+        /// <param name="A">Divident</param>
+        /// <param name="B">Divisor</param>
+        /// <returns>result</returns>
+        public static  complex operator /( complex A,  Int32 B) {
+            if (IsNaN(A)) return NaN;
+            
+            if (A.real == 0 && A.imag == 0) {
+                if (B == 0) return NaN; 
+                return ( complex )0;
+            } else {
+                if (false)
+                {
+                    if (IsInfinity(A)) {
+                        return NaN; 
+                    } else {
+                        return ( complex )0;
+                    }
+                }
+            }
+            complex ret;
+            if (B == 0) return INF ;
+            ret.real =  (double) (A.real / B);
+            ret.imag =  (double) (A.imag / B);
+            return ret;
+        }
+        /// <summary>
+        /// Equality comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>result</returns>
+        /// <remarks>Real inputs are converted to a complex number and the result is compared to the complex input.</remarks>
+        public static bool operator ==( complex A,  Int32 B) {
+            return (A.real == B && A.imag == 0.0);
+        }
+        /// <summary>
+        /// Unequality comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real and imaginary parts of A and B are not equal, false otherwise</returns>
+        /// <remarks>Real inputs are converted to a complex number and the result is compared to the complex input.</remarks>
+        public static bool operator !=( complex A,  Int32 B) {
+            return (A.imag != 0.0) || (A.real != B);
+        }
+        /// <summary>
+        /// Freater than comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is greater than real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator > ( complex A,  Int32 B) {
+            return (A.real > B);
+        }
+        /// <summary>
+        /// Lower than comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is lower then real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator <(  complex A,  Int32 B) {
+            return (A.real < B);
+        }
+        /// <summary>
+        /// Greater than or equal to comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is greater than real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator >=( complex A,  Int32 B) {
+            return (A.real >= B);
+        }
+        /// <summary>
+        /// Lower than or equal to comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is lower then real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator <=( complex A,  Int32 B) {
+            return (A.real <= B);
+        }
+       
+        /// <summary>
+        /// Add two complex numbers
+        /// </summary>
+        /// <param name="A">First summand</param>
+        /// <param name="B">Second summand</param>
+        /// <returns>Result</returns>
+        public static  complex operator +( complex A,  float B) {
+            complex ret;
+            ret.real =  (double) (A.real + B);
+            ret.imag =  (double) A.imag;
+            return ret;
+        }
+        /// <summary>
+        /// Subtract two values
+        /// </summary>
+        /// <param name="A">Minuend</param>
+        /// <param name="B">Subtrahend</param>
+        /// <returns>result</returns>
+        public static  complex operator -( complex A,  float B) {
+            complex ret;
+            ret.real =  (double) (A.real - B);
+            ret.imag =  (double) A.imag;
+            return ret;
+        }
+        /// <summary>
+        /// Multiply two values
+        /// </summary>
+        /// <param name="A">First factor</param>
+        /// <param name="B">Second factor</param>
+        /// <returns>result</returns>
+        public static  complex operator *( complex A,  float B) {
+            complex ret;
+            ret.real =  (double) (A.real * B);
+            ret.imag =  (double) (A.imag * B);
+            return ret;
+        }
+        /// <summary>
+        /// Divide two numbers
+        /// </summary>
+        /// <param name="A">Divident</param>
+        /// <param name="B">Divisor</param>
+        /// <returns>result</returns>
+        public static  complex operator /( complex A,  float B) {
+            if (IsNaN(A)) return NaN;
+            if (float.IsNaN(B)) return NaN;
+            if (A.real == 0 && A.imag == 0) {
+                if (B == 0) return NaN; 
+                return ( complex )0;
+            } else {
+                if (float.IsInfinity(B))
+                {
+                    if (IsInfinity(A)) {
+                        return NaN; 
+                    } else {
+                        return ( complex )0;
+                    }
+                }
+            }
+            complex ret;
+            if (B == 0) return INF ;
+            ret.real =  (double) (A.real / B);
+            ret.imag =  (double) (A.imag / B);
+            return ret;
+        }
+        /// <summary>
+        /// Equality comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>result</returns>
+        /// <remarks>Real inputs are converted to a complex number and the result is compared to the complex input.</remarks>
+        public static bool operator ==( complex A,  float B) {
+            return (A.real == B && A.imag == 0.0);
+        }
+        /// <summary>
+        /// Unequality comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real and imaginary parts of A and B are not equal, false otherwise</returns>
+        /// <remarks>Real inputs are converted to a complex number and the result is compared to the complex input.</remarks>
+        public static bool operator !=( complex A,  float B) {
+            return (A.imag != 0.0) || (A.real != B);
+        }
+        /// <summary>
+        /// Freater than comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is greater than real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator > ( complex A,  float B) {
+            return (A.real > B);
+        }
+        /// <summary>
+        /// Lower than comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is lower then real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator <(  complex A,  float B) {
+            return (A.real < B);
+        }
+        /// <summary>
+        /// Greater than or equal to comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is greater than real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator >=( complex A,  float B) {
+            return (A.real >= B);
+        }
+        /// <summary>
+        /// Lower than or equal to comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is lower then real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator <=( complex A,  float B) {
+            return (A.real <= B);
+        }
+       
+        /// <summary>
+        /// Add two complex numbers
+        /// </summary>
+        /// <param name="A">First summand</param>
+        /// <param name="B">Second summand</param>
+        /// <returns>Result</returns>
+        public static  complex operator +( complex A,  byte B) {
+            complex ret;
+            ret.real =  (double) (A.real + B);
+            ret.imag =  (double) A.imag;
+            return ret;
+        }
+        /// <summary>
+        /// Subtract two values
+        /// </summary>
+        /// <param name="A">Minuend</param>
+        /// <param name="B">Subtrahend</param>
+        /// <returns>result</returns>
+        public static  complex operator -( complex A,  byte B) {
+            complex ret;
+            ret.real =  (double) (A.real - B);
+            ret.imag =  (double) A.imag;
+            return ret;
+        }
+        /// <summary>
+        /// Multiply two values
+        /// </summary>
+        /// <param name="A">First factor</param>
+        /// <param name="B">Second factor</param>
+        /// <returns>result</returns>
+        public static  complex operator *( complex A,  byte B) {
+            complex ret;
+            ret.real =  (double) (A.real * B);
+            ret.imag =  (double) (A.imag * B);
+            return ret;
+        }
+        /// <summary>
+        /// Divide two numbers
+        /// </summary>
+        /// <param name="A">Divident</param>
+        /// <param name="B">Divisor</param>
+        /// <returns>result</returns>
+        public static  complex operator /( complex A,  byte B) {
+            if (IsNaN(A)) return NaN;
+            
+            if (A.real == 0 && A.imag == 0) {
+                if (B == 0) return NaN; 
+                return ( complex )0;
+            } else {
+                if (false)
+                {
+                    if (IsInfinity(A)) {
+                        return NaN; 
+                    } else {
+                        return ( complex )0;
+                    }
+                }
+            }
+            complex ret;
+            if (B == 0) return INF ;
+            ret.real =  (double) (A.real / B);
+            ret.imag =  (double) (A.imag / B);
+            return ret;
+        }
+        /// <summary>
+        /// Equality comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>result</returns>
+        /// <remarks>Real inputs are converted to a complex number and the result is compared to the complex input.</remarks>
+        public static bool operator ==( complex A,  byte B) {
+            return (A.real == B && A.imag == 0.0);
+        }
+        /// <summary>
+        /// Unequality comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real and imaginary parts of A and B are not equal, false otherwise</returns>
+        /// <remarks>Real inputs are converted to a complex number and the result is compared to the complex input.</remarks>
+        public static bool operator !=( complex A,  byte B) {
+            return (A.imag != 0.0) || (A.real != B);
+        }
+        /// <summary>
+        /// Freater than comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is greater than real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator > ( complex A,  byte B) {
+            return (A.real > B);
+        }
+        /// <summary>
+        /// Lower than comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is lower then real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator <(  complex A,  byte B) {
+            return (A.real < B);
+        }
+        /// <summary>
+        /// Greater than or equal to comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is greater than real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator >=( complex A,  byte B) {
+            return (A.real >= B);
+        }
+        /// <summary>
+        /// Lower than or equal to comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is lower then real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator <=( complex A,  byte B) {
+            return (A.real <= B);
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+
+        
+        /// <summary>
+        /// Add two complex values
+        /// </summary>
+        /// <param name="A">First summand</param>
+        /// <param name="B">Second summand</param>
+        /// <returns>Result</returns>
+        public static  complex operator +( double A,  complex B) {
+             complex ret; 
+            ret.real =  (double) (A + B.real);
+            ret.imag =  (double) B.imag;
+            return ret;
+        }
+        /// <summary>
+        /// Subtract two values
+        /// </summary>
+        /// <param name="A">Minuend</param>
+        /// <param name="B">Subtrahend</param>
+        /// <returns>Result</returns>
+        public static  complex operator -( double A,  complex B) {
+             complex ret;
+            ret.real =  (double) (A - B.real);
+            ret.imag = - (double) B.imag; 
+            return ret;
+        }
+        /// <summary>
+        /// Multiply two values
+        /// </summary>
+        /// <param name="A">First factor</param>
+        /// <param name="B">Second factor</param>
+        /// <returns>Result</returns>
+        public static  complex operator *( double A,  complex B) {
+             complex ret;
+            ret.real =  (double) (A * B.real);
+            ret.imag =  (double) (A * B.imag);
+            return ret;
+        }
+        /// <summary>
+        /// Divide two values
+        /// </summary>
+        /// <param name="A">Divident</param>
+        /// <param name="B">Divisor</param>
+        /// <returns>Result</returns>
+        public static  complex operator /( double A,  complex B) {
+             complex ret; 
+            if (A == 0) {
+                if (IsInfinity(B)) return NaN; 
+            } else {
+                if (IsInfinity(B)) return ( complex )0; 
+            }
+            if (B.real == 0 && B.imag == 0) {
+                return INF;
+            }
+            // this algorithm is taken from [1]. The one described in [2] was not taken. Tests 
+            // did not show any advantage when using double precision floating point arithmetic.
+             double tmp; 
+            if (Math.Abs(B.real) >= Math.Abs(B.imag)) {
+                tmp =  (double) (B.imag * (1/B.real)); 
+                ret.imag =  (double) (B.real + B.imag*tmp); 
+                ret.real =  (double) A/ret.imag; 
+                ret.imag = -  (double) (A*tmp)/ret.imag; 
+            } else {
+                tmp =  (double) (B.real * (1/B.imag));
+                ret.imag =  (double) (B.imag + B.real*tmp); 
+                ret.real =  (double) (A*tmp)/ret.imag; 
+                ret.imag = -  (double) A/ret.imag; 
+            }
+            return ret;
+        }
+        /// <summary>
+        /// Equality comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>Result</returns>
+        /// <remarks>Real inputs are converted to a complex number and the result is compared to the complex input.</remarks>
+        public static bool operator ==( double A,  complex B) {
+            return (B.real == A && B.imag == 0.0);
+        }
+        /// <summary>
+        /// Unequality comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real and imaginary parts of A and B are not equal, false otherwise</returns>
+        /// <remarks>Real inputs are converted to a complex number and the result is compared to the complex input.</remarks>
+        public static bool operator !=( double A,  complex B) {
+            return (B.imag != 0.0) || (B.real != A);
+        }
+        /// <summary>
+        /// Greater than comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is greater than real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator > ( double A,  complex B) {
+            return (A > B.real);
+        }
+        /// <summary>
+        /// Lower than comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is lower then real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator < ( double A,  complex B) {
+            return (A < B.real);
+        }
+        /// <summary>
+        /// Greater than or equal to comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is greater than real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator >=( double A,  complex B) {
+            return (A >= B.real);
+        }
+        /// <summary>
+        /// Lower than or equal to comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is lower then real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator <=( double A,  complex B) {
+            return (A <= B.real);
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+       
+        /// <summary>
+        /// Add two complex values
+        /// </summary>
+        /// <param name="A">First summand</param>
+        /// <param name="B">Second summand</param>
+        /// <returns>Result</returns>
+        public static  complex operator +( Int64 A,  complex B) {
+            complex ret; 
+            ret.real =  (double) (A + B.real);
+            ret.imag =  (double) B.imag;
+            return ret;
+        }
+        /// <summary>
+        /// Subtract two values
+        /// </summary>
+        /// <param name="A">Minuend</param>
+        /// <param name="B">Subtrahend</param>
+        /// <returns>Result</returns>
+        public static  complex operator -( Int64 A,  complex B) {
+            complex ret;
+            ret.real =  (double) (A - B.real);
+            ret.imag = - (double) B.imag; 
+            return ret;
+        }
+        /// <summary>
+        /// Multiply two values
+        /// </summary>
+        /// <param name="A">First factor</param>
+        /// <param name="B">Second factor</param>
+        /// <returns>Result</returns>
+        public static  complex operator *( Int64 A,  complex B) {
+            complex ret;
+            ret.real =  (double) (A * B.real);
+            ret.imag =  (double) (A * B.imag);
+            return ret;
+        }
+        /// <summary>
+        /// Divide two values
+        /// </summary>
+        /// <param name="A">Divident</param>
+        /// <param name="B">Divisor</param>
+        /// <returns>Result</returns>
+        public static  complex operator /( Int64 A,  complex B) {
+            complex ret; 
+            if (A == 0) {
+                if (IsInfinity(B)) return NaN; 
+            } else {
+                if (IsInfinity(B)) return ( complex )0; 
+            }
+            if (B.real == 0 && B.imag == 0) {
+                return INF;
+            }
+            // this algorithm is taken from [1]. The one described in [2] was not taken. Tests 
+            // did not show any advantage when using double precision floating point arithmetic.
+            double tmp; 
+            if (Math.Abs(B.real) >= Math.Abs(B.imag)) {
+                tmp =  (double) (B.imag * (1/B.real)); 
+                ret.imag =  (double) (B.real + B.imag*tmp); 
+                ret.real =  (double) A/ret.imag; 
+                ret.imag = -  (double) (A*tmp)/ret.imag; 
+            } else {
+                tmp =  (double) (B.real * (1/B.imag));
+                ret.imag =  (double) (B.imag + B.real*tmp); 
+                ret.real =  (double) (A*tmp)/ret.imag; 
+                ret.imag = -  (double) A/ret.imag; 
+            }
+            return ret;
+        }
+        /// <summary>
+        /// Equality comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>Result</returns>
+        /// <remarks>Real inputs are converted to a complex number and the result is compared to the complex input.</remarks>
+        public static bool operator ==( Int64 A,  complex B) {
+            return (B.real == A && B.imag == 0.0);
+        }
+        /// <summary>
+        /// Unequality comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real and imaginary parts of A and B are not equal, false otherwise</returns>
+        /// <remarks>Real inputs are converted to a complex number and the result is compared to the complex input.</remarks>
+        public static bool operator !=( Int64 A,  complex B) {
+            return (B.imag != 0.0) || (B.real != A);
+        }
+        /// <summary>
+        /// Greater than comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is greater than real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator > ( Int64 A,  complex B) {
+            return (A > B.real);
+        }
+        /// <summary>
+        /// Lower than comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is lower then real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator < ( Int64 A,  complex B) {
+            return (A < B.real);
+        }
+        /// <summary>
+        /// Greater than or equal to comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is greater than real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator >=( Int64 A,  complex B) {
+            return (A >= B.real);
+        }
+        /// <summary>
+        /// Lower than or equal to comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is lower then real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator <=( Int64 A,  complex B) {
+            return (A <= B.real);
+        }
+       
+        /// <summary>
+        /// Add two complex values
+        /// </summary>
+        /// <param name="A">First summand</param>
+        /// <param name="B">Second summand</param>
+        /// <returns>Result</returns>
+        public static  complex operator +( Int32 A,  complex B) {
+            complex ret; 
+            ret.real =  (double) (A + B.real);
+            ret.imag =  (double) B.imag;
+            return ret;
+        }
+        /// <summary>
+        /// Subtract two values
+        /// </summary>
+        /// <param name="A">Minuend</param>
+        /// <param name="B">Subtrahend</param>
+        /// <returns>Result</returns>
+        public static  complex operator -( Int32 A,  complex B) {
+            complex ret;
+            ret.real =  (double) (A - B.real);
+            ret.imag = - (double) B.imag; 
+            return ret;
+        }
+        /// <summary>
+        /// Multiply two values
+        /// </summary>
+        /// <param name="A">First factor</param>
+        /// <param name="B">Second factor</param>
+        /// <returns>Result</returns>
+        public static  complex operator *( Int32 A,  complex B) {
+            complex ret;
+            ret.real =  (double) (A * B.real);
+            ret.imag =  (double) (A * B.imag);
+            return ret;
+        }
+        /// <summary>
+        /// Divide two values
+        /// </summary>
+        /// <param name="A">Divident</param>
+        /// <param name="B">Divisor</param>
+        /// <returns>Result</returns>
+        public static  complex operator /( Int32 A,  complex B) {
+            complex ret; 
+            if (A == 0) {
+                if (IsInfinity(B)) return NaN; 
+            } else {
+                if (IsInfinity(B)) return ( complex )0; 
+            }
+            if (B.real == 0 && B.imag == 0) {
+                return INF;
+            }
+            // this algorithm is taken from [1]. The one described in [2] was not taken. Tests 
+            // did not show any advantage when using double precision floating point arithmetic.
+            double tmp; 
+            if (Math.Abs(B.real) >= Math.Abs(B.imag)) {
+                tmp =  (double) (B.imag * (1/B.real)); 
+                ret.imag =  (double) (B.real + B.imag*tmp); 
+                ret.real =  (double) A/ret.imag; 
+                ret.imag = -  (double) (A*tmp)/ret.imag; 
+            } else {
+                tmp =  (double) (B.real * (1/B.imag));
+                ret.imag =  (double) (B.imag + B.real*tmp); 
+                ret.real =  (double) (A*tmp)/ret.imag; 
+                ret.imag = -  (double) A/ret.imag; 
+            }
+            return ret;
+        }
+        /// <summary>
+        /// Equality comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>Result</returns>
+        /// <remarks>Real inputs are converted to a complex number and the result is compared to the complex input.</remarks>
+        public static bool operator ==( Int32 A,  complex B) {
+            return (B.real == A && B.imag == 0.0);
+        }
+        /// <summary>
+        /// Unequality comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real and imaginary parts of A and B are not equal, false otherwise</returns>
+        /// <remarks>Real inputs are converted to a complex number and the result is compared to the complex input.</remarks>
+        public static bool operator !=( Int32 A,  complex B) {
+            return (B.imag != 0.0) || (B.real != A);
+        }
+        /// <summary>
+        /// Greater than comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is greater than real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator > ( Int32 A,  complex B) {
+            return (A > B.real);
+        }
+        /// <summary>
+        /// Lower than comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is lower then real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator < ( Int32 A,  complex B) {
+            return (A < B.real);
+        }
+        /// <summary>
+        /// Greater than or equal to comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is greater than real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator >=( Int32 A,  complex B) {
+            return (A >= B.real);
+        }
+        /// <summary>
+        /// Lower than or equal to comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is lower then real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator <=( Int32 A,  complex B) {
+            return (A <= B.real);
+        }
+       
+        /// <summary>
+        /// Add two complex values
+        /// </summary>
+        /// <param name="A">First summand</param>
+        /// <param name="B">Second summand</param>
+        /// <returns>Result</returns>
+        public static  complex operator +( float A,  complex B) {
+            complex ret; 
+            ret.real =  (double) (A + B.real);
+            ret.imag =  (double) B.imag;
+            return ret;
+        }
+        /// <summary>
+        /// Subtract two values
+        /// </summary>
+        /// <param name="A">Minuend</param>
+        /// <param name="B">Subtrahend</param>
+        /// <returns>Result</returns>
+        public static  complex operator -( float A,  complex B) {
+            complex ret;
+            ret.real =  (double) (A - B.real);
+            ret.imag = - (double) B.imag; 
+            return ret;
+        }
+        /// <summary>
+        /// Multiply two values
+        /// </summary>
+        /// <param name="A">First factor</param>
+        /// <param name="B">Second factor</param>
+        /// <returns>Result</returns>
+        public static  complex operator *( float A,  complex B) {
+            complex ret;
+            ret.real =  (double) (A * B.real);
+            ret.imag =  (double) (A * B.imag);
+            return ret;
+        }
+        /// <summary>
+        /// Divide two values
+        /// </summary>
+        /// <param name="A">Divident</param>
+        /// <param name="B">Divisor</param>
+        /// <returns>Result</returns>
+        public static  complex operator /( float A,  complex B) {
+            complex ret; 
+            if (A == 0) {
+                if (IsInfinity(B)) return NaN; 
+            } else {
+                if (IsInfinity(B)) return ( complex )0; 
+            }
+            if (B.real == 0 && B.imag == 0) {
+                return INF;
+            }
+            // this algorithm is taken from [1]. The one described in [2] was not taken. Tests 
+            // did not show any advantage when using double precision floating point arithmetic.
+            double tmp; 
+            if (Math.Abs(B.real) >= Math.Abs(B.imag)) {
+                tmp =  (double) (B.imag * (1/B.real)); 
+                ret.imag =  (double) (B.real + B.imag*tmp); 
+                ret.real =  (double) A/ret.imag; 
+                ret.imag = -  (double) (A*tmp)/ret.imag; 
+            } else {
+                tmp =  (double) (B.real * (1/B.imag));
+                ret.imag =  (double) (B.imag + B.real*tmp); 
+                ret.real =  (double) (A*tmp)/ret.imag; 
+                ret.imag = -  (double) A/ret.imag; 
+            }
+            return ret;
+        }
+        /// <summary>
+        /// Equality comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>Result</returns>
+        /// <remarks>Real inputs are converted to a complex number and the result is compared to the complex input.</remarks>
+        public static bool operator ==( float A,  complex B) {
+            return (B.real == A && B.imag == 0.0);
+        }
+        /// <summary>
+        /// Unequality comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real and imaginary parts of A and B are not equal, false otherwise</returns>
+        /// <remarks>Real inputs are converted to a complex number and the result is compared to the complex input.</remarks>
+        public static bool operator !=( float A,  complex B) {
+            return (B.imag != 0.0) || (B.real != A);
+        }
+        /// <summary>
+        /// Greater than comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is greater than real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator > ( float A,  complex B) {
+            return (A > B.real);
+        }
+        /// <summary>
+        /// Lower than comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is lower then real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator < ( float A,  complex B) {
+            return (A < B.real);
+        }
+        /// <summary>
+        /// Greater than or equal to comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is greater than real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator >=( float A,  complex B) {
+            return (A >= B.real);
+        }
+        /// <summary>
+        /// Lower than or equal to comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is lower then real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator <=( float A,  complex B) {
+            return (A <= B.real);
+        }
+       
+        /// <summary>
+        /// Add two complex values
+        /// </summary>
+        /// <param name="A">First summand</param>
+        /// <param name="B">Second summand</param>
+        /// <returns>Result</returns>
+        public static  complex operator +( byte A,  complex B) {
+            complex ret; 
+            ret.real =  (double) (A + B.real);
+            ret.imag =  (double) B.imag;
+            return ret;
+        }
+        /// <summary>
+        /// Subtract two values
+        /// </summary>
+        /// <param name="A">Minuend</param>
+        /// <param name="B">Subtrahend</param>
+        /// <returns>Result</returns>
+        public static  complex operator -( byte A,  complex B) {
+            complex ret;
+            ret.real =  (double) (A - B.real);
+            ret.imag = - (double) B.imag; 
+            return ret;
+        }
+        /// <summary>
+        /// Multiply two values
+        /// </summary>
+        /// <param name="A">First factor</param>
+        /// <param name="B">Second factor</param>
+        /// <returns>Result</returns>
+        public static  complex operator *( byte A,  complex B) {
+            complex ret;
+            ret.real =  (double) (A * B.real);
+            ret.imag =  (double) (A * B.imag);
+            return ret;
+        }
+        /// <summary>
+        /// Divide two values
+        /// </summary>
+        /// <param name="A">Divident</param>
+        /// <param name="B">Divisor</param>
+        /// <returns>Result</returns>
+        public static  complex operator /( byte A,  complex B) {
+            complex ret; 
+            if (A == 0) {
+                if (IsInfinity(B)) return NaN; 
+            } else {
+                if (IsInfinity(B)) return ( complex )0; 
+            }
+            if (B.real == 0 && B.imag == 0) {
+                return INF;
+            }
+            // this algorithm is taken from [1]. The one described in [2] was not taken. Tests 
+            // did not show any advantage when using double precision floating point arithmetic.
+            double tmp; 
+            if (Math.Abs(B.real) >= Math.Abs(B.imag)) {
+                tmp =  (double) (B.imag * (1/B.real)); 
+                ret.imag =  (double) (B.real + B.imag*tmp); 
+                ret.real =  (double) A/ret.imag; 
+                ret.imag = -  (double) (A*tmp)/ret.imag; 
+            } else {
+                tmp =  (double) (B.real * (1/B.imag));
+                ret.imag =  (double) (B.imag + B.real*tmp); 
+                ret.real =  (double) (A*tmp)/ret.imag; 
+                ret.imag = -  (double) A/ret.imag; 
+            }
+            return ret;
+        }
+        /// <summary>
+        /// Equality comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>Result</returns>
+        /// <remarks>Real inputs are converted to a complex number and the result is compared to the complex input.</remarks>
+        public static bool operator ==( byte A,  complex B) {
+            return (B.real == A && B.imag == 0.0);
+        }
+        /// <summary>
+        /// Unequality comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real and imaginary parts of A and B are not equal, false otherwise</returns>
+        /// <remarks>Real inputs are converted to a complex number and the result is compared to the complex input.</remarks>
+        public static bool operator !=( byte A,  complex B) {
+            return (B.imag != 0.0) || (B.real != A);
+        }
+        /// <summary>
+        /// Greater than comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is greater than real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator > ( byte A,  complex B) {
+            return (A > B.real);
+        }
+        /// <summary>
+        /// Lower than comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is lower then real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator < ( byte A,  complex B) {
+            return (A < B.real);
+        }
+        /// <summary>
+        /// Greater than or equal to comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is greater than real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator >=( byte A,  complex B) {
+            return (A >= B.real);
+        }
+        /// <summary>
+        /// Lower than or equal to comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is lower then real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator <=( byte A,  complex B) {
+            return (A <= B.real);
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+        #region unary minus
+        /// <summary>
+        /// Unary minus operator
+        /// </summary>
+        /// <param name="A">Complex input</param>
+        /// <returns>Complex number similar to A, having real and imag part negated</returns>
+        public static complex operator -( complex A) {
+            complex ret = new complex(); 
+            ret.imag = -A.imag; 
+            ret.real = -A.real; 
+            return ret;
+        }
+        #endregion
+
+        #region CAST_OPERATORS
+        /// <summary>
+        /// Cast value to complex number
+        /// </summary>
+        /// <param name="a">Value to cast</param>
+        /// <returns>Complex number with the real part having the same value as a and the imaginary part is 0.</returns>
+        public static implicit operator complex(double a) {
+            return new complex(a, 0.0);
+        }
+        /// <summary>
+        /// Cast value to complex number
+        /// </summary>
+        /// <param name="a">Value to cast</param>
+        /// <returns>Complex number with the real part having the same value as the a and the imaginary part is 0.</returns>
+        public static implicit operator complex(float a) {
+            return new complex(a, 0.0);
+        }
+        /// <summary>
+        /// Cast value to complex number
+        /// </summary>
+        /// <param name="a">Value to cast</param>
+        /// <returns>Complex number being a copy of the real and imaginary parts of a.</returns>
+        public static implicit operator complex(fcomplex a) {
+            return new complex(a.real, a.imag);
+        }
+        /// <summary>
+        /// Cast value to complex number
+        /// </summary>
+        /// <param name="a">Value to cast</param>
+        /// <returns>Complex number with the real part having the same value as a and the imaginary part is 0.</returns>
+        public static implicit operator complex(byte a) {
+            return new complex(a, 0.0);
+        }
+        /// <summary>
+        /// Cast value to complex number
+        /// </summary>
+        /// <param name="a">Value to cast</param>
+        /// <returns>Complex number with the real part having the same value as a and the imaginary part is 0.</returns>
+        public static implicit operator complex(Int32 a) {
+            return new complex(a, 0.0);
+        }
+        /// <summary>
+        /// Cast value to complex number
+        /// </summary>
+        /// <param name="a">Value to cast</param>
+        /// <returns>Complex number with the real part having the same value as a and the imaginary part is 0.</returns>
+        public static implicit operator complex(Int64 a) {
+            return new complex(a, 0.0);
+        }
+
+        /// <summary>
+        /// Cast value from complex number
+        /// </summary>
+        /// <param name="a">Complex value to cast</param>
+        /// <returns>Double number with the real part of a </returns>
+        public static explicit operator double(complex a) {
+            return a.real; 
+        }
+        /// <summary>
+        /// Cast value from complex number
+        /// </summary>
+        /// <param name="a">Complex value to cast</param>
+        /// <returns>number with the real part of a </returns>
+        /// <remarks>the return value is the result of a cast from double to float.</remarks>
+        public static explicit operator float(complex a) {
+            return (float)a.real;
+        }
+        /// <summary>
+        /// Cast value from complex number
+        /// </summary>
+        /// <param name="a">Complex value to cast</param>
+        /// <returns>float complex number with the real and imaginary parts being a copy of a </returns>
+        /// <remarks>The real and imaginary parts are the result of a cast to float.</remarks>
+        public static explicit operator fcomplex(complex a) {
+            return new fcomplex((float)a.real, (float)a.imag);
+        }
+        /// <summary>
+        /// Cast value from complex number
+        /// </summary>
+        /// <param name="a">Complex value to cast</param>
+        /// <returns>Number with the real part of a </returns>
+        /// <remarks>The return value is the result of a cast to byte.</remarks>
+        public static explicit operator byte(complex a) {
+            return (byte) a.real; 
+        }
+        /// <summary>
+        /// Cast value from complex number
+        /// </summary>
+        /// <param name="a">Complex value to cast</param>
+        /// <returns>Number with the real part of a </returns>
+        /// <remarks>The return value is the result of a cast to Int32.</remarks>
+        public static explicit operator Int32(complex a) {
+            return (Int32) a.real; 
+        }
+        /// <summary>
+        /// Cast value from complex number
+        /// </summary>
+        /// <param name="a">Complex value to cast</param>
+        /// <returns>number with the real part of a </returns>
+        /// <remarks>the return value is the result of a cast to Int64.</remarks>
+        public static explicit operator Int64(complex a) {
+            return (Int64) a.real; 
+        }
+
+        public static implicit operator complex(System.Numerics.Complex a) {
+            return new complex(a.Real, a.Imaginary); 
+        }
+#endregion CAST_OPERATORS
+
+        #region Functions Basic Math
+        /// <summary>
+        /// Absolute value of input
+        /// </summary>
+        /// <param name="input">Input value</param>
+        /// <returns>The absolute value of the input</returns>
+        public static double Abs(complex input) {
+            return Math.Sqrt(input.real * input.real + input.imag * input.imag);
+        }
+        /// <summary>
+        /// Phase angle of complex number
+        /// </summary>
+        /// <param name="input">Input value</param>
+        /// <returns>The phase angle of the input</returns>
+        /// <remarks>For the result the Atan2 function of the <see cref="Math"/> class is used.</remarks>
+        public static double Angle(complex input) {
+            return Math.Atan2(input.imag, input.real);
+        }
+        /// <summary>
+        /// Arcus tangens of complex input
+        /// </summary>
+        /// <param name="input">Complex input</param>
+        /// <returns>Arcus tangens of complex input</returns>
+        /// <remarks></remarks>
+        public static complex Atan(complex input) {
+            complex ret = new complex(0, (float)0.5);
+            return (ret * Log((complex.i + input) / (complex.i - input)));
+        }
+        /// <summary>
+        /// Arcus cosinus of complex input
+        /// </summary>
+        /// <param name="input">Complex input</param>
+        /// <returns>Arcus cosinus of input</returns>
+        public static complex Acos(complex input) {
+            complex ni = complex.i * -1.0;
+            return complex.Log(complex.Sqrt(input * input - 1)
+                + input) * ni;
+        }
+        /// <summary>
+        /// Arcus cosinus of input
+        /// </summary>
+        /// <param name="input">Input value</param>
+        /// <returns>Arcus cosinus of input</returns>
+        public static complex Acos(double input) {
+            if (Math.Abs(input) <= 1.0)
+                return new complex(Math.Acos(input), 0.0);
+            else {
+                return Acos((complex)input);
+            }
+        }
+        /// <summary>
+        /// Arcus sinus of complex input
+        /// </summary>
+        /// <param name="input">Input value</param>
+        /// <returns>Arcus sinus of input</returns>
+        public static complex Asin(double input) {
+            if (Math.Abs(input) <= 1.0)
+                return new complex(Math.Asin(input), 0.0);
+            else {
+                return Asin((complex)input);
+            }
+        }
+        /// <summary>
+        /// Arcus sinus of input
+        /// </summary>
+        /// <param name="input">Input value</param>
+        /// <returns>Arcus sinus of  input</returns>
+        public static complex Asin(complex input) {
+            complex ret = Acos(input);
+            ret.real = Math.PI / 2 - ret.real;
+            return ret;
+        }
+        /// <summary>
+        /// Round towards positive infinity
+        /// </summary>
+        /// <param name="input">Input value</param>
+        /// <returns>Result is the next integer value greater then input</returns>
+        /// <remarks>ILMath.Ceiling operates in both: real and imaginary parts seperately</remarks>
+        public static complex Ceiling (complex input){
+            return new complex(
+                    Math.Ceiling(input.real),
+                    Math.Ceiling(input.imag)
+            );
+        }
+        /// <summary>
+        /// Round towards negative infinity
+        /// </summary>
+        /// <param name="input">Input value</param>
+        /// <returns>Result is the next integer value lower then input</returns>
+        /// <remarks>ILMath.Floor operates in both: real and imaginary parts seperately</remarks>
+        public static complex Floor (complex input){
+            return new complex(
+                    Math.Floor(input.real),
+                    Math.Floor(input.imag)
+            );
+        }
+        /// <summary>
+        /// Rounds towards nearest integer
+        /// </summary>
+        /// <param name="input">Input value</param>
+        /// <returns>Result is the nearest integer value for input</returns>
+        /// <remarks>ILMath.Round operates in both: real and imaginary parts deperately</remarks>
+        public static complex Round (complex input){
+            return new complex(
+                    Math.Round(input.real),
+                    Math.Round(input.imag)
+            );
+        }
+        /// <summary>
+        /// Signum function
+        /// </summary>
+        /// <param name="input">Complex input </param>
+        /// <returns>Sesult as input / Abs(input)</returns>
+        /// <remarks>Sign(input) with input being complex returns the projection onto
+        /// the unit circle. If input is 0+0i the result will be 0+0i.</remarks>
+        public static complex Sign (complex input){
+            if (input.real == 0.0 && input.imag == 0.0)
+                return new complex(); 
+            else {
+                double mag = Math.Sqrt(input.real * input.real + input.imag * input.imag); 
+                return new complex(
+                    input.real / mag,
+                    input.imag / mag);
+            }
+        }
+        /// <summary>
+        /// Truncate a floating point complex value
+        /// </summary>
+        /// <param name="input">Input value</param>
+        /// <returns>Integer part of input</returns>
+        /// <remarks>Operates on real and imaginary parts seperately.</remarks>
+        public static complex Truncate (complex input){
+            return new complex(
+                    Math.Truncate(input.real),
+                    Math.Truncate(input.imag)
+            );
+        }
+        /// <summary>
+        /// Cosinus
+        /// </summary>
+        /// <param name="input">Input value</param>
+        /// <returns>Cosine of input</returns>
+        /// <remarks><para>The cosine is computed by the trigonometric euler equation: </para>
+        /// <para>0.5 * [exp(i input) + exp(-i input)]</para></remarks>
+        public static complex Cos(complex input) {
+            complex i = new complex(0, 1.0);
+            complex mi = new complex(0, -1.0);
+            return (Exp(i * input) + Exp(mi * input)) / 2.0;
+        }
+        /// <summary>
+        /// Cosinus hyperbolicus
+        /// </summary>
+        /// <param name="input">Input</param>
+        /// <returns>Cosine hyperbolicus of input</returns>
+        /// <remarks><para>The cosine is computed by the trigonometric euler equation: </para>
+        /// <para>(Exp(input) + Exp(-1.0 * input)) / 2.0</para></remarks>
+        public static complex Cosh(complex input) {
+            return (Exp(input) + Exp(-1.0 * input)) / 2.0;
+        }
+        /// <summary>
+        /// Sinus
+        /// </summary>
+        /// <param name="input">Input value</param>
+        /// <returns>Sinus of input</returns>
+        /// <remarks><para>The sinus is computed by the trigonometric euler equation: </para>
+        /// <para>(Exp(i * input) - Exp(-1.0 * i * input)) / (2.0 * i)</para></remarks>
+        public static complex Sin(complex input) {
+            complex i = new complex(0, 1.0);
+            complex mi = new complex(0, -1.0);
+            return (Exp(i * input) - Exp(mi * input)) / (2.0 * i);
+        }
+        /// <summary>
+        /// Sinus hyperbolicus
+        /// </summary>
+        /// <param name="input">Input</param>
+        /// <returns>Sinus hyperbolicus of input</returns>
+        /// <remarks><para>The sinus hyperbolicus is computed by the trigonometric euler equation: </para>
+        /// <para>(Exp(input) - Exp(-1.0 * input)) / 2.0</para></remarks>
+        public static complex Sinh(complex input) {
+            return (Exp(input) - Exp(-1.0 * input)) / 2.0;
+        }
+        /// <summary>
+        /// Complex exponent
+        /// </summary>
+        /// <param name="exponent">Exponent</param>
+        /// <returns>Result of exp(exponent)</returns>
+        /// <remarks>For complex exponents, exp(exponent) is computed by
+        /// <para>complex.FromPol(Math.Exp(exponent.real), exponent.imag)</para></remarks>
+        public static complex Exp(complex exponent) {
+            return complex.FromPol(Math.Exp(exponent.real), exponent.imag);
+        }
+        /// <summary>
+        /// Complex power for real exponent
+        /// </summary>
+        /// <param name="input">Basis</param>
+        /// <param name="exponent">Exponent</param>
+        /// <returns>Result of input power exponent</returns>
+        /// <remarks>The computation will be carried out by 
+        /// <para>exp(log(input) * exponent)</para></remarks>
+        public static complex Pow(complex input, double exponent) {
+            complex ret = input.Log();
+            ret.imag *= exponent;
+            ret.real *= exponent;
+            return ret.Exp();
+        }
+        /// <summary>
+        /// Complex power - real basis, real exponent
+        /// </summary>
+        /// <param name="basis">Basis</param>
+        /// <param name="exponent">Exponent</param>
+        /// <returns>Complex number.</returns>
+        /// <remarks>The result will be a complex number. For negative basis 
+        /// the basis will be converted to a complex number and the power 
+        /// will be computed in the complex plane.</remarks>
+        public static complex Pow(double basis, double exponent) {
+            if (basis >= 0.0)
+                return Math.Pow(basis, exponent);
+            else
+                return Pow((complex)basis, exponent);
+        }
+        /// <summary>
+        /// Complex power - complex exponent
+        /// </summary>
+        /// <param name="basis">Basis</param>
+        /// <param name="exponent">Exponent</param>
+        /// <returns>Complex number exp(log(basis) * exponent).</returns>
+        /// <remarks>The result will be the complex number exp(log(basis) * exponent). </remarks>
+        public static complex Pow(complex basis, complex exponent) {
+            complex ret = (basis.Log() * exponent);
+            return ret.Exp();
+        }
+        /// <summary>
+        /// Square root
+        /// </summary>
+        /// <param name="input">Input value</param>
+        /// <returns>The square root of input</returns>
+        /// <remarks>If input is smaller than 0.0, the computation will be done in the complex plane. </remarks>
+        public static complex Sqrt(double input) {
+            if (input > 0.0)
+                return new complex(Math.Sqrt(input), 0.0);
+            else
+                return Sqrt(input);
+        }
+        /// <summary>
+        /// Square root
+        /// </summary>
+        /// <param name="input">Input value</param>
+        /// <returns>The square root of input</returns>
+        /// <remarks>Numerical recipes in C: Appendix C </remarks>
+        public static complex Sqrt(complex input) {
+            // Reference : numerical recipes in C: Appendix C
+            complex ret = new complex();
+            double x, y, w, r;
+            if (input.real == 0.0 && input.imag == 0.0)
+                return ret;
+            else {
+                x = (double)Math.Abs(input.real);
+                y = (double)Math.Abs(input.imag);
+                if (x >= y) {
+                    r = y / x;
+                    w = Math.Sqrt(x) * Math.Sqrt(0.5 * (1.0 + Math.Sqrt(1.0 + r * r)));
+                } else {
+                    r = x / y;
+                    w = Math.Sqrt(y) * Math.Sqrt(0.5 * (r + Math.Sqrt(1.0 + r * r)));
+                }
+                if (input.real >= 0.0) {
+                    ret.real = w;
+                    ret.imag = input.imag / (2.0 * w);
+                } else {
+                    ret.imag = (input.imag >= 0) ? w : -w;
+                    ret.real = input.imag / (2.0 * ret.imag);
+                }
+                return ret;
+            }
+        }
+        /// <summary>
+        /// Tangens
+        /// </summary>
+        /// <param name="input">Input value</param>
+        /// <returns>Tangens of input</returns>
+        /// <remarks>The tangens is 
+        /// <para>sin(input) / cos(input)</para>
+        /// if cos(input) == 0.0+0.0i, INF will be returned.</remarks>
+        public static complex Tan(complex input) {
+            complex ci = Cos(input);
+            if (ci.real == 0.0 && ci.imag == 0.0)
+                return INF;
+            return (Sin(input) / ci);
+        }
+        /// <summary>
+        /// Tangens hyperbolicus
+        /// </summary>
+        /// <param name="input">Input value</param>
+        /// <returns>Tangens hyperbolicus</returns>
+        /// <remarks>The tangens hyperbolicus is 
+        /// <para>sinh(input) / cosh(input)</para>
+        /// if cosh(input) == 0.0+0.0i, INF will be returned.</remarks>
+        public static complex Tanh(complex input) {
+            complex si = Cosh(input);
+            if (si.real == 0.0 && si.imag == 0.0)
+                return INF;
+            return (Sinh(input) / si);
+        }
+        /// <summary>
+        /// Complex logarithm 
+        /// </summary>
+        /// <param name="input">Input value</param>
+        /// <returns>Complex logarithm of input</returns>
+        /// <remarks>The real part of the logarithm is computed by 
+        /// <para>log (abs (input))</para>
+        /// <para>The imaginary part holds the phase of input.</para>
+        /// </remarks>
+        public static complex Log(complex input) {
+            complex ret = new complex();
+            ret.real = Math.Log(Math.Sqrt(input.real * input.real + input.imag * input.imag));
+            ret.imag = Math.Atan2(input.imag, input.real);
+            return ret;
+        }
+        /// <summary>
+        /// Logarithm of real input 
+        /// </summary>
+        /// <param name="input">Input value - may be negative</param>
+        /// <returns>Complex logarithm</returns>
+        public static complex Log(double input) {
+            return Log (new complex(input,0.0)); 
+        }
+        /// <summary>
+        /// Logarithm of base 10 of real input 
+        /// </summary>
+        /// <param name="input">Input value - may be negative</param>
+        /// <returns>Complex logarithm of base 10</returns>
+        public static complex Log10(double input) {
+            return Log(new complex(input,0.0)) * 0.43429448190325176;
+        }
+        /// <summary>
+        /// Logarithm of base 2 of real input 
+        /// </summary>
+        /// <param name="input">Input value - may be negative</param>
+        /// <returns>Complex logarithm of base 2</returns>
+        public static complex Log2(double input) {
+            return Log(new complex(input,0.0)) * 1.4426950408889641;
+        }
+        /// <summary>
+        /// Logarithm of base 10
+        /// </summary>
+        /// <param name="input">Input value</param>
+        /// <returns>Logarithm of base 10</returns>
+        /// <seealso cref="ILNumerics.complex.Log(complex)"/>
+        public static complex Log10(complex input) {
+            return Log(input) * 0.43429448190325176;
+        }
+        /// <summary>
+        /// Logarithm of base 2
+        /// </summary>
+        /// <param name="input">Input value</param>
+        /// <returns>Logarithm of base 2.</returns>
+        /// <seealso cref="ILNumerics.complex.Log(complex)"/>
+        public static complex Log2(complex input) {
+            return Log(input) * 1.4426950408889634;
+        }
+        /// <summary>
+        /// Convert polar notation into cartesian notation
+        /// </summary>
+        /// <param name="magnitude">Magnitude</param>
+        /// <param name="angle">Phase</param>
+        /// <returns>Complex value having magnitude and phase</returns>
+        public static complex FromPol(double magnitude, double angle) {
+            return new complex(
+                magnitude * Math.Cos(angle),
+                magnitude * Math.Sin(angle)
+            );
+        }
+        /// <summary>
+        /// Convert to string
+        /// </summary>
+        /// <returns>String displaying the comlex number (full precision)</returns>
+        public override String ToString() {
+            if (imag>=0)
+                return String.Format("{0} + {1}i",real,imag);
+            else 
+                return String.Format("{0} - {1}i",real,-imag);
+        }
+        private static string m_precSpecI = ""; 
+        private static string m_precSpecR = ""; 
+        private static int m_lastDigits = 0; 
+        /// <summary>
+        /// Print formated output of this number, determine number of digits
+        /// </summary>
+        /// <param name="digits">Number of digits</param>
+        /// <returns>Formated output</returns>
+        public string ToString(int digits) {
+            if (digits < 1) return ""; 
+            if (digits != m_lastDigits) {
+                m_lastDigits = digits; 
+                m_precSpecR = String.Format("{{0:f{0}}}",digits);
+                m_precSpecI = String.Format("{{1:f{0}}}i",digits);
+            }
+            if (imag >= 0) {
+                return String.Format(m_precSpecR+"+"+m_precSpecI,real,imag); 
+            } else {
+                return String.Format(m_precSpecR+"-"+m_precSpecI,real,-imag); 
+            }
+        }
+        /// <summary>
+        /// Magnitude of this complex instance
+        /// </summary>
+        /// <returns>Magnitude</returns>
+        public double Abs() {
+            return Math.Sqrt(real * real + imag * imag);
+        }
+        /// <summary>
+        /// Phase of this complex instance
+        /// </summary>
+        /// <returns>Phase</returns>
+        public double Angle() {
+            return Math.Atan2(imag, real);
+        }
+        /// <summary>
+        /// Arcus cosinus of this complex instance
+        /// </summary>
+        /// <returns>Arcus cosinus</returns>
+        public complex Acos() {
+            complex ret = new complex(0, -1);
+            return complex.Log(complex.Sqrt(this * this - 1)
+                + this) * ret;
+        }
+        /// <summary>
+        /// Arcus sinus of this complex instance
+        /// </summary>
+        /// <returns>arcus sinus</returns>
+        public complex Asin() {
+            complex ret = Acos(this);
+            ret.real = Math.PI / 2 - ret.real;
+            return ret;
+        }
+        /// <summary>
+        /// Exponential / power of base e
+        /// </summary>
+        /// <returns>Power of base e</returns>
+        public complex Exp() {
+            return complex.FromPol(Math.Exp(real), imag);
+        }
+        /// <summary>
+        /// Complex power real exponent
+        /// </summary>
+        /// <param name="exponent">Exponent</param>
+        /// <returns>New complex number with result</returns>
+        /// <remarks>If this instance is a and the exponent is e than 
+        /// the result will be the complex number exp(log(a) * e). </remarks>
+        public complex Pow(double exponent) {
+            complex ret = Log();
+            ret.imag *= exponent;
+            ret.real *= exponent;
+            return ret.Exp();
+        }
+        /// <summary>
+        /// Complex power - complex exponent
+        /// </summary>
+        /// <param name="exponent">Exponent</param>
+        /// <returns>Complex number exp(log(this) * exponent).</returns>
+        /// <remarks>If this instance is a than 
+        /// the result will be the complex number exp(log(a) * exponent). </remarks>
+        public complex Pow(complex exponent) {
+            complex ret = (Log() * exponent);
+            return ret.Exp();
+        }
+        /// <summary>
+        /// Square root of this complex value
+        /// </summary>
+        /// <returns>Square root of this complex value</returns>
+        public complex Sqrt() {
+            // Reference : numerical recipes in C: Appendix C
+            complex ret = new complex();
+            double x, y, w, r;
+            if (real == 0.0 && imag == 0.0)
+                return ret;
+            else {
+                x = (double)Math.Abs(real);
+                y = (double)Math.Abs(imag);
+                if (x >= y) {
+                    r = y / x;
+                    w = Math.Sqrt(x) * Math.Sqrt(0.5 * (1.0 + Math.Sqrt(1.0 + r * r)));
+                } else {
+                    r = x / y;
+                    w = Math.Sqrt(y) * Math.Sqrt(0.5 * (r + Math.Sqrt(1.0 + r * r)));
+                }
+                if (real >= 0.0) {
+                    ret.real = w;
+                    ret.imag = imag / (2.0 * w);
+                } else {
+                    ret.imag = (imag >= 0) ? w : -w;
+                    ret.real = imag / ( 2.0 * ret.imag );
+                }
+                return ret;
+            }
+        }
+        /// <summary>
+        /// Logarithm of base e
+        /// </summary>
+        /// <returns>Logarithm of base e</returns>
+        /// <remarks>The logarithm of a complex number A is defined as follows: <br />
+        /// <list type="none"><item>real part: log(abs(A))</item>
+        /// <item>imag part: Atan2(imag(A),real(A))</item></list>
+        /// </remarks>
+        public complex Log() {
+            complex ret = new complex();
+            ret.real = Math.Log(Math.Sqrt(real * real + imag * imag));
+            ret.imag = Math.Atan2(imag, real);
+            return ret;
+        }
+        /// <summary>
+        /// Test if any of real or imaginary parts are NAN's
+        /// </summary>
+        /// <param name="input">Complex number to test</param>
+        /// <returns>true if any of real or imag part is not a number</returns>
+        public static bool IsNaN(complex input) {
+            if (double.IsNaN(input.real) || double.IsNaN(input.imag)) 
+                return true; 
+            else 
+                return false; 
+        }
+        /// <summary>
+        /// Test if any of real or imaginary parts are infinite
+        /// </summary>
+        /// <param name="input">Complex number to test</param>
+        /// <returns>true if any of real or imag part is infinite</returns>
+        public static bool IsInfinity(complex input) {  
+            if (double.IsInfinity(input.real) || double.IsInfinity(input.imag)) 
+                return true; 
+            else 
+                return false; 
+        }
+        /// <summary>
+        /// Test if any of real or imaginary parts are pos.nfinite
+        /// </summary>
+        /// <param name="input">Complex number to test</param>
+        /// <returns>true if any of real or imag part is positive infinite</returns>
+        public static bool IsPositiveInfinity(complex input) {  
+            if (double.IsPositiveInfinity(input.real) || double.IsPositiveInfinity(input.imag)) 
+                return true; 
+            else 
+                return false; 
+        }
+        /// <summary>
+        /// Test if any of real or imaginary parts are neg. infinite
+        /// </summary>
+        /// <param name="input">Complex number to test</param>
+        /// <returns>true if any of real or imag part is negative infinite</returns>
+        public static bool IsNegativeInfinity(complex input) {  
+            if (double.IsNegativeInfinity(input.real) || double.IsNegativeInfinity(input.imag)) 
+                return true; 
+            else 
+                return false; 
+        }
+        /// <summary>
+        /// Test if any of real or imaginary parts are finite
+        /// </summary>
+        /// <param name="input">Complex number to test</param>
+        /// <returns>true if any of real and imag part is finite</returns>
+        public static bool IsFinite (complex input) {
+            if (ILMath.isfinite(input.real) && ILMath.isfinite(input.imag)) 
+                return true; 
+            else 
+                return false; 
+        }
+        /// <summary>
+        /// Test if both of real or imaginary parts are 0
+        /// </summary>
+        /// <returns>true if real and imag part is 0</returns>
+        public bool iszero() {
+            if (real == 0.0 && imag == 0.0) 
+                return true; 
+            else 
+                return false; 
+        }
+        #endregion Functions Basic Math
+    }
+    
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILDebuggerProxy.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILDebuggerProxy.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILDebuggerProxy.cs	(revision 9102)
@@ -0,0 +1,125 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Runtime; 
+using System.Runtime.InteropServices; 
+using System.Diagnostics; 
+using ILNumerics.Storage; 
+
+namespace ILNumerics.Misc {
+    /// <summary>
+    /// This class is for internal use only. Do not instantiate from this class!
+    /// </summary>
+    /// <typeparam name="T"></typeparam>
+    public class ILArrayDebuggerProxy<T> {
+        private ILDenseStorage<T> m_storage; 
+        private ILSize Dimensions {
+            get {
+                return m_storage.Size;
+            }
+        }
+        //[System.Diagnostics.DebuggerDisplay("{valuesToString,nq}")]
+        //public string Values {
+        //    get {
+        //        return m_array.Storage.ValuesToString(-1).ToString();
+        //    }
+        //}
+        [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
+        public RowVisualizer[] Rows {
+            get {
+                string [] tmp = m_storage.ValuesToString(200).ToString().Split(new string[1]{Environment.NewLine},StringSplitOptions.None); 
+                return RowVisualizer.Convert(tmp); 
+            }
+        }
+
+        public ILArrayDebuggerProxy (ILDenseArray<T> array) : base() {
+            m_storage = array.Storage; 
+        }
+        internal ILArrayDebuggerProxy (ILDenseStorage<T> storage) : base() {
+            m_storage = storage; 
+        }
+    }
+    [DebuggerDisplay("{Value,nq}")]
+    public class RowVisualizer {
+        public string Value;
+
+        internal static RowVisualizer[] Convert(string[] tmp) {
+            RowVisualizer[] ret = new RowVisualizer[tmp.Length];
+            for (int i = 0; i < tmp.Length; i++) {
+                ret[i] = new RowVisualizer() { Value = tmp[i] }; 
+            }
+            return ret; 
+        }
+  
+    }
+
+}
+#if DEBUG    
+    public static class DebuggerTraceHelper {
+
+        private static readonly string FILENAME = "DebugTraceLog.txt"; 
+        static DebuggerTraceHelper() {
+            if (System.IO.File.Exists(FILENAME))
+                System.IO.File.Delete(FILENAME); 
+        }
+        [ThreadStatic]
+        private static StringBuilder m_output;
+        private static object s_lock = new object(); 
+        public static StringBuilder Output {
+            get {
+                lock (s_lock) {
+                    if (m_output == null)
+                        m_output = new StringBuilder();
+                    if (m_output.Length > 10000) {
+                        System.IO.File.AppendAllText(FILENAME, m_output.ToString());
+                        m_output.Clear();
+                    }
+                    m_output.Append(System.DateTime.Now.ToLongTimeString() + ": ");
+                    return m_output;
+                }
+            }
+        }
+
+    }
+#endif
+
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILException.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILException.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILException.cs	(revision 9102)
@@ -0,0 +1,268 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+
+namespace ILNumerics.Exceptions
+{
+    /// <summary>
+    /// Generic exception, base class for all exceptions thrown by ILNumerics
+    /// </summary>
+    public class ILException : System.Exception
+    {
+        /// <summary>
+        /// Constructor
+        /// </summary>
+        /// <param name="message">Additional message to be included</param>
+        public ILException(String message) : base(message) { }
+        /// <summary>
+        /// Constructor
+        /// </summary>
+        /// <param name="message">Additional message to be included</param>
+        /// <param name="innerException">Inner Exception</param>
+        public ILException(String message, Exception innerException) 
+                : base(message, innerException) { }
+    }
+    /// <summary>
+    /// Base class for mathematical exceptions. Needed e.g. in interpreter for proper error
+    /// messages
+    /// </summary>
+    public class ILMathException : ILException
+    {
+        /// <summary>
+        /// Constructor
+        /// </summary>
+        /// <param name="message">Additional message to be included</param>
+        public ILMathException(String message) : base(message) { }
+        /// <summary>
+        /// Constructor
+        /// </summary>
+        /// <param name="message">Additional message to be included</param>
+        /// <param name="innerException">Inner Exception</param>
+        public ILMathException(String message, Exception innerException) 
+                : base(message, innerException) { }
+    }
+
+    /// <summary>
+    /// One of the most common exceptions: The matrix sizes do not match
+    /// </summary>
+    public class ILDimensionMismatchException : ILMathException
+    {
+        /// <summary>
+        /// Constructor
+        /// </summary>
+        public ILDimensionMismatchException() : base("Matrix dimensions must match") { }
+        /// <summary>
+        /// Constructor
+        /// </summary>
+        /// <param name="message">Additional message to be included</param>
+        /// <param name="innerException">Inner Exception</param>
+        public ILDimensionMismatchException(String message, Exception innerException) 
+                : base(message, innerException) { }
+        /// <summary>
+        /// Constructor
+        /// </summary>
+        /// <param name="message">Additional message to be included</param>
+        public ILDimensionMismatchException(string message) : base(message) { }
+    }
+
+    /// <summary>
+    /// Something was wrong with the arguments supplied
+    /// </summary>
+    public class ILArgumentException : ILException {
+        /// <summary>
+        /// Constructor
+        /// </summary>
+        /// <param name="message">Additional message to be included</param>
+        public ILArgumentException(String message)
+            : base(message) {}
+        /// <summary>
+        /// Constructor
+        /// </summary>
+        /// <param name="message">Additional message to be included</param>
+        /// <param name="innerException">Inner Exception</param>
+        public ILArgumentException(String message, Exception innerException) 
+                : base(message, innerException) { }
+    }
+    /// <summary>
+    /// A function was called with the wrong number of arguments
+    /// </summary>
+    public class ILArgumentNumberException : ILArgumentException {
+        /// <summary>
+        /// Constructor
+        /// </summary>
+        /// <param name="message">Additional message to be included</param>
+        public ILArgumentNumberException(String message)
+            : base(message) { }
+        /// <summary>
+        /// Constructor
+        /// </summary>
+        /// <param name="message">Additional message to be included</param>
+        /// <param name="innerException">Inner Exception</param>
+        public ILArgumentNumberException(String message, Exception innerException)
+            : base(message, innerException) { }
+    }
+    /// <summary>
+    /// A function argument has the wrong size
+    /// </summary>
+    public class ILArgumentSizeException : ILArgumentException {
+        /// <summary>
+        /// Constructor
+        /// </summary>
+        /// <param name="message">Additional message to be included</param>
+        public ILArgumentSizeException(String message)
+            : base(message) { }
+        /// <summary>
+        /// Constructor
+        /// </summary>
+        /// <param name="message">Additional message to be included</param>
+        /// <param name="innerException">Inner Exception</param>
+        public ILArgumentSizeException(String message, Exception innerException)
+            : base(message, innerException) { }
+    }
+    /// <summary>
+    /// A function was called with a wrong argument type
+    /// </summary>
+    /// <remarks>This exception might be thrown if the size or inner 
+    /// type of a argument is invalid. (e.g. matrix expected, but 3D array found)
+    /// </remarks>
+    public class ILArgumentTypeException : ILArgumentException {
+        /// <summary>
+        /// Constructor
+        /// </summary>
+        /// <param name="message">Additional message to be included</param>
+        public ILArgumentTypeException(String message)
+            : base(message) {}
+        /// <summary>
+        /// Constructor
+        /// </summary>
+        /// <param name="message">Additional message to be included</param>
+        /// <param name="innerException">Inner Exception</param>
+         public ILArgumentTypeException(String message, Exception innerException) 
+                : base(message, innerException) { }
+    }
+    
+    /// <summary>
+    /// A request could not be completed due to not enough memory available
+    /// </summary>
+    public class ILMemoryException : ILException {
+        /// <summary>
+        /// Constructor
+        /// </summary>
+        /// <param name="message">Additional message to be included</param>
+        public ILMemoryException(String message)
+            : base(message) {}
+        /// <summary>
+        /// Constructor
+        /// </summary>
+        /// <param name="message">Additional message to be included</param>
+        /// <param name="innerException">Inner Exception</param>
+        public ILMemoryException(String message, Exception innerException) 
+                : base(message, innerException) { }
+    }
+    /// <summary>
+    /// Thrown on illegal casting attempts
+    /// </summary>
+    public class ILCastException : ILException
+    {
+        /// <summary>
+        /// Costructor
+        /// </summary>
+        /// <param name="message">Addditional message to be included into the exception</param>
+        public ILCastException(String message)
+            : base(message) { }
+        /// <summary>
+        /// Costructor
+        /// </summary>
+        /// <param name="message">Additional message to be included into the exception</param>
+        /// <param name="innerException">On cascaded exception handling, the exception catched before</param>
+        public ILCastException(String message, Exception innerException)
+            : base(message, innerException) { }
+    }
+    /// <summary>
+    /// ILOutputException, thrown if an I/O attempt fails
+    /// </summary>
+    public class ILOutputException : ILException
+    {
+        /// <summary>
+        /// Constructor
+        /// </summary>
+        /// <param name="message">Additional message to be included</param>
+        public ILOutputException(String message)
+            : base(message) { }
+        /// <summary>
+        /// Constructor
+        /// </summary>
+        /// <param name="message">Additional message to be included</param>
+        /// <param name="innerException">Inner Exception</param>
+        public ILOutputException(String message, Exception innerException)
+            : base(message, innerException) { }
+    }
+
+    /// <summary>
+    /// Exception thrown if an operation could not completed
+    /// </summary>
+    public class ILInvalidOperationException : ILException
+    {
+        /// <summary>
+        /// Constructor
+        /// </summary>
+        /// <param name="message">Additional message to be included</param>
+        public ILInvalidOperationException(String message)
+            : base(message) {}
+        /// <summary>
+        /// Constructor
+        /// </summary>
+        /// <param name="message">Additional message to be included</param>
+        /// <param name="innerException">Inner Exception</param>
+        public ILInvalidOperationException(String message, Exception innerException) 
+                : base(message, innerException) { }
+    }
+    /// <summary>
+    /// No valid license could be found
+    /// </summary>
+    public class ILInvalidLicenseException : ILException {
+        /// <summary>
+        /// Create a new ILInvalidLicenseException 
+        /// </summary>
+        /// <param name="message">Additional message to be included</param>
+        public ILInvalidLicenseException(String message, Exception innerExc)
+            : base(message, innerExc) {}
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILExpression.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILExpression.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILExpression.cs	(revision 9102)
@@ -0,0 +1,141 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+#pragma warning disable 1591
+
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Linq.Expressions; 
+using ILNumerics.Storage; 
+
+namespace ILNumerics.Misc {
+    public class ILExpression : ILDenseArray<Expression> {
+
+        public ILExpression(Expression exp) : base(new ILDenseStorage<Expression>(
+            new Expression[1] { exp }, ILSize.Scalar1_1), false) {
+        }
+
+        public Expression Expression {
+            get { return GetValue(0); }
+        }
+
+        #region operator overload
+        public static ILExpression operator -(ILExpression a, ILExpression b) {
+            return new ILExpression(Expression.Subtract(a.Expression, b.Expression));
+        }
+        public static ILExpression operator +(ILExpression a, ILExpression b) {
+            return new ILExpression(Expression.Add(a.Expression, b.Expression));
+        }
+        public static ILExpression operator *(ILExpression a, ILExpression b) {
+            return new ILExpression(Expression.Multiply(a.Expression, b.Expression));
+        }
+        public static ILExpression operator /(ILExpression a, ILExpression b) {
+            return new ILExpression(Expression.Divide(a.Expression, b.Expression));
+        }
+        
+        public static ILExpression operator +(ILExpression expr, ILBaseArray a) {
+            return new ILExpression(Expression.Add(expr.Expression, BA2Expr(a)));
+        }
+        public static ILExpression operator +(ILBaseArray a, ILExpression expr) {
+            return new ILExpression(Expression.Add(BA2Expr(a), expr.Expression));
+        }
+        public static ILExpression operator -(ILExpression expr, ILBaseArray a) {
+            return new ILExpression(Expression.Subtract(expr.Expression, BA2Expr(a)));
+        }
+        public static ILExpression operator -(ILBaseArray a, ILExpression expr) {
+            return new ILExpression(Expression.Subtract(BA2Expr(a), expr.Expression));
+        }
+
+        public static ILExpression operator /(ILExpression expr, ILBaseArray a) {
+            return new ILExpression(Expression.Divide(expr.Expression, BA2Expr(a)));
+        }
+        public static ILExpression operator /(ILBaseArray a, ILExpression expr) {
+            return new ILExpression(Expression.Divide(BA2Expr(a), expr.Expression));
+        }
+        public static ILExpression operator *(ILExpression expr, ILBaseArray a) {
+            return new ILExpression(Expression.Multiply(expr.Expression, BA2Expr(a)));
+        }
+        public static ILExpression operator *(ILBaseArray a, ILExpression expr) {
+            return new ILExpression(Expression.Multiply(BA2Expr(a), expr.Expression));
+        }
+        #endregion 
+
+        #region helper
+        private static MethodCallExpression BA2Expr(ILBaseArray a) {
+            MemberExpression storageExpr = Expression.Property(Expression.Constant(a), typeof(ILBaseArray).GetProperty("Storage", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance));
+            MethodCallExpression getValExpr = Expression.Call(
+                                                storageExpr
+                                                , typeof(ILStorage).GetMethod("GetValue", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic)
+                                                , Expression.Constant(new int[] { 0 }));
+            MethodCallExpression convertInt32 = Expression.Call(
+                                                typeof(Convert).GetMethod("ToInt32", new Type[] { typeof(object) })
+                                                , getValExpr);
+            return convertInt32;
+        }
+        #endregion
+
+        #region ILBaseArray Interface
+
+        public override bool IsComplex {
+            get { return false; }
+        }
+
+        public override bool IsNumeric {
+            get { return false; }
+        }
+
+        public override void ToStream(System.IO.Stream outStream, string format, ILArrayStreamSerializationFlags method) {
+            throw new NotImplementedException();
+        }
+        internal override bool EnterScope() {
+            return false;
+        }
+        #endregion ILBaseArray Interface 
+    
+        internal static int Evaluate(Expression iLExpression, int dimLength) {
+            ParameterExpression endParameter = (ParameterExpression)ILMath.end.Expression;
+            int res = Expression.Lambda<Func<int,int>>(iLExpression,new ParameterExpression[]{ endParameter }).Compile()(dimLength);
+            return res; 
+        }
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILExtensionMethods.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILExtensionMethods.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILExtensionMethods.cs	(revision 9102)
@@ -0,0 +1,268 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices; 
+using System.Text;
+using System.Numerics; 
+using ILNumerics.Storage; 
+
+namespace ILNumerics {
+    /// <summary>
+    /// Extension methods for ILNumerics types
+    /// </summary>
+    public static class ILExtensionMethods {
+        /// <summary> 
+        /// Convert this complex ILNumerics array to a system array of type System.Numerics.Complex[]
+        /// </summary>
+        /// <param name="A">this ILNumerics array</param>
+        /// <param name="Storage">[option] if given, this system array will be used as storage for the conversion. Defaul: null (a new System.Array is returned)</param>
+        /// <returns>System.Array with the elements of A</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if the storage given does not have sufficient length for all elements of the ILNumerics array</exception>
+        /// <remarks><para>The elements of the ILNumerics array will be copied to the System.Array and converted to the System.Numerics.Complex type.</para>
+        /// <para>The System.Array returned will contain all elements of the ILNumerics arrays after conversion - in column major order.</para>
+        /// <example>
+        /// This example demonstrates a common scenario for interchanging System.Numerics.Complex[] with ILNumerics complex arrays. It takes the converion between System.Numerics.Complex and ILNumerics.complex 
+        /// into account, as well as the memory management of all storage involved. 
+        /// <code>
+        /// ILArray&lt;complex> A = sqrtc(B); 
+        /// // interfacing an external library as System.Numerics.Complex[]
+        /// // We dont provide a System.Array as target for the conversion,
+        /// // so it will be fetched from the ILNumerics memory management. 
+        /// System.Numerics.Complex[] A_MSComplex = A.ToMSComplex(); 
+        /// // .. do some work here with A_MSComplex
+        /// // ...
+        /// // The results get converted back to ILNumerics array 
+        /// ILArray&lt;complex> Result = A_MSComplex.ToILArray(A.S, true); 
+        /// </code>
+        /// <para>For the conversion of the System.Numerics.Complex[] array back to an ILNumerics array, we use the same size (<c>A.S</c>) as before. Here, any size 
+        /// would work, as long as it fits into the number of elements of the source System.Array.</para>
+        /// <para>Note that the calls to <c>A.ToMSComplex()</c> and <c>A_MSComplex.ToILArray(A.S, true)</c> will fetch and return all System.Arrays involved into/from the 
+        /// ILINumerics memory pool. So if called frequently, no pressure on the GC is produced, what qualifies this scheme for high performance scenarios.</para> 
+        /// </example>
+        /// </remarks>
+        /// <seealso cref="ToILArray(Complex[], ILSize, bool )"/>
+        public unsafe static Complex[] ToMSComplex(this ILArray<complex> A, Complex[] Storage = null) {
+            return ToMSComplexHelper(A.Storage, Storage);
+        }
+        /// <summary>
+        /// Convert this complex ILNumerics array to a system array of type System.Numerics.Complex[]
+        /// </summary>
+        /// <param name="A">this ILNumerics array</param>
+        /// <param name="Storage">[option] if given, this system array will be used as storage for the conversion. Defaul: null (a new System.Array is returned)</param>
+        /// <returns>System.Array with the elements of A</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if the storage given does not have sufficient length for all elements of the ILNumerics array</exception>
+        /// <remarks><para>The elements of the ILNumerics array will be copied to the System.Array and converted to the System.Numerics.Complex type.</para>
+        /// <para>The System.Array returned will contain all elements of the ILNumerics arrays after conversion - in column major order.</para>
+        /// <example>
+        /// This example demonstrates a common scenario for interchanging System.Numerics.Complex[] with ILNumerics complex arrays. It takes the converion between System.Numerics.Complex and ILNumerics.complex 
+        /// into account, as well as the memory management of all storage involved. 
+        /// <code>
+        /// ILArray&lt;complex> A = sqrtc(B); 
+        /// // interfacing an external library as System.Numerics.Complex[]
+        /// // We dont provide a System.Array as target for the conversion,
+        /// // so it will be fetched from the ILNumerics memory management. 
+        /// System.Numerics.Complex[] A_MSComplex = A.ToMSComplex(); 
+        /// // .. do some work here with A_MSComplex
+        /// // ...
+        /// // The results get converted back to ILNumerics array 
+        /// ILArray&lt;complex> Result = A_MSComplex.ToILArray(A.S, true); 
+        /// </code>
+        /// <para>For the conversion of the System.Numerics.Complex[] array back to an ILNumerics array, we use the same size (<c>A.S</c>) as before. Here, any size 
+        /// would work, as long as it fits into the number of elements of the source System.Array.</para>
+        /// <para>Note that the calls to <c>A.ToMSComplex()</c> and <c>A_MSComplex.ToILArray(A.S, true)</c> will fetch and return all System.Arrays involved into/from the 
+        /// ILINumerics memory pool. So if called frequently, no pressure on the GC is produced, what qualifies this scheme for high performance scenarios.</para> 
+        /// </example>
+        /// </remarks>
+        /// <seealso cref="ToILArray(Complex[], ILSize, bool )"/>
+        public unsafe static Complex[] ToMSComplex(this ILInArray<complex> A, Complex[] Storage = null) {
+            return ToMSComplexHelper(A.Storage, Storage);
+        }
+        /// <summary>
+        /// Convert this complex ILNumerics array to a system array of type System.Numerics.Complex[]
+        /// </summary>
+        /// <param name="A">this ILNumerics array</param>
+        /// <param name="Storage">[option] if given, this system array will be used as storage for the conversion. Defaul: null (a new System.Array is returned)</param>
+        /// <returns>System.Array with the elements of A</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if the storage given does not have sufficient length for all elements of the ILNumerics array</exception>
+        /// <remarks><para>The elements of the ILNumerics array will be copied to the System.Array and converted to the System.Numerics.Complex type.</para>
+        /// <para>The System.Array returned will contain all elements of the ILNumerics arrays after conversion - in column major order.</para>
+        /// <example>
+        /// This example demonstrates a common scenario for interchanging System.Numerics.Complex[] with ILNumerics complex arrays. It takes the converion between System.Numerics.Complex and ILNumerics.complex 
+        /// into account, as well as the memory management of all storage involved. 
+        /// <code>
+        /// ILArray&lt;complex> A = sqrtc(B); 
+        /// // interfacing an external library as System.Numerics.Complex[]
+        /// // We dont provide a System.Array as target for the conversion,
+        /// // so it will be fetched from the ILNumerics memory management. 
+        /// System.Numerics.Complex[] A_MSComplex = A.ToMSComplex(); 
+        /// // .. do some work here with A_MSComplex
+        /// // ...
+        /// // The results get converted back to ILNumerics array 
+        /// ILArray&lt;complex> Result = A_MSComplex.ToILArray(A.S, true); 
+        /// </code>
+        /// <para>For the conversion of the System.Numerics.Complex[] array back to an ILNumerics array, we use the same size (<c>A.S</c>) as before. Here, any size 
+        /// would work, as long as it fits into the number of elements of the source System.Array.</para>
+        /// <para>Note that the calls to <c>A.ToMSComplex()</c> and <c>A_MSComplex.ToILArray(A.S, true)</c> will fetch and return all System.Arrays involved into/from the 
+        /// ILINumerics memory pool. So if called frequently, no pressure on the GC is produced, what qualifies this scheme for high performance scenarios.</para> 
+        /// </example>
+        /// </remarks>
+        /// <seealso cref="ToILArray(Complex[], ILSize, bool )"/>
+        public unsafe static Complex[] ToMSComplex(this ILOutArray<complex> A, Complex[] Storage = null) {
+            return ToMSComplexHelper(A.Storage, Storage);
+        }
+        /// <summary>
+        /// Convert this complex ILNumerics array to a system array of type System.Numerics.Complex[]
+        /// </summary>
+        /// <param name="A">this ILNumerics array</param>
+        /// <param name="Storage">[option] if given, this system array will be used as storage for the conversion. Defaul: null (a new System.Array is returned)</param>
+        /// <returns>System.Array with the elements of A</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if the storage given does not have sufficient length for all elements of the ILNumerics array</exception>
+        /// <remarks><para>The elements of the ILNumerics array will be copied to the System.Array and converted to the System.Numerics.Complex type.</para>
+        /// <para>The System.Array returned will contain all elements of the ILNumerics arrays after conversion - in column major order.</para>
+        /// <example>
+        /// This example demonstrates a common scenario for interchanging System.Numerics.Complex[] with ILNumerics complex arrays. It takes the converion between System.Numerics.Complex and ILNumerics.complex 
+        /// into account, as well as the memory management of all storage involved. 
+        /// <code>
+        /// ILArray&lt;complex> A = sqrtc(B); 
+        /// // interfacing an external library as System.Numerics.Complex[]
+        /// // We dont provide a System.Array as target for the conversion,
+        /// // so it will be fetched from the ILNumerics memory management. 
+        /// System.Numerics.Complex[] A_MSComplex = A.ToMSComplex(); 
+        /// // .. do some work here with A_MSComplex
+        /// // ...
+        /// // The results get converted back to ILNumerics array 
+        /// ILArray&lt;complex> Result = A_MSComplex.ToILArray(A.S, true); 
+        /// </code>
+        /// <para>For the conversion of the System.Numerics.Complex[] array back to an ILNumerics array, we use the same size (<c>A.S</c>) as before. Here, any size 
+        /// would work, as long as it fits into the number of elements of the source System.Array.</para>
+        /// <para>Note that the calls to <c>A.ToMSComplex()</c> and <c>A_MSComplex.ToILArray(A.S, true)</c> will fetch and return all System.Arrays involved into/from the 
+        /// ILINumerics memory pool. So if called frequently, no pressure on the GC is produced, what qualifies this scheme for high performance scenarios.</para> 
+        /// </example>
+        /// </remarks>
+        /// <seealso cref="ToILArray(Complex[], ILSize, bool )"/>
+        public unsafe static Complex[] ToMSComplex(this ILRetArray<complex> A, Complex[] Storage = null) {
+            try {
+                return ToMSComplexHelper(A.Storage, Storage);
+            } finally {
+                A.Dispose(); 
+            }
+        }
+
+        unsafe private static Complex[] ToMSComplexHelper(ILDenseStorage<complex> A, Complex[] Storage) {
+            if (object.Equals(A, null) || A.Size.NumberOfElements == 0)
+                return new Complex[0];
+
+            if (!object.Equals(Storage, null) && Storage.Length < A.Size.NumberOfElements)
+                throw new Exceptions.ILArgumentException("The storage array given is too small for the conversion.");
+
+            Complex[] retArr = (object.Equals(Storage, null)) ? ILMath.New<Complex>(A.Size.NumberOfElements) : Storage;
+
+            GCHandle retHandle = GCHandle.Alloc(retArr, GCHandleType.Pinned);
+            GCHandle inHandle = GCHandle.Alloc(A.GetArrayForRead(), GCHandleType.Pinned);
+            complex* retP = (complex*)retHandle.AddrOfPinnedObject();
+            complex* inP = (complex*)inHandle.AddrOfPinnedObject();
+            ILMath.complex2ComplexHelper(inP, retP, A.Size.NumberOfElements);
+            retHandle.Free();
+            inHandle.Free();
+            return retArr;
+        }
+
+        /// <summary>
+        /// Convert this System.Numerics.Complex[] array to an ILNumerics array with ILNumerics.complex elements
+        /// </summary>
+        /// <param name="Storage">the source array, System.Numerics.Complex[]</param>
+        /// <param name="size">[optional] if specified, the size and shape of the ILNumerics array returned. Otherwise, a vector of length Storage.Length will be returned.</param>
+        /// <param name="recycleStorage">[optional] Places the incoming System.Numerics.Complex[] array into the ILNumerics memory pool. Default: false.</param>
+        /// <returns>ILNumerics array of element type ILNumerics.complex</returns>
+        /// <remarks>
+        /// <para>If the <paramref name="size"/> argument was given, it must define an array shape according to the actual length of <paramref name="Storage"/>. Therefore, 
+        /// <c>size.NumberOfElements &leq; Storage.Length</c> must be valid.
+        /// </para>
+        /// <para>In a high performance scenario, it is recommended to have the function recycle the incoming storage after use. If <paramref name="recycleStorage"/> is set to <c>true</c>, 
+        /// the user is responsible not to reference the incoming array afterwards. The array will be stored into the ILNumerics memory pool and eventually be used for later 
+        /// allocation requests (for instance in <see cref="ToMSComplex(ILArray<complex>, Complex[])"/>).</para>
+        /// <example>
+        /// This example demonstrates a common scenario for interchanging System.Numerics.Complex[] with ILNumerics complex arrays. It takes the converion between System.Numerics.Complex and ILNumerics.complex 
+        /// into account, as well as the memory management of all storage involved. 
+        /// <code>
+        /// ILArray&lt;complex> A = sqrtc(B); 
+        /// // interfacing an external library as System.Numerics.Complex[]
+        /// // We dont provide a System.Array as target for the conversion,
+        /// // so it will be fetched from the ILNumerics memory management. 
+        /// System.Numerics.Complex[] A_MSComplex = A.ToMSComplex(); 
+        /// // .. do some work here with A_MSComplex
+        /// // ...
+        /// // The results get converted back to ILNumerics array 
+        /// ILArray&lt;complex> Result = A_MSComplex.ToILArray(A.S, true); 
+        /// </code>
+        /// <para>For the conversion of the System.Numerics.Complex[] array back to an ILNumerics array, we use the same size (<c>A.S</c>) as before. Here, any size 
+        /// would work, as long as it fits into the number of elements of the source System.Array.</para>
+        /// <para>Note that the calls to <c>A.ToMSComplex()</c> and <c>A_MSComplex.ToILArray(A.S, true)</c> will fetch and return all System.Arrays involved into/from the 
+        /// ILINumerics memory pool. So if called frequently, no pressure on the GC is produced, what qualifies this scheme for high performance scenarios.</para> 
+        /// </example>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if the length of the <paramref name="Storage"/> is less than <c>size.NumberOfElements</c></exception>
+        public unsafe static ILRetArray<complex> ToILArray(this Complex[] Storage, ILSize size = null, bool recycleStorage = false) {
+            if (Storage == null || Storage.Length == 0) 
+                return ILMath.empty<complex>(); 
+            
+            ILSize outSize = (size == null) ? ILMath.size(Storage.Length, 1) : size;
+            if (outSize.NumberOfElements > Storage.Length) 
+                throw new Exceptions.ILArgumentException("Invalid size definition! The number of elements defined by 'size' must be less or equal to the length of 'Storage'.");
+
+            complex[] retArr = ILMath.New<complex>(outSize.NumberOfElements); 
+
+            GCHandle retHandle = GCHandle.Alloc(retArr, GCHandleType.Pinned);
+            GCHandle inHandle = GCHandle.Alloc(Storage, GCHandleType.Pinned);
+            complex* retP = (complex*)retHandle.AddrOfPinnedObject();
+            complex* inP = (complex*)inHandle.AddrOfPinnedObject();
+            ILMath.complex2ComplexHelper(inP, retP, outSize.NumberOfElements);
+            retHandle.Free();
+            inHandle.Free();
+
+            if (recycleStorage) {
+                ILMath.free(Storage);
+            }
+            return ILMath.array<complex>(retArr, outSize);
+        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILFComplex.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILFComplex.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILFComplex.cs	(revision 9102)
@@ -0,0 +1,2344 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+#pragma warning disable 162 
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.InteropServices;
+
+
+
+namespace ILNumerics {
+    /// <summary>
+    /// Floating point complex value data type of float (single) precision
+    /// </summary>
+    /// <remarks>This class extends the system value types for real numbers to complex float 
+    /// values. Besides the publicly available members 'real' and 'imag' it provides all the 
+    /// basis functionality the floating point System.double brings (abs, log, sqrt, tan etc.) for 
+    /// float precision complex,
+    /// as well as it overrides the basic unary and binary operators for all common system value 
+    /// types including rarely used types (e.g. UInt16). This includes the basic numerical operations 
+    /// like '+','-','/','*' and the relational operators: '==','>','>=' etc. Also there are some 
+    /// explicit and some implicit casting operators from / to fcomplex values into system 
+    /// value types. </remarks>
+    [Serializable]    
+    [StructLayout(LayoutKind.Sequential)]
+    public struct fcomplex : IEquatable<fcomplex> {
+        /// <summary>
+        /// Real part of this complex number
+        /// </summary>
+        public float real;
+        /// <summary>
+        /// Imaginary part of this complex number
+        /// </summary>
+        public float imag;
+        /// <summary>
+        /// Imaginary unit 
+        /// </summary>
+        public static readonly fcomplex i = new fcomplex(0.0f,1.0f); 
+
+        /// <summary>
+        /// Construct new float complex number
+        /// </summary>
+        /// <param name="real">Real part</param>
+        /// <param name="imag">Imaginary part</param>
+        public fcomplex(float real, float imag) {
+            this.real = real;
+            this.imag = imag;
+        }
+        
+        /// <summary>
+        /// Complex conjugate 
+        /// </summary>
+        public fcomplex conj {
+            get{
+                return new fcomplex(real,imag * (-1.0f));
+            }
+        }
+
+        /// <summary>
+        /// Positive infinity for real and imag part of complex value
+        /// </summary>
+        public static fcomplex INF {
+            get {
+                return new fcomplex(
+                    float.PositiveInfinity,
+                    float.PositiveInfinity
+                );
+            }
+        }
+
+        /// <summary>
+        /// New fcomplex, real and imaginary parts are zero
+        /// </summary>
+       public static fcomplex Zero {
+            get {
+                return new fcomplex(0f,0f);
+            }
+        }
+
+        /// <summary>
+        /// fcomplex quantity, marked as being "not a number"
+        /// </summary>
+        public static fcomplex NaN {
+            get {
+                return new fcomplex(float.NaN,float.NaN); 
+            }
+        }
+
+        /// <summary>
+        /// Are obj's real and imaginary part identical to the real and imaginary parts of this fcomplex
+        /// </summary>
+        /// <param name="obj">fcomplex object to determine the equality for</param>
+        /// <returns>true if obj is of fcomplex type and its real and imag part has the same 
+        /// values as the real and imaginary part of this array.</returns>
+        public override bool Equals(object obj) {
+            if (obj is fcomplex && ((fcomplex)obj) == this)
+                return true; 
+            return false; 
+        }
+
+        /// <summary>
+        /// Check if a fcomplex number equals this fcomplex number
+        /// </summary>
+        /// <param name="other">other complex number</param>
+        /// <returns>true if both, real and imaginary parts of both complex number are (binary) equal, false otherwise</returns>
+        public bool Equals(fcomplex other) {
+            return real.Equals(other.real) && imag.Equals(other.imag);
+        }
+
+        /// <summary>
+        /// Give HashCode of this fcomplex number
+        /// </summary>
+        /// <returns>HashCode of this fcomplex number</returns>
+        public override int GetHashCode() {
+            return 31 * real.GetHashCode() + imag.GetHashCode();
+        }
+
+
+        
+
+#region HYCALPER AUTO GENERATED CODE
+
+       
+        /// <summary>
+        /// Add two complex numbers
+        /// </summary>
+        /// <param name="A">First summand</param>
+        /// <param name="B">Second summand</param>
+        /// <returns>result</returns>
+        public static  complex operator +( fcomplex A,  complex B) {
+            complex ret; 
+             ret.real =  (double) (A.real + B.real );
+             ret.imag =  (double) (A.imag + B.imag );
+            return ret;
+        }
+        /// <summary>
+        /// Subtract two complex values
+        /// </summary>
+        /// <param name="A">Minuend</param>
+        /// <param name="B">Subtrahend</param>
+        /// <returns>result</returns>
+        public static  complex operator -( fcomplex A,  complex B) {
+            complex ret; 
+            ret.real =  (double) (A.real  - B.real );
+            ret.imag =  (double) (A.imag - B.imag );
+            return ret;
+        }
+        /// <summary>
+        /// Multiply two complex values
+        /// </summary>
+        /// <param name="A">First factor</param>
+        /// <param name="B">Second factor</param>
+        /// <returns>result</returns>
+        public static  complex operator *( fcomplex A,  complex B) {
+            complex ret;
+            ret.real =  (double) ((A.real * B.real ) - (A.imag * B.imag ));
+            ret.imag =  (double) ((A.real * B.imag ) + (A.imag * B.real ));
+            return ret; 
+        }
+        /// <summary>
+        /// Divide two numbers
+        /// </summary>
+        /// <param name="A">Divident</param>
+        /// <param name="B">Divisor</param>
+        /// <returns>Result</returns>
+        /// <remarks><para>Unless the operator must handle special inputs (Inf or 0 values), 
+        /// the algorithm described in [1] is used for division. This is considered to be 
+        /// more robust against floating point overflow than the naive approach of simple 
+        /// cartesian division.</para>
+        /// <para>References: [1]: Smith, R.L., Algorithm 116: Complex division. Commun.ACM 5,8 (1962),435 <br />
+        /// [2]: Stewart, G.W., A note on complex division, ACM trans.on math software, Vol.11, N.3 (1985)</para></remarks>
+        public static  complex operator /( fcomplex A,  complex B) {
+            if (B.imag == 0) return A / B.real; 
+            return A * (1 / B); 
+            if (IsNaN(A) ||  complex .IsNaN(B)) return NaN;
+            //if ( complex .IsInfinity(B)) return NaN;            
+            //if (A.real == 0 && A.imag == 0) return ( complex )0;
+            complex ret;
+            if (B.real == 0) {
+                ret.imag =  (double) -(A.real / B.imag); 
+                ret.real =  (double) (A.imag / B.imag); 
+                return ret; 
+            }
+            // this would be the naive approach. But it come with to little robustness against overflow
+            //double norm2 = B.real * B.real + B.imag * B.imag;
+            //if (norm2 == 0) return INF;    // this may be removed, since division by 0 results in inf anyway ? 
+            //ret.real =  (double) (((A.real  * B.real ) + (A.imag  * B.imag )) / norm2);
+            //ret.imag =  (double) (((A.imag  * B.real ) - (A.real  * B.imag )) / norm2); 
+            
+            // this algorithm is taken from [1]. The one described in [2] was not taken. Tests 
+            // did not show any advantage when using double precision floating point arithmetic.
+            double tmp1, tmp2; 
+            if (Math.Abs(B.real) >= Math.Abs(B.imag)) {
+                tmp1 =  (double) (B.imag * (1/B.real)); 
+                tmp2 =  (double) (B.real + B.imag*tmp1); 
+                ret.real =  (double) (A.real + A.imag*tmp1)/tmp2; 
+                ret.imag =  (double) (A.imag - A.real*tmp1)/tmp2; 
+            } else {
+                tmp1 =  (double) (B.real * (1/B.imag));
+                tmp2 =  (double) (B.imag + B.real*tmp1); 
+                ret.real =  (double) (A.imag + A.real*tmp1)/tmp2; 
+                ret.imag = -  (double) (A.real - A.imag*tmp1)/tmp2; 
+            }
+            return ret;                                            
+        }
+        /// <summary>
+        /// Equality comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true, if real and imaginary part are identical</returns>
+        public static bool operator ==( fcomplex A,  complex B) {
+            return (A.imag  == B.imag ) && (A.real  == B.real );
+        }
+        /// <summary>
+        /// Unequality comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real and imaginary parts of A and B are not equal, false otherwise</returns>
+        public static bool operator !=( fcomplex A,  complex B) {
+            return (A.imag  != B.imag ) || (A.real  != B.real );
+        }
+        /// <summary>
+        /// Greater than comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is greater than real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator > ( fcomplex A,  complex B) {
+            return (A.real > B.real );
+        }
+        /// <summary>
+        /// Lower than comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is lower then real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator < ( fcomplex A,  complex B) {
+            return (A.real < B.real );
+        }
+        /// <summary>
+        /// Greater than or equal to comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is greater than real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator >=( fcomplex A,  complex B) {
+            return (A.real >= B.real );
+        }
+        /// <summary>
+        /// Lower than or equal to comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is lower then real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator <=( fcomplex A,  complex B) { 
+            return (A.real <= B.real );
+        }
+       
+        /// <summary>
+        /// Add two complex numbers
+        /// </summary>
+        /// <param name="A">First summand</param>
+        /// <param name="B">Second summand</param>
+        /// <returns>result</returns>
+        public static  fcomplex operator +( fcomplex A,  fcomplex B) {
+            fcomplex ret; 
+             ret.real =  (float) (A.real + B.real );
+             ret.imag =  (float) (A.imag + B.imag );
+            return ret;
+        }
+        /// <summary>
+        /// Subtract two complex values
+        /// </summary>
+        /// <param name="A">Minuend</param>
+        /// <param name="B">Subtrahend</param>
+        /// <returns>result</returns>
+        public static  fcomplex operator -( fcomplex A,  fcomplex B) {
+            fcomplex ret; 
+            ret.real =  (float) (A.real  - B.real );
+            ret.imag =  (float) (A.imag - B.imag );
+            return ret;
+        }
+        /// <summary>
+        /// Multiply two complex values
+        /// </summary>
+        /// <param name="A">First factor</param>
+        /// <param name="B">Second factor</param>
+        /// <returns>result</returns>
+        public static  fcomplex operator *( fcomplex A,  fcomplex B) {
+            fcomplex ret;
+            ret.real =  (float) ((A.real * B.real ) - (A.imag * B.imag ));
+            ret.imag =  (float) ((A.real * B.imag ) + (A.imag * B.real ));
+            return ret; 
+        }
+        /// <summary>
+        /// Divide two numbers
+        /// </summary>
+        /// <param name="A">Divident</param>
+        /// <param name="B">Divisor</param>
+        /// <returns>Result</returns>
+        /// <remarks><para>Unless the operator must handle special inputs (Inf or 0 values), 
+        /// the algorithm described in [1] is used for division. This is considered to be 
+        /// more robust against floating point overflow than the naive approach of simple 
+        /// cartesian division.</para>
+        /// <para>References: [1]: Smith, R.L., Algorithm 116: Complex division. Commun.ACM 5,8 (1962),435 <br />
+        /// [2]: Stewart, G.W., A note on complex division, ACM trans.on math software, Vol.11, N.3 (1985)</para></remarks>
+        public static  fcomplex operator /( fcomplex A,  fcomplex B) {
+            if (B.imag == 0) return A / B.real; 
+            return A * (1 / B); 
+            if (IsNaN(A) ||  fcomplex .IsNaN(B)) return NaN;
+            //if ( fcomplex .IsInfinity(B)) return NaN;            
+            //if (A.real == 0 && A.imag == 0) return ( fcomplex )0;
+            fcomplex ret;
+            if (B.real == 0) {
+                ret.imag =  (float) -(A.real / B.imag); 
+                ret.real =  (float) (A.imag / B.imag); 
+                return ret; 
+            }
+            // this would be the naive approach. But it come with to little robustness against overflow
+            //double norm2 = B.real * B.real + B.imag * B.imag;
+            //if (norm2 == 0) return INF;    // this may be removed, since division by 0 results in inf anyway ? 
+            //ret.real =  (float) (((A.real  * B.real ) + (A.imag  * B.imag )) / norm2);
+            //ret.imag =  (float) (((A.imag  * B.real ) - (A.real  * B.imag )) / norm2); 
+            
+            // this algorithm is taken from [1]. The one described in [2] was not taken. Tests 
+            // did not show any advantage when using double precision floating point arithmetic.
+            float tmp1, tmp2; 
+            if (Math.Abs(B.real) >= Math.Abs(B.imag)) {
+                tmp1 =  (float) (B.imag * (1/B.real)); 
+                tmp2 =  (float) (B.real + B.imag*tmp1); 
+                ret.real =  (float) (A.real + A.imag*tmp1)/tmp2; 
+                ret.imag =  (float) (A.imag - A.real*tmp1)/tmp2; 
+            } else {
+                tmp1 =  (float) (B.real * (1/B.imag));
+                tmp2 =  (float) (B.imag + B.real*tmp1); 
+                ret.real =  (float) (A.imag + A.real*tmp1)/tmp2; 
+                ret.imag = -  (float) (A.real - A.imag*tmp1)/tmp2; 
+            }
+            return ret;                                            
+        }
+        /// <summary>
+        /// Equality comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true, if real and imaginary part are identical</returns>
+        public static bool operator ==( fcomplex A,  fcomplex B) {
+            return (A.imag  == B.imag ) && (A.real  == B.real );
+        }
+        /// <summary>
+        /// Unequality comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real and imaginary parts of A and B are not equal, false otherwise</returns>
+        public static bool operator !=( fcomplex A,  fcomplex B) {
+            return (A.imag  != B.imag ) || (A.real  != B.real );
+        }
+        /// <summary>
+        /// Greater than comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is greater than real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator > ( fcomplex A,  fcomplex B) {
+            return (A.real > B.real );
+        }
+        /// <summary>
+        /// Lower than comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is lower then real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator < ( fcomplex A,  fcomplex B) {
+            return (A.real < B.real );
+        }
+        /// <summary>
+        /// Greater than or equal to comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is greater than real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator >=( fcomplex A,  fcomplex B) {
+            return (A.real >= B.real );
+        }
+        /// <summary>
+        /// Lower than or equal to comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is lower then real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator <=( fcomplex A,  fcomplex B) { 
+            return (A.real <= B.real );
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+
+        
+
+#region HYCALPER AUTO GENERATED CODE
+
+       
+        /// <summary>
+        /// Add two complex numbers
+        /// </summary>
+        /// <param name="A">First summand</param>
+        /// <param name="B">Second summand</param>
+        /// <returns>Result</returns>
+        public static  fcomplex operator +( fcomplex A,  Int64 B) {
+            fcomplex ret;
+            ret.real =  (float) (A.real + B);
+            ret.imag =  (float) A.imag;
+            return ret;
+        }
+        /// <summary>
+        /// Subtract two values
+        /// </summary>
+        /// <param name="A">Minuend</param>
+        /// <param name="B">Subtrahend</param>
+        /// <returns>result</returns>
+        public static  fcomplex operator -( fcomplex A,  Int64 B) {
+            fcomplex ret;
+            ret.real =  (float) (A.real - B);
+            ret.imag =  (float) A.imag;
+            return ret;
+        }
+        /// <summary>
+        /// Multiply two values
+        /// </summary>
+        /// <param name="A">First factor</param>
+        /// <param name="B">Second factor</param>
+        /// <returns>result</returns>
+        public static  fcomplex operator *( fcomplex A,  Int64 B) {
+            fcomplex ret;
+            ret.real =  (float) (A.real * B);
+            ret.imag =  (float) (A.imag * B);
+            return ret;
+        }
+        /// <summary>
+        /// Divide two numbers
+        /// </summary>
+        /// <param name="A">Divident</param>
+        /// <param name="B">Divisor</param>
+        /// <returns>result</returns>
+        public static  fcomplex operator /( fcomplex A,  Int64 B) {
+            if (IsNaN(A)) return NaN;
+            
+            if (A.real == 0 && A.imag == 0) {
+                if (B == 0) return NaN; 
+                return ( fcomplex )0;
+            } else {
+                if (false)
+                {
+                    if (IsInfinity(A)) {
+                        return NaN; 
+                    } else {
+                        return ( fcomplex )0;
+                    }
+                }
+            }
+            fcomplex ret;
+            if (B == 0) return INF ;
+            ret.real =  (float) (A.real / B);
+            ret.imag =  (float) (A.imag / B);
+            return ret;
+        }
+        /// <summary>
+        /// Equality comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>result</returns>
+        /// <remarks>Real inputs are converted to a complex number and the result is compared to the complex input.</remarks>
+        public static bool operator ==( fcomplex A,  Int64 B) {
+            return (A.real == B && A.imag == 0.0);
+        }
+        /// <summary>
+        /// Unequality comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real and imaginary parts of A and B are not equal, false otherwise</returns>
+        /// <remarks>Real inputs are converted to a complex number and the result is compared to the complex input.</remarks>
+        public static bool operator !=( fcomplex A,  Int64 B) {
+            return (A.imag != 0.0) || (A.real != B);
+        }
+        /// <summary>
+        /// Freater than comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is greater than real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator > ( fcomplex A,  Int64 B) {
+            return (A.real > B);
+        }
+        /// <summary>
+        /// Lower than comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is lower then real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator <(  fcomplex A,  Int64 B) {
+            return (A.real < B);
+        }
+        /// <summary>
+        /// Greater than or equal to comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is greater than real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator >=( fcomplex A,  Int64 B) {
+            return (A.real >= B);
+        }
+        /// <summary>
+        /// Lower than or equal to comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is lower then real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator <=( fcomplex A,  Int64 B) {
+            return (A.real <= B);
+        }
+       
+        /// <summary>
+        /// Add two complex numbers
+        /// </summary>
+        /// <param name="A">First summand</param>
+        /// <param name="B">Second summand</param>
+        /// <returns>Result</returns>
+        public static  fcomplex operator +( fcomplex A,  Int32 B) {
+            fcomplex ret;
+            ret.real =  (float) (A.real + B);
+            ret.imag =  (float) A.imag;
+            return ret;
+        }
+        /// <summary>
+        /// Subtract two values
+        /// </summary>
+        /// <param name="A">Minuend</param>
+        /// <param name="B">Subtrahend</param>
+        /// <returns>result</returns>
+        public static  fcomplex operator -( fcomplex A,  Int32 B) {
+            fcomplex ret;
+            ret.real =  (float) (A.real - B);
+            ret.imag =  (float) A.imag;
+            return ret;
+        }
+        /// <summary>
+        /// Multiply two values
+        /// </summary>
+        /// <param name="A">First factor</param>
+        /// <param name="B">Second factor</param>
+        /// <returns>result</returns>
+        public static  fcomplex operator *( fcomplex A,  Int32 B) {
+            fcomplex ret;
+            ret.real =  (float) (A.real * B);
+            ret.imag =  (float) (A.imag * B);
+            return ret;
+        }
+        /// <summary>
+        /// Divide two numbers
+        /// </summary>
+        /// <param name="A">Divident</param>
+        /// <param name="B">Divisor</param>
+        /// <returns>result</returns>
+        public static  fcomplex operator /( fcomplex A,  Int32 B) {
+            if (IsNaN(A)) return NaN;
+            
+            if (A.real == 0 && A.imag == 0) {
+                if (B == 0) return NaN; 
+                return ( fcomplex )0;
+            } else {
+                if (false)
+                {
+                    if (IsInfinity(A)) {
+                        return NaN; 
+                    } else {
+                        return ( fcomplex )0;
+                    }
+                }
+            }
+            fcomplex ret;
+            if (B == 0) return INF ;
+            ret.real =  (float) (A.real / B);
+            ret.imag =  (float) (A.imag / B);
+            return ret;
+        }
+        /// <summary>
+        /// Equality comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>result</returns>
+        /// <remarks>Real inputs are converted to a complex number and the result is compared to the complex input.</remarks>
+        public static bool operator ==( fcomplex A,  Int32 B) {
+            return (A.real == B && A.imag == 0.0);
+        }
+        /// <summary>
+        /// Unequality comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real and imaginary parts of A and B are not equal, false otherwise</returns>
+        /// <remarks>Real inputs are converted to a complex number and the result is compared to the complex input.</remarks>
+        public static bool operator !=( fcomplex A,  Int32 B) {
+            return (A.imag != 0.0) || (A.real != B);
+        }
+        /// <summary>
+        /// Freater than comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is greater than real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator > ( fcomplex A,  Int32 B) {
+            return (A.real > B);
+        }
+        /// <summary>
+        /// Lower than comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is lower then real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator <(  fcomplex A,  Int32 B) {
+            return (A.real < B);
+        }
+        /// <summary>
+        /// Greater than or equal to comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is greater than real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator >=( fcomplex A,  Int32 B) {
+            return (A.real >= B);
+        }
+        /// <summary>
+        /// Lower than or equal to comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is lower then real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator <=( fcomplex A,  Int32 B) {
+            return (A.real <= B);
+        }
+       
+        /// <summary>
+        /// Add two complex numbers
+        /// </summary>
+        /// <param name="A">First summand</param>
+        /// <param name="B">Second summand</param>
+        /// <returns>Result</returns>
+        public static  fcomplex operator +( fcomplex A,  float B) {
+            fcomplex ret;
+            ret.real =  (float) (A.real + B);
+            ret.imag =  (float) A.imag;
+            return ret;
+        }
+        /// <summary>
+        /// Subtract two values
+        /// </summary>
+        /// <param name="A">Minuend</param>
+        /// <param name="B">Subtrahend</param>
+        /// <returns>result</returns>
+        public static  fcomplex operator -( fcomplex A,  float B) {
+            fcomplex ret;
+            ret.real =  (float) (A.real - B);
+            ret.imag =  (float) A.imag;
+            return ret;
+        }
+        /// <summary>
+        /// Multiply two values
+        /// </summary>
+        /// <param name="A">First factor</param>
+        /// <param name="B">Second factor</param>
+        /// <returns>result</returns>
+        public static  fcomplex operator *( fcomplex A,  float B) {
+            fcomplex ret;
+            ret.real =  (float) (A.real * B);
+            ret.imag =  (float) (A.imag * B);
+            return ret;
+        }
+        /// <summary>
+        /// Divide two numbers
+        /// </summary>
+        /// <param name="A">Divident</param>
+        /// <param name="B">Divisor</param>
+        /// <returns>result</returns>
+        public static  fcomplex operator /( fcomplex A,  float B) {
+            if (IsNaN(A)) return NaN;
+            if (float.IsNaN(B)) return NaN;
+            if (A.real == 0 && A.imag == 0) {
+                if (B == 0) return NaN; 
+                return ( fcomplex )0;
+            } else {
+                if (float.IsInfinity(B))
+                {
+                    if (IsInfinity(A)) {
+                        return NaN; 
+                    } else {
+                        return ( fcomplex )0;
+                    }
+                }
+            }
+            fcomplex ret;
+            if (B == 0) return INF ;
+            ret.real =  (float) (A.real / B);
+            ret.imag =  (float) (A.imag / B);
+            return ret;
+        }
+        /// <summary>
+        /// Equality comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>result</returns>
+        /// <remarks>Real inputs are converted to a complex number and the result is compared to the complex input.</remarks>
+        public static bool operator ==( fcomplex A,  float B) {
+            return (A.real == B && A.imag == 0.0);
+        }
+        /// <summary>
+        /// Unequality comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real and imaginary parts of A and B are not equal, false otherwise</returns>
+        /// <remarks>Real inputs are converted to a complex number and the result is compared to the complex input.</remarks>
+        public static bool operator !=( fcomplex A,  float B) {
+            return (A.imag != 0.0) || (A.real != B);
+        }
+        /// <summary>
+        /// Freater than comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is greater than real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator > ( fcomplex A,  float B) {
+            return (A.real > B);
+        }
+        /// <summary>
+        /// Lower than comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is lower then real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator <(  fcomplex A,  float B) {
+            return (A.real < B);
+        }
+        /// <summary>
+        /// Greater than or equal to comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is greater than real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator >=( fcomplex A,  float B) {
+            return (A.real >= B);
+        }
+        /// <summary>
+        /// Lower than or equal to comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is lower then real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator <=( fcomplex A,  float B) {
+            return (A.real <= B);
+        }
+       
+        /// <summary>
+        /// Add two complex numbers
+        /// </summary>
+        /// <param name="A">First summand</param>
+        /// <param name="B">Second summand</param>
+        /// <returns>Result</returns>
+        public static  fcomplex operator +( fcomplex A,  byte B) {
+            fcomplex ret;
+            ret.real =  (float) (A.real + B);
+            ret.imag =  (float) A.imag;
+            return ret;
+        }
+        /// <summary>
+        /// Subtract two values
+        /// </summary>
+        /// <param name="A">Minuend</param>
+        /// <param name="B">Subtrahend</param>
+        /// <returns>result</returns>
+        public static  fcomplex operator -( fcomplex A,  byte B) {
+            fcomplex ret;
+            ret.real =  (float) (A.real - B);
+            ret.imag =  (float) A.imag;
+            return ret;
+        }
+        /// <summary>
+        /// Multiply two values
+        /// </summary>
+        /// <param name="A">First factor</param>
+        /// <param name="B">Second factor</param>
+        /// <returns>result</returns>
+        public static  fcomplex operator *( fcomplex A,  byte B) {
+            fcomplex ret;
+            ret.real =  (float) (A.real * B);
+            ret.imag =  (float) (A.imag * B);
+            return ret;
+        }
+        /// <summary>
+        /// Divide two numbers
+        /// </summary>
+        /// <param name="A">Divident</param>
+        /// <param name="B">Divisor</param>
+        /// <returns>result</returns>
+        public static  fcomplex operator /( fcomplex A,  byte B) {
+            if (IsNaN(A)) return NaN;
+            
+            if (A.real == 0 && A.imag == 0) {
+                if (B == 0) return NaN; 
+                return ( fcomplex )0;
+            } else {
+                if (false)
+                {
+                    if (IsInfinity(A)) {
+                        return NaN; 
+                    } else {
+                        return ( fcomplex )0;
+                    }
+                }
+            }
+            fcomplex ret;
+            if (B == 0) return INF ;
+            ret.real =  (float) (A.real / B);
+            ret.imag =  (float) (A.imag / B);
+            return ret;
+        }
+        /// <summary>
+        /// Equality comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>result</returns>
+        /// <remarks>Real inputs are converted to a complex number and the result is compared to the complex input.</remarks>
+        public static bool operator ==( fcomplex A,  byte B) {
+            return (A.real == B && A.imag == 0.0);
+        }
+        /// <summary>
+        /// Unequality comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real and imaginary parts of A and B are not equal, false otherwise</returns>
+        /// <remarks>Real inputs are converted to a complex number and the result is compared to the complex input.</remarks>
+        public static bool operator !=( fcomplex A,  byte B) {
+            return (A.imag != 0.0) || (A.real != B);
+        }
+        /// <summary>
+        /// Freater than comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is greater than real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator > ( fcomplex A,  byte B) {
+            return (A.real > B);
+        }
+        /// <summary>
+        /// Lower than comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is lower then real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator <(  fcomplex A,  byte B) {
+            return (A.real < B);
+        }
+        /// <summary>
+        /// Greater than or equal to comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is greater than real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator >=( fcomplex A,  byte B) {
+            return (A.real >= B);
+        }
+        /// <summary>
+        /// Lower than or equal to comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is lower then real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator <=( fcomplex A,  byte B) {
+            return (A.real <= B);
+        }
+       
+        /// <summary>
+        /// Add two complex numbers
+        /// </summary>
+        /// <param name="A">First summand</param>
+        /// <param name="B">Second summand</param>
+        /// <returns>Result</returns>
+        public static  fcomplex operator +( fcomplex A,  double B) {
+            fcomplex ret;
+            ret.real =  (float) (A.real + B);
+            ret.imag =  (float) A.imag;
+            return ret;
+        }
+        /// <summary>
+        /// Subtract two values
+        /// </summary>
+        /// <param name="A">Minuend</param>
+        /// <param name="B">Subtrahend</param>
+        /// <returns>result</returns>
+        public static  fcomplex operator -( fcomplex A,  double B) {
+            fcomplex ret;
+            ret.real =  (float) (A.real - B);
+            ret.imag =  (float) A.imag;
+            return ret;
+        }
+        /// <summary>
+        /// Multiply two values
+        /// </summary>
+        /// <param name="A">First factor</param>
+        /// <param name="B">Second factor</param>
+        /// <returns>result</returns>
+        public static  fcomplex operator *( fcomplex A,  double B) {
+            fcomplex ret;
+            ret.real =  (float) (A.real * B);
+            ret.imag =  (float) (A.imag * B);
+            return ret;
+        }
+        /// <summary>
+        /// Divide two numbers
+        /// </summary>
+        /// <param name="A">Divident</param>
+        /// <param name="B">Divisor</param>
+        /// <returns>result</returns>
+        public static  fcomplex operator /( fcomplex A,  double B) {
+            if (IsNaN(A)) return NaN;
+            if (double.IsNaN(B)) return NaN;
+            if (A.real == 0 && A.imag == 0) {
+                if (B == 0) return NaN; 
+                return ( fcomplex )0;
+            } else {
+                if (double.IsInfinity(B))
+                {
+                    if (IsInfinity(A)) {
+                        return NaN; 
+                    } else {
+                        return ( fcomplex )0;
+                    }
+                }
+            }
+            fcomplex ret;
+            if (B == 0) return INF ;
+            ret.real =  (float) (A.real / B);
+            ret.imag =  (float) (A.imag / B);
+            return ret;
+        }
+        /// <summary>
+        /// Equality comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>result</returns>
+        /// <remarks>Real inputs are converted to a complex number and the result is compared to the complex input.</remarks>
+        public static bool operator ==( fcomplex A,  double B) {
+            return (A.real == B && A.imag == 0.0);
+        }
+        /// <summary>
+        /// Unequality comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real and imaginary parts of A and B are not equal, false otherwise</returns>
+        /// <remarks>Real inputs are converted to a complex number and the result is compared to the complex input.</remarks>
+        public static bool operator !=( fcomplex A,  double B) {
+            return (A.imag != 0.0) || (A.real != B);
+        }
+        /// <summary>
+        /// Freater than comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is greater than real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator > ( fcomplex A,  double B) {
+            return (A.real > B);
+        }
+        /// <summary>
+        /// Lower than comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is lower then real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator <(  fcomplex A,  double B) {
+            return (A.real < B);
+        }
+        /// <summary>
+        /// Greater than or equal to comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is greater than real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator >=( fcomplex A,  double B) {
+            return (A.real >= B);
+        }
+        /// <summary>
+        /// Lower than or equal to comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is lower then real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator <=( fcomplex A,  double B) {
+            return (A.real <= B);
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+
+        
+
+#region HYCALPER AUTO GENERATED CODE
+
+       
+        /// <summary>
+        /// Add two complex values
+        /// </summary>
+        /// <param name="A">First summand</param>
+        /// <param name="B">Second summand</param>
+        /// <returns>Result</returns>
+        public static  fcomplex operator +( Int64 A,  fcomplex B) {
+            fcomplex ret; 
+            ret.real =  (float) (A + B.real);
+            ret.imag =  (float) B.imag;
+            return ret;
+        }
+        /// <summary>
+        /// Subtract two values
+        /// </summary>
+        /// <param name="A">Minuend</param>
+        /// <param name="B">Subtrahend</param>
+        /// <returns>Result</returns>
+        public static  fcomplex operator -( Int64 A,  fcomplex B) {
+            fcomplex ret;
+            ret.real =  (float) (A - B.real);
+            ret.imag = - (float) B.imag; 
+            return ret;
+        }
+        /// <summary>
+        /// Multiply two values
+        /// </summary>
+        /// <param name="A">First factor</param>
+        /// <param name="B">Second factor</param>
+        /// <returns>Result</returns>
+        public static  fcomplex operator *( Int64 A,  fcomplex B) {
+            fcomplex ret;
+            ret.real =  (float) (A * B.real);
+            ret.imag =  (float) (A * B.imag);
+            return ret;
+        }
+        /// <summary>
+        /// Divide two values
+        /// </summary>
+        /// <param name="A">Divident</param>
+        /// <param name="B">Divisor</param>
+        /// <returns>Result</returns>
+        public static  fcomplex operator /( Int64 A,  fcomplex B) {
+            fcomplex ret; 
+            if (A == 0) {
+                if (IsInfinity(B)) return NaN; 
+            } else {
+                if (IsInfinity(B)) return ( fcomplex )0; 
+            }
+            if (B.real == 0 && B.imag == 0) {
+                return INF;
+            }
+            // this algorithm is taken from [1]. The one described in [2] was not taken. Tests 
+            // did not show any advantage when using double precision floating point arithmetic.
+            double tmp; 
+            if (Math.Abs(B.real) >= Math.Abs(B.imag)) {
+                tmp =  (float) (B.imag * (1/B.real)); 
+                ret.imag =  (float) (B.real + B.imag*tmp); 
+                ret.real =  (float) A/ret.imag; 
+                ret.imag = -  (float) (A*tmp)/ret.imag; 
+            } else {
+                tmp =  (float) (B.real * (1/B.imag));
+                ret.imag =  (float) (B.imag + B.real*tmp); 
+                ret.real =  (float) (A*tmp)/ret.imag; 
+                ret.imag = -  (float) A/ret.imag; 
+            }
+            return ret;
+        }
+        /// <summary>
+        /// Equality comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>Result</returns>
+        /// <remarks>Real inputs are converted to a complex number and the result is compared to the complex input.</remarks>
+        public static bool operator ==( Int64 A,  fcomplex B) {
+            return (B.real == A && B.imag == 0.0);
+        }
+        /// <summary>
+        /// Unequality comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real and imaginary parts of A and B are not equal, false otherwise</returns>
+        /// <remarks>Real inputs are converted to a complex number and the result is compared to the complex input.</remarks>
+        public static bool operator !=( Int64 A,  fcomplex B) {
+            return (B.imag != 0.0) || (B.real != A);
+        }
+        /// <summary>
+        /// Greater than comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is greater than real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator > ( Int64 A,  fcomplex B) {
+            return (A > B.real);
+        }
+        /// <summary>
+        /// Lower than comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is lower then real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator < ( Int64 A,  fcomplex B) {
+            return (A < B.real);
+        }
+        /// <summary>
+        /// Greater than or equal to comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is greater than real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator >=( Int64 A,  fcomplex B) {
+            return (A >= B.real);
+        }
+        /// <summary>
+        /// Lower than or equal to comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is lower then real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator <=( Int64 A,  fcomplex B) {
+            return (A <= B.real);
+        }
+       
+        /// <summary>
+        /// Add two complex values
+        /// </summary>
+        /// <param name="A">First summand</param>
+        /// <param name="B">Second summand</param>
+        /// <returns>Result</returns>
+        public static  fcomplex operator +( Int32 A,  fcomplex B) {
+            fcomplex ret; 
+            ret.real =  (float) (A + B.real);
+            ret.imag =  (float) B.imag;
+            return ret;
+        }
+        /// <summary>
+        /// Subtract two values
+        /// </summary>
+        /// <param name="A">Minuend</param>
+        /// <param name="B">Subtrahend</param>
+        /// <returns>Result</returns>
+        public static  fcomplex operator -( Int32 A,  fcomplex B) {
+            fcomplex ret;
+            ret.real =  (float) (A - B.real);
+            ret.imag = - (float) B.imag; 
+            return ret;
+        }
+        /// <summary>
+        /// Multiply two values
+        /// </summary>
+        /// <param name="A">First factor</param>
+        /// <param name="B">Second factor</param>
+        /// <returns>Result</returns>
+        public static  fcomplex operator *( Int32 A,  fcomplex B) {
+            fcomplex ret;
+            ret.real =  (float) (A * B.real);
+            ret.imag =  (float) (A * B.imag);
+            return ret;
+        }
+        /// <summary>
+        /// Divide two values
+        /// </summary>
+        /// <param name="A">Divident</param>
+        /// <param name="B">Divisor</param>
+        /// <returns>Result</returns>
+        public static  fcomplex operator /( Int32 A,  fcomplex B) {
+            fcomplex ret; 
+            if (A == 0) {
+                if (IsInfinity(B)) return NaN; 
+            } else {
+                if (IsInfinity(B)) return ( fcomplex )0; 
+            }
+            if (B.real == 0 && B.imag == 0) {
+                return INF;
+            }
+            // this algorithm is taken from [1]. The one described in [2] was not taken. Tests 
+            // did not show any advantage when using double precision floating point arithmetic.
+            double tmp; 
+            if (Math.Abs(B.real) >= Math.Abs(B.imag)) {
+                tmp =  (float) (B.imag * (1/B.real)); 
+                ret.imag =  (float) (B.real + B.imag*tmp); 
+                ret.real =  (float) A/ret.imag; 
+                ret.imag = -  (float) (A*tmp)/ret.imag; 
+            } else {
+                tmp =  (float) (B.real * (1/B.imag));
+                ret.imag =  (float) (B.imag + B.real*tmp); 
+                ret.real =  (float) (A*tmp)/ret.imag; 
+                ret.imag = -  (float) A/ret.imag; 
+            }
+            return ret;
+        }
+        /// <summary>
+        /// Equality comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>Result</returns>
+        /// <remarks>Real inputs are converted to a complex number and the result is compared to the complex input.</remarks>
+        public static bool operator ==( Int32 A,  fcomplex B) {
+            return (B.real == A && B.imag == 0.0);
+        }
+        /// <summary>
+        /// Unequality comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real and imaginary parts of A and B are not equal, false otherwise</returns>
+        /// <remarks>Real inputs are converted to a complex number and the result is compared to the complex input.</remarks>
+        public static bool operator !=( Int32 A,  fcomplex B) {
+            return (B.imag != 0.0) || (B.real != A);
+        }
+        /// <summary>
+        /// Greater than comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is greater than real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator > ( Int32 A,  fcomplex B) {
+            return (A > B.real);
+        }
+        /// <summary>
+        /// Lower than comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is lower then real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator < ( Int32 A,  fcomplex B) {
+            return (A < B.real);
+        }
+        /// <summary>
+        /// Greater than or equal to comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is greater than real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator >=( Int32 A,  fcomplex B) {
+            return (A >= B.real);
+        }
+        /// <summary>
+        /// Lower than or equal to comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is lower then real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator <=( Int32 A,  fcomplex B) {
+            return (A <= B.real);
+        }
+       
+        /// <summary>
+        /// Add two complex values
+        /// </summary>
+        /// <param name="A">First summand</param>
+        /// <param name="B">Second summand</param>
+        /// <returns>Result</returns>
+        public static  fcomplex operator +( float A,  fcomplex B) {
+            fcomplex ret; 
+            ret.real =  (float) (A + B.real);
+            ret.imag =  (float) B.imag;
+            return ret;
+        }
+        /// <summary>
+        /// Subtract two values
+        /// </summary>
+        /// <param name="A">Minuend</param>
+        /// <param name="B">Subtrahend</param>
+        /// <returns>Result</returns>
+        public static  fcomplex operator -( float A,  fcomplex B) {
+            fcomplex ret;
+            ret.real =  (float) (A - B.real);
+            ret.imag = - (float) B.imag; 
+            return ret;
+        }
+        /// <summary>
+        /// Multiply two values
+        /// </summary>
+        /// <param name="A">First factor</param>
+        /// <param name="B">Second factor</param>
+        /// <returns>Result</returns>
+        public static  fcomplex operator *( float A,  fcomplex B) {
+            fcomplex ret;
+            ret.real =  (float) (A * B.real);
+            ret.imag =  (float) (A * B.imag);
+            return ret;
+        }
+        /// <summary>
+        /// Divide two values
+        /// </summary>
+        /// <param name="A">Divident</param>
+        /// <param name="B">Divisor</param>
+        /// <returns>Result</returns>
+        public static  fcomplex operator /( float A,  fcomplex B) {
+            fcomplex ret; 
+            if (A == 0) {
+                if (IsInfinity(B)) return NaN; 
+            } else {
+                if (IsInfinity(B)) return ( fcomplex )0; 
+            }
+            if (B.real == 0 && B.imag == 0) {
+                return INF;
+            }
+            // this algorithm is taken from [1]. The one described in [2] was not taken. Tests 
+            // did not show any advantage when using double precision floating point arithmetic.
+            double tmp; 
+            if (Math.Abs(B.real) >= Math.Abs(B.imag)) {
+                tmp =  (float) (B.imag * (1/B.real)); 
+                ret.imag =  (float) (B.real + B.imag*tmp); 
+                ret.real =  (float) A/ret.imag; 
+                ret.imag = -  (float) (A*tmp)/ret.imag; 
+            } else {
+                tmp =  (float) (B.real * (1/B.imag));
+                ret.imag =  (float) (B.imag + B.real*tmp); 
+                ret.real =  (float) (A*tmp)/ret.imag; 
+                ret.imag = -  (float) A/ret.imag; 
+            }
+            return ret;
+        }
+        /// <summary>
+        /// Equality comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>Result</returns>
+        /// <remarks>Real inputs are converted to a complex number and the result is compared to the complex input.</remarks>
+        public static bool operator ==( float A,  fcomplex B) {
+            return (B.real == A && B.imag == 0.0);
+        }
+        /// <summary>
+        /// Unequality comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real and imaginary parts of A and B are not equal, false otherwise</returns>
+        /// <remarks>Real inputs are converted to a complex number and the result is compared to the complex input.</remarks>
+        public static bool operator !=( float A,  fcomplex B) {
+            return (B.imag != 0.0) || (B.real != A);
+        }
+        /// <summary>
+        /// Greater than comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is greater than real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator > ( float A,  fcomplex B) {
+            return (A > B.real);
+        }
+        /// <summary>
+        /// Lower than comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is lower then real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator < ( float A,  fcomplex B) {
+            return (A < B.real);
+        }
+        /// <summary>
+        /// Greater than or equal to comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is greater than real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator >=( float A,  fcomplex B) {
+            return (A >= B.real);
+        }
+        /// <summary>
+        /// Lower than or equal to comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is lower then real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator <=( float A,  fcomplex B) {
+            return (A <= B.real);
+        }
+       
+        /// <summary>
+        /// Add two complex values
+        /// </summary>
+        /// <param name="A">First summand</param>
+        /// <param name="B">Second summand</param>
+        /// <returns>Result</returns>
+        public static  fcomplex operator +( byte A,  fcomplex B) {
+            fcomplex ret; 
+            ret.real =  (float) (A + B.real);
+            ret.imag =  (float) B.imag;
+            return ret;
+        }
+        /// <summary>
+        /// Subtract two values
+        /// </summary>
+        /// <param name="A">Minuend</param>
+        /// <param name="B">Subtrahend</param>
+        /// <returns>Result</returns>
+        public static  fcomplex operator -( byte A,  fcomplex B) {
+            fcomplex ret;
+            ret.real =  (float) (A - B.real);
+            ret.imag = - (float) B.imag; 
+            return ret;
+        }
+        /// <summary>
+        /// Multiply two values
+        /// </summary>
+        /// <param name="A">First factor</param>
+        /// <param name="B">Second factor</param>
+        /// <returns>Result</returns>
+        public static  fcomplex operator *( byte A,  fcomplex B) {
+            fcomplex ret;
+            ret.real =  (float) (A * B.real);
+            ret.imag =  (float) (A * B.imag);
+            return ret;
+        }
+        /// <summary>
+        /// Divide two values
+        /// </summary>
+        /// <param name="A">Divident</param>
+        /// <param name="B">Divisor</param>
+        /// <returns>Result</returns>
+        public static  fcomplex operator /( byte A,  fcomplex B) {
+            fcomplex ret; 
+            if (A == 0) {
+                if (IsInfinity(B)) return NaN; 
+            } else {
+                if (IsInfinity(B)) return ( fcomplex )0; 
+            }
+            if (B.real == 0 && B.imag == 0) {
+                return INF;
+            }
+            // this algorithm is taken from [1]. The one described in [2] was not taken. Tests 
+            // did not show any advantage when using double precision floating point arithmetic.
+            double tmp; 
+            if (Math.Abs(B.real) >= Math.Abs(B.imag)) {
+                tmp =  (float) (B.imag * (1/B.real)); 
+                ret.imag =  (float) (B.real + B.imag*tmp); 
+                ret.real =  (float) A/ret.imag; 
+                ret.imag = -  (float) (A*tmp)/ret.imag; 
+            } else {
+                tmp =  (float) (B.real * (1/B.imag));
+                ret.imag =  (float) (B.imag + B.real*tmp); 
+                ret.real =  (float) (A*tmp)/ret.imag; 
+                ret.imag = -  (float) A/ret.imag; 
+            }
+            return ret;
+        }
+        /// <summary>
+        /// Equality comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>Result</returns>
+        /// <remarks>Real inputs are converted to a complex number and the result is compared to the complex input.</remarks>
+        public static bool operator ==( byte A,  fcomplex B) {
+            return (B.real == A && B.imag == 0.0);
+        }
+        /// <summary>
+        /// Unequality comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real and imaginary parts of A and B are not equal, false otherwise</returns>
+        /// <remarks>Real inputs are converted to a complex number and the result is compared to the complex input.</remarks>
+        public static bool operator !=( byte A,  fcomplex B) {
+            return (B.imag != 0.0) || (B.real != A);
+        }
+        /// <summary>
+        /// Greater than comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is greater than real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator > ( byte A,  fcomplex B) {
+            return (A > B.real);
+        }
+        /// <summary>
+        /// Lower than comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is lower then real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator < ( byte A,  fcomplex B) {
+            return (A < B.real);
+        }
+        /// <summary>
+        /// Greater than or equal to comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is greater than real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator >=( byte A,  fcomplex B) {
+            return (A >= B.real);
+        }
+        /// <summary>
+        /// Lower than or equal to comparison for complex numbers
+        /// </summary>
+        /// <param name="A">Left side</param>
+        /// <param name="B">Right side</param>
+        /// <returns>true if real part of A is lower then real part of B, false otherwise</returns>
+        /// <remarks>Only the real parts are compared!</remarks>
+        public static bool operator <=( byte A,  fcomplex B) {
+            return (A <= B.real);
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+        #region unary minus
+        /// <summary>
+        /// Unary minus operator
+        /// </summary>
+        /// <param name="in1">fcomplex input</param>
+        /// <returns>fcomplex number similar to in1, having real and imag part negated</returns>
+        public static fcomplex operator -( fcomplex in1) {
+            fcomplex ret = new fcomplex(); 
+            ret.imag = -in1.imag; 
+            ret.real = -in1.real; 
+            return ret;
+        }
+        #endregion
+
+        /// <summary>
+        /// Magnitude value of float complex number
+        /// </summary>
+        /// <param name="input">fcomplex number</param>
+        /// <returns>Magnitude of input</returns>
+        public static float Abs(fcomplex input) {
+            return (float) Math.Sqrt ( input.real * input.real + input.imag * input.imag );
+        }
+        /// <summary>
+        /// Angle of complex number
+        /// </summary>
+        /// <param name="input">fcomplex number to compute angle of</param>
+        /// <returns>Angle of input</returns>
+        public static double Angle(fcomplex input) {
+            return (float) Math.Atan2 ( input.imag, input.real );
+        }
+        /// <summary>
+        /// Arcus cosinus for float complex number
+        /// </summary>
+        /// <param name="input">fcomplex input</param>
+        /// <returns>Arcus cosinus of input</returns>
+        /// <remarks>The arcus cosinus of a complex number is computed by
+        /// <para>Log(Sqrt(input^2 - 1) + input) * i </para></remarks>
+        public static fcomplex Acos(fcomplex input) {
+            fcomplex ret = new fcomplex ( 0, -1 );
+            return fcomplex.Log ( fcomplex.Sqrt ( input * input - 1 )
+                + input ) * ret;
+        }
+        /// <summary>
+        /// Arcus cosinus of real number
+        /// </summary>
+        /// <param name="input">float input</param>
+        /// <returns>Arcus cosinus of input</returns>
+        /// <remarks>For input > 1.0, <see cref="ILNumerics.fcomplex.Acos(fcomplex)"/> will be used. </remarks>
+        public static fcomplex Acos(float input) {
+            if (Math.Abs(input) <= 1.0)
+                return new fcomplex((float)Math.Acos(input), 0.0f);
+            else {
+                return Acos((fcomplex)input);
+            }
+        }
+        /// <summary>
+        /// Arcus sinus of real number
+        /// </summary>
+        /// <param name="input">float input</param>
+        /// <returns>Arcus sinus of input</returns>
+        /// <remarks>For input > 1.0, <see cref="ILNumerics.fcomplex.Asin(fcomplex)"/> will be used. </remarks>
+        public static fcomplex Asin(float input) {
+            if (Math.Abs(input) <= 1.0)
+                return new fcomplex((float)Math.Asin(input), 0.0f);
+            else {
+                return Asin((fcomplex)input);
+            }
+        }
+        /// <summary>
+        /// Arcus sinus for complex number
+        /// </summary>
+        /// <param name="input">fcomplex input</param>
+        /// <returns>Arcus sinus of input</returns>
+        public static fcomplex Asin(fcomplex input) {
+            fcomplex ret = Acos ( input );
+            ret.real = (float) (Math.PI / 2 - ret.real);
+            return ret; 
+        }
+        /// <summary>
+        /// Power of base e for float complex number
+        /// </summary>
+        /// <param name="input">fcomplex input</param>
+        /// <returns>Result of Exp(input)</returns>
+        public static fcomplex Exp(fcomplex input) {
+            return fcomplex.FromPol ( (float) Math.Exp ( input.real ), input.imag );
+        }
+        /// <summary>
+        /// fcomplex power real exponent
+        /// </summary>
+        /// <param name="input">Basis </param>
+        /// <param name="exponent">Exponent</param>
+        /// <returns>New fcomplex number with result</returns>
+        public static fcomplex Pow(fcomplex input, double exponent) {
+            fcomplex ret = input.Log ();
+            ret.imag *= (float) exponent;
+            ret.real *= (float) exponent;
+            return ret.Exp ();
+        }
+        /// <summary>
+        /// Complex power - real basis, real exponent
+        /// </summary>
+        /// <param name="basis">Basis</param>
+        /// <param name="exponent">Exponent</param>
+        /// <returns>fcomplex number.</returns>
+        /// <remarks>The result will be a fcomplex number. For negative basis 
+        /// the basis will be converted to a fcomplex number and the power 
+        /// will be computed in the fcomplex plane.</remarks>
+        public static fcomplex Pow(double basis, double exponent) {
+            if (basis < 0) {
+                return Pow((fcomplex)basis, exponent);
+            } else {
+                return (fcomplex)Math.Pow(basis, exponent);
+            }
+        }
+        /// <summary>
+        /// Power: complex base, complex exponent
+        /// </summary>
+        /// <param name="basis">Basis</param>
+        /// <param name="exponent">Exponent</param>
+        /// <returns>result of basis^exponent</returns>
+        public static fcomplex Pow(fcomplex basis, fcomplex exponent) {
+            fcomplex ret = ( basis.Log () * exponent );
+            return ret.Exp ();
+        }
+        /// <summary>
+        /// Square root of real input
+        /// </summary>
+        /// <param name="input">float input</param>
+        /// <returns>Square root of input</returns>
+        public static fcomplex Sqrt(float input) {
+            if (input > 0)
+                return new fcomplex((float)Math.Sqrt(input), 0.0f);
+            else
+                return Sqrt((fcomplex)input); 
+        }
+        /// <summary>
+        /// Square root of complex number
+        /// </summary>
+        /// <param name="input">fcomplex input</param>
+        /// <returns>Square root of input</returns>
+        public static fcomplex Sqrt(fcomplex input) {
+            // Reference : numerical recipes in C: Appendix C
+            fcomplex ret = new fcomplex ();
+            double x, y, w, r;
+            if (input.real == 0.0 && input.imag == 0.0)
+                return ret;
+            else {
+                x = (float) Math.Abs ( input.real );
+                y = (float) Math.Abs ( input.imag );
+                if (x >= y) {
+                    r = y / x;
+                    w = Math.Sqrt ( x ) * Math.Sqrt ( 0.5 * ( 1.0 + Math.Sqrt ( 1.0 + r * r ) ) );
+                } else {
+                    r = x / y;
+                    w = Math.Sqrt ( y ) * Math.Sqrt ( 0.5 * ( r + Math.Sqrt ( 1.0 + r * r ) ) );
+                }
+                if (input.real >= 0.0) {
+                    ret.real = (float) w;
+                    ret.imag = (float) (input.imag / ( 2.0 * w ));
+                } else {
+                    ret.imag = (float) (( input.imag >= 0 ) ? w : -w);
+                    ret.real = (float) (input.imag / ( 2.0 * ret.imag ));
+                }
+                return ret;
+            }
+        }
+        /// <summary>
+        /// Tangens of float complex number
+        /// </summary>
+        /// <param name="input">fcomplex input</param>
+        /// <returns>Tangens of input</returns>
+        public static fcomplex Tan(fcomplex input) {
+            fcomplex ci = Cos(input);
+            if (ci.real == (float)0.0 && ci.imag == (float)0.0)
+                return INF;
+            return (Sin(input) / ci);
+        }
+        /// <summary>
+        /// Tangens hyperbolicus of float complex input
+        /// </summary>
+        /// <param name="input">fcomplex input</param>
+        /// <returns>Tangens hyperbolicus</returns>
+        public static fcomplex Tanh(fcomplex input) {
+            fcomplex si = Sin(input);
+            if (si.real == (float)0.0 && si.imag == (float)0.0)
+                return INF;
+            return (Cos(input) / si);
+        }
+        /// <summary>
+        /// Logarithm of complex input
+        /// </summary>
+        /// <param name="input">fcomplex input</param>
+        /// <returns>Logarithm of input</returns>
+        public static fcomplex Log(fcomplex input) {
+            fcomplex ret = new fcomplex ();
+            ret.real = (float) Math.Log ( Math.Sqrt ( input.real * input.real + input.imag * input.imag ) );
+            ret.imag = (float) Math.Atan2 ( input.imag, input.real );
+            return ret;
+        }
+        /// <summary>
+        /// Logarithm to base 10
+        /// </summary>
+        /// <param name="input">fcomplex input</param>
+        /// <returns>Logarithm of input</returns>
+        public static fcomplex Log10(fcomplex input) {
+            return Log(input) / 2.30258509299405f;
+        }
+        /// <summary>
+        /// Logarithm of base 2
+        /// </summary>
+        /// <param name="input">fcomplex input</param>
+        /// <returns>Logarithm of input</returns>
+        public static fcomplex Log2(fcomplex input) {
+            return Log(input) / 0.693147180559945f;
+        }
+        /// <summary>
+        /// Logarithm of real input 
+        /// </summary>
+        /// <param name="input">float input - may be negative</param>
+        /// <returns>Complex logarithm</returns>
+        public static fcomplex Log(float input) {
+            return Log (new fcomplex(input,0.0f)); 
+        }
+        /// <summary>
+        /// Logarithm of base 10 of real input 
+        /// </summary>
+        /// <param name="input">float input - may be negative</param>
+        /// <returns>Complex logarithm of base 10</returns>
+        public static fcomplex Log10(float input) {
+            return Log(new fcomplex(input,0.0f)) / 2.30258509299405f;
+        }
+        /// <summary>
+        /// Logarithm of base 2
+        /// </summary>
+        /// <param name="input">float input - may be negative</param>
+        /// <returns>Complex logarithm of base 2</returns>
+        public static fcomplex Log2(float input) {
+            return Log(new fcomplex(input,0.0f)) / 0.693147180559945f;
+        }
+        /// <summary>
+        /// Convert from polar to cartesian form
+        /// </summary>
+        /// <param name="magnitude">Magnitude</param>
+        /// <param name="angle">Angle</param>
+        /// <returns>fcomplex number with magnitude <c>magnitude</c> 
+        /// and phase <c>angle</c></returns>
+        public static fcomplex FromPol(float magnitude, float angle) {
+            return new fcomplex (
+                (magnitude * (float)Math.Cos ( angle )),
+                (magnitude * (float)Math.Sin ( angle ))
+            );
+        }
+        /// <summary>
+        /// Convert this float complex number to string 
+        /// </summary>
+        /// <returns>String representation of this float complex number</returns>
+        public override String ToString() {
+            if (imag>=0)
+                return String.Format("{0} + {1}i",real,imag);
+            else 
+                return String.Format("{0} {1}i",real,imag);
+        }
+        private static string m_precSpecI = ""; 
+        private static string m_precSpecR = ""; 
+        private static int m_lastDigits = 0; 
+        /// <summary>
+        /// Print formated output of this number, determine number of digits
+        /// </summary>
+        /// <param name="digits">Number of digits</param>
+        /// <returns>Formatted output</returns>
+        public string ToString(int digits) {
+            if (digits < 1) return ""; 
+            if (digits != m_lastDigits) {
+                m_lastDigits = digits; 
+                m_precSpecR = String.Format("{{0:f{0}}}",digits);
+                m_precSpecI = String.Format("{{1:f{0}}}i",digits);
+            }
+            if (imag >= 0) {
+                return String.Format(m_precSpecR+"+"+m_precSpecI,real,imag); 
+            } else {
+                return String.Format(m_precSpecR+m_precSpecI,real,imag); 
+            }
+        }
+        /// <summary>
+        /// Magnitude of this float complex number
+        /// </summary>
+        /// <returns>Magnitude</returns>
+        public float Abs() {
+            return (float)Math.Sqrt(real * real + imag * imag);
+        }
+        /// <summary>
+        /// Phase angle of this float complex number
+        /// </summary>
+        /// <returns>Phase angle </returns>
+        public double Angle() {
+            return (float)Math.Atan2(imag, real);
+        }
+        /// <summary>
+        /// Arcus cosinus of this float complex number
+        /// </summary>
+        /// <returns>Arcus cosinus</returns>
+        public fcomplex Acos() {
+            fcomplex ret = new fcomplex(0, -1);
+            return fcomplex.Log(fcomplex.Sqrt(this * this - 1)
+                + this) * ret;
+        }
+        /// <summary>
+        /// Arcus sinus of this float complex number
+        /// </summary>
+        /// <returns>Arcus sinus</returns>
+        public fcomplex Asin() {
+            fcomplex ret = Acos(this);
+            ret.real = (float)(Math.PI / 2 - ret.real);
+            return ret;
+        }
+        /// <summary>
+        /// Arcus tangens of float complex number
+        /// </summary>
+        /// <param name="input">fcomplex input</param>
+        /// <returns>Arcus tangens of input</returns>
+        public static fcomplex Atan(fcomplex input) {
+            fcomplex ret = new fcomplex(0, (float)0.5);
+            return (ret * Log((fcomplex.i + input) / (fcomplex.i - input)));
+        }
+        /// <summary>
+        /// Round towards next greater integer
+        /// </summary>
+        /// <param name="input">fcomplex input</param>
+        /// <returns>Rounded float complex number</returns>
+        /// <remarks>Real and imaginary parts are independently rounded 
+        /// towards the next integer value towards positive infinity.</remarks>
+        public static fcomplex Ceiling (fcomplex input){
+            return new fcomplex(
+                    (float)Math.Ceiling(input.real),
+                    (float)Math.Ceiling(input.imag)
+            );
+        }
+        /// <summary>
+        /// Round towards next lower integer
+        /// </summary>
+        /// <param name="input">fcomplex input</param>
+        /// <returns>Rounded float complex number</returns>
+        /// <remarks>Real and imaginary parts are independently rounded 
+        /// towards the next integer value towards negative infinity.</remarks>
+        public static fcomplex Floor (fcomplex input){
+            return new fcomplex(
+                    (float)Math.Floor(input.real),
+                    (float)Math.Floor(input.imag)
+            );
+        }
+        /// <summary>
+        /// Round mercantilistic
+        /// </summary>
+        /// <param name="input">fcomplex number</param>
+        /// <returns>Rounded number</returns>
+        /// <remarks>Real and imaginaty parts are rounded independently. </remarks>
+        public static fcomplex Round (fcomplex input){
+            return new fcomplex(
+                    (float)Math.Round(input.real),
+                    (float)Math.Round(input.imag)
+            );
+        }
+        /// <summary>
+        /// Signum function
+        /// </summary>
+        /// <param name="input">fcomplex input</param>
+        /// <returns> Signum of input</returns>
+        /// <remarks>
+        /// For numbers a = 0.0 + 0.0i, sign(a)'s real and imag parts are 0.0. 
+        /// For all other numbers sign(a) is the projection onto the unit circle.</remarks>
+        public static fcomplex Sign(fcomplex input){
+            if (input.real == 0.0 && input.imag == 0.0)
+                return new fcomplex(); 
+            else {
+                float mag = (float)Math.Sqrt(input.real * input.real + input.imag * input.imag); 
+                return new fcomplex(
+                    input.real / mag,
+                    input.imag / mag);
+            }
+        }
+        /// <summary>
+        /// Truncate a floating point complex value
+        /// </summary>
+        /// <param name="input">fcomplex input</param>
+        /// <returns>Integer part of input</returns>
+        /// <remarks>Operates on real and imaginary parts seperately.</remarks>
+        public static fcomplex Truncate (fcomplex input){
+            return new fcomplex(
+                    (float)Math.Truncate(input.real),
+                    (float)Math.Truncate(input.imag)
+            );
+        }
+        /// <summary>
+        /// Cosinus
+        /// </summary>
+        /// <param name="input">fcomplex input</param>
+        /// <returns>Cosinus of input</returns>
+        /// <remarks><para>The cosinus is computed by the trigonometric euler equation: </para>
+        /// <para>0.5 * [exp(i input) + exp(-i input)]</para></remarks>
+        public static fcomplex Cos(fcomplex input) {
+            fcomplex i = new fcomplex(0, 1.0f);
+            fcomplex ni = new fcomplex(0, -1.0f);
+            return (Exp(i * input) + Exp(ni * input)) / 2.0f;
+        }
+        /// <summary>
+        /// Cosinus hyperbolicus
+        /// </summary>
+        /// <param name="input">fcomplex input</param>
+        /// <returns>Cosinus hyperbolicus of input</returns>
+        /// <remarks><para>The cosinus is computed by the trigonometric euler equation: </para>
+        /// <para>(Exp(input) + Exp(-1.0 * input)) / 2.0</para></remarks>
+        public static fcomplex Cosh(fcomplex input) {
+            return (Exp(input) + Exp(-1.0f * input)) / 2.0f;
+        }
+        /// <summary>
+        /// Sinus
+        /// </summary>
+        /// <param name="input">fcomplex input</param>
+        /// <returns>Sinus of input</returns>
+        /// <remarks><para>The sinus is computed by the trigonometric euler equation: </para>
+        /// <para>(Exp(i * input) - Exp(-1.0 * i * input)) / (2.0 * i)</para></remarks>
+        public static fcomplex Sin(fcomplex input) {
+            fcomplex i = new fcomplex(0, (float)1.0);
+            fcomplex mi = new fcomplex(0, (float)-1.0);
+            return (Exp(i * input) - Exp(mi * input)) / (2.0 * i);
+        }
+        /// <summary>
+        /// Sinus hyperbolicus
+        /// </summary>
+        /// <param name="input">fcomplex input</param>
+        /// <returns>Sinus hyperbolicus of input</returns>
+        /// <remarks><para>The sinus hyperbolicus is computed by the trigonometric euler equation: </para>
+        /// <para>(Exp(input) - Exp(-1.0 * input)) / 2.0</para></remarks>
+        public static fcomplex Sinh(fcomplex input) {
+            fcomplex ret = new fcomplex(0, 2);
+            fcomplex i = new fcomplex(0, (float)1.0);
+            fcomplex mi = new fcomplex(0, (float)-1.0);
+            return (Exp(input) - Exp(-1.0 * input)) / 2.0;
+        }
+        /// <summary>
+        /// Exponential / power of base e
+        /// </summary>
+        /// <returns>Power of base e</returns>
+        public fcomplex Exp() {
+            return fcomplex.FromPol((float)Math.Exp(real), imag);
+        }
+        /// <summary>
+        /// Power of fcomplex number, real exponent
+        /// </summary>
+        /// <param name="exponent">Exponent</param>
+        /// <returns>New fcomplex number with result</returns>
+        public fcomplex Pow(double exponent) {
+            fcomplex ret = Log();
+            ret.imag *= (float)exponent;
+            ret.real *= (float)exponent;
+            return ret.Exp();
+        }
+        /// <summary>
+        /// Power of fcomplex number, complex exponent
+        /// </summary>
+        /// <param name="exponent">Exponent</param>
+        /// <returns>New fcomplex number with result</returns>
+        public fcomplex Pow(fcomplex exponent) {
+            fcomplex ret = (Log() * exponent);
+            return ret.Exp();
+        }
+        /// <summary>
+        /// Square root of fcomplex number
+        /// </summary>
+        /// <returns>Square root</returns>
+        public fcomplex Sqrt() {
+            // Reference : numerical recipes in C: Appendix C
+            fcomplex ret = new fcomplex();
+            double x, y, w, r;
+            if ( real == 0.0 && imag == 0.0)
+                return ret;
+            else {
+                x = (float)Math.Abs(real);
+                y = (float)Math.Abs( imag);
+                if (x >= y) {
+                    r = y / x;
+                    w = Math.Sqrt(x) * Math.Sqrt(0.5 * (1.0 + Math.Sqrt(1.0 + r * r)));
+                } else {
+                    r = x / y;
+                    w = Math.Sqrt(y) * Math.Sqrt(0.5 * (r + Math.Sqrt(1.0 + r * r)));
+                }
+                if ( real >= 0.0) {
+                    ret.real = (float)w;
+                    ret.imag = (float)( imag / (2.0 * w));
+                } else {
+                    ret.imag = (float)(( imag >= 0) ? w : -w);
+                    ret.real = (float)( imag / (2.0 * ret.imag));
+                }
+                return ret;
+            }
+        }
+        /// <summary>
+        /// Logarithm of fcomplex number
+        /// </summary>
+        /// <returns>Natural logarithm</returns>
+        /// <remarks>The logarithm of a complex number A is defined as follows: <br />
+        /// <list type="none"><item>real part: log(abs(A))</item>
+        /// <item>imag part: Atan2(imag(A),real(A))</item></list>
+        /// </remarks>
+        public fcomplex Log() {
+            fcomplex ret = new fcomplex();
+            ret.real = (float)Math.Log(Math.Sqrt( real *  real +  imag *  imag));
+            ret.imag = (float)Math.Atan2( imag,  real);
+            return ret;
+        }
+        /// <summary>
+        /// Test if any of real or imaginary parts are NAN's
+        /// </summary>
+        /// <param name="input">fcomplex input</param>
+        /// <returns>true if any of real or imag part is not a number</returns>
+        public static bool IsNaN(fcomplex input) {
+            if (Single.IsNaN(input.real) || Single.IsNaN(input.imag)) 
+                return true; 
+            else 
+                return false; 
+        }
+        /// <summary>
+        /// Test if any of real or imaginary parts are infinite
+        /// </summary>
+        /// <param name="input">fcomplex input</param>
+        /// <returns>true if any of real or imag part is infinite</returns>
+        public static bool IsInfinity(fcomplex input) {  
+            if (Single.IsInfinity(input.real) || Single.IsInfinity(input.imag)) 
+                return true; 
+            else 
+                return false; 
+        }
+        /// <summary>
+        /// Test if any of real or imaginary parts are pos. infinite
+        /// </summary>
+        /// <param name="input">fcomplex input</param>
+        /// <returns>true if any of real or imag part is positive infinite</returns>
+        public static bool IsPositiveInfinity(fcomplex input) {  
+            if (Single.IsPositiveInfinity(input.real) || Single.IsPositiveInfinity(input.imag)) 
+                return true; 
+            else 
+                return false; 
+        }
+        /// <summary>
+        /// Test if any of real or imaginary parts are neg. infinite
+        /// </summary>
+        /// <param name="input">fcomplex input</param>
+        /// <returns>true if any of real or imag part is negative infinite</returns>
+        public static bool IsNegativeInfinity(fcomplex input) {  
+            if (Single.IsNegativeInfinity(input.real) || Single.IsNegativeInfinity(input.imag)) 
+                return true; 
+            else 
+                return false; 
+        }
+        /// <summary>
+        /// Test if any of real or imaginary parts are finite
+        /// </summary>
+        /// <param name="input">fcomplex input</param>
+        /// <returns>true if any of real and imag part is finite</returns>
+        public static bool IsFinite (fcomplex input) {
+            if (ILMath.isfinite(input.real) && ILMath.isfinite(input.imag)) 
+                return true; 
+            else 
+                return false; 
+        }
+
+        #region CAST_OPERATORS
+        /// <summary>
+        /// Implicit cast real number into complex number
+        /// </summary>
+        /// <param name="a">double</param>
+        /// <returns>fcomplex number with real part equals a</returns>
+        public static implicit operator fcomplex(double a) {
+            return new fcomplex((float)a, 0.0F);
+        }
+        /// <summary>
+        /// Implicit cast real number into complex number
+        /// </summary>
+        /// <param name="a">float</param>
+        /// <returns>fcomplex number with real part equals a</returns>
+        public static implicit operator fcomplex(float a) {
+            return new fcomplex(a, 0.0F);
+        }
+        /// <summary>
+        /// Implicit cast real number into complex number
+        /// </summary>
+        /// <param name="a">byte</param>
+        /// <returns>fcomplex number with real part equals a</returns>
+        public static implicit operator fcomplex(byte a) {
+            return new fcomplex(a, 0.0F);
+        }
+        /// <summary>
+        /// Implicit cast real number into complex number
+        /// </summary>
+        /// <param name="a">char</param>
+        /// <returns>fcomplex number with real part equals a</returns>
+        public static implicit operator fcomplex(char a) {
+            return new fcomplex(a, 0.0F);
+        }
+        /// <summary>
+        /// Implicit cast real number into complex number
+        /// </summary>
+        /// <param name="a">Int16</param>
+        /// <returns>fcomplex number with real part equals a</returns>
+        public static implicit operator fcomplex(Int16 a) {
+            return new fcomplex(a, 0.0F);
+        }
+        /// <summary>
+        /// Implicit cast real number into complex number
+        /// </summary>
+        /// <param name="a">Int32</param>
+        /// <returns>fcomplex number with real part equals a</returns>
+        public static implicit operator fcomplex(Int32 a) {
+            return new fcomplex((float)a, 0.0F);    
+        }
+        /// <summary>
+        /// Implicit cast real number into complex number
+        /// </summary>
+        /// <param name="a">Int64</param>
+        /// <returns>fcomplex number with real part equals a</returns>
+        public static implicit operator fcomplex(Int64 a) {
+            return new fcomplex((float)a, 0.0F);
+        }
+        /// <summary>
+        /// Implicit cast real number into complex number
+        /// </summary>
+        /// <param name="a">UInt16</param>
+        /// <returns>fcomplex number with real part equals a</returns>
+        public static implicit operator fcomplex(UInt16 a) {
+            return new fcomplex((float)a, 0.0F);
+        }
+        /// <summary>
+        /// Implicit cast real number into complex number
+        /// </summary>
+        /// <param name="a">UInt32</param>
+        /// <returns>fcomplex number with real part equals a</returns>
+        public static implicit operator fcomplex(UInt32 a) {
+            return new fcomplex((float)a, 0.0F);
+        }
+        /// <summary>
+        /// Implicit cast real number into complex number
+        /// </summary>
+        /// <param name="a">UInt64</param>
+        /// <returns>fcomplex number with real part equals a</returns>
+        public static implicit operator fcomplex(UInt64 a) {
+            return new fcomplex((float)a, 0.0F);
+        }
+
+        /// <summary>
+        /// Explicit cast complex number into real number
+        /// </summary>
+        /// <param name="a">fcomplex number</param>
+        /// <returns>Real number with real part of a</returns>
+        public static explicit operator double(fcomplex a) {
+            return a.real; 
+        }
+        /// <summary>
+        /// Explicit cast complex number into real number
+        /// </summary>
+        /// <param name="a">fcomplex number</param>
+        /// <returns>Real number with real part of a</returns>
+        public static explicit operator float(fcomplex a) {
+            return (float)a.real;
+        }
+        /// <summary>
+        /// Explicit cast complex number into real number
+        /// </summary>
+        /// <param name="a">fcomplex number</param>
+        /// <returns>Real number with real part of a</returns>
+        public static explicit operator byte(fcomplex a) {
+            return (byte) a.real; 
+        }
+        /// <summary>
+        /// Explicit cast complex number into real number
+        /// </summary>
+        /// <param name="a">fcomplex number</param>
+        /// <returns>Real number with real part of a</returns>
+        public static explicit operator char(fcomplex a) {
+            return (char) a.real; 
+        }
+        /// <summary>
+        /// Explicit cast complex number into real number
+        /// </summary>
+        /// <param name="a">fcomplex number</param>
+        /// <returns>Real number with real part of a</returns>
+        public static explicit operator Int16(fcomplex a) {
+            return (Int16) a.real; 
+        }
+        /// <summary>
+        /// Explicit cast complex number into real number
+        /// </summary>
+        /// <param name="a">complex number</param>
+        /// <returns>Real number with real part of a</returns>
+        public static explicit operator Int32(fcomplex a) {
+            return (Int32) a.real; 
+        }
+        /// <summary>
+        /// Explicit cast complex number into real number
+        /// </summary>
+        /// <param name="a">fcomplex number</param>
+        /// <returns>Real number with real part of a</returns>
+        public static explicit operator Int64(fcomplex a) {
+            return (Int64) a.real; 
+        }
+        /// <summary>
+        /// Explicit cast complex number into real number
+        /// </summary>
+        /// <param name="a">fcomplex number</param>
+        /// <returns>Real number with real part of a</returns>
+        public static explicit operator UInt16(fcomplex a) {
+            return (UInt16) a.real; 
+        }
+        /// <summary>
+        /// Explicit cast complex number into real number
+        /// </summary>
+        /// <param name="a">fcomplex number</param>
+        /// <returns>Real number with real part of a</returns>
+        public static explicit operator UInt32(fcomplex a) {
+            return (UInt32) a.real; 
+        }
+        /// <summary>
+        /// Explicit cast complex number into real number
+        /// </summary>
+        /// <param name="a">fcomplex number</param>
+        /// <returns>Real number with real part of a</returns>
+        public static explicit operator UInt64(fcomplex a) {
+            return (UInt64) a.real; 
+        }
+        /// <summary>
+        /// Test if real and imag part are zero
+        /// </summary>
+        /// <returns>true if real and imag parts are zero, false else</returns>
+        public bool iszero() {
+            if (real == 0.0f && imag == 0.0f) 
+                return true; 
+            else 
+                return false; 
+        }
+        #endregion CAST_OPERATORS
+
+    }
+    
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILMatFile5.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILMatFile5.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILMatFile5.cs	(revision 9102)
@@ -0,0 +1,2412 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.IO; 
+using System.IO.Compression; 
+using ILNumerics; 
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics.Exceptions; 
+
+
+namespace ILNumerics {
+    
+    /// <summary>
+    /// Matlab .mat file wrapper class
+    /// </summary>
+    /// <remarks>This class reads and writes Matlab .mat files version 6! ! 
+    /// All numeric array types are supported. The reading and writing of 
+    /// Matlab cell arrays is not supported yet.</remarks>
+    public sealed class ILMatFile : IDisposable {
+
+        #region attributes 
+        [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
+        private string m_filename = "(unknown)"; 
+        /// <summary>
+        /// Path to mat file, if this object was created from an existing mat file.
+        /// </summary>
+        public string Filelocation {
+            get {
+                return m_filename; 
+            }
+        }
+        [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
+        private ILCell m_data = ILMath.cell();
+        [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
+        private string headerFromFile;
+        #endregion
+                      
+        #region constants
+        /// <summary>
+        /// Inner types for MATLAB data elements
+        /// </summary>
+        public enum MatFileType : int {
+            /// <summary>
+            /// unknown 
+            /// </summary>
+            miUNKNOWN = 0,
+            /// <summary>
+            /// Int8
+            /// </summary>
+            miINT8 = 1,
+            /// <summary>
+            /// UInt8
+            /// </summary>
+            miUINT8 = 2,
+            /// <summary>
+            /// Int16
+            /// </summary>
+            miINT16 = 3,
+            /// <summary>
+            /// UInt16
+            /// </summary>
+            miUINT16 = 4,
+            /// <summary>
+            /// int32
+            /// </summary>
+            miINT32 = 5,
+            /// <summary>
+            /// UInt32
+            /// </summary>
+            miUINT32 = 6,
+            /// <summary>
+            /// float
+            /// </summary>
+            miSINGLE = 7,
+            /// <summary>
+            /// double
+            /// </summary>
+            miDOUBLE = 9,
+            /// <summary>
+            /// Int64
+            /// </summary>
+            miINT64 = 12,
+            /// <summary>
+            /// UInt64
+            /// </summary>
+            miUINT64 = 13,
+            /// <summary>
+            /// matrix type (general)
+            /// </summary>
+            miMATRIX = 14,
+            /// <summary>
+            /// compressed
+            /// </summary>
+            miCOMPRESSED = 15,
+            /// <summary>
+            /// utf8 encoded
+            /// </summary>
+            miUTF8 = 16,
+            /// <summary>
+            /// utf16 encoded
+            /// </summary>
+            miUTF16 = 17,
+            /// <summary>
+            /// utf32 encoded
+            /// </summary>
+            miUTF32 = 18
+        }
+        /// <summary>
+        /// Types for matrix chunks
+        /// </summary>
+        public enum MatFileArrayClass {
+            /// <summary>
+            /// cell
+            /// </summary>
+            mxCELL_CLASS = 1,
+            /// <summary>
+            /// struct
+            /// </summary>
+            mxSTRUCT_CLASS = 2,
+            /// <summary>
+            /// object
+            /// </summary>
+            mxOBJECT_CLASS = 3,
+            /// <summary>
+            /// char
+            /// </summary>
+            mxCHAR_CLASS = 4,
+            /// <summary>
+            /// sparse
+            /// </summary>
+            mxSPARSE_CLASS = 5,
+            /// <summary>
+            /// double
+            /// </summary>
+            mxDOUBLE_CLASS = 6,
+            /// <summary>
+            /// float
+            /// </summary>
+            mxSINGLE_CLASS = 7,
+            /// <summary>
+            /// Int8
+            /// </summary>
+            mxINT8_CLASS = 8,
+            /// <summary>
+            /// UInt8
+            /// </summary>
+            mxUINT8_CLASS = 9,
+            /// <summary>
+            /// Int16
+            /// </summary>
+            mxINT16_CLASS = 10,
+            /// <summary>
+            /// UInt16
+            /// </summary>
+            mxUINT16_CLASS = 11,
+            /// <summary>
+            /// Int32
+            /// </summary>
+            mxINT32_CLASS = 12,
+            /// <summary>
+            /// UInt32
+            /// </summary>
+            mxUINT32_CLASS = 13,
+            /// <summary>
+            /// Int32
+            /// </summary>
+            mxINT64_CLASS = 14,
+            /// <summary>
+            /// UInt32
+            /// </summary>
+            mxUINT64_CLASS = 15
+        }
+
+        /// <summary>
+        /// List of keywords which Matlab disallows for variable names
+        /// </summary>
+        public static readonly string[] ReservedKeywords = new string[] {
+            "break",
+            "case"  ,
+            "catch"  ,
+            "continue",
+            "else"    ,
+            "elseif"  ,
+            "end"     ,
+            "for"     ,
+            "function",
+            "global"  ,
+            "if"      ,
+            "otherwise",
+            "persistent",
+            "return"    ,
+            "switch"    ,
+            "try"       ,
+            "while"                
+        };
+
+        private static int miSIZE_INT32    = 4;
+        private static int miSIZE_INT16    = 2;
+        private static int miSIZE_INT8     = 1;
+        private static int miSIZE_UINT32   = 4;
+        private static int miSIZE_UINT16   = 2;
+        private static int miSIZE_UINT8    = 1;
+        private static int miSIZE_DOUBLE   = 8;
+        private static int miSIZE_SINGLE   = 4;
+        private static int miSIZE_UTF32    = 4;
+        private static int miSIZE_INT64    = 8;
+        private static int miSIZE_UINT64   = 8;
+
+
+        /* Matlab Array Types (Classes) */
+        private static int mxUNKNOWN_CLASS = 0;
+        private static int mxCELL_CLASS    = 1;
+        private static int mxSTRUCT_CLASS  = 2;
+        private static int mxOBJECT_CLASS  = 3;
+        private static int mxCHAR_CLASS    = 4;
+        private static int mxSPARSE_CLASS  = 5;
+        private static int mxDOUBLE_CLASS  = 6;
+        private static int mxSINGLE_CLASS  = 7;
+        private static int mxINT8_CLASS    = 8;
+        private static int mxUINT8_CLASS   = 9;
+        private static int mxINT16_CLASS   = 10;
+        private static int mxUINT16_CLASS  = 11;
+        private static int mxINT32_CLASS   = 12;
+        private static int mxUINT32_CLASS  = 13;
+        private static int mxINT64_CLASS   = 14;
+        private static int mxUINT64_CLASS  = 15;
+        private static int mxFUNCTION_CLASS= 16;
+        private static int mxOPAQUE_CLASS  = 17;
+        
+        private static int mtFLAG_COMPLEX  = 0x0800;
+        private static int mtFLAG_GLOBAL   = 0x0400;
+        private static int mtFLAG_LOGICAL  = 0x0200;
+        private static int mtFLAG_TYPE     = 0xff;
+        #endregion
+
+        #region private helper
+        /// <summary>
+        /// size of single elements stored in Matlab's *.mat files
+        /// </summary>
+        /// <param name="type">one of Matlab's inner element types</param>
+        /// <returns>size in bytes </returns>
+        private static int sizeOf(MatFileType type)
+        {
+            switch ( type )
+            {
+                case MatFileType.miINT8:
+                    return miSIZE_INT8;
+                case MatFileType.miUINT8:
+                    return miSIZE_UINT8;
+                case MatFileType.miINT16:
+                    return miSIZE_INT16;
+                case MatFileType.miUINT16:
+                    return miSIZE_UINT16;
+                case MatFileType.miINT32:
+                    return miSIZE_INT32;
+                case MatFileType.miUINT32:
+                    return miSIZE_UINT32;
+                case MatFileType.miINT64:
+                    return miSIZE_INT64; 
+                case MatFileType.miUINT64:
+                    return miSIZE_UINT64; 
+                case MatFileType.miDOUBLE:
+                    return miSIZE_DOUBLE;
+                case MatFileType.miSINGLE:
+                    return miSIZE_SINGLE;
+                case MatFileType.miUTF32:
+                    return miSIZE_UTF32;
+                default:
+                    throw new ILArgumentException("Invalid MatFileType specified: " + type.ToString()); 
+            }
+        }
+        private ILBaseArray read_compressed(BinaryReader br, int len) {
+            throw new NotImplementedException("Compressed matfile format is not supported yet! Use '-v6' option in Matlab to create the matfile!"); 
+            //long startpos = br.BaseStream.Position; 
+            ////ZOutputStream zstream = new ZOutputStream(br.BaseStream); 
+            //GZipStream str = new GZipStream(br.BaseStream,CompressionMode.Decompress); 
+            //BinaryReader bread = new BinaryReader(str);
+            //MatFileType dataType = (MatFileType)Enum.Parse(typeof(MatFileType), bread.ReadInt32().ToString()); 
+            //int elementLength = bread.ReadInt32();
+            //ILBaseArray ret = null; 
+            //if (dataType == MatFileType.miMATRIX) {
+            //    ret = read_miMATRIX(bread);     
+            //}
+            //return ret; 
+        }
+        private void read_header(BinaryReader br) {
+            headerFromFile = br.ReadBytes(116).ToString();
+            // skip subsystem data 
+            br.ReadBytes(8);
+            // version 
+            int version = br.ReadInt16();
+            if (br.ReadChar() != 'I' || br.ReadByte() != 'M')
+                throw new Exception("This file eventually was written on a machine, which is not compatible " +
+                    " to this one due to an endian type issue!");
+        }
+        /// <summary>
+        /// read ONE array (arbitrary dimensions/type) from MAT file 
+        /// </summary>
+        /// <param name="br">binary reader initialized and pointing to the beginning of the subarray element.</param>
+        /// <returns>ILBaseArray of size and type originally stored into the mat file.</returns>
+        private ILBaseArray read_miMATRIX(BinaryReader br) {
+            long entryPositionInStream = br.BaseStream.Position;
+            bool complex = false;
+            bool logical = false;
+            int mxClass = 0;
+            int[] dimensions = new int[0];
+            MatFileType storageType = MatFileType.miUNKNOWN;
+            int nrElements = 1;
+            string name;
+            ILBaseArray ret;
+            // read array flags 
+            Int32 readInt = br.ReadInt32();
+            if (readInt != 6)
+                throw new Exception("found invalid datatype in array flag! currently only 'mxArray' types are supported!");
+            readInt = br.ReadInt32();
+            if (readInt != 8)
+                throw new Exception("unexpected array flag length. expected: 8 /found: " + readInt);
+            readInt = br.ReadInt32();
+            complex = (readInt & mtFLAG_COMPLEX) != 0;
+            logical = (readInt & mtFLAG_LOGICAL) != 0;
+            mxClass = readInt & 0x00ff;
+            // unknown
+            br.ReadInt32();
+            // Read dimensions array 
+            readInt = br.ReadInt32();
+            if (readInt != 5)
+                throw new Exception("found invalid datatype in dimension flag!");
+            readInt = br.ReadInt32();
+            if (readInt < 2)
+                throw new Exception("Invalid number of dimensions found: " + readInt);
+            dimensions = new int[(int)readInt / 4];
+            for (int i = 0; i < dimensions.Length; i++) {
+                dimensions[i] = br.ReadInt32();
+                nrElements *= dimensions[i];
+            }
+            // padidng if needed
+            if ((dimensions.Length % 2) != 0)
+                br.ReadInt32();
+            // read Name - check for small data element format 
+            readInt = br.ReadInt32();
+            int nrSmallBytes = (int)((readInt & 0xffff0000) >> 16);
+            if (nrSmallBytes != 0) {
+                // process small element format 
+                if ((readInt & 0xffff) != 1)
+                    throw new Exception("Invalid datype for (compressed) name element found: " + (readInt & 0x00ff));
+                StringBuilder nameBuild = new StringBuilder();
+                nameBuild.Append(br.ReadChars(nrSmallBytes));
+                // padding if needed
+                while (nrSmallBytes < 4) {
+                    br.ReadByte();
+                    nrSmallBytes++;
+                }
+                name = nameBuild.ToString();
+            } else {
+                // process 'long' format 
+                if (readInt != 1)
+                    throw new Exception("Invalid datype for name element found: " + readInt);
+                readInt = br.ReadInt32();
+                StringBuilder nameBuild = new StringBuilder();
+                nameBuild.Append(br.ReadChars(readInt));
+                while (readInt % 8 != 0) {
+                    readInt++;
+                    br.ReadByte();
+                }
+                name = nameBuild.ToString();
+            }
+            // read data flags + check if small format
+            readInt = br.ReadInt32();
+            nrSmallBytes = (Int16)((readInt & 0xffff0000) >> 16);
+            System.Array realData = null;
+            System.Array imagData = null;
+            int len;
+            if (nrSmallBytes != 0 && nrElements <= 4) {
+                // small data element format for scalars only! 
+                // process small format -> real part 
+                storageType = (MatFileType)(readInt & 0xffff);
+                len = nrSmallBytes;
+                readElementGeneric(br, storageType, out realData, ref len, 4);
+                // padding
+                //while (nrSmallBytes < 4 && br.BaseStream.Position < br.BaseStream.Length) {
+                //    br.ReadByte(); 
+                //    nrSmallBytes++; 
+                //}
+            } else {
+                // read regular data : real part
+                storageType = (MatFileType)Enum.Parse(typeof(MatFileType), readInt.ToString());
+                len = br.ReadInt32();
+                nrSmallBytes = len;
+                readElementGeneric(br, storageType, out realData, ref len);
+                // (padding is done in readElementGeneric)
+            }
+
+            // read imag part + check if small format
+            if (complex) {
+                readInt = br.ReadInt32();
+                nrSmallBytes = (Int16)((readInt & 0xffff0000) >> 16);
+                if (nrSmallBytes != 0 && nrElements <= 4) {
+                    // process small format -> imag part 
+                    storageType = (MatFileType)(readInt & 0xffff);
+                    len = nrSmallBytes;
+                    readElementGeneric(br, storageType, out imagData, ref len, 4);
+                    // padding
+                    //while (nrSmallBytes < 4 && br.BaseStream.Position < br.BaseStream.Length) {
+                    //    br.ReadByte(); 
+                    //    nrSmallBytes++; 
+                    //}
+                } else {
+                    // read regular data : image part
+                    storageType = (MatFileType)Enum.Parse(typeof(MatFileType), readInt.ToString()); ;
+                    len = br.ReadInt32();
+                    nrSmallBytes = len;
+                    readElementGeneric(br, storageType, out imagData, ref len);
+                    // (padding's done in readElementGeneric)
+                }
+            }
+            // convert to original data type 
+            if (complex) {
+                if (mxClass == mxSINGLE_CLASS) {
+                    fcomplex[] retArr = new fcomplex[nrElements];
+                    float[] realPart = Convert2SingleArray(realData);
+                    float[] imagPart = Convert2SingleArray(imagData);
+                    for (int i = 0; i < nrElements; i++) {
+                        retArr[i] = new fcomplex(realPart[i], imagPart[i]);
+                    }
+                    ret = new ILRetArray<fcomplex>(retArr, dimensions);
+                } else {
+                    complex[] retArr = new complex[nrElements];
+                    double[] realPart = Convert2DoubleArray(realData);
+                    double[] imagPart = Convert2DoubleArray(imagData);
+                    for (int i = 0; i < nrElements; i++) {
+                        retArr[i] = new complex(realPart[i], imagPart[i]);
+                    }
+                    ret = new ILRetArray<complex>(retArr, dimensions);
+                }
+            } else if (logical) {
+                int numNonzero = 0;
+                byte[] retArr = Convert2Logical(realData, out numNonzero);
+                ret = new ILRetLogical(retArr, new ILSize(dimensions), numNonzero);
+            } else {
+                if (false) {
+
+                    
+                } else if (mxClass ==  mxDOUBLE_CLASS) {
+                    
+                    double[] dataArr =   Convert2DoubleArray(realData);
+                    ret = new ILRetArray<double>(dataArr, dimensions);
+
+#region HYCALPER AUTO GENERATED CODE
+
+                   
+                } else if (mxClass ==  mxUINT8_CLASS) {
+                   
+                    byte[] dataArr =  Convert2ByteArray(realData);
+                    ret = new ILRetArray<byte>(dataArr, dimensions);
+                   
+                } else if (mxClass ==  mxUINT64_CLASS) {
+                   
+                    UInt64[] dataArr =  Convert2UInt64Array(realData);
+                    ret = new ILRetArray<UInt64>(dataArr, dimensions);
+                   
+                } else if (mxClass ==  mxINT64_CLASS) {
+                   
+                    Int64[] dataArr =  Convert2Int64Array(realData);
+                    ret = new ILRetArray<Int64>(dataArr, dimensions);
+                   
+                } else if (mxClass ==  mxUINT32_CLASS) {
+                   
+                    UInt32[] dataArr =  Convert2UInt32Array(realData);
+                    ret = new ILRetArray<UInt32>(dataArr, dimensions);
+                   
+                } else if (mxClass ==  mxINT32_CLASS) {
+                   
+                    Int32[] dataArr =  Convert2Int32Array(realData);
+                    ret = new ILRetArray<Int32>(dataArr, dimensions);
+                   
+                } else if (mxClass ==  mxUINT16_CLASS) {
+                   
+                    UInt16[] dataArr =  Convert2UInt16Array(realData);
+                    ret = new ILRetArray<UInt16>(dataArr, dimensions);
+                   
+                } else if (mxClass ==  mxINT16_CLASS) {
+                   
+                    Int16[] dataArr =  Convert2Int16Array(realData);
+                    ret = new ILRetArray<Int16>(dataArr, dimensions);
+                   
+                } else if (mxClass ==  mxUINT8_CLASS) {
+                   
+                    char[] dataArr =  Convert2CharArray(realData);
+                    ret = new ILRetArray<char>(dataArr, dimensions);
+                   
+                } else if (mxClass ==  mxINT8_CLASS) {
+                   
+                    byte[] dataArr =  Convert2ByteArray(realData);
+                    ret = new ILRetArray<byte>(dataArr, dimensions);
+                   
+                } else if (mxClass ==  mxSINGLE_CLASS) {
+                   
+                    float[] dataArr =  Convert2SingleArray(realData);
+                    ret = new ILRetArray<float>(dataArr, dimensions);
+                   
+                } else if (mxClass ==  mxCHAR_CLASS) {
+                   
+                    char[] dataArr =  Convert2CharArray(realData);
+                    ret = new ILRetArray<char>(dataArr, dimensions);
+
+#endregion HYCALPER AUTO GENERATED CODE
+               } else {
+                    throw new Exception("element data type is not supported");
+                }
+            }
+            // set name       
+            ret.Name = name;
+            return ret;
+        }
+
+
+        
+
+        private  double[]  Convert2DoubleArray(System.Array input) {
+            // keep track of type matches ! No checks will be made! 
+            
+            double[] ret = new  double[input.Length];
+            switch (input.GetType().Name.ToLower()) {
+                case "char[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( double)(char)input.GetValue(i);
+                    }
+                    break;
+
+                case "uint64[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( double)(UInt64)input.GetValue(i);
+                    }
+                    break;
+
+                case "uint32[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( double)(UInt32)input.GetValue(i);
+                    }
+                    break;
+
+                case "uint16[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( double)(UInt16)input.GetValue(i);
+                    }
+                    break;
+
+                case "int64[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( double)(Int64)input.GetValue(i);
+                    }
+                    break;
+
+                case "int32[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( double)(Int32)input.GetValue(i);
+                    }
+                    break;
+
+                case "int16[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( double)(Int16)input.GetValue(i);
+                    }
+                    break;
+
+                case "single[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( double)(float)input.GetValue(i);
+                    }
+                    break;
+
+                case "double[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( double)(double)input.GetValue(i);
+                    }
+                    break;
+
+                case "byte[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( double)(byte)input.GetValue(i);
+                    }
+                    break;
+                case "sbyte[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( double)(sbyte)input.GetValue(i);
+                    }
+                    break;
+                default:
+                    throw new InvalidCastException("cannot convert from '" + input.GetType().Name + "'!");
+            }
+            return ret;
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+       
+
+        private  sbyte[]  Convert2SByteArray(System.Array input) {
+            // keep track of type matches ! No checks will be made! 
+           
+            sbyte[] ret = new  sbyte[input.Length];
+            switch (input.GetType().Name.ToLower()) {
+                case "char[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( sbyte)(char)input.GetValue(i);
+                    }
+                    break;
+
+                case "uint64[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( sbyte)(UInt64)input.GetValue(i);
+                    }
+                    break;
+
+                case "uint32[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( sbyte)(UInt32)input.GetValue(i);
+                    }
+                    break;
+
+                case "uint16[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( sbyte)(UInt16)input.GetValue(i);
+                    }
+                    break;
+
+                case "int64[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( sbyte)(Int64)input.GetValue(i);
+                    }
+                    break;
+
+                case "int32[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( sbyte)(Int32)input.GetValue(i);
+                    }
+                    break;
+
+                case "int16[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( sbyte)(Int16)input.GetValue(i);
+                    }
+                    break;
+
+                case "single[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( sbyte)(float)input.GetValue(i);
+                    }
+                    break;
+
+                case "double[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( sbyte)(double)input.GetValue(i);
+                    }
+                    break;
+
+                case "byte[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( sbyte)(byte)input.GetValue(i);
+                    }
+                    break;
+                case "sbyte[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( sbyte)(sbyte)input.GetValue(i);
+                    }
+                    break;
+                default:
+                    throw new InvalidCastException("cannot convert from '" + input.GetType().Name + "'!");
+            }
+            return ret;
+        }
+       
+
+        private  byte[]  Convert2ByteArray(System.Array input) {
+            // keep track of type matches ! No checks will be made! 
+           
+            byte[] ret = new  byte[input.Length];
+            switch (input.GetType().Name.ToLower()) {
+                case "char[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( byte)(char)input.GetValue(i);
+                    }
+                    break;
+
+                case "uint64[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( byte)(UInt64)input.GetValue(i);
+                    }
+                    break;
+
+                case "uint32[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( byte)(UInt32)input.GetValue(i);
+                    }
+                    break;
+
+                case "uint16[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( byte)(UInt16)input.GetValue(i);
+                    }
+                    break;
+
+                case "int64[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( byte)(Int64)input.GetValue(i);
+                    }
+                    break;
+
+                case "int32[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( byte)(Int32)input.GetValue(i);
+                    }
+                    break;
+
+                case "int16[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( byte)(Int16)input.GetValue(i);
+                    }
+                    break;
+
+                case "single[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( byte)(float)input.GetValue(i);
+                    }
+                    break;
+
+                case "double[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( byte)(double)input.GetValue(i);
+                    }
+                    break;
+
+                case "byte[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( byte)(byte)input.GetValue(i);
+                    }
+                    break;
+                case "sbyte[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( byte)(sbyte)input.GetValue(i);
+                    }
+                    break;
+                default:
+                    throw new InvalidCastException("cannot convert from '" + input.GetType().Name + "'!");
+            }
+            return ret;
+        }
+       
+
+        private  UInt64[]  Convert2UInt64Array(System.Array input) {
+            // keep track of type matches ! No checks will be made! 
+           
+            UInt64[] ret = new  UInt64[input.Length];
+            switch (input.GetType().Name.ToLower()) {
+                case "char[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( UInt64)(char)input.GetValue(i);
+                    }
+                    break;
+
+                case "uint64[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( UInt64)(UInt64)input.GetValue(i);
+                    }
+                    break;
+
+                case "uint32[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( UInt64)(UInt32)input.GetValue(i);
+                    }
+                    break;
+
+                case "uint16[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( UInt64)(UInt16)input.GetValue(i);
+                    }
+                    break;
+
+                case "int64[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( UInt64)(Int64)input.GetValue(i);
+                    }
+                    break;
+
+                case "int32[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( UInt64)(Int32)input.GetValue(i);
+                    }
+                    break;
+
+                case "int16[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( UInt64)(Int16)input.GetValue(i);
+                    }
+                    break;
+
+                case "single[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( UInt64)(float)input.GetValue(i);
+                    }
+                    break;
+
+                case "double[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( UInt64)(double)input.GetValue(i);
+                    }
+                    break;
+
+                case "byte[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( UInt64)(byte)input.GetValue(i);
+                    }
+                    break;
+                case "sbyte[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( UInt64)(sbyte)input.GetValue(i);
+                    }
+                    break;
+                default:
+                    throw new InvalidCastException("cannot convert from '" + input.GetType().Name + "'!");
+            }
+            return ret;
+        }
+       
+
+        private  UInt32[]  Convert2UInt32Array(System.Array input) {
+            // keep track of type matches ! No checks will be made! 
+           
+            UInt32[] ret = new  UInt32[input.Length];
+            switch (input.GetType().Name.ToLower()) {
+                case "char[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( UInt32)(char)input.GetValue(i);
+                    }
+                    break;
+
+                case "uint64[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( UInt32)(UInt64)input.GetValue(i);
+                    }
+                    break;
+
+                case "uint32[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( UInt32)(UInt32)input.GetValue(i);
+                    }
+                    break;
+
+                case "uint16[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( UInt32)(UInt16)input.GetValue(i);
+                    }
+                    break;
+
+                case "int64[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( UInt32)(Int64)input.GetValue(i);
+                    }
+                    break;
+
+                case "int32[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( UInt32)(Int32)input.GetValue(i);
+                    }
+                    break;
+
+                case "int16[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( UInt32)(Int16)input.GetValue(i);
+                    }
+                    break;
+
+                case "single[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( UInt32)(float)input.GetValue(i);
+                    }
+                    break;
+
+                case "double[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( UInt32)(double)input.GetValue(i);
+                    }
+                    break;
+
+                case "byte[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( UInt32)(byte)input.GetValue(i);
+                    }
+                    break;
+                case "sbyte[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( UInt32)(sbyte)input.GetValue(i);
+                    }
+                    break;
+                default:
+                    throw new InvalidCastException("cannot convert from '" + input.GetType().Name + "'!");
+            }
+            return ret;
+        }
+       
+
+        private  UInt16[]  Convert2UInt16Array(System.Array input) {
+            // keep track of type matches ! No checks will be made! 
+           
+            UInt16[] ret = new  UInt16[input.Length];
+            switch (input.GetType().Name.ToLower()) {
+                case "char[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( UInt16)(char)input.GetValue(i);
+                    }
+                    break;
+
+                case "uint64[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( UInt16)(UInt64)input.GetValue(i);
+                    }
+                    break;
+
+                case "uint32[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( UInt16)(UInt32)input.GetValue(i);
+                    }
+                    break;
+
+                case "uint16[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( UInt16)(UInt16)input.GetValue(i);
+                    }
+                    break;
+
+                case "int64[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( UInt16)(Int64)input.GetValue(i);
+                    }
+                    break;
+
+                case "int32[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( UInt16)(Int32)input.GetValue(i);
+                    }
+                    break;
+
+                case "int16[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( UInt16)(Int16)input.GetValue(i);
+                    }
+                    break;
+
+                case "single[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( UInt16)(float)input.GetValue(i);
+                    }
+                    break;
+
+                case "double[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( UInt16)(double)input.GetValue(i);
+                    }
+                    break;
+
+                case "byte[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( UInt16)(byte)input.GetValue(i);
+                    }
+                    break;
+                case "sbyte[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( UInt16)(sbyte)input.GetValue(i);
+                    }
+                    break;
+                default:
+                    throw new InvalidCastException("cannot convert from '" + input.GetType().Name + "'!");
+            }
+            return ret;
+        }
+       
+
+        private  Int64[]  Convert2Int64Array(System.Array input) {
+            // keep track of type matches ! No checks will be made! 
+           
+            Int64[] ret = new  Int64[input.Length];
+            switch (input.GetType().Name.ToLower()) {
+                case "char[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( Int64)(char)input.GetValue(i);
+                    }
+                    break;
+
+                case "uint64[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( Int64)(UInt64)input.GetValue(i);
+                    }
+                    break;
+
+                case "uint32[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( Int64)(UInt32)input.GetValue(i);
+                    }
+                    break;
+
+                case "uint16[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( Int64)(UInt16)input.GetValue(i);
+                    }
+                    break;
+
+                case "int64[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( Int64)(Int64)input.GetValue(i);
+                    }
+                    break;
+
+                case "int32[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( Int64)(Int32)input.GetValue(i);
+                    }
+                    break;
+
+                case "int16[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( Int64)(Int16)input.GetValue(i);
+                    }
+                    break;
+
+                case "single[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( Int64)(float)input.GetValue(i);
+                    }
+                    break;
+
+                case "double[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( Int64)(double)input.GetValue(i);
+                    }
+                    break;
+
+                case "byte[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( Int64)(byte)input.GetValue(i);
+                    }
+                    break;
+                case "sbyte[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( Int64)(sbyte)input.GetValue(i);
+                    }
+                    break;
+                default:
+                    throw new InvalidCastException("cannot convert from '" + input.GetType().Name + "'!");
+            }
+            return ret;
+        }
+       
+
+        private  Int32[]  Convert2Int32Array(System.Array input) {
+            // keep track of type matches ! No checks will be made! 
+           
+            Int32[] ret = new  Int32[input.Length];
+            switch (input.GetType().Name.ToLower()) {
+                case "char[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( Int32)(char)input.GetValue(i);
+                    }
+                    break;
+
+                case "uint64[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( Int32)(UInt64)input.GetValue(i);
+                    }
+                    break;
+
+                case "uint32[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( Int32)(UInt32)input.GetValue(i);
+                    }
+                    break;
+
+                case "uint16[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( Int32)(UInt16)input.GetValue(i);
+                    }
+                    break;
+
+                case "int64[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( Int32)(Int64)input.GetValue(i);
+                    }
+                    break;
+
+                case "int32[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( Int32)(Int32)input.GetValue(i);
+                    }
+                    break;
+
+                case "int16[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( Int32)(Int16)input.GetValue(i);
+                    }
+                    break;
+
+                case "single[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( Int32)(float)input.GetValue(i);
+                    }
+                    break;
+
+                case "double[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( Int32)(double)input.GetValue(i);
+                    }
+                    break;
+
+                case "byte[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( Int32)(byte)input.GetValue(i);
+                    }
+                    break;
+                case "sbyte[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( Int32)(sbyte)input.GetValue(i);
+                    }
+                    break;
+                default:
+                    throw new InvalidCastException("cannot convert from '" + input.GetType().Name + "'!");
+            }
+            return ret;
+        }
+       
+
+        private  Int16[]  Convert2Int16Array(System.Array input) {
+            // keep track of type matches ! No checks will be made! 
+           
+            Int16[] ret = new  Int16[input.Length];
+            switch (input.GetType().Name.ToLower()) {
+                case "char[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( Int16)(char)input.GetValue(i);
+                    }
+                    break;
+
+                case "uint64[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( Int16)(UInt64)input.GetValue(i);
+                    }
+                    break;
+
+                case "uint32[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( Int16)(UInt32)input.GetValue(i);
+                    }
+                    break;
+
+                case "uint16[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( Int16)(UInt16)input.GetValue(i);
+                    }
+                    break;
+
+                case "int64[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( Int16)(Int64)input.GetValue(i);
+                    }
+                    break;
+
+                case "int32[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( Int16)(Int32)input.GetValue(i);
+                    }
+                    break;
+
+                case "int16[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( Int16)(Int16)input.GetValue(i);
+                    }
+                    break;
+
+                case "single[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( Int16)(float)input.GetValue(i);
+                    }
+                    break;
+
+                case "double[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( Int16)(double)input.GetValue(i);
+                    }
+                    break;
+
+                case "byte[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( Int16)(byte)input.GetValue(i);
+                    }
+                    break;
+                case "sbyte[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( Int16)(sbyte)input.GetValue(i);
+                    }
+                    break;
+                default:
+                    throw new InvalidCastException("cannot convert from '" + input.GetType().Name + "'!");
+            }
+            return ret;
+        }
+       
+
+        private  char[]  Convert2CharArray(System.Array input) {
+            // keep track of type matches ! No checks will be made! 
+           
+            char[] ret = new  char[input.Length];
+            switch (input.GetType().Name.ToLower()) {
+                case "char[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( char)(char)input.GetValue(i);
+                    }
+                    break;
+
+                case "uint64[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( char)(UInt64)input.GetValue(i);
+                    }
+                    break;
+
+                case "uint32[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( char)(UInt32)input.GetValue(i);
+                    }
+                    break;
+
+                case "uint16[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( char)(UInt16)input.GetValue(i);
+                    }
+                    break;
+
+                case "int64[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( char)(Int64)input.GetValue(i);
+                    }
+                    break;
+
+                case "int32[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( char)(Int32)input.GetValue(i);
+                    }
+                    break;
+
+                case "int16[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( char)(Int16)input.GetValue(i);
+                    }
+                    break;
+
+                case "single[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( char)(float)input.GetValue(i);
+                    }
+                    break;
+
+                case "double[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( char)(double)input.GetValue(i);
+                    }
+                    break;
+
+                case "byte[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( char)(byte)input.GetValue(i);
+                    }
+                    break;
+                case "sbyte[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( char)(sbyte)input.GetValue(i);
+                    }
+                    break;
+                default:
+                    throw new InvalidCastException("cannot convert from '" + input.GetType().Name + "'!");
+            }
+            return ret;
+        }
+       
+
+        private  float[]  Convert2SingleArray(System.Array input) {
+            // keep track of type matches ! No checks will be made! 
+           
+            float[] ret = new  float[input.Length];
+            switch (input.GetType().Name.ToLower()) {
+                case "char[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( float)(char)input.GetValue(i);
+                    }
+                    break;
+
+                case "uint64[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( float)(UInt64)input.GetValue(i);
+                    }
+                    break;
+
+                case "uint32[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( float)(UInt32)input.GetValue(i);
+                    }
+                    break;
+
+                case "uint16[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( float)(UInt16)input.GetValue(i);
+                    }
+                    break;
+
+                case "int64[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( float)(Int64)input.GetValue(i);
+                    }
+                    break;
+
+                case "int32[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( float)(Int32)input.GetValue(i);
+                    }
+                    break;
+
+                case "int16[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( float)(Int16)input.GetValue(i);
+                    }
+                    break;
+
+                case "single[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( float)(float)input.GetValue(i);
+                    }
+                    break;
+
+                case "double[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( float)(double)input.GetValue(i);
+                    }
+                    break;
+
+                case "byte[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( float)(byte)input.GetValue(i);
+                    }
+                    break;
+                case "sbyte[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        ret[i] = ( float)(sbyte)input.GetValue(i);
+                    }
+                    break;
+                default:
+                    throw new InvalidCastException("cannot convert from '" + input.GetType().Name + "'!");
+            }
+            return ret;
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+        private byte[] Convert2Logical(System.Array input, out int numNonzero) {
+            // keep track of type matches ! No checks will be made! 
+            numNonzero = 0;
+            byte[] ret = new byte[input.Length];
+            switch (input.GetType().Name.ToLower()) {
+                case "char[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        if ((char)input.GetValue(i) == 0) {
+                            ret[i] = 0;
+                        } else {
+                            ret[i] = 1;
+                            numNonzero++;
+                        }
+                    }
+                    break;
+
+                case "uint64[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        if ((UInt64)input.GetValue(i) == 0) {
+                            ret[i] = 0;
+                        } else {
+                            ret[i] = 1;
+                            numNonzero++;
+                        }
+                    }
+                    break;
+
+                case "uint32[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        if ((UInt32)input.GetValue(i) == 0) {
+                            ret[i] = 0;
+                        } else {
+                            ret[i] = 1;
+                            numNonzero++;
+                        }
+                    }
+                    break;
+
+                case "uint16[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        if ((UInt16)input.GetValue(i) == 0) {
+                            ret[i] = 0;
+                        } else {
+                            ret[i] = 1;
+                            numNonzero++;
+                        }
+                    }
+                    break;
+
+                case "int64[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        if ((Int64)input.GetValue(i) == 0) {
+                            ret[i] = 0;
+                        } else {
+                            ret[i] = 1;
+                            numNonzero++;
+                        }
+                    }
+                    break;
+
+                case "int32[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        if ((Int32)input.GetValue(i) == 0) {
+                            ret[i] = 0;
+                        } else {
+                            ret[i] = 1;
+                            numNonzero++;
+                        }
+                    }
+                    break;
+
+                case "int16[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        if ((Int16)input.GetValue(i) == 0) {
+                            ret[i] = 0;
+                        } else {
+                            ret[i] = 1;
+                            numNonzero++;
+                        }
+                    }
+                    break;
+
+                case "single[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        if ((float)input.GetValue(i) == 0) {
+                            ret[i] = 0;
+                        } else {
+                            ret[i] = 1;
+                            numNonzero++;
+                        }
+                    }
+                    break;
+
+                case "double[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        if ((double)input.GetValue(i) == 0) {
+                            ret[i] = 0;
+                        } else {
+                            ret[i] = 1;
+                            numNonzero++;
+                        }
+                    }
+                    break;
+
+                case "byte[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        if ((byte)input.GetValue(i) == 0) {
+                            ret[i] = 0;
+                        } else {
+                            ret[i] = 1;
+                            numNonzero++;
+                        }
+                    }
+                    break;
+
+                case "sbyte[]":
+                    for (int i = 0; i < input.Length; i++) {
+                        if ((sbyte)input.GetValue(i) == 0) {
+                            ret[i] = 0;
+                        } else {
+                            ret[i] = 1;
+                            numNonzero++;
+                        }
+                    }
+                    break;
+                default:
+                    throw new InvalidCastException("cannot convert from '" + input.GetType().Name + "'!");
+            }
+            return ret;
+        }
+        private static void readElementGeneric(BinaryReader br, MatFileType storageType, out System.Array realData, ref Int32 len) {
+            readElementGeneric(br, storageType, out realData, ref len, 8);
+        }
+        /// <summary>
+        /// read array of supported matlab data types 
+        /// </summary>
+        /// <param name="br">binary reader, opened and correctly positioned</param>
+        /// <param name="storageType">actual storage type</param>
+        /// <param name="realData">output: on return, the array read</param>
+        /// <param name="len">input: number of bytes to read, on return: number of elements in array</param>
+        /// <param name="paddBytes">padding border, the stream will be read to the next border of length 'paddBytes'.</param>
+        private static void readElementGeneric(BinaryReader br, MatFileType storageType, out System.Array realData, ref Int32 len, int paddBytes) {
+            Int32 readInt = len;
+            switch (storageType) {
+                case MatFileType.miINT8:
+                    realData = System.Array.CreateInstance(typeof(sbyte), readInt / sizeOf(storageType));
+                    len = realData.Length;
+                    for (int i = 0; i < len; i++) {
+                        realData.SetValue(br.ReadSByte(), i);
+                    }
+                    while (len % paddBytes != 0) {
+                        br.ReadByte();
+                        len++;
+                    }
+                    break;
+                case MatFileType.miUINT8:
+                    realData = System.Array.CreateInstance(typeof(byte), readInt / sizeOf(storageType));
+                    len = realData.Length;
+                    realData = br.ReadBytes(len);
+                    while (len % paddBytes != 0) {
+                        br.ReadByte();
+                        len++;
+                    }
+                    break;
+                case MatFileType.miINT16:
+                    realData = System.Array.CreateInstance(typeof(short), readInt / sizeOf(storageType));
+                    len = realData.Length;
+                    for (int i = 0; i < len; i++) {
+                        realData.SetValue(br.ReadInt16(), i);
+                    }
+                    while ((len * sizeOf(storageType) % paddBytes) != 0) {
+                        len++;
+                        br.ReadInt16();
+                    }
+                    break;
+                case MatFileType.miUINT16:
+                    realData = System.Array.CreateInstance(typeof(UInt16), readInt / sizeOf(storageType));
+                    len = realData.Length;
+                    for (int i = 0; i < len; i++) {
+                        realData.SetValue(br.ReadUInt16(), i);
+                    }
+                    while ((len * sizeOf(storageType) % paddBytes) != 0) {
+                        len++;
+                        br.ReadUInt16();
+                    }
+                    break;
+                case MatFileType.miINT32:
+                    realData = System.Array.CreateInstance(typeof(Int32), readInt / sizeOf(storageType));
+                    len = realData.Length;
+                    for (int i = 0; i < len; i++) {
+                        realData.SetValue(br.ReadInt32(), i);
+                    }
+                    while ((len * sizeOf(storageType) % paddBytes) != 0) {
+                        len++;
+                        br.ReadInt32();
+                    }
+                    break;
+                case MatFileType.miUINT32:
+                    realData = System.Array.CreateInstance(typeof(UInt32), readInt / sizeOf(storageType));
+                    len = realData.Length;
+                    for (int i = 0; i < len; i++) {
+                        realData.SetValue(br.ReadUInt32(), i);
+                    }
+                    while ((len * sizeOf(storageType) % paddBytes) != 0) {
+                        len++;
+                        br.ReadUInt32();
+                    }
+                    break;
+                case MatFileType.miSINGLE:
+                    realData = System.Array.CreateInstance(typeof(float), readInt / sizeOf(storageType));
+                    len = realData.Length;
+                    for (int i = 0; i < len; i++) {
+                        realData.SetValue(br.ReadSingle(), i);
+                    }
+                    while ((len * sizeOf(storageType) % paddBytes) != 0) {
+                        len++;
+                        br.ReadSingle();
+                    }
+                    break;
+                case MatFileType.miDOUBLE:
+                    realData = System.Array.CreateInstance(typeof(double), readInt / sizeOf(storageType));
+                    len = realData.Length;
+                    for (int i = 0; i < len; i++) {
+                        realData.SetValue(br.ReadDouble(), i);
+                    }
+                    while ((len * sizeOf(storageType) % paddBytes) != 0) {
+                        len++;
+                        br.ReadDouble();
+                    }
+                    break;
+                case MatFileType.miINT64:
+                    realData = System.Array.CreateInstance(typeof(Int64), readInt / sizeOf(storageType));
+                    len = realData.Length;
+                    for (int i = 0; i < len; i++) {
+                        realData.SetValue(br.ReadInt64(), i);
+                    }
+                    while ((len * sizeOf(storageType) % paddBytes) != 0) {
+                        len++;
+                        br.ReadInt64();
+                    }
+                    break;
+                case MatFileType.miUINT64:
+                    realData = System.Array.CreateInstance(typeof(UInt64), readInt / sizeOf(storageType));
+                    len = realData.Length;
+                    for (int i = 0; i < len; i++) {
+                        realData.SetValue(br.ReadUInt64(), i);
+                    }
+                    while ((len * sizeOf(storageType) % paddBytes) != 0) {
+                        len++;
+                        br.ReadInt64();
+                    }
+                    break;
+                case MatFileType.miMATRIX:
+                    throw new NotSupportedException("matrix data type not expected as inner datatype!");
+                case MatFileType.miCOMPRESSED:
+                    throw new NotSupportedException("Compressed matrix are not supported (yet)! ");
+                case MatFileType.miUTF8:
+                    realData = System.Array.CreateInstance(typeof(UTF8Encoding), readInt / sizeOf(storageType));
+                    len = realData.Length;
+                    for (int i = 0; i < len; i++) {
+                        realData.SetValue(br.ReadUInt16(), i);
+                    }
+                    while ((len * sizeOf(storageType) % paddBytes) != 0) {
+                        len++;
+                        br.ReadInt16();
+                    }
+                    break;
+                case MatFileType.miUTF16:
+                    throw new NotSupportedException("UTF16 data type not supported (yet)!");
+                case MatFileType.miUTF32:
+                    realData = System.Array.CreateInstance(typeof(UTF32Encoding), readInt / sizeOf(storageType));
+                    len = realData.Length;
+                    for (int i = 0; i < len; i++) {
+                        realData.SetValue(br.ReadChars(2), i);
+                    }
+                    while ((len * sizeOf(storageType) % paddBytes) != 0) {
+                        len++;
+                        br.ReadChars(2);
+                    }
+                    break;
+                default:
+                    throw new Exception("Unknown element data type found! Cancelling...");
+            }
+        }
+        private void write(BinaryWriter fileout) {
+            try {
+                // write MAT-header
+                StringBuilder headerLine = new StringBuilder("vers. 5.0 MAT-FILE Creator: ILNumerics, 2011");
+                while (headerLine.Length < 123)
+                    headerLine.Append(' ');
+                fileout.Write(headerLine.ToString());
+                fileout.Write((short)0x0100);
+                fileout.Write((short)0x4d49);
+                int tmpInt = 0;
+                foreach (string name in Keys) {
+                    ILBaseArray arr = this[name];
+                    using (ILScope.Enter(arr)) {
+                        // determine overall length
+                        int[] dimensionSubelement = createDimensionSubelement(arr);
+                        byte[] nameElememData; int nameElemType;
+                        createNameSubelement(name, out nameElemType, out nameElememData);
+                        // write subarray header               
+                        // mxarray subelement type
+                        fileout.Write((int)MatFileType.miMATRIX);
+                        // determine length of single array element
+                        int elemLen = getElementLength(arr);
+                        //System.Diagnostics.Debug.Assert(arr.IsMatrix,"TODO: n-dim. arrays are not implemented yet!"); 
+                        // overall length of subarray container 
+                        int allLength = 16 // array flags 
+                                      + dimensionSubelement.Length * 4   // dimension element
+                                      + nameElememData.Length + 8; // name element 
+                        int dataSubelemLen = elemLen * arr.Size.NumberOfElements + 8;
+                        // recognize padding! 
+                        if (dataSubelemLen % 8 != 0)
+                            dataSubelemLen += (8 - ((elemLen * arr.Size.NumberOfElements) % 8));
+                        allLength += dataSubelemLen;
+                        if (arr.IsComplex)
+                            allLength += dataSubelemLen;
+                        fileout.Write(allLength);
+                        // subelement: array flags 
+                        // miUInt32 , length: 8
+                        fileout.Write((int)MatFileType.miUINT32);
+                        fileout.Write(8);
+                        // write array flags  
+                        int flag = getElementClass(arr);
+                        if (arr.IsComplex)
+                            flag |= mtFLAG_COMPLEX;
+                        if (arr is ILBaseLogical)
+                            flag |= mtFLAG_LOGICAL;
+                        fileout.Write(flag);
+                        fileout.Write(0);      // this is later used for sparse arrays 
+                        // write dimensions tag     
+                        for (int i = 0; i < dimensionSubelement.Length; i++)
+                            fileout.Write(dimensionSubelement[i]);
+                        // write array name      
+                        fileout.Write((int)MatFileType.miINT8);
+                        fileout.Write(name.Length);
+                        fileout.Write(nameElememData);
+                        // write matrix elements     
+                        allLength = arr.Size.NumberOfElements;
+                        if (false) {
+
+                        } else if (arr is ILDenseArray<double>) {
+                            // header of array subdata element      
+                            fileout.Write((int) MatFileType.miDOUBLE);
+                            fileout.Write(allLength * elemLen);
+                            ILDenseArray<double> tmp = (arr as ILDenseArray<double>);
+                            
+                            double[] arrArray = tmp.GetArrayForRead();
+                            for (int i = 0; i < arr.Size.NumberOfElements; i++) {
+                                fileout.Write( //
+                                    arrArray[i]  // 
+                                );
+                            }
+
+#region HYCALPER AUTO GENERATED CODE
+
+                        } else if (arr is ILDenseArray<fcomplex>) {
+                            // header of array subdata element      
+                            fileout.Write((int) MatFileType.miSINGLE);
+                            fileout.Write(allLength * elemLen);
+                            ILDenseArray<fcomplex> tmp = (arr as ILDenseArray<fcomplex>);
+                           
+                            fcomplex[] arrArray = tmp.GetArrayForRead();
+                            for (int i = 0; i < arr.Size.NumberOfElements; i++) {
+                                fileout.Write( 
+                                    arrArray[i]  .real 
+                                );
+                            }
+                        } else if (arr is ILDenseArray<complex>) {
+                            // header of array subdata element      
+                            fileout.Write((int) MatFileType.miDOUBLE);
+                            fileout.Write(allLength * elemLen);
+                            ILDenseArray<complex> tmp = (arr as ILDenseArray<complex>);
+                           
+                            complex[] arrArray = tmp.GetArrayForRead();
+                            for (int i = 0; i < arr.Size.NumberOfElements; i++) {
+                                fileout.Write( 
+                                    arrArray[i]  .real 
+                                );
+                            }
+                        } else if (arr is ILDenseArray<UInt32>) {
+                            // header of array subdata element      
+                            fileout.Write((int) MatFileType.miUINT32);
+                            fileout.Write(allLength * elemLen);
+                            ILDenseArray<UInt32> tmp = (arr as ILDenseArray<UInt32>);
+                           
+                            UInt32[] arrArray = tmp.GetArrayForRead();
+                            for (int i = 0; i < arr.Size.NumberOfElements; i++) {
+                                fileout.Write( 
+                                    arrArray[i]   
+                                );
+                            }
+                        } else if (arr is ILDenseArray<UInt16>) {
+                            // header of array subdata element      
+                            fileout.Write((int) MatFileType.miUINT16);
+                            fileout.Write(allLength * elemLen);
+                            ILDenseArray<UInt16> tmp = (arr as ILDenseArray<UInt16>);
+                           
+                            UInt16[] arrArray = tmp.GetArrayForRead();
+                            for (int i = 0; i < arr.Size.NumberOfElements; i++) {
+                                fileout.Write( 
+                                    arrArray[i]   
+                                );
+                            }
+                        } else if (arr is ILDenseArray<Int32>) {
+                            // header of array subdata element      
+                            fileout.Write((int) MatFileType.miINT32);
+                            fileout.Write(allLength * elemLen);
+                            ILDenseArray<Int32> tmp = (arr as ILDenseArray<Int32>);
+                           
+                            Int32[] arrArray = tmp.GetArrayForRead();
+                            for (int i = 0; i < arr.Size.NumberOfElements; i++) {
+                                fileout.Write( 
+                                    arrArray[i]   
+                                );
+                            }
+                        } else if (arr is ILDenseArray<Int16>) {
+                            // header of array subdata element      
+                            fileout.Write((int) MatFileType.miINT16);
+                            fileout.Write(allLength * elemLen);
+                            ILDenseArray<Int16> tmp = (arr as ILDenseArray<Int16>);
+                           
+                            Int16[] arrArray = tmp.GetArrayForRead();
+                            for (int i = 0; i < arr.Size.NumberOfElements; i++) {
+                                fileout.Write( 
+                                    arrArray[i]   
+                                );
+                            }
+                        } else if (arr is ILDenseArray<float>) {
+                            // header of array subdata element      
+                            fileout.Write((int) MatFileType.miSINGLE);
+                            fileout.Write(allLength * elemLen);
+                            ILDenseArray<float> tmp = (arr as ILDenseArray<float>);
+                           
+                            float[] arrArray = tmp.GetArrayForRead();
+                            for (int i = 0; i < arr.Size.NumberOfElements; i++) {
+                                fileout.Write( 
+                                    arrArray[i]   
+                                );
+                            }
+                        } else if (arr is ILDenseArray<char>) {
+                            // header of array subdata element      
+                            fileout.Write((int) MatFileType.miUINT16);
+                            fileout.Write(allLength * elemLen);
+                            ILDenseArray<char> tmp = (arr as ILDenseArray<char>);
+                           
+                            char[] arrArray = tmp.GetArrayForRead();
+                            for (int i = 0; i < arr.Size.NumberOfElements; i++) {
+                                fileout.Write( (UInt16)
+                                    arrArray[i]   
+                                );
+                            }
+                        } else if (arr is ILDenseArray<byte>) {
+                            // header of array subdata element      
+                            fileout.Write((int) MatFileType.miUINT8);
+                            fileout.Write(allLength * elemLen);
+                            ILDenseArray<byte> tmp = (arr as ILDenseArray<byte>);
+                           
+                            byte[] arrArray = tmp.GetArrayForRead();
+                            for (int i = 0; i < arr.Size.NumberOfElements; i++) {
+                                fileout.Write( 
+                                    arrArray[i]   
+                                );
+                            }
+                        } else if (arr is ILDenseArray<UInt64>) {
+                            // header of array subdata element      
+                            fileout.Write((int) MatFileType.miUINT64);
+                            fileout.Write(allLength * elemLen);
+                            ILDenseArray<UInt64> tmp = (arr as ILDenseArray<UInt64>);
+                           
+                            UInt64[] arrArray = tmp.GetArrayForRead();
+                            for (int i = 0; i < arr.Size.NumberOfElements; i++) {
+                                fileout.Write( 
+                                    arrArray[i]   
+                                );
+                            }
+                        } else if (arr is ILDenseArray<Int64>) {
+                            // header of array subdata element      
+                            fileout.Write((int) MatFileType.miINT64);
+                            fileout.Write(allLength * elemLen);
+                            ILDenseArray<Int64> tmp = (arr as ILDenseArray<Int64>);
+                           
+                            Int64[] arrArray = tmp.GetArrayForRead();
+                            for (int i = 0; i < arr.Size.NumberOfElements; i++) {
+                                fileout.Write( 
+                                    arrArray[i]   
+                                );
+                            }
+                        } else if (arr is ILDenseArray<sbyte>) {
+                            // header of array subdata element      
+                            fileout.Write((int) MatFileType.miINT8);
+                            fileout.Write(allLength * elemLen);
+                            ILDenseArray<sbyte> tmp = (arr as ILDenseArray<sbyte>);
+                           
+                            sbyte[] arrArray = tmp.GetArrayForRead();
+                            for (int i = 0; i < arr.Size.NumberOfElements; i++) {
+                                fileout.Write( 
+                                    arrArray[i]   
+                                );
+                            }
+
+#endregion HYCALPER AUTO GENERATED CODE
+                       } else {
+                            throw new FormatException("The format of the array was not known!");
+                        }
+                        // pad to 8 byte border 
+                        tmpInt = allLength * elemLen;
+                        byte dummy = 0;
+                        while (tmpInt % 8 != 0) {
+                            fileout.Write(dummy);
+                            tmpInt++;
+                        }
+                        #region imaginary part
+                        if (arr.IsComplex) {
+                            if (arr is ILDenseArray<complex>) {
+                                ILDenseArray<complex> tmp = (arr as ILDenseArray<complex>);
+                                // header of array subdata element      
+                                fileout.Write((int)MatFileType.miDOUBLE);
+                                fileout.Write(allLength * elemLen);
+                                complex[] arrArray = tmp.GetArrayForRead();
+                                for (int i = 0; i < arrArray.Length; i++) {
+                                    fileout.Write(arrArray[i].imag
+                                    );
+                                }
+                            } else if (arr is ILDenseArray<fcomplex>) {
+                                fileout.Write((int)MatFileType.miSINGLE);
+                                fileout.Write(allLength * elemLen);
+                                ILDenseArray<fcomplex> tmp = (arr as ILDenseArray<fcomplex>);
+                                fcomplex[] arrArray = tmp.GetArrayForRead();
+                                for (int i = 0; i < arrArray.Length; i++) {
+                                    fileout.Write(arrArray[i].imag
+                                    );
+                                }
+                            }
+                            // pad to 8 byte border 
+                            tmpInt = allLength * elemLen;
+                            dummy = 0;
+                            while (tmpInt % 8 != 0) {
+                                fileout.Write(dummy);
+                                tmpInt++;
+                            }
+                        }
+                        #endregion
+                    }
+                }
+                fileout.Close();
+            } catch (Exception e) {
+                throw e;
+            }
+        }
+        /// <summary>
+        /// create name subelement for Matfile storage - padded to 8 byte border
+        /// </summary>
+        /// <param name="arrName">name property</param>
+        /// <param name="type">will be 'miINT8' on return</param>
+        /// <param name="data">return data array </param>
+        private void createNameSubelement(string arrName, out int type, out byte[] data) {
+            int len = arrName.Length;
+            if (len % 8 != 0)
+                len += (8 - len % 8);
+            data = new byte[len];
+            for (int i = 0; i < arrName.Length; i++) {
+                data[i] = (byte)arrName[i];
+            }
+            type = (int)MatFileType.miINT8;
+            return;
+        }
+        private int[] createDimensionSubelement(ILBaseArray arr) {
+            int[] ret;
+            int LengthInt;
+            // determine length of dimensions array byte (padding to full 8 byte border)
+            if (arr.Size.NumberOfDimensions % 2 == 0) {
+                LengthInt = (arr.Size.NumberOfDimensions + 2);
+            } else {
+                // must pad to 8 byte border
+                LengthInt = (arr.Size.NumberOfDimensions + 3);
+            }
+            ret = new int[LengthInt];
+            ret[0] = (int)MatFileType.miINT32;
+            ret[1] = arr.Size.NumberOfDimensions * 4;
+            for (int i = 0; i < arr.Size.NumberOfDimensions; i++) {
+                ret[i + 2] = arr.Size[i];
+            }
+            return ret;
+        }
+        private int IndexOf(string name) {
+            for (int i = 0; i < Count; i++) {
+                if (m_data.GetValue<string>(i, 1, 0) == name)
+                    return i;
+            }
+            return -1;
+        }
+        private string findName(ILBaseArray value) {
+            string elementType = string.Empty;
+            Type type = value.GetType();
+            if (type.GetGenericArguments() != null && type.GetGenericArguments().Length > 0) {
+                elementType = type.GetGenericArguments()[0].Name;
+            } else {
+                elementType = type.Name;
+            }
+            string dimString = String.Join("x", value.Size.ToIntArray());
+            string baseName = String.Format("{0}_{1}", elementType, dimString);
+
+            // make the new name unique
+            string tempName = baseName;
+            int postFix = 0;
+            while (IndexOf(tempName) >= 0) {
+                tempName = baseName + "_" + postFix.ToString();
+                postFix++;
+            }
+            return tempName;
+        }
+        /// <summary>
+        /// get mat file array class type corresponding to this arra element type
+        /// </summary>
+        /// <param name="arr">arra with generic system type or complex/fcomplex</param>
+        /// <returns>mat file array class type code (int value)</returns>
+        private static int getElementClass(ILBaseArray arr) {
+            Type arrType = arr.GetType();
+            if (arr is ILRetLogical || arr is ILLogical)
+                return (int)MatFileArrayClass.mxINT8_CLASS;
+            if (!arrType.IsGenericType)
+                throw new ILInvalidOperationException("The array type to be saved is not applicable!");
+            string innerType = arrType.GetGenericArguments()[0].Name;
+            switch (innerType) {
+                case "Double":
+                    return (int)MatFileArrayClass.mxDOUBLE_CLASS;
+                case "Single":
+                    return (int)MatFileArrayClass.mxSINGLE_CLASS;
+                case "Int16":
+                    return (int)MatFileArrayClass.mxINT16_CLASS;
+                case "Int32":
+                    return (int)MatFileArrayClass.mxINT32_CLASS;
+                case "Int64":
+                    return (int)MatFileArrayClass.mxINT64_CLASS;
+                case "UInt16":
+                    return (int)MatFileArrayClass.mxUINT16_CLASS;
+                case "UInt32":
+                    return (int)MatFileArrayClass.mxUINT32_CLASS;
+                case "UInt64":
+                    return (int)MatFileArrayClass.mxUINT64_CLASS;
+                case "complex":
+                    return (int)MatFileArrayClass.mxDOUBLE_CLASS;
+                case "fcomplex":
+                    return (int)MatFileArrayClass.mxSINGLE_CLASS;
+                case "Byte":
+                    return (int)MatFileArrayClass.mxUINT8_CLASS;
+                case "Char":
+                    return (int)MatFileArrayClass.mxCHAR_CLASS;
+                default:
+                    throw new ILInvalidOperationException("Arrays of inner element type: '" + innerType + "' can not be written as Matfile!");
+            }
+        }
+        /// <summary>
+        /// get storage length of inner array elements 
+        /// </summary>
+        /// <param name="arr">base array in question</param>
+        /// <returns>storage length in bytes</returns>
+        private static int getElementLength(ILBaseArray arr) {
+            Type arrType = arr.GetType();
+            string innerType;
+            if (arr is ILRetLogical || arr is ILLogical)
+                return 1;
+            if (!arrType.IsGenericType)
+                throw new ILInvalidOperationException("The array type to be saved is not applicable!");
+            innerType = arrType.GetGenericArguments()[0].Name;
+            switch (innerType) {
+                case "Double":
+                    return miSIZE_DOUBLE;
+                case "Single":
+                    return miSIZE_SINGLE;
+                case "Int16":
+                    return miSIZE_INT16;
+                case "Int32":
+                    return miSIZE_INT32;
+                case "Int64":
+                    return miSIZE_INT64;
+                case "UInt16":
+                    return miSIZE_UINT16;
+                case "UInt32":
+                    return miSIZE_UINT32;
+                case "UInt64":
+                    return miSIZE_UINT64;
+                case "complex":
+                    return miSIZE_DOUBLE;
+                case "fcomplex":
+                    return miSIZE_SINGLE;
+                case "Byte":
+                    return miSIZE_INT8;
+                case "Char":
+                    return miSIZE_UINT16;
+                default:
+                    throw new ILInvalidOperationException("Arrays of inner element type: '" + innerType + "' can not be written as Matfile!");
+            }
+        }
+        #endregion
+
+        #region public interface
+        /// <summary>
+        /// Convert MatFileType enumeration member to string representation
+        /// </summary>
+        /// <param name="type">MatFileType enumeration member</param>
+        /// <returns>String representing the Matlab's inner element type</returns>
+        /// <remarks>This function is obsolete. You may directly use the enumeration's functionality instead.</remarks>
+        public static String typeToString(MatFileType type)
+        {
+            String s;
+            switch (type)
+            {
+                case MatFileType.miUNKNOWN:
+                    s = "unknown";
+                    break;
+                case MatFileType.miINT8:
+                    s = "int8";
+                    break;
+                case MatFileType.miUINT8:
+                    s = "uint8";
+                    break;
+                case MatFileType.miINT16:
+                    s = "int16";
+                    break;
+                case MatFileType.miUINT16:
+                    s = "uint16";
+                    break;
+                case MatFileType.miINT32:
+                    s = "int32";
+                    break;
+                case MatFileType.miUINT32:
+                    s = "uint32";
+                    break;
+                case MatFileType.miSINGLE:
+                    s = "single";
+                    break;
+                case MatFileType.miDOUBLE:
+                    s = "double";
+                    break;
+                case MatFileType.miINT64:
+                    s = "int64";
+                    break;
+                case MatFileType.miUINT64:
+                    s = "uint64";
+                    break;
+                case MatFileType.miMATRIX:
+                    s = "matrix";
+                    break;
+                case MatFileType.miCOMPRESSED:
+                    s = "compressed";
+                    break;
+                case MatFileType.miUTF8:
+                    s = "uft8";
+                    break;
+                case MatFileType.miUTF16:
+                    s = "utf16";
+                    break;
+                case MatFileType.miUTF32:
+                    s = "utf32";
+                    break;
+                default:
+                    s = "unknown";
+                    break; 
+            }
+            return s;
+        }
+        /// <summary>
+        /// Add array to collection of arrays in this ILMatFile container
+        /// </summary>
+        /// <param name="A">Array to be added to ILMatFile</param>
+        /// <returns>String used to identify the array in the collection of arrays</returns>
+        /// <remarks><para>The internal <c>Name</c> property of array given will be used as identification key.</para>
+        /// <para>Note, the test if elements of A are supported by MatFile specification is done if the MatFile is to be written to stream ('write').</para></remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILInvalidOperationException">If the internal name of A does not fullfill the restrictions given by Matlab.</exception>
+        public string AddArray(ILBaseArray A, string key = "") {
+            using (ILScope.Enter(A)) {
+                string name = key;
+                if (String.IsNullOrEmpty(name)) {
+                    name = A.Name;
+                }
+                if (String.IsNullOrEmpty(name)) {
+                    name = findName(A);
+                }
+                this[name] = A;
+                return name;
+            }
+        }
+        /// <summary>
+        /// List all key names currently stored with arrays 
+        /// </summary>
+        [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.RootHidden)]
+        public IList<string> Keys {
+            get {
+                List<string> ret = new List<string>();
+                for (int i = 0; i < m_data.S[0]; i++) {
+                    ret.Add(m_data.GetValue<string>(i, 1, 0));
+                }
+                return ret;
+            }
+        }
+        /// <summary>
+        /// Retrieve a cell with all arrays stored in the mat file
+        /// </summary>
+        /// <remarks>The cell returned will be clone of the arrays stored in the mat file. Altering any cell 
+        /// elements will leave the arrays in the matfile (class/memory object) untouched.
+        /// <para>The cell returned will be of size [n,2], where n is the number of arrays contained. The 
+        /// first row saved the arrays, the second row containes scalar string arrays with the name of 
+        /// the array in the corresponding row.</para>
+        /// </remarks>
+        public ILRetCell Arrays {
+            get { return m_data.C; }
+            protected set { m_data.a = value; }
+        }
+        /// <summary>
+        /// Write this mat file into a binary stream
+        /// </summary>
+        /// <param name="stream">Stream to receive data. This will commonly be a FileStream object.</param>
+        /// <remarks>
+        /// <para>This method writes the full content of the current mat file into a binary stream. The file 
+        /// afterwards is suitable to be read again by ILNumerics.MatFile classes or by compatible *.mat file 
+        /// readers - including Matlab, e.g.</para>
+        /// <example><code>
+        /// MatFile m = new MatFile(myarrays); 
+        /// using (Stream s = new FileStream("test.mat",FileMode.Create)) {
+        ///     m.Write(s);
+        /// }
+        /// </code></example></remarks>
+        public void Write(Stream stream) {
+            using (BinaryWriter fileout = new BinaryWriter(stream)) {
+                write(fileout);
+            }
+        }
+        /// <summary>
+        /// Write all arrays to *.mat file
+        /// </summary>
+        /// <param name="filename">Filename of the file to write the mat file to</param>
+        /// <remarks>
+        /// <para>The method writes the full content of the matfile to the file specified. If the filename 
+        /// points to a file which already exists, that file will be overwritten. Otherwise a new file will
+        /// be created. </para>
+        /// <para>The file will be suitable for reading by ILNumerics.MatFile classes or by compatible *.mat file 
+        /// readers - including e.g. matlab</para>
+        /// </remarks>
+        public void Write(string filename) {
+            using (FileStream fs = new FileStream(filename, FileMode.OpenOrCreate)) {
+                Write(fs);
+            }
+        }
+        /// <summary>
+        /// Add/set arrays to the MatFile array container
+        /// </summary>
+        /// <param name="name">The name of the array for display in Matlab</param>
+        /// <remarks><para>For get access the name must exist as key in the container. Use the MatFile.Keys property to get a list of all names if needed</para>
+        /// <para>For set access, the name given must not be null or empty. It cannot be one of the <see cref="ReservedKeywords">ReservedKeywords</see>.
+        /// If the name allready exist in the collection as name, the array currently assigned to it will be replaced. If the value is null, the current array will be removed from the list. If the name does 
+        /// not already exist, the new array will be added and assigned to this name.</para>
+        /// <para>Restrictions on array names: Matlab allowes variables to have names of maximum length 63. Therefore, if the 
+        /// name given was larger than 63, it will be abbreviated. Names must start with a letter and contain only digits, (ASCII) letters or underscores '_'.</para></remarks>
+        /// <exception cref="ILArgumentException">If the name does not fullfill the restrictions given from Matlab</exception>
+        public ILBaseArray this[string name] {
+            internal get {
+                return m_data.GetBaseArray(IndexOf(name), 0); 
+            }
+            set {
+                using (ILScope.Enter(value)) {
+                    #region test if name is valid
+                    if (String.IsNullOrEmpty(name)) {
+                        name = findName(value);
+                    }
+                    foreach (string nono in ReservedKeywords) {
+                        if (name == nono)
+                            throw new ILArgumentException("MatFile: the name " + nono + " is a reserved keyword in Matlab and may not be used as array name!");
+                    }
+                    if (name.Length > 63)
+                        name = name.Substring(0, 63);
+                    if (!Char.IsLetter(name[0]))
+                        throw new ILArgumentException("MatFile: the name must start with a letter!");
+                    int i;
+                    for (i = 1; i < name.Length; i++) {
+                        char c = name[i];
+                        if (!Char.IsLetter(c) && !Char.IsDigit(c) && c != '_')
+                            throw new ILArgumentException("MatFile: variable names must contain letters, digits or underscores only!");
+                    }
+                    #endregion
+                    i = IndexOf(name);
+                    if (i >= 0) {
+                        // alter array
+                        if (object.Equals(value, null))
+                            // remove from 
+                            m_data[i, ILMath.full] = null;
+                        else
+                            m_data.SetValue(value, i, 0);
+                    } else {
+                        if (object.Equals(value, null))
+                            return;
+                        // add array 
+                        m_data.SetValue(name, m_data.S[0], 1);
+                        m_data.SetValue(value, m_data.S[0] - 1, 0);
+                    }
+                }
+            }
+        }
+        /// <summary>
+        /// Number of arrays in the mat file container
+        /// </summary>
+        public int Count { get { return m_data.S[0]; } }
+        /// <summary>
+        /// Retrieve array by name
+        /// </summary>
+        /// <typeparam name="T">Expected type of the array</typeparam>
+        /// <param name="name">Name of the array to retrieve</param>
+        /// <returns>A clone of the array found or null, if no array with the given name exists</returns>
+        public ILRetArray<T> GetArray<T>(string name) {
+            int ind = IndexOf(name);
+            if (ind >= 0)
+                return m_data.GetArray<T>(ind, 0);
+            throw new ILArgumentException("no array with name '" + name + "' found"); 
+        }
+        /// <summary>
+        /// Retrieve array by index
+        /// </summary>
+        /// <typeparam name="T">Expected type of the array</typeparam>
+        /// <param name="index">Index of the array</param>
+        /// <returns>A clone of the array found or null, if no array at the given index exists</returns>
+        public ILRetArray<T> GetArray<T>(ILBaseArray index) {
+            using (ILScope.Enter(index)) {
+                if (!index.IsScalar || !index.IsNumeric)
+                    throw new ILArgumentException("index argument must be a numeric scalar");
+                int ind = ILMath.toint32(index).GetValue(0);
+                if (ind >= m_data.S[0])
+                    throw new ILArgumentException("index argument must be in range 0..Count-1");
+                return m_data.GetArray<T>(ind, 0);
+            }
+        }
+        #endregion
+
+        #region constructors
+        /// <summary>
+        /// Create MatFile object from existing mat file 
+        /// </summary>
+        /// <param name="file2open">Path to Matlab mat file to open</param>
+        /// <remarks>Curently mat files up to Matlab version 6.5 are supported. Compressed mat file content is not supported yet.</remarks>
+        public ILMatFile(string file2open) {
+
+            using (ILScope.Enter()) {
+                m_filename = file2open;
+                using (FileStream fs = File.OpenRead(file2open)) {
+                    BinaryReader br = new BinaryReader(fs);
+                    read_header(br);
+                    // read elements 
+                    ILCell targetCell = ILMath.cell(new ILSize(0, 2), null);
+                    while (br.BaseStream.Position < br.BaseStream.Length - 7) {
+                        MatFileType dataType = (MatFileType)Enum.Parse(typeof(MatFileType), br.ReadInt32().ToString());
+                        // the length of this chunk may be used for error checking, but....
+                        int len = br.ReadInt32();
+                        switch (dataType) {
+                            case MatFileType.miCOMPRESSED:
+                                ILBaseArray mat = read_compressed(br, len);
+                                targetCell.SetValue(mat.Name, targetCell.S[0], 1); 
+                                targetCell.SetValue(mat, targetCell.S[0] - 1, 0);
+                                break;
+                            case MatFileType.miMATRIX:
+                                mat = read_miMATRIX(br);
+                                targetCell.SetValue(mat.Name, targetCell.S[0], 1); 
+                                targetCell.SetValue(mat, targetCell.S[0] - 1, 0);
+                                break;
+                            default:
+                                // ignore all other elements, not supported yet
+                                break;
+                        }
+                    }
+                    m_data.a = targetCell;
+                    br.Close();
+                }
+            }
+        }
+        /// <summary>
+        /// Create MatFile object from ILBaseArray
+        /// </summary>
+        /// <param name="input">ILBaseArray of arbitrary size/type</param>
+        /// <exception cref="ArgumentNullException">If input array was null or one of the names in the input arrays does not fullfill the restrictions made from Matlab</exception>
+        public ILMatFile(params ILBaseArray[] input) {
+            if (object.Equals(input,null))
+                throw new ArgumentNullException ("input array may not be null!"); 
+            //m_data = new ILCell(input.Length,2);
+            for (int i=0; i < input.Length; i++) {
+                if (String.IsNullOrWhiteSpace(input[i].Name)) {
+                    this["ILArray" + i.ToString()] = input[i]; 
+                } else {
+                    this[input[i].Name] = input[i]; 
+                }
+            }
+        }
+        /// <summary>
+        /// Create an empty MatFile object
+        /// </summary>
+        public ILMatFile() {
+            m_data = new ILCell(0,2);
+        }
+        #endregion
+
+
+        #region IDisposable Members
+        /// <summary>
+        /// Dispose all arrays of the matfile object
+        /// </summary>
+        /// <remarks>Calling dispose should be the last action for a matfile object. It is recommended to 
+        /// utilize the matfile class in using blocks (C#) only.</remarks>
+        public void Dispose() {
+            if (!object.Equals(m_data,null)) 
+                m_data.Dispose(); 
+        }
+
+        #endregion
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILMemoryPool.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILMemoryPool.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILMemoryPool.cs	(revision 9102)
@@ -0,0 +1,157 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections; 
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Exceptions; 
+using ILNumerics.Misc; 
+
+namespace ILNumerics {
+    /// <summary>
+    /// The ILNumerics Memory Pool is the heart of the ILNumerics memory management.
+    /// </summary>
+    /// <remarks>The pool reduces the pressure on the systems memory done by larger objects.
+    /// <para>Arrays created in ILNumerics will try to reclaim its memory from this pool. If attempt fails, the memory is gathered from the managed heap normally.</para>
+    /// <para>Disposed array objects register their underlying storage in the pool for later reusing. The process is triggered by a deterministic disposal 
+    /// pattern in conjunction with <a href="http://ilnumerics.net/$Arrays.html">ILNumerics array types</a> and <a href="http://ilnumerics.net/$FunctionRules.html">ILNumerics Function Rules</a>.</para></remarks>
+    /// <see cref=""/>
+    public sealed class ILMemoryPool {
+        /// <summary>
+        /// The only global ILMemoryPool instance 
+        /// </summary>
+        public static readonly ILMemoryPool Pool = new ILMemoryPool();
+        internal static readonly Dictionary<Type,IILMemoryPool> Pools = new Dictionary<Type,IILMemoryPool>(); 
+        ///// <summary>
+        ///// todo: remove!! 
+        ///// </summary>
+        ///// <typeparam name="T"></typeparam>
+        ///// <returns></returns>
+        //public void SetIncrementLenghtPercent<T>(double value) {
+        //    ILMemoryPoolInternal<T>.Pool.MaxRequestedLengthIncrease = value; 
+        //}
+        //public double GetIncrementLenghtPercent<T>()
+        //{
+        //    return ILMemoryPoolInternal<T>.Pool.MaxRequestedLengthIncrease;
+        //}
+        internal long MinArrayLength<T>()
+        {
+            return ILMemoryPoolInternal<T>.Pool.MinArrayLength;
+        }
+        //public void SetMinArrayLength<T>(long value) {
+        //    ILMemoryPoolInternal<T>.Pool.MinArrayLength = value;
+        //}
+        /// <summary>
+        /// Get new array of type T from memory pool.
+        /// </summary>
+        /// <typeparam name="T">Element type</typeparam>
+        /// <param name="length">Size of T[]</param>
+        /// <param name="clear">If true, set the elements in T[] to default(T)</param>
+        /// <param name="cleared">Always true if <paramref name="clear"/> was set. Otherwise this will be true if the array was newly created instead of being recycled from the pool. False otherwise.</param>
+        /// <remarks><para>If the pool contains an unused matching element of sufficient size this element will be returned. If <paramref name="clear"/> was false,
+        /// the result might still contain the old data.</para>
+        /// <para>If the pool does not contain a matching element a new one is created.</para>
+        /// <para><b>Note:</b> The returned array may be larger than requested if it was recycled from the pool.</para></remarks>
+        /// <returns>An array of type T of at least length <paramref name="length"/></returns>
+        public T[] New<T>(long length, bool clear, out bool cleared) {
+            return ILMemoryPoolInternal<T>.Pool.New(length, clear, out cleared);
+        }
+
+        /// <summary>
+        /// Get a new array of type T from the memory pool
+        /// </summary>
+        /// <typeparam name="T">Element type</typeparam>
+        /// <param name="length">Required minimum length</param>
+        /// <remarks>The returned array is only guaranteed to have at least length <paramref name="length"/>. If it is recycled from the pool it may be longer.
+        /// There is no guarantee on the values contained in the returned array. To force these to have a default value use <see cref="ILMemoryPool.New&lt;T&gt;(long length, bool clear, out bool cleared)"/></remarks>
+        /// <returns>An array of type T of at least length <paramref name="length"/>.</returns>
+        public T[] New<T>(long length)
+        {
+            return ILMemoryPoolInternal<T>.Pool.New(length);
+        }
+
+        /// <summary>
+        /// Return a array of type T that is not needed anymore to the pool.
+        /// </summary>
+        /// <typeparam name="T">Element type</typeparam>
+        /// <param name="array">The array to add to the pool</param>
+        /// <remarks>You may also "free" objects not retrieved from the pool, in which case they are registered in the pool.</remarks>
+        public void Free<T>(T[] array) {
+            ILMemoryPoolInternal<T>.Pool.Free(array); 
+        }
+
+       
+        /// <summary>
+        /// Get maximal potential size of the memory pool for objects of type T
+        /// </summary>
+        /// <typeparam name="T">Element type</typeparam>
+        /// <returns>Maximal number of bytes in pool</returns>
+        public long MaxBytes<T>() {
+            return ILMemoryPoolInternal<T>.Pool.MaxBytes; 
+        }
+
+        /// <summary>
+        /// Reset &amp; reconfigure the pool 
+        /// </summary>
+        /// <param name="MinPoolArrayLen">Minimum length for array object to be stored inside the pool</param>
+        /// <param name="maxSizeMB">Overall size the memory pool consumes at most</param>
+        /// <remarks>Reset will dispose all objects currently hold in the pool!</remarks>
+        public void Reset<T>(long MinPoolArrayLen, int maxSizeMB) {
+            ILMemoryPoolInternal<T>.Pool.Reset(MinPoolArrayLen, maxSizeMB); 
+        }
+
+        /// <summary>
+        /// Give information about pool state
+        /// </summary>
+        /// <param name="shortVersion">true (default): abbreviate infos to: current MB in Pool, reclaimed MB for livetime, reclaimed objects for livetime. False: give full info</param>
+        /// <returns>Infos about current pool state</returns>
+        public string Info(bool shortVersion = true) {
+            if (Pools.ContainsKey(typeof(double))) {
+                return Pools[typeof(double)].Info(shortVersion); 
+            } else if (Pools.Count > 0) {
+                foreach (IILMemoryPool pool in Pools.Values) {
+                    return pool.Info(shortVersion); 
+                }
+            }
+            return "no pool found"; 
+        }
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILMemoryPoolInternal.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILMemoryPoolInternal.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILMemoryPoolInternal.cs	(revision 9102)
@@ -0,0 +1,642 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections; 
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Exceptions; 
+using ILNumerics.Data; 
+
+namespace ILNumerics.Misc {
+    /// <summary>
+    /// Memory pool serving as temporary storage for System.Array objects
+    /// </summary>
+    /// <remarks>The pool reduces the pressure on the systems memory caused by larger objects.
+    /// <para>Arrays created in ILNumerics will first try to reclaim their memory from this pool. If that 
+    /// fails, the memory is allocated from the managed heap only.</para>
+    /// <para>Disposed array objects register their underlying System.Array in the pool for 
+    /// later reusing. The process is triggered by the ILNumerics memory management automatically.</para></remarks>
+    internal partial class ILMemoryPoolInternal<T> : IILMemoryPool {
+
+        internal enum MemoryPoolShrinkStrategies {
+            Popularity, 
+            Smallest
+        }
+
+        #region attributes
+        private Dictionary<long,Stack<T[]>> m_pool; 
+        private Dictionary<long,int> m_requests;
+        private ILAVLTree m_lengths; 
+        private Dictionary<long, string> m_profiler; 
+        private long m_maxBytes; 
+        private long m_curBytes; 
+        private long m_minArrLength;
+        private long m_reclaimedBytesCount;
+        private long m_reclaimedObjectsCount;
+        private int m_catchedOOMs; 
+        private bool[] m_rateHistVals = new bool[100]; 
+        private int m_rateHistPos = 0;
+        private int m_shrinksCount = 0;  
+        private int m_curObjectsCount = 0;
+        private double m_autoIncreaseNewRequests = 1.1;
+        private double m_maxRequestedLengthIncrease = 1.2;
+        private double m_maxBytesIncreaseRate = 1.02;
+        private double m_OOMdecreaseMaxBytesRate = 0.8;
+        private Comparer<KeyValuePair<long, int>> m_comparer = new ILRequestsValueComparer(); 
+        private static readonly int s_singleElementSize;
+        private static readonly double s_shrinkPercent = .5;
+        private static readonly double s_shrinkRequestLenghtIncreaseRate; 
+        private static readonly string s_elementTypeName; 
+        internal static ILMemoryPoolInternal<T> Pool; 
+        internal static ILPerformanceCounter<T> s_performanceCounters = new ILPerformanceCounter<T>(); 
+#if VERBOSE
+        internal static string s_logfilename = String.Format("ILMemoryPool_VERBOSE_Log_{0}.log",typeof(T).Name); 
+        internal static StringBuilder s_logBuilder = new StringBuilder("ILMemoryPoolInternal allocation history from " + DateTime.Now.ToShortDateString() + " " + DateTime.Now.ToShortTimeString() + Environment.NewLine); 
+#endif 
+        #endregion
+
+        #region properties
+        /// <summary>
+        /// factor used, to allow returned arrays to exceed the requested array length
+        /// </summary>
+        public double MaxRequestedLengthIncrease {
+            get { return m_maxRequestedLengthIncrease; }
+            set {
+                m_maxRequestedLengthIncrease = value;
+                if (Settings.s_measurePerformanceAtRuntime)
+                    s_performanceCounters.PCAcceptLengthIncreaseSet((int)Math.Log10(m_maxRequestedLengthIncrease)); 
+            }
+        }
+        /// <summary>
+        /// minimum length of array objects for recognition in the pool (default: 80k)
+        /// </summary>
+        public long MinArrayLength {
+            get { return m_minArrLength; }
+            set { m_minArrLength = value; }
+        }
+        /// <summary>
+        /// maximum size of the pool configured in bytes
+        /// </summary>
+        public long MaxBytes {
+            get { return m_maxBytes; }
+            set { 
+                m_maxBytes = value;
+                if (Settings.s_measurePerformanceAtRuntime) 
+                    s_performanceCounters.PCmaximumPoolSizeSet(m_maxBytes); 
+            }
+        }
+        /// <summary>
+        /// percentage of allocation requests which could be successfully be completed
+        /// </summary>
+        public double SuccessRate {
+            get  {
+                int succ = 0; 
+                foreach (bool b in m_rateHistVals) {
+                    if (b) succ++; 
+                }
+                return succ / (double)m_rateHistVals.Length * 100d; 
+            }
+        }
+        /// <summary>
+        /// Number of reclaimed bytes since the pool exists
+        /// </summary>
+        /// <remarks>The counter will be reset by calls to <see cref="ILNumerics.Misc.ILMemoryPool.Reset(int, int)"/></remarks>
+        public long ReclaimedBytesCount {
+            get { return m_reclaimedBytesCount; }
+        }
+        /// <summary>
+        /// Number of reclaimed objects since the pool exists
+        /// </summary>
+        /// <remarks>The counter will be reset by calls to <see cref="ILNumerics.Misc.ILMemoryPool.Reset(int, int)"/></remarks>
+        public long ReclaimedObjectsCount {
+            get { return m_reclaimedObjectsCount; }
+        }
+        #endregion
+
+        #region constructors
+        private ILMemoryPoolInternal() 
+            : this (getDefaultMinArrayLength(),200) {} // (int)(Environment.WorkingSet / 1024.0 / 1024 / 10)) { }
+
+        private ILMemoryPoolInternal(int MinArrayLength, int PoolSizeMB) {
+            m_maxBytes = PoolSizeMB * 1024 * 1024; 
+            m_minArrLength = MinArrayLength; 
+            m_requests = new Dictionary<long,int>(); 
+            m_pool = new Dictionary<long,Stack<T[]>>(); 
+            m_lengths = new ILAVLTree(); 
+            m_profiler = new Dictionary<long,string>(); 
+            MaxRequestedLengthIncrease = 1.2; 
+            ILMemoryPool.Pools.Add(typeof(T),this); 
+        }
+
+        static ILMemoryPoolInternal() {
+            if (typeof(T).IsValueType) {
+                T tmp = default(T);
+                s_singleElementSize = Math.Max(System.Runtime.InteropServices.Marshal.SizeOf(tmp), 1);
+            } else {
+                s_singleElementSize = 4; 
+            }
+            Pool = new ILMemoryPoolInternal<T>();
+            s_elementTypeName = typeof(T).Name; 
+
+#if DEBUG   
+            //System.Diagnostics.StackTrace.METHODS_TO_SKIP
+#endif
+
+#if VERBOSE
+            // manage log file 
+            System.IO.File.Delete(s_logfilename); 
+#endif
+        }
+
+        #endregion
+
+        #region public API
+        /// <summary>
+        /// Reset &amp; reconfigure the pool 
+        /// </summary>
+        /// <param name="MinArrayLength">Minimum length for array object to be stored inside the pool</param>
+        /// <param name="PoolSizeMB">Overall size the memory pool consumes at most</param>
+        /// <remarks>Reset will dispose all objects currently hold in the pool!</remarks>
+        public void Reset ( long MinArrayLength, int PoolSizeMB ) {
+            lock (this) {
+                if (PoolSizeMB < 10) 
+                    PoolSizeMB = 10; 
+                m_maxBytes = PoolSizeMB * 1024 * 1024; 
+                m_minArrLength = MinArrayLength; 
+                DisposeContent(); 
+                m_reclaimedBytesCount = 0; 
+                m_reclaimedObjectsCount = 0; 
+            }
+        }
+        /// <summary>
+        /// Dispose all objects currently hold in the pool 
+        /// </summary>
+        /// <remarks>The pool get cleared and continues working with the same parameters after the call has finished. </remarks>
+        public void DisposeContent() {
+            lock (this) {
+                //m_requests.Clear(); // lets keep the statistics
+                m_pool.Clear(); 
+                m_lengths.Clear();
+                m_requests.Clear(); 
+                m_curBytes = 0;
+                m_curObjectsCount = 0;
+
+                if (Settings.s_measurePerformanceAtRuntime) {
+                    s_performanceCounters.PCoverallSizeSet(0);
+                }
+            }
+        }
+        /// <summary>
+        /// Return or register an array object of value type in the pool that is not used anymore, i.e. free it
+        /// </summary>
+        /// <typeparam name="T">arbitrary element type</typeparam>
+        /// <param name="arr">array</param>
+        /// <remarks><para>In order to be stored in the pool, the array must meet the minimum array length and must fit into the global pool size.
+        /// Null objects or empty arrays or array not suitable for the pool will be silently ignored.</para>
+        /// <para>If the new array is too large to fit into the remaining pool space, the oldest objects in the pool will be released until the object can get registered.</para></remarks>
+        public void Free(T[] arr) {
+#if VERBOSE
+            //System.Diagnostics.Debug.WriteLine("ILMemoryPoolInternal registering array: {0}[] {1}",typeof(T).Name, arr.Length);  
+            Log(arr.Length,"REG"); 
+#endif 
+            if (arr == null || arr.Length == 0 || arr.Length < m_minArrLength)
+                return; 
+#if DEBUG 
+                //System.Diagnostics.StackTrace st = new System.Diagnostics.StackTrace(); 
+                //DebuggerTraceHelper.Output.Append(String.Format("\r\n{0}[{1}]-{2}\r\n{3}\r\n======================================"
+                //    ,arr.ToString(), arr.Length, arr.GetHashCode() ,st.ToString()));
+                //DebuggerTraceHelper.Output.Append(String.Format("=============================")); 
+#endif
+            if (!String.IsNullOrEmpty(Settings.s_memoryPoolProfileFileName)) {
+                lock (m_profiler) {
+                    int key = arr.GetHashCode();
+                    if (m_profiler.ContainsKey(key))
+                        m_profiler.Remove(key);
+                }
+            }
+            // determine size of new array
+            long newSize = arr.Length * s_singleElementSize + 8; // up to .NET 4.0
+            if (newSize >= m_maxBytes) {
+                m_maxBytes = newSize+1; 
+                return; 
+            }
+            lock (this) {
+                if (m_curBytes + newSize > m_maxBytes) 
+                    Shrink(newSize); 
+                // add the array to the pool 
+                Stack<T[]> inPool; 
+                if (m_pool.TryGetValue(arr.Length, out inPool)) {
+                    // append to pool
+                    System.Diagnostics.Debug.Assert(!inPool.Contains(arr)); 
+                    inPool.Push(arr);
+                } else {
+                    // add new length to pool 
+                    inPool = new Stack<T[]>(); 
+                    inPool.Push(arr); 
+                    m_pool.Add(arr.Length,inPool);     
+                }
+                m_lengths.Add(arr.Length);
+                m_curObjectsCount++; 
+                m_curBytes += newSize;
+                if (Settings.s_measurePerformanceAtRuntime) {
+                    s_performanceCounters.PCoverallSizeSet(m_curBytes);
+                    s_performanceCounters.PCcurObjectsCountSet(m_curObjectsCount);
+                }
+            }
+        }
+        /// <summary>
+        /// Request a System.Array instance, may not be cleared
+        /// </summary>
+        /// <typeparam name="T">value type</typeparam>
+        /// <param name="length"><b>minimum</b> length of array</param>
+        /// <returns>System.Array - either from the pool or a newly created array</returns>
+        /// <remarks><para>If a suitable System.Array was found in the pool, this object is returned. 
+        /// Otherwise a new array is created.</para>
+        /// <para>There is no way of determining, if the array was reclaimed from pool or newly created! 
+        /// If you must be sure, the element values are set to default(T), call the overloaded version 
+        /// <see cref="ILNumerics.Misc.ILMemoryPool.New&lt;T&gt;(int, bool, out bool)"/> instead!</para>
+        /// <para>If a new array could not get created due to an OutOfMemoryException, a garbage collection
+        /// is triggered and the array is again requested from the pool. If this again fails, another attempt 
+        /// to create the array is done. Exceptions may thrown from this last attempt are not catched and 
+        /// therefore must be handled by the calling function.</para></remarks>
+        public T[] New(long length) {
+#if VERBOSE
+            //System.Diagnostics.Debug.WriteLine(String.Format("Pool<{0}>: requesting length: {1}", typeof(T).Name, length));
+            Log((int)length,"NEW"); 
+#endif 
+            T[] ret = null;
+            lock (this) {
+                // try to find a suitable object in the pool first 
+                if (length >= m_minArrLength && (ret = GetFromPool(length)) != null) {
+                    int oldRequestCount = 0;
+                    length = ret.Length; 
+                    m_requests.TryGetValue(length, out oldRequestCount);
+                    m_requests[length] = ++oldRequestCount;
+                    return ret;
+                }
+            }
+            // must create a new one
+            try {
+                length = (long)(m_autoIncreaseNewRequests * length);
+                ret = new T[length];
+            } catch (OutOfMemoryException) {
+                m_catchedOOMs++;
+                m_maxBytes = (long) (m_maxBytes * m_OOMdecreaseMaxBytesRate);
+                if (Settings.s_measurePerformanceAtRuntime) {
+                    s_performanceCounters.PCOOMcatchedIncrement();
+                }
+                DisposeContent();
+            }
+            if (ret == null) {
+                ret = new T[length];
+            }
+            lock (this) {
+                int oldRequestCount = 0;
+                m_requests.TryGetValue(length, out oldRequestCount);
+                m_requests[length] = ++oldRequestCount;
+            }
+            return ret;
+        }
+        /// <summary>
+        /// Request a System.Array instance and optionally clear the array
+        /// </summary>
+        /// <typeparam name="T">value type</typeparam>
+        /// <param name="length">length of array</param>
+        /// <param name="clear">if true, the elements of the array returned are set to default(T).</param>
+        /// <param name="iscleared">out paramater determining if the array returned has been cleared</param>
+        /// <returns>System.Array - either from the pool or a newly created array</returns>
+        /// <remarks><para>If a suitable System.Array was found in the pool, this object is returned. Otherwise a new array is created.</para>
+        /// <para>If the <paramref name="clear">clear </paramref> parameter was set to false, the
+        /// <paramref name="iscleared">iscleared</paramref> parameter can be used to determine, if the object
+        /// was returnd from the pool and may need extra clearing.</para>
+        /// <para>If a new array could not get created due to an OutOfMemoryException, a garbage 
+        /// collection is triggered and the array is again requested from the pool. If this again failes, 
+        /// another attempt to create the array is done. Exceptions eventually thrown from this last 
+        /// attempt are not catched and given back to the callee.</para></remarks>
+        public T[] New(long length, bool clear, out bool iscleared) {
+#if VERBOSE
+            //System.Diagnostics.Debug.Write(String.Format("Pool<{0}>: requesting length: {1}", typeof(T).Name, length));
+            Log(length,"NEW"); 
+#endif 
+            T[] ret = null;
+            lock (this) {
+                // try to find a suitable object in the pool first 
+                if (length >= m_minArrLength && (ret = GetFromPool(length)) != null) {
+                    int oldRequestCount = 0;
+                    length = ret.Length; 
+                    m_requests.TryGetValue(length, out oldRequestCount);
+                    m_requests[length] = ++oldRequestCount;
+                    if (clear) {
+                        for (int i = 0; i < length; i++) {
+                            ret[i] = default(T);
+                        }
+                        iscleared = true;
+                    } else {
+                        iscleared = false;
+                    }
+                    return ret;
+                }
+            }
+            // must create a new one
+            try {
+                length = (int)(m_autoIncreaseNewRequests * length);
+                ret = new T[length];
+            } catch (OutOfMemoryException) {
+                DisposeContent();
+                m_maxBytes = (long)(m_maxBytes * m_OOMdecreaseMaxBytesRate);
+                m_catchedOOMs++;
+                if (Settings.s_measurePerformanceAtRuntime) {
+                    s_performanceCounters.PCOOMcatchedIncrement();
+                }
+            }
+            if (ret == null) {
+                ret = new T[length];
+            }
+            iscleared = true;
+            lock (this) {
+                int oldRequestCount = 0;
+                length = ret.Length;
+                m_requests.TryGetValue(length, out oldRequestCount);
+                m_requests[length] = ++oldRequestCount;
+            }
+            return ret;
+        }
+        /// <summary>
+        /// Give infos about pool state, optionally reset counters
+        /// </summary>
+        /// <param name="shortVersion">true: abbreviate infos to: current MB in Pool, reclaimed MB for livetime, reclaimed objects for livetime. False: give full info (see below)</param>
+        /// <param name="reset">true: reset internal counter for reclaimed objects/ - bytes</param>
+        /// <returns>infos about current pool state</returns>
+        public string Info(bool shortVersion, bool reset) {
+            if (shortVersion) {
+                string s = String.Format("CurMB: {0}| CurObj: {1}| ReclMB: {2}| ReclObj: {3}| Rate: {4:G6}",m_curBytes/1024/1024,countObj(),m_reclaimedBytesCount/1024/1024,m_reclaimedObjectsCount,SuccessRate); 
+                if (reset) {
+                    m_reclaimedBytesCount = 0; 
+                    m_reclaimedObjectsCount = 0; 
+                }
+                return s; 
+            } else {
+                StringBuilder sb = new StringBuilder(); 
+                sb.Append("ILMemoryPool - "); 
+                sb.Append(DateTime.Now.ToLongTimeString() + Environment.NewLine);
+                string tmp; 
+                lock (this) {
+                    sb.Append(String.Format("CurMB: {0}| CurObj: {1}| ReclMB: {2}| ReclObj: {3}| Rate: {4:G6}",m_curBytes/1024/1024,countObj(),m_reclaimedBytesCount/1024/1024,m_reclaimedObjectsCount,SuccessRate) + Environment.NewLine); 
+                    sb.Append(String.Format("OOM: {0}| Shrink: {1:}| LFact: {2:G2}| MaxMB: {3}\r\n",m_catchedOOMs, m_shrinksCount, m_maxRequestedLengthIncrease, m_maxBytes/1024/1024)); 
+                    foreach (KeyValuePair<long,Stack<T[]>> item in m_pool) {
+                        sb.Append(item.Key + ": "); 
+                        foreach(Array a in item.Value) {
+                            tmp = a.GetType().GetElementType().Name; 
+                            if (char.IsNumber(tmp[tmp.Length-1])) {
+                                tmp = new String(new char[]{tmp[0], tmp[tmp.Length-1]}); 
+                            } else {
+                                tmp = tmp.Substring(0,2);
+                            }
+                            sb.Append(tmp); 
+                            sb.Append(" "); 
+                        }
+                        sb.Append(Environment.NewLine); 
+                    }
+                    if (reset) {
+                        m_reclaimedBytesCount = 0; 
+                        m_reclaimedObjectsCount = 0; 
+                    }
+                }
+                return sb.ToString(); 
+            }
+        }
+        /// <summary>
+        /// Give extended infos about pool state
+        /// </summary>
+        /// <returns>Full info about current and reclaimed pool objects</returns>
+        /// <remarks>For short version infos use the overloaded version <see cref="ILNumerics.Misc.ILMemoryPool.Info(bool)"/></remarks>
+        public string Info() {
+            return Info(false, false); 
+        }
+        /// <summary>
+        /// Give infos about pool state, optionally reset counters
+        /// </summary>
+        /// <param name="shortVersion">true: abbreviate infos to: current MB in Pool, reclaimed MB for livetime, reclaimed objects for livetime. False: give full info (see below)</param>
+        /// <returns>infos about current pool state</returns>
+        public string Info(bool shortVersion) {
+            return Info(shortVersion, false); 
+        }
+        #endregion
+
+        #region private helper
+#if VERBOSE
+        private void Log( int length, string prefix ) {
+            lock (this) {
+                s_logBuilder.Append(
+                    String.Format("{0},\t{1},\t{2},\t{3}" + Environment.NewLine
+                                    , prefix
+                                    , System.DateTime.Now.ToShortDateString()
+                                    , System.DateTime.Now.ToLongTimeString() + "." + System.DateTime.Now.Millisecond.ToString()
+                                    , length));
+                if (s_logBuilder.Length > 10000) {
+                    System.IO.File.AppendAllText(s_logfilename, s_logBuilder.ToString()); 
+                    s_logBuilder.Clear();
+                }
+            }
+        }
+#endif
+        private T[] GetFromPool(long length) {
+            Stack<T[]> inPool; 
+            T[] ret = null; 
+            lock (this) {
+                if (m_pool.TryGetValue(length, out inPool)) {
+                    ret = inPool.Pop();
+                    long newSize = (ret.Length * s_singleElementSize + 8);
+                    m_curBytes -= newSize;
+                    m_curObjectsCount--;
+                    if (Settings.s_measurePerformanceAtRuntime) {
+                        s_performanceCounters.PCcurObjectsCountSet(m_curObjectsCount);
+                        s_performanceCounters.PCoverallSizeSet(m_curBytes);
+                        s_performanceCounters.PCsuccessRateIncrement();
+                        s_performanceCounters.PCsuccessRateBaseIncrement();
+                        s_performanceCounters.PCreclaimedObjectsCountIncrement();
+                    }
+                    if (inPool.Count == 0) {
+                        m_pool.Remove(length);
+                        m_lengths.Remove(length);
+                        m_requests.Remove(length);
+                    }
+                    m_reclaimedObjectsCount += 1;
+                    m_reclaimedBytesCount += newSize;
+                    m_rateHistVals[m_rateHistPos++] = true;
+                    if (m_rateHistPos >= m_rateHistVals.Length)
+                        m_rateHistPos = 0;
+                } else {
+                    // try to get next larger array 
+                    long largerLength = m_lengths.Next(length);
+                    if (largerLength >= 0 && largerLength <= length * m_maxRequestedLengthIncrease) {
+                        return GetFromPool(largerLength); 
+                    }
+                }
+            }
+            if (ret == null) {
+                m_rateHistVals[m_rateHistPos++] = false;
+                if (Settings.s_measurePerformanceAtRuntime) {
+                    s_performanceCounters.PCsuccessRateBaseIncrement();
+                }
+                if (m_rateHistPos >= m_rateHistVals.Length) 
+                    m_rateHistPos = 0; 
+            } else if (!String.IsNullOrEmpty(Settings.s_memoryPoolProfileFileName)) {
+                lock (m_profiler) {
+                    int key = ret.GetHashCode();
+                    m_profiler[key] = s_elementTypeName + "[" + length + "] - " + new System.Diagnostics.StackTrace(4).ToString();
+                    if (m_profiler.Count > 500) {
+                        //throw new Exception("The profiler status indicates the existence of a memory leak! Check the stack traces for common functions requesting an array which is never returnd to the pool!");
+                        System.IO.File.WriteAllText(Settings.s_memoryPoolProfileFileName, 
+                                String.Join(Environment.NewLine, m_profiler.Values)); 
+                        m_profiler.Clear(); 
+                    } 
+                }
+            }
+            return ret; 
+        }
+        private int countObj() {
+            int ret = 0; 
+            lock (this)
+            foreach (KeyValuePair<long,Stack<T[]>> item in m_pool) {
+                foreach(Array a in item.Value) {
+                    ret ++; 
+                }
+            }
+            return ret; 
+        }
+        private static int getDefaultMinArrayLength() {
+            T[] tmp = new T[0];
+            if (tmp is double[]) {
+                return 500; 
+            } else {
+                return 70 * 1024 / s_singleElementSize; 
+            }
+        }
+        /// <summary>
+        /// shrink the pool's content to SHRINK_PERCENT of the maximum pool size or at the size, suitable to store requestLen
+        /// </summary>
+        /// <param name="requestLen">minimum length to make available (bytes)</param>
+        private void Shrink(long requestLen) {
+            try {
+                long targetSize = Math.Min(m_maxBytes - requestLen, (long)(s_shrinkPercent * m_maxBytes));
+                if (m_curBytes <= targetSize)
+                    return;
+                if (Settings.s_measurePerformanceAtRuntime) {
+                    s_performanceCounters.PCshrinksCountIncrement();
+                } m_shrinksCount++;
+                // recalculate new parameters
+                m_maxBytes = (long)(m_maxBytesIncreaseRate * m_maxBytes);
+                if (m_pool.Count <= 1) {
+                    MaxRequestedLengthIncrease /= 1.02; 
+                } else {
+                    MaxRequestedLengthIncrease *= 1.02; 
+                }
+
+                // first clear all arrays in pool, which were not requested
+                List<int> keys4Remove = new List<int>();
+                foreach (int key in m_pool.Keys) {
+                    if (!m_requests.ContainsKey(key)) {
+                        keys4Remove.Add(key);
+                    }
+                }
+                foreach (int key in keys4Remove) {
+                    int size = key * s_singleElementSize + 8;
+                    Stack<T[]> arrays = m_pool[key];
+                    while (arrays.Count > 0) {
+                        arrays.Pop();
+                        m_curBytes -= size;
+                        m_curObjectsCount--;
+                        //if (m_curBytes < targetSize) return; 
+                    }
+                    if (arrays.Count == 0) {
+                        m_requests.Remove(key);
+                        m_pool.Remove(key);
+                        m_lengths.Remove(key);
+                    }
+                }
+                if (m_curBytes < targetSize) {
+                    if (Settings.s_measurePerformanceAtRuntime) {
+                        s_performanceCounters.PCoverallSizeSet(m_curBytes);
+                        s_performanceCounters.PCcurObjectsCountSet(m_curObjectsCount);
+                    }
+                    return;
+                }
+                // sort requests statistics by its values 
+
+                List<KeyValuePair<long, int>> sorted = new List<KeyValuePair<long, int>>(m_requests);
+                sorted.Sort(m_comparer);
+                foreach (KeyValuePair<long, int> item in sorted) {
+                    long curKey = item.Key;
+                    Stack<T[]> inPool;
+                    if (!m_pool.TryGetValue(curKey, out inPool)) {
+                        continue;
+                    }
+                    while (inPool.Count > 0 && m_curBytes > targetSize) {
+                        inPool.Pop();
+                        m_curBytes -= ((long)curKey * s_singleElementSize + 8);
+                        m_curObjectsCount--;
+                    }
+                    if (inPool.Count == 0) {
+                        m_lengths.Remove(curKey);
+                        m_pool.Remove(curKey);
+                        m_requests.Remove(curKey);
+                    }
+                    if (m_curBytes <= targetSize) {
+                        if (Settings.s_measurePerformanceAtRuntime) {
+                            s_performanceCounters.PCoverallSizeSet(m_curBytes);
+                            s_performanceCounters.PCcurObjectsCountSet(m_curObjectsCount);
+                        }
+                        return;
+                    }
+                }
+                if (Settings.s_measurePerformanceAtRuntime) {
+                    s_performanceCounters.PCoverallSizeSet(m_curBytes);
+                    s_performanceCounters.PCcurObjectsCountSet(m_curObjectsCount);
+                }
+            } finally {
+                m_requests.Clear(); 
+            }
+        }
+        #endregion
+
+    }
+}
+
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILNRandom.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILNRandom.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILNRandom.cs	(revision 9102)
@@ -0,0 +1,76 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace ILNumerics.Misc {
+    internal class ILNRandom {
+        private double m_spareRand = 0; 
+        private bool m_hasSpareRand = false; 
+        private Random m_rand; 
+
+        public ILNRandom (int seed) {
+            m_rand = new Random(seed); 
+        }
+        public ILNRandom() {
+            m_rand = new Random(Environment.TickCount); 
+        }
+
+        public double NextDouble() {
+            if (m_hasSpareRand) {
+                m_hasSpareRand = false; 
+                return m_spareRand; 
+            } else {
+                double v1 = 0.0, v2, rsq = 0.0, fac = 0.0;  
+                do {
+                    v1 = 2.0 * m_rand.NextDouble() -1.0; 
+                    v2 = 2.0 * m_rand.NextDouble() -1.0; 
+                    rsq = v1 * v1 + v2 * v2; 
+                } while (rsq >= 1.0 || rsq == 0.0); 
+                fac = Math.Sqrt(-2.0 * Math.Log(rsq) / rsq); 
+                m_spareRand = v1 * fac; 
+                m_hasSpareRand = true; 
+                return v2 * fac; 
+            }
+        }
+        
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILPerformanceCounterMemoryPool.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILPerformanceCounterMemoryPool.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILPerformanceCounterMemoryPool.cs	(revision 9102)
@@ -0,0 +1,179 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Diagnostics; 
+
+namespace ILNumerics.Misc {
+
+    internal partial class ILMemoryPoolInternal<T> : IILMemoryPool {
+        internal class ILPerformanceCounter<Ti> {
+            // some constants (may get localized)
+            private static readonly string PERFORMANCECOUNTER_CATEGORY_NAME = "ILNumerics Memory Pool";
+            private static readonly string PERFORMANCECOUNTER_CATEGORY_NAME_HELP = "Monitors usage statistics for the ILNumerics Memory Pool";
+            private static readonly string PERFORMANCECOUNTER_OVERALLSIZE = "Overall Bytes";
+            private static readonly string PERFORMANCECOUNTER_OVERALLSIZE_HELP = "Sum of the sizes of all arrays currently hold in the pool.";
+            private static readonly string PERFORMANCECOUNTER_OOMCATCHED = "Number of catched OOMs";
+            private static readonly string PERFORMANCECOUNTER_OOMCATCHED_HELP = "The overall number of OutOfMemoryExceptions catched since the application started.";
+            private static readonly string PERFORMANCECOUNTER_SUCCESS_RATE = "Success Rate %";
+            private static readonly string PERFORMANCECOUNTER_SUCCESS_RATE_HELP = "Gives the percentage of successfully reused arrays for the last 100 requests.";
+            private static readonly string PERFORMANCECOUNTER_CUR_OBJECTS_COUNT = "Current Objects Count";
+            private static readonly string PERFORMANCECOUNTER_CUR_OBJECTS_COUNT_HELP = "Number of arrays of that type currently hold in the memory pool";
+            private static readonly string PERFORMANCECOUNTER_REC_OBJECTS_COUNT = "Reclaimed Objects Count";
+            private static readonly string PERFORMANCECOUNTER_REC_OBJECTS_COUNT_HELP = "Overall count of objects which could sucessfully get reclaimed from the pool.";
+            private static readonly string PERFORMANCECOUNTER_MAX_POOL_SIZE = "Max Pool Size";
+            private static readonly string PERFORMANCECOUNTER_MAX_POOL_SIZE_HELP = "The maximum size the pool currently is allowed to grow before it gets shrinked.";
+            private static readonly string PERFORMANCECOUNTER_SHRINK_COUNT = "Shrink Count";
+            private static readonly string PERFORMANCECOUNTER_SHRINK_COUNT_HELP = "Overall number of times the pool had to be shrinked because of the size getting to large or OOM exceptions being thrown.";
+            private static readonly string PERFORMANCECOUNTER_DISPOSED_HIGH = "Disposed large arrays";
+            private static readonly string PERFORMANCECOUNTER_DISPOSED_HIGH_HELP = "number of disposed large arrays which possibly would be stored in the pool";
+            private static readonly string PERFORMANCECOUNTER_LENGTH_FACTOR = "Lengthening Factor (Log.)";
+            private static readonly string PERFORMANCECOUNTER_LENGTH_FACTOR_HELP = "Current logarithmic setting of the relative length an array will be considered 'matching' on incoming requests";
+            private bool m_countingActive = false;
+            public PerformanceCounter m_PCcurObjectsCount; 
+            public PerformanceCounter m_PCoverallSize; 
+            public PerformanceCounter m_PCOOMcatched; 
+            public PerformanceCounter m_PCsuccessRate; 
+            public PerformanceCounter m_PCsuccessRateBase; 
+            public PerformanceCounter m_PCreclaimedObjectsCount; 
+            public PerformanceCounter m_PCmaximumPoolSize; 
+            public PerformanceCounter m_PCshrinksCount; 
+            public PerformanceCounter m_PCDisposedHigh; 
+            public PerformanceCounter m_PCacceptLengthIncreaseRate; 
+
+            public ILPerformanceCounter() {
+                if (!Settings.s_measurePerformanceAtRuntime) return; 
+                // check if the category is installed 
+                if (!PerformanceCounterCategory.Exists(PERFORMANCECOUNTER_CATEGORY_NAME)) {
+                    // even if we handle to install the category, the counters will be
+                    // not available immediately. So we disable them for this session. 
+                    m_countingActive = false; 
+                    try {
+                        // try to install 
+                        CounterCreationDataCollection ccdc = new CounterCreationDataCollection();
+                        ccdc.Add(new CounterCreationData(PERFORMANCECOUNTER_CUR_OBJECTS_COUNT, PERFORMANCECOUNTER_CUR_OBJECTS_COUNT_HELP, PerformanceCounterType.NumberOfItems32));
+                        ccdc.Add(new CounterCreationData(PERFORMANCECOUNTER_MAX_POOL_SIZE, PERFORMANCECOUNTER_MAX_POOL_SIZE_HELP, PerformanceCounterType.NumberOfItems64));
+                        ccdc.Add(new CounterCreationData(PERFORMANCECOUNTER_OOMCATCHED, PERFORMANCECOUNTER_OOMCATCHED_HELP, PerformanceCounterType.NumberOfItems32));
+                        ccdc.Add(new CounterCreationData(PERFORMANCECOUNTER_OVERALLSIZE, PERFORMANCECOUNTER_OVERALLSIZE_HELP, PerformanceCounterType.NumberOfItems64));
+                        ccdc.Add(new CounterCreationData(PERFORMANCECOUNTER_REC_OBJECTS_COUNT, PERFORMANCECOUNTER_REC_OBJECTS_COUNT_HELP, PerformanceCounterType.NumberOfItems64));
+                        ccdc.Add(new CounterCreationData(PERFORMANCECOUNTER_SHRINK_COUNT, PERFORMANCECOUNTER_SHRINK_COUNT_HELP, PerformanceCounterType.NumberOfItems32));
+                        ccdc.Add(new CounterCreationData(PERFORMANCECOUNTER_SUCCESS_RATE, PERFORMANCECOUNTER_SUCCESS_RATE_HELP, PerformanceCounterType.RawFraction));
+                        ccdc.Add(new CounterCreationData(PERFORMANCECOUNTER_SUCCESS_RATE+ "Base", PERFORMANCECOUNTER_SUCCESS_RATE_HELP, PerformanceCounterType.RawBase));
+                        ccdc.Add(new CounterCreationData(PERFORMANCECOUNTER_DISPOSED_HIGH, PERFORMANCECOUNTER_DISPOSED_HIGH_HELP, PerformanceCounterType.NumberOfItems64));
+                        ccdc.Add(new CounterCreationData(PERFORMANCECOUNTER_LENGTH_FACTOR, PERFORMANCECOUNTER_LENGTH_FACTOR_HELP, PerformanceCounterType.NumberOfItems32));
+                        
+                        PerformanceCounterCategory.Create(PERFORMANCECOUNTER_CATEGORY_NAME, PERFORMANCECOUNTER_CATEGORY_NAME_HELP
+                                                        ,PerformanceCounterCategoryType.MultiInstance,ccdc); 
+                    } catch (System.Security.SecurityException) { }
+                } else {
+                    m_countingActive = true; 
+                    // init performance counters for this type 
+                    string currentGenericElementType = " <" + typeof(Ti).Name + ">"; 
+                    m_PCcurObjectsCount  = new PerformanceCounter(PERFORMANCECOUNTER_CATEGORY_NAME,PERFORMANCECOUNTER_CUR_OBJECTS_COUNT, currentGenericElementType, false); 
+                    m_PCmaximumPoolSize  = new PerformanceCounter(PERFORMANCECOUNTER_CATEGORY_NAME,PERFORMANCECOUNTER_MAX_POOL_SIZE, currentGenericElementType, false); 
+                    m_PCOOMcatched  = new PerformanceCounter(PERFORMANCECOUNTER_CATEGORY_NAME,PERFORMANCECOUNTER_OOMCATCHED, currentGenericElementType, false); 
+                    m_PCoverallSize  = new PerformanceCounter(PERFORMANCECOUNTER_CATEGORY_NAME,PERFORMANCECOUNTER_OVERALLSIZE, currentGenericElementType, false); 
+                    m_PCreclaimedObjectsCount  = new PerformanceCounter(PERFORMANCECOUNTER_CATEGORY_NAME,PERFORMANCECOUNTER_REC_OBJECTS_COUNT, currentGenericElementType, false); 
+                    m_PCshrinksCount  = new PerformanceCounter(PERFORMANCECOUNTER_CATEGORY_NAME,PERFORMANCECOUNTER_SHRINK_COUNT, currentGenericElementType, false); 
+                    m_PCsuccessRate  = new PerformanceCounter(PERFORMANCECOUNTER_CATEGORY_NAME,PERFORMANCECOUNTER_SUCCESS_RATE, currentGenericElementType, false); 
+                    m_PCsuccessRateBase  = new PerformanceCounter(PERFORMANCECOUNTER_CATEGORY_NAME,PERFORMANCECOUNTER_SUCCESS_RATE+"Base", currentGenericElementType, false); 
+                    m_PCDisposedHigh  = new PerformanceCounter(PERFORMANCECOUNTER_CATEGORY_NAME,PERFORMANCECOUNTER_DISPOSED_HIGH, currentGenericElementType, false);
+                    m_PCacceptLengthIncreaseRate = new PerformanceCounter(PERFORMANCECOUNTER_CATEGORY_NAME, PERFORMANCECOUNTER_LENGTH_FACTOR, currentGenericElementType, false); 
+                
+                    m_PCcurObjectsCount.RawValue = 0;   
+                    m_PCmaximumPoolSize.RawValue = 0;   
+                    m_PCOOMcatched.RawValue = 0;   
+                    m_PCoverallSize.RawValue = 0;   
+                    m_PCreclaimedObjectsCount.RawValue = 0;   
+                    m_PCshrinksCount.RawValue = 0;   
+                    m_PCsuccessRate.RawValue = 0;   
+                    m_PCsuccessRateBase.RawValue = 0;  
+                    m_PCDisposedHigh.RawValue = 0; 
+                    m_PCacceptLengthIncreaseRate.RawValue = 0; 
+
+                }
+            }
+            public void PCcurObjectsCountSet(int val) {
+                if (m_PCcurObjectsCount != null)
+                    m_PCcurObjectsCount.RawValue = val;
+            }
+            public void PCDisposedHighIncrement() {
+                if (m_PCDisposedHigh != null)
+                    m_PCDisposedHigh.Increment();
+            }
+            public void PCAcceptLengthIncreaseSet(long value) {
+                if (m_PCacceptLengthIncreaseRate != null)
+                    m_PCacceptLengthIncreaseRate.RawValue = value;
+            }
+            public void PCmaximumPoolSizeSet(long value) {
+                if (m_PCmaximumPoolSize != null)
+                    m_PCmaximumPoolSize.RawValue = value;
+            }
+            public void PCOOMcatchedIncrement() {
+                if (m_PCOOMcatched != null)
+                    m_PCOOMcatched.Increment();
+            }
+            public void PCreclaimedObjectsCountIncrement() {
+                if (m_PCreclaimedObjectsCount != null)
+                    m_PCreclaimedObjectsCount.Increment();
+            }
+            public void PCshrinksCountIncrement() {
+                if (m_PCshrinksCount != null)
+                    m_PCshrinksCount.Increment();
+            }
+            public void PCsuccessRateIncrement() {
+                if (m_PCsuccessRate != null)
+                    m_PCsuccessRate.Increment();
+            }
+            public void PCsuccessRateBaseIncrement() {
+                if (m_PCsuccessRateBase != null)
+                    m_PCsuccessRateBase.Increment();
+            }
+            internal void PCoverallSizeSet(long curBytes) {
+                if (m_PCoverallSize != null) {
+                    m_PCoverallSize.RawValue = curBytes; 
+                }
+            }
+        }
+    }
+}
+
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILPerformanceCounterThreadPool.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILPerformanceCounterThreadPool.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILPerformanceCounterThreadPool.cs	(revision 9102)
@@ -0,0 +1,98 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Diagnostics; 
+
+namespace ILNumerics.Misc {
+
+    internal partial class ILThreadPool  {
+        internal class ILPerformanceCounter {
+            // some constants (may get localized)
+            private static readonly string PERFORMANCECOUNTER_CATEGORY_NAME = "ILNumerics Thread Pool";
+            private static readonly string PERFORMANCECOUNTER_CATEGORY_NAME_HELP = "Monitors treading related data.";
+            private static readonly string PERFORMANCECOUNTER_CURRENT_NUMBER_THREADS = "Number of worker threads";
+            private static readonly string PERFORMANCECOUNTER_CURRENT_NUMBER_THREADS_HELP = "Number of threads currently active for parallel operations.";
+            private static readonly string PERFORMANCECOUNTER_TIME_WAITING_FOR_THREADS = "Time waited for other threads";
+            private static readonly string PERFORMANCECOUNTER_TIME_WAITING_FOR_THREADS_HELP = "Timespan in milliseconds, which the main thread was waiting for worker threads to finish the last operation.";
+            
+            private bool m_countingActive = false;
+            public PerformanceCounter m_PCcurThreadsCount; 
+            public PerformanceCounter m_PCwait4Threads; 
+
+            public ILPerformanceCounter() {
+                if (!Settings.s_measurePerformanceAtRuntime) return; 
+                // check if the category is installed 
+                if (!PerformanceCounterCategory.Exists(PERFORMANCECOUNTER_CATEGORY_NAME)) {
+                    // even if we handle to install the category, the counters will be
+                    // not available immediately. So we disable them for this session. 
+                    m_countingActive = false; 
+                    try {
+                        // try to install 
+                        CounterCreationDataCollection ccdc = new CounterCreationDataCollection();
+                        ccdc.Add(new CounterCreationData(PERFORMANCECOUNTER_CURRENT_NUMBER_THREADS, PERFORMANCECOUNTER_CURRENT_NUMBER_THREADS_HELP, PerformanceCounterType.NumberOfItems32));
+                        ccdc.Add(new CounterCreationData(PERFORMANCECOUNTER_TIME_WAITING_FOR_THREADS, PERFORMANCECOUNTER_TIME_WAITING_FOR_THREADS_HELP, PerformanceCounterType.NumberOfItems64));
+                        
+                        PerformanceCounterCategory.Create(PERFORMANCECOUNTER_CATEGORY_NAME, PERFORMANCECOUNTER_CATEGORY_NAME_HELP
+                                                        ,PerformanceCounterCategoryType.SingleInstance,ccdc); 
+                    } catch (System.Security.SecurityException) { }
+                }
+                m_countingActive = true; 
+                m_PCcurThreadsCount = new PerformanceCounter(PERFORMANCECOUNTER_CATEGORY_NAME, PERFORMANCECOUNTER_CURRENT_NUMBER_THREADS, false);
+                m_PCwait4Threads = new PerformanceCounter(PERFORMANCECOUNTER_CATEGORY_NAME, PERFORMANCECOUNTER_TIME_WAITING_FOR_THREADS, false);
+
+                m_PCcurThreadsCount.RawValue = 0;
+                m_PCwait4Threads.RawValue = 0; 
+
+            }
+            public void PCcurNumberThreadsSet(int val) {
+                if (m_PCcurThreadsCount != null)
+                    m_PCcurThreadsCount.RawValue = val;
+            }
+            public void PCwaited4ThreadsSet(long value) {
+                if (m_PCwait4Threads != null)
+                    m_PCwait4Threads.RawValue = value;
+            }
+        }
+    }
+}
+
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILPerformer.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILPerformer.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILPerformer.cs	(revision 9102)
@@ -0,0 +1,74 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Text;
+
+namespace ILNumerics.Misc
+{
+	/// <summary>
+	/// Measures time spans.
+	/// </summary>
+	internal class ILPerformer
+	{
+		private long m_start; 
+		private long m_lastDuration; 
+		public ILPerformer() {
+			Tic();
+		}
+		public void Tic() {
+			m_start = Environment.TickCount;
+		}
+		public String Toc() {
+			long msec = Environment.TickCount;
+			if (msec < m_start) 
+				msec += Int32.MaxValue;  // recover overflow
+			m_lastDuration = (msec - m_start); 
+			return ToString();
+		}
+		public long Duration {
+			get {
+				return m_lastDuration;
+			}
+		}
+		public override string ToString() {
+			return m_lastDuration.ToString();
+		}
+	}
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILRand.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILRand.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILRand.cs	(revision 9102)
@@ -0,0 +1,81 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.IO; 
+using ILNumerics.Exceptions; 
+
+namespace ILNumerics.Misc {
+    internal class ILRand {
+
+        private bool m_istrial = false;
+
+        public bool Istrial {
+            get { return m_istrial; }
+            set { m_istrial = value; }
+        }
+        private bool m_ispaid = false;
+
+        public bool Ispaid {
+            get { return m_ispaid; }
+            set { m_ispaid = value; }
+        }
+        private DateTime m_expires = DateTime.Now;
+
+        public DateTime Expires {
+            get { return m_expires; }
+            set { m_expires = value; }
+        } 
+
+        internal ILRand (string s) {
+            evaluate(s.ToCharArray()); 
+        }
+
+        private void evaluate(char[] chars) {
+            if (chars.Length < 10) 
+                throw new ILInvalidOperationException("unable to read licensing information!");
+            // algo to decompile information
+            m_ispaid = true; 
+            m_expires = DateTime.MaxValue; 
+        }
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILRequestsValueComparer.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILRequestsValueComparer.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILRequestsValueComparer.cs	(revision 9102)
@@ -0,0 +1,57 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace ILNumerics.Misc {
+    internal class ILRequestsValueComparer : Comparer<KeyValuePair<long, int>> {
+
+        public override int Compare(KeyValuePair<long, int> x, KeyValuePair<long, int> y) {
+            if (x.Value < y.Value) 
+                return -1; 
+            else if (x.Value > y.Value) 
+                return 1; 
+            else 
+                return 0; 
+        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILScope.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILScope.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILScope.cs	(revision 9102)
@@ -0,0 +1,194 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+
+namespace ILNumerics {
+    /// <summary>
+    /// An artificial scope class, used by the ILNumerics memory management
+    /// </summary>
+    public class ILScope : IDisposable {
+
+        internal class ILThreadingContext {
+            public Stack<ILBaseArray> Arrays = new Stack<ILBaseArray>(100);
+            public Stack<ILScope> Scopes = new Stack<ILScope>(100);
+
+            public void RegisterArray(ILBaseArray A) {
+                if (Scopes.Count > 0) /* && A.EnterScope() ) */ { //ho: commented out, because otherwise common local arrays do return false and hence get not registered in implicit conversions here! 
+                    Arrays.Push(A);
+                    Scopes.Peek().Count++;
+                }
+            }
+        }
+        [ThreadStatic]
+        private static ILThreadingContext s_threadContext; 
+        /// <summary>
+        /// Begins an artificial scope block within a local function block
+        /// </summary>
+        /// <param name="inputArrays">Any <b>input</b> arry, given as parameter for the current function</param>
+        /// <returns>A new scope</returns>
+        /// <remarks><para>The <c>ILScope</c> class plays an important role for the ILNumerics memory management. When writing functions in ILNumerics, 
+        /// <c>ILScope</c> is used, to define blocks of artificial scopes for local function blocks. ILNumerics ensures, no memory is left as garbage, once 
+        /// such a scope block was left. Furthermore, it garantees, input arrays are kept alive during the execution of the block. By following these 
+        /// <a href="http://ilnumerics.net/$GeneralRules.html" target="ILMain">simple rules</a>, ILNumerics is able to optimize the execution of the algorithm regarding 
+        /// execution speed and memory footprint.</para></remarks>
+        /// <example><para>The examples demonstrates a custom function in ILNumerics. It demonstrates the use of distinct array types in the function declaration and the use of 
+        /// artificial scopes.</para>
+        /// <code><![CDATA[ILRetArray<double> FreqPeaks(ILInArray<double> inData, ILOutArray<double> freq = null, double sampFreq = 44.1) { 
+        ///
+        ///    using (ILScope.Enter(inData)) {    
+        ///             
+        ///        ILArray<double> Data = check(inData); 
+        ///        ILArray<double> retLength = min(ceil(Data.Length / 2.0 + 1), 5.0);   
+        ///        ILArray<double> Window = stdWindowFunc(Data.Length);  
+        ///        ILArray<double> magnitudes = abs(fft(Data * Window));  
+        ///        magnitudes = magnitudes[r(0,end / 2 + 1)];  
+        /// 
+        ///        ILArray<double> indices = empty();  
+        ///        ILArray<double> sorted = sort(magnitudes, indices, descending:true);  
+        ///        if (!isnull(freq)) 
+        ///            freq.a = (sampFreq / 2.0 / magnitudes.Length * indices)[r(0,retLength-1)];  
+        ///        return magnitudes[r(0,retLength-1)];  
+        ///    } 
+        ///}]]></code>
+        /// </example>
+        public static IDisposable Enter(params ILBaseArray[] inputArrays) {
+            return new ILScope(inputArrays);
+        }
+        /// <summary>
+        /// Begins an artificial scope block within a local function block
+        /// </summary>
+        /// <param name="inputArrays">Any <b>input</b> arry, given as parameter for the current function</param>
+        /// <returns>A new scope</returns>
+        /// <remarks><para>The <c>ILScope</c> class plays an important role for the ILNumerics memory management. When writing functions in ILNumerics, 
+        /// <c>ILScope</c> is used, to define blocks of artificial scopes for local function blocks. ILNumerics ensures, no memory is left as garbage, once 
+        /// such a scope block was left. Furthermore, it garantees, input arrays are kept alive during the execution of the block. By following these 
+        /// <a href="http://ilnumerics.net/$GeneralRules.html" target="ILMain">simple rules</a>, ILNumerics is able to optimize the execution of the algorithm regarding 
+        /// execution speed and memory footprint.</para></remarks>
+        /// <example><para>The examples demonstrates a custom function in ILNumerics. It demonstrates the use of distinct array types in the function declaration and the use of 
+        /// artificial scopes.</para>
+        /// <code><![CDATA[ILRetArray<double> FreqPeaks(ILInArray<double> inData, ILOutArray<double> freq = null, double sampFreq = 44.1) { 
+        ///
+        ///    using (ILScope.Enter(inData)) {    
+        ///             
+        ///        ILArray<double> Data = check(inData); 
+        ///        ILArray<double> retLength = min(ceil(Data.Length / 2.0 + 1), 5.0);   
+        ///        ILArray<double> Window = stdWindowFunc(Data.Length);  
+        ///        ILArray<double> magnitudes = abs(fft(Data * Window));  
+        ///        magnitudes = magnitudes[r(0,end / 2 + 1)];  
+        /// 
+        ///        ILArray<double> indices = empty();  
+        ///        ILArray<double> sorted = sort(magnitudes, indices, descending:true);  
+        ///        if (!isnull(freq)) 
+        ///            freq.a = (sampFreq / 2.0 / magnitudes.Length * indices)[r(0,retLength-1)];  
+        ///        return magnitudes[r(0,retLength-1)];  
+        ///    } 
+        ///}]]></code>
+        /// </example>
+        public static IDisposable Enter(ILBaseArray inputArrays) {
+            return new ILScope(inputArrays);
+        }
+        /// <summary>
+        /// The threading context - individual for each thread
+        /// </summary>
+        internal static ILThreadingContext Context {
+            get {
+                ILThreadingContext ret = s_threadContext;
+                if (ret == null) {
+                    s_threadContext = new ILThreadingContext();
+                    ret = s_threadContext; 
+                }
+                return ret; 
+            }
+        }
+
+        internal int Count = 0;
+
+        internal ILScope(ILBaseArray array) {
+             if (!object.Equals(array,null)) {
+                Stack<ILBaseArray> stack = Context.Arrays;
+                int oldStackCount = stack.Count;
+                if (array.EnterScope()) {
+                    stack.Push(array);
+                }
+                Count = stack.Count - oldStackCount;
+            }
+            Context.Scopes.Push(this);
+        }
+        internal ILScope(params ILBaseArray[] inputArrays) {
+            if (inputArrays != null) {
+                Stack<ILBaseArray> stack = Context.Arrays;
+                int oldStackCount = stack.Count;
+                foreach (var a in inputArrays) {
+                    if (!object.Equals(a, null)) {
+                        if (a.EnterScope()) {
+                            stack.Push(a);
+                        }
+                    }
+                }
+                Count = stack.Count - oldStackCount;
+            }
+            Context.Scopes.Push(this); 
+            
+        }
+        #region IDisposable Members
+
+        /// <summary>
+        /// Dispose all arrays in this scope
+        /// </summary>
+        public void Dispose() {
+            Stack<ILBaseArray> stack = Context.Arrays; 
+            for (int i = Count; i-- > 0; ) {
+                stack.Pop().LeaveScope();
+            }
+#if VERBOSE
+            System.Diagnostics.Debug.Assert(object.Equals(Context.Scopes.Peek(), this));
+            System.Diagnostics.Debug.WriteLine ("Leaving scope {0} - disposing {1} arrays",Context.Scopes.Peek().GetHashCode(),Count); 
+#endif 
+            Context.Scopes.Pop();
+        }
+
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILScopeList.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILScopeList.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILScopeList.cs	(revision 9102)
@@ -0,0 +1,108 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace ILNumerics {
+    internal class ILScopeList<T> {
+
+        #region attributes
+        T[] m_data; 
+        int m_count; 
+        #endregion
+
+        #region properties 
+        public int Count {
+            get { return m_count; }
+            set { m_count = value; }
+        }
+        #endregion
+
+        #region
+        public ILScopeList() {
+            m_data = new T[10]; 
+            m_count = 0; 
+        }
+        public ILScopeList(int capacity) {
+            m_data = new T[capacity]; 
+            m_count = 0; 
+        }
+        #endregion
+
+        #region public interface
+        public T Pop() {
+            if (m_count == 0) throw new IndexOutOfRangeException("The ILScopeList is empty. Pop cannot be completed.");
+            T ret = m_data[--m_count]; 
+            m_data[m_count + 1] = default(T); 
+            return ret; 
+        }
+        public void Push(T element) {
+            ensureLength(m_count); 
+            m_data[m_count++] = element; 
+        }
+        public T Peek() {
+            if (m_count == 0) throw new IndexOutOfRangeException("The ILScopeList is empty. Peek cannot be completed.");
+            return m_data[m_count-1]; 
+        }
+        /// <summary>
+        /// peek element at distance 'index' from END!!
+        /// </summary>
+        /// <param name="index"></param>
+        /// <returns></returns>
+        public T Peek(int index) {
+            index = m_count - 1 - index; 
+            return m_data[index]; 
+        }
+        #endregion
+
+        #region private helper 
+        private void ensureLength(int newIndex) {
+            while (newIndex >= m_data.Length) {
+                T[] newArr = new T[m_data.Length * 2]; 
+                System.Array.Copy(m_data,newArr,m_count); 
+                m_data = newArr; 
+            }
+        }
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILSettings.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILSettings.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILSettings.cs	(revision 9102)
@@ -0,0 +1,358 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Configuration;
+using ILNumerics.Misc; 
+
+namespace ILNumerics {
+
+    /// <summary>
+    /// The class provides static setting properties to control the behaviour of ILNumerics, see <a href="http://ilnumerics.net/$Configuration.html">Configuration</a> in the online documentation
+    /// </summary>
+    public class Settings {
+
+        static Settings() {
+            // Load the static cache values from the Defaul instance
+            // This enables the user to change default values via app.config 
+            // and still provides a fast setting provider for internal functions.
+            LoadDefaults();
+        }
+
+        #region static local attributes
+        // local settings caches 
+        internal static int s_minimumQuicksortLength;
+        internal static int s_maxNumberThreads;
+        internal static bool s_maxNumberThreadsConfigured; 
+        internal static int s_minParallelElement3Count;   // int.MaxValue; // 
+        internal static int s_minParallelElement2Count;  // int.MaxValue; // 
+        internal static int s_minParallelElement1Count; // int.MaxValue; // 
+        internal static int s_minElementLength4SystemArrayCopy;
+        internal static int s_maxSafeQuicksortRecursionDepth;
+        internal static int s_memoryPoolProfileMinLength;
+        internal static int s_memoryPoolProfileMaxLength;
+        internal static bool s_measurePerformanceAtRuntime; 
+        internal static string s_memoryPoolProfileFileName; //"ILNumerics.MemoryPool.Profiler.txt";
+        internal static bool s_useThreadAffinity;
+        internal static bool s_allowInArrayAssignments; 
+        internal static bool s_createRowVectorsByDefault; 
+        internal static LogicalConversionMode s_logicalArrayToBoolConversion = LogicalConversionMode.NonScalarThrowsException;
+
+        #endregion
+
+        #region static global caches
+        /// <summary>
+        /// Performance switch, dis-/allow direct assignments to input parameters - brings more efficient 
+        /// memory management, default: true (safer, less efficient)
+        /// </summary>
+        /// <remarks>
+        /// <para>If this switch is set to 'false', you promise not to assign any values to input parameters 
+        /// of type <c>ILInArray</c>, <c>ILInCell</c> or <c>ILInLogical</c>. This allows ILNumerics for more efficent 
+        /// memory management, decreases the overall memory footprint of the application and enables certain 
+        /// array operations to be automatically computed in-place. Depending on the specific algorithm
+        /// the performance profit may range from 1% up to even about 30%.</para>
+        /// This switch should be set for the whole application globally. It is not recommended to change the state of 
+        /// this switch once the application runs.
+        /// <para>Since this switch targets the full application, all functions and modules involved must also follow 
+        /// that contract! For all builtin functions of ILNumerics, compliance with this rule is garanteed. This means, if you are 
+        /// not using any 3rd party algorithms and are able to make sure your own functions follow that scheme as well, it is safe 
+        /// to set this switch to <c>false</c> and profit from faster execution times.</para>
+        /// <para>See the <a href="http://ilnumerics.net/$PerfMemoryOpt.html">Optimizing Performance</a> article in the online documentation.</para></remarks>
+        public static bool AllowInArrayAssignments {
+            get {
+                return s_allowInArrayAssignments; 
+            }
+            set {
+                s_allowInArrayAssignments = value; 
+            }
+        }
+
+        /// <summary>
+        /// Control layout of vectors when not specified explicitly.
+        /// <list type="bullet">
+        /// <item>
+        /// <term>true</term>
+        /// <description>When a vector is created without exlicitely specifying its shape, create a row vector</description>
+        /// </item>
+        /// <item>
+        /// <term>false (default)</term>
+        /// <description>When a vector is created without exlicitely specifying its shape, create a column vector</description>
+        /// </item></list>
+        /// </summary>
+        /// <remarks>This setting affects the way ILNumerics handles the default shape for vectors created. One example is <see cref="ILNumerics.ILMath.array{T}( T[])"/>, 
+        /// where only the number of elements is given - but no size is specified. By default, ILNumerics will interpret the elements as targeting the <b>first</b> 
+        /// dimension, ie. dimension #0. This will create a column vector. Setting this switch to 'true' will make ILNumerics to create a row vector in 
+        /// such situations instead.</remarks>
+        public static bool CreateRowVectorsByDefault {
+            get {
+                return s_createRowVectorsByDefault; 
+            }
+            set {
+                s_createRowVectorsByDefault = value; 
+            }
+        }
+        /// <summary>
+        /// Upper limit of the range of array length to gather profiler information for
+        /// </summary>
+        public static int MemoryPoolProfileMaxLength {
+            get {
+                return s_memoryPoolProfileMaxLength;
+            }
+            set {
+                s_memoryPoolProfileMaxLength = value;
+            }
+        }
+        /// <summary>
+        /// Lower limit of the range of array length to gather profiler information for
+        /// </summary>
+        public static int MemoryPoolProfileMinLength {
+            get {
+                return s_memoryPoolProfileMinLength;
+            }
+            set {
+                s_memoryPoolProfileMinLength = value;
+            }
+        }
+        /// <summary>
+        /// If set to any non empty value, this setting triggers the memory pool profiler
+        /// </summary>
+        /// <remarks>Profiling the memory pool gives insights into those functions, which potentially 
+        /// cause memory leaks in your application. It writes extensive stack trace information into the 
+        /// logfile determined by this setting. It will contain the stack trace of any function, requesting 
+        /// memory from the pool, which is never given back to the pool. Use this information in order to find and 
+        /// correct those places - and increase stability and performance of your application. However, 
+        /// make sure, this switch is cleared (or renamed) for production systems, since running the profiler 
+        /// will diminish performance significantly.</remarks>
+        public static string MemoryPoolProfileFileName {
+            get {
+                return s_memoryPoolProfileFileName;
+            }
+            set {
+                s_memoryPoolProfileFileName = value;
+            }
+        }
+
+        /// <summary>
+        /// Gives the current setting for the reporting of runtime performance measures to the windows performance monitor (perfmon) (readonly)
+        /// </summary>
+        /// <remarks>Activating this switch requires administrative rights on each system the application is run - at least for the first time! This is 
+        /// necessary in order to register the performance counters to the system. Afterwards, the application does not require administrative rights anymore.
+        /// <para>Measuring the performance at runtime does not produce a substantial impact on the performance of your algorithm. However, due to the need for elevated rights 
+        /// the feature is disabled by default. In order to enable it, a configuration variable named "ILNMeasurePerformanceAtRuntime" needs to be set in your 
+        /// application configuration file.</para></remarks>
+        public static bool MeasurePerformanceAtRuntime {
+            get { return s_measurePerformanceAtRuntime; }
+        }
+
+        /// <summary>
+        /// Determine the minimum length for arrays to be sorted via Quicksort algorithm, smaller arrays are sorted via insertion sort
+        /// </summary>
+        public static int MinimumQuicksortLength {
+            get { return s_minimumQuicksortLength; }
+            set { s_minimumQuicksortLength = value; }
+        }
+        /// <summary>
+        /// Maximum number of threads for parallel execution of internal functions in ILNumerics
+        /// </summary>
+        /// <remarks>
+        /// <para>In order to maximize execution speed of numerical algorithms, the value of <c>MaxNumberThreads</c> should be equal to the number 
+        /// of <b>real</b> processor cores on the system. For processors utilizing <a href="http://en.wikipedia.org/wiki/Hyper-threading">Hyper-threading</a> the number on virtual cores 
+        /// may be higher. However, since those virtual cores share certain ressources for execution, parallel utiliziation can not efficently be done with them. In this cases, the number of 'cores' 
+        /// appearing e.g. in the windows task manager is misleading and the true number of independent cores should be used for <c>MaxNumberThreads</c> instead. Consult your proccessor vendor in order to find out, how many 
+        /// independant cores your system utilizes.</para>
+        /// <para>Since the number of independent cores is not reliably determined by .NET, ILNumerics defaults to 2 cores on all multicore machines. Therefore, this setting should be <a href="http://ilnumerics.net/$Configuration.html">set manually</a> for 
+        /// better processor utilization on multicore machines.</para>
+        /// <para>If your algorithm uses custom parallel execution models, it may 
+        /// be necessary to set this value to '1'. ILNumerics will run single threaded than - leaving you the option to configure 
+        /// the execution on parallel threads on your own.</para>
+        /// <para>The setting of this value also effects the corresponding value of any unmanaged optimized support library (e.g. MKL) internally used by ILNumerics.</para>
+        /// </remarks>
+        public static int MaxNumberThreads {
+            get { return s_maxNumberThreads; }
+            set {
+                if (value < 1)
+                    throw new ILNumerics.Exceptions.ILArgumentException("number of worker threads must be greater than 0");
+                Misc.ILThreadPool.Pool.MaxNumberThreads = value - 1; 
+                s_maxNumberThreads = value;
+            }
+        }
+        /// <summary>
+        /// Determine, if the current setting of <see cref="MaxNumberThreads"/> is the result of a custom configuration
+        /// </summary>
+        public static bool MaxNumberThreadsConfigured {
+            get { return s_maxNumberThreadsConfigured; }
+            private set { s_maxNumberThreadsConfigured = value; }
+        }
+
+        /// <summary>
+        /// Threshold used to determine, if computations of O(n^3) built-in-functions are done in parallel on multicore machines
+        /// </summary>
+        public static int MinParallelElement3Count {
+            get { return s_minParallelElement3Count; }
+            set { s_minParallelElement3Count = value; }
+        }
+
+        /// <summary>
+        /// Threshold used to determine, if computations of O(n^2) built-in-functions are done in parallel on multicore machines
+        /// </summary>
+        public static int MinParallelElement2Count {
+            get { return s_minParallelElement2Count; }
+            set { s_minParallelElement2Count = value; }
+        }
+
+        /// <summary>
+        /// Threshold used to determine, if computations of O(n) built-in-functions are done in parallel on multicore machines
+        /// </summary>
+        public static int MinParallelElement1Count {
+            get { return s_minParallelElement1Count; }
+            set { s_minParallelElement1Count = value; }
+        }
+        
+        /// <summary>
+        /// Maximal recursion depth the quicksort can go. default: 100 (for array length up to 2^100)
+        /// </summary>
+        public static int MaxSafeQuicksortRecursionDepth {
+            get { return s_maxSafeQuicksortRecursionDepth; }
+            set { s_maxSafeQuicksortRecursionDepth = value; }
+        }
+
+        /// <summary>
+        /// Controls implicit conversions from logical arrays to System.Boolean
+        /// </summary>
+        /// <remarks>This setting specifies, how logical arrays are converted to System.Boolean. Those 
+        /// conversions are important, in order to simplify expressions like 
+        /// <code>if (A &gt; B) { ... }</code> on arrays A and B. 
+        /// <para>Here, the comparison <code>A &gt; B</code> creates a logical array of the same size than A and B. The logical array contains
+        /// the result of the elementwise 'greater than' comparison. This setting here controls, how that logical is converted
+        /// to a System.Boolean, in order to evaluate the 'if' condition. </para>
+        /// <para>The default is <c>LogicalConversionMode.NonScalarThrowsException</c>, which would cause an exception to be thrown in 
+        /// the example above. Only scalar logical arrays can be used in such implicit conversions than.</para>
+        /// <para>In order to further simplify the syntax, the <c>LogicalConversionMode.ImplicitAllAll</c> setting can be used. The above expression
+        /// would evaluate to true, if <b>all</b> elements of B are greater than corresponding elements of A. This settings therefore 
+        /// eases the syntax for most situations. However, since most comparison operators comply to the underlying <b>all</b> rule, 
+        /// the '!=' (not equal to) operator does not - at least to the extend of common intuition. In an expression: 
+        /// <code>if (A != B) { ... }</code> one would intuitively expect to execute the code block, if <b>at least one element</b> of A does not equal the corresponding element
+        /// of B. However, due to the <b>all</b> rule, this is not the case! In fact, the code would be executed only, if <b>all</b> elements would 
+        /// evaluate to true. I.e. if no single pair of corresponding elements in A and B are equal. In order to 
+        /// get the intuitively expected behavior, one would override this by:
+        /// <code>if (ILMath.any(A != B)) { ... } </code> 
+        /// Since it may cause hard to find bugs, this setting should be used with care.</para></remarks>
+        public static LogicalConversionMode LogicalArrayToBoolConversion {
+            get { return s_logicalArrayToBoolConversion; }
+            set { s_logicalArrayToBoolConversion = value; }
+        }
+        /// <summary>
+        /// Determine, if main and worker threads should bind to constant cpus or not. The default is not to bind.
+        /// </summary>
+        /// <remarks>It usually is more efficient, to leave control of cpu binding to the runtime. However, if in certain situations, more control is required, this flag can 
+        /// be used to make ILNumerics worker threads be affine to corresponding (native) threads.</remarks>
+        public static bool UseThreadAffinity {
+            get { return s_useThreadAffinity; }
+            set { s_useThreadAffinity = value; }
+        }
+        #endregion
+
+        #region public interface 
+        /// <summary>
+        /// (Re)load settings from the application configuration file
+        /// </summary>
+        public static void LoadDefaults() {
+            
+            tryLoadSetting<int>("ILNMinimumQuicksortLength", ref s_minimumQuicksortLength, int.Parse, 10);
+            if (!tryLoadSetting<int>("ILNMaxNumberThreads", ref s_maxNumberThreads, int.Parse, 2)) {
+                // determine number of threads in another way: here: hardcoded
+                if (Environment.ProcessorCount > 1 && !System.Diagnostics.Debugger.IsAttached)
+                    s_maxNumberThreads = 2;
+                else
+                    s_maxNumberThreads = 1;
+                MaxNumberThreadsConfigured = false;
+                // TODO: try to determine number of PHYSICAL cores automatically
+                // try to load number of physical cores rather than logical cores - utilize CPUID via native function pointer!  
+            } else {
+                MaxNumberThreadsConfigured = true; 
+            }
+            tryLoadSetting<int>("ILNMinParallelElement3Count", ref s_minParallelElement3Count, int.Parse, 500);
+            tryLoadSetting<int>("ILNMinParallelElement2Count", ref s_minParallelElement2Count, int.Parse, 1000);
+            tryLoadSetting<int>("ILNMinParallelElement1Count", ref s_minParallelElement1Count, int.Parse, (System.Environment.Is64BitProcess) ? 2000 : 2000);
+            tryLoadSetting<int>("ILNMaxSafeQuicksortRecursionDepth", ref s_maxSafeQuicksortRecursionDepth, int.Parse, 100);
+            tryLoadSetting<LogicalConversionMode>("ILNLogicalArrayToBoolConversion", ref s_logicalArrayToBoolConversion, logicalEnumParse, LogicalConversionMode.NonScalarThrowsException);
+            tryLoadSetting<string>("ILNMemoryPoolProfileFileName", ref s_memoryPoolProfileFileName, dummyStringCopy, "");
+            tryLoadSetting<int>("ILNMemoryPoolProfileMaxLength", ref s_memoryPoolProfileMaxLength, int.Parse, 500);
+            tryLoadSetting<int>("ILNMemoryPoolProfileMinLength", ref s_memoryPoolProfileMinLength, int.Parse, 500);
+            tryLoadSetting<int>("ILNMinElementLength4SystemArrayCopy", ref s_minElementLength4SystemArrayCopy, int.Parse, 50);
+            tryLoadSetting<bool>("ILNUseThreadAffinity", ref s_useThreadAffinity, bool.Parse, false);
+            tryLoadSetting<bool>("ILNCreateRowVectorsByDefault", ref s_createRowVectorsByDefault, bool.Parse, false);
+            tryLoadSetting<bool>("ILNAllowInArrayAssignments", ref s_allowInArrayAssignments, bool.Parse, true);
+            string configLicenseFilename = null, configLicenseResourceName = null;
+            tryLoadSetting<string>("ILNLicenseFilename", ref configLicenseFilename, dummyStringCopy, "ILNumerics.lic");
+            tryLoadSetting<string>("ILNLicenseResourceName", ref configLicenseResourceName, dummyStringCopy, "ILNumerics.lic");
+            tryLoadSetting<bool>("ILNMeasurePerformanceAtRuntime", ref s_measurePerformanceAtRuntime, bool.Parse, false);
+
+        }
+        #endregion
+
+        #region private helper 
+        private static bool tryLoadSetting<T>(string settingsName, ref T obj, System.Converter<string, T> convert, T defaultValue) {
+            string value = System.Configuration.ConfigurationManager.AppSettings[settingsName];
+            T tmp;
+            if (!string.IsNullOrEmpty(value)) {
+                try {
+                    tmp = convert(value); // may throws exception! 
+                    obj = tmp;
+                    return true;
+                } catch (Exception exc) {
+                    tmp = defaultValue;
+                    throw new ILNumerics.Exceptions.ILArgumentException("Error reading default setting from application configuration, appsettings section: Invalid value for: '" + settingsName + "'", exc);
+                }
+            } else {
+                obj = defaultValue;
+                return false;
+            }
+        }
+        internal static string dummyStringCopy(string val) { return val.Trim(); }
+        internal static LogicalConversionMode logicalEnumParse(string val) {
+            LogicalConversionMode ret;
+            if (Enum.TryParse<LogicalConversionMode>(val, out ret)) {
+                return ret;
+            }
+            throw new ILNumerics.Exceptions.ILArgumentException("The configuration value for 'ILNLogicalArrayToBoolConversion' is not valid.");
+        }
+        #endregion
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILSize.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILSize.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILSize.cs	(revision 9102)
@@ -0,0 +1,764 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using ILNumerics.Storage;     
+using ILNumerics.Exceptions;
+using System.Collections.Generic; 
+
+namespace ILNumerics
+{
+    /// <summary>
+    /// ILSize - dimensions for array objects (immutable)
+    /// </summary>
+    /// <remarks>The class internally manages the dimensions of ILNumerics arrays. 
+    /// The class is immutable. Therefore, once created, it informs the user 
+    /// about all dimension related properties, but cannot get altered.</remarks>
+    [Serializable]
+    [System.Diagnostics.DebuggerDisplay("{ToString(),nq}")]
+    public class ILSize {
+        
+        #region attributes
+        internal int [] m_dims; 
+        int m_nrDims = 0;
+        int m_numberOfElements = 0;
+        int m_length = 0;
+        int [] m_seqDistancesCache; 
+        static ILSize s_emptyDimension = new ILSize(0,0); 
+        static ILSize s_scalarDimension = new ILSize(1,1); 
+        static ILSize s_twoElementDim = new ILSize(2,1); 
+        static ILSize s_threeElementDim = new ILSize(3,1);
+        
+        [ThreadStatic]
+        static List<int> s_listCache;
+        static List<int> ListCache {
+            get {
+                List<int> ret = s_listCache;
+                if (ret == null) {
+                    s_listCache = new List<int>();
+                    ret = s_listCache;
+                }
+                return ret; 
+            }
+        }
+        #endregion
+
+        #region constructors
+        /// <summary>
+        /// Create new ILSize 
+        /// </summary>
+        /// <param name="dims">variable length dimensions specifier</param>
+        /// <remarks>Trailing singleton dimensions of dims will be kept.</remarks>
+        public ILSize(params int[] dims) {
+            if (dims == null)
+                throw new ILArgumentException("invalid dimension specification. the number of dimensions must not be 0.");
+            int outLen = Math.Max(2, dims.Length);
+            m_dims = new int[outLen];
+            for (int i = 0; i < dims.Length; i++) {
+                m_dims[i] = dims[i];
+            }
+            for (int i = dims.Length; i < 2; i++) {
+                m_dims[i] = 1;
+            }
+            m_numberOfElements = 1;
+            m_nrDims = m_dims.Length;
+            int t = 0,
+                d;
+            for (; t < m_dims.Length; t++) {
+                d = m_dims[t];
+                if (d > m_length) m_length = d;
+                m_numberOfElements *= d;
+            }
+        }
+
+        /// <summary>
+        /// Create new size descriptor from given data
+        /// </summary>
+        /// <param name="size">Size description</param>
+        public ILSize(params ILBaseArray[] size)
+            : this (convert2int(size)) {
+
+        }
+
+        /// <summary>
+        /// Create new size descriptor
+        /// </summary>
+        /// <param name="trimSingletons">true: trailing singleton 
+        /// dimensions will be trimmed, false: keep trailing singleton dimensions</param>
+        /// <param name="size">Size description</param>
+        public ILSize (bool trimSingletons, params int[] size)  {
+            if (!trimSingletons) {
+                if (size == null)
+                    throw new ILArgumentException("invalid size specification. the number of dimensions must not be 0.");
+                int outLen = Math.Max(2, size.Length);
+                m_dims = new int[outLen];
+                for (int i = 0; i < size.Length; i++) {
+                    m_dims[i] = size[i];
+                }
+                for (int i = size.Length; i < 2; i++) {
+                    m_dims[i] = 1;
+                }
+                m_numberOfElements = 1;
+                m_nrDims = m_dims.Length;
+                int t = 0,
+                    d;
+                for (; t < m_dims.Length; t++) {
+                    d = m_dims[t];
+                    if (d > m_length) m_length = d;
+                    m_numberOfElements *= d;
+                }
+            } else {
+                ListCache.Clear();
+                s_listCache.AddRange(size);
+                while (s_listCache.Count < 2)
+                    s_listCache.Add(1);
+                if (trimSingletons)
+                    for (int i = s_listCache.Count; i-- > 2; ) {
+                        if (s_listCache[i] == 1) s_listCache.RemoveAt(i);
+                        else break;
+                    }
+                m_dims = s_listCache.ToArray();
+                m_numberOfElements = 1;
+                m_nrDims = m_dims.Length;
+                int t = 0,
+                    d;
+                for (; t < m_dims.Length; t++) {
+                    d = m_dims[t];
+                    if (d > m_length) m_length = d;
+                    m_numberOfElements *= d;
+                }
+            }
+        }
+
+        /// <summary>
+        /// An size descriptor of size 0x0
+        /// </summary>
+        public static ILSize Empty00 {
+            get { 
+                return s_emptyDimension; }
+        }
+        /// <summary>
+        /// An size descriptor of size 1x1
+        /// </summary>
+        public static ILSize Scalar1_1
+        {
+            get { 
+                return s_scalarDimension; }
+        }
+        /// <summary>
+        /// An size descriptor of size 2x1
+        /// </summary>
+
+        public static ILSize Column2_1 {
+            get { 
+                return s_twoElementDim; }
+        }
+        /// <summary>
+        /// An size descriptor of size 3x1
+        /// </summary>
+        public static ILSize Column3_1 {
+            get { 
+                return s_threeElementDim; }
+        }
+        #endregion
+
+        #region properties
+        /// <summary>Get number of dimensions.</summary>
+        public int NumberOfDimensions {
+            get {
+                return m_nrDims; 
+            }
+        }
+
+        /// <summary>
+        /// Number of non singleton dimensions of the array
+        /// </summary>
+        /// <remarks>Non singleton dimensions are dimensions which length is larger than 1. 
+        /// Empty dimensions (length = 0) will not be taken into account.</remarks>
+        public int NonSingletonDimensions {
+            // ToDo: Definition of non-singelton (= not 1) should be reconsidered. Here 0 is not counted as non-singelton
+            get {
+                int ret = 0;
+                for (int i = 0; i < m_nrDims; i++) {
+                    if (m_dims[i] > 1) ret++;
+                }
+                return ret;
+            }
+        }
+        /// <summary>
+        /// Number of elements in the array
+        /// </summary>
+        public int NumberOfElements {
+            get {
+                return m_numberOfElements;
+            }
+        }
+        /// <summary>
+        /// Length of the longest dimension
+        /// </summary>
+        public int Longest {
+            get {
+                return m_length; 
+            }
+        }
+        /// <summary>
+        /// Find dimension to work on, if non was specified by user
+        /// </summary>
+        /// <returns>Index of first non singleton dimension (i.e. dimension that is not 1) or 0, if this array is a scalar.</returns>
+        internal int WorkingDimension() {
+            // if (m_numberOfElements <= 1) return -1; 
+            for (int i = 0; i < m_nrDims; i++) {
+                if (m_dims[i] != 1) return i; 
+            }
+            // return -1; // this should not happen! Test on scalar above 
+            return 0; // All dimensions are 1, return first one
+        }
+        #endregion 
+
+        #region public member
+        /// <summary>
+        /// Storage distance of elements in dimension dim
+        /// </summary>
+        /// <param name="dim">0-based index of dimension to query the element distance for</param>
+        /// <returns>Storage distance of elements between adjacent elements of dimension dim
+        /// </returns>
+        /// <remarks>If dimension index dim is larger than the number of 
+        /// dimensions of this array, the number of elements will 
+        /// be returned (trailing singleton dimensions).</remarks>
+        public int SequentialIndexDistance(int dim) {
+            if (dim >= m_nrDims)
+                return m_numberOfElements; 
+            dim %= m_nrDims; 
+            int ret = 1; 
+            for (int i = 0; i < dim && i < m_nrDims; i++) {
+                ret *= m_dims[i];
+            }
+            return ret; 
+        }
+        /// <summary>
+        /// Distances between adjacent elements for all dimensions
+        /// </summary>
+        /// <param name="minLength">minimum length of array to be 
+        /// returned. If this is larger than the number of dimensions 
+        /// in this size descriptor, the array will have minLength elements, 
+        /// with elements outside this dimensions repeating the value 
+        /// of the last dimension. The length of the array returned will 
+        /// be equal or greater than max(minLength,NumberOfDimensions).</param>
+        /// <remarks>This is provided for performance reasons and should be 
+        /// used internally only. It enables developer of index access routines 
+        /// to cache the elements distances directly inside their functions 
+        /// without having to query the info on every index access.
+        /// <para>Keep in mind, only the distances for the number of my 
+        /// dimensions are returned. Higher dimensions must be set to 
+        /// NumberOfElements if needed. This is different than querying 
+        /// the distances by SequentialIndexDistance(int), which will assume 
+        /// and return trailing dimensions to be 1.</para>
+        /// <para>IMPORTANT: ALTERING THE ARRAY RETURNED IS NOT ALLOWED AND 
+        /// MAY LEAD TO SERIOUS INSTABILITY AND UNWANTED SIDE EFFECTS!</para></remarks>
+        internal int[] GetSequentialIndexDistances(int minLength) {
+            minLength = Math.Max(m_nrDims,minLength);
+            if (m_seqDistancesCache == null || m_seqDistancesCache.Length < minLength){
+                m_seqDistancesCache = new int[minLength]; 
+                int tmp = 1, i = 0; 
+                for (; i < m_nrDims; i++) {
+                    m_seqDistancesCache[i] = tmp; 
+                    tmp *= m_dims[i];
+                }
+                for (; i < m_seqDistancesCache.Length; i++) {
+                    m_seqDistancesCache[i] = tmp; 
+                }
+            }
+            return m_seqDistancesCache; 
+        }
+        /// <summary>
+        /// Transfer my dimensions to integer array 
+        /// </summary>
+        /// <returns>Integer array containing a copy of all dimensions length</returns>
+        public int[] ToIntArray(){
+            return (int[])m_dims.Clone(); 
+        }
+        /// <summary>
+        /// Transfer my dimensions to integer array 
+        /// </summary>
+        /// <param name="length">Minimum length of output array. If length 
+        /// is larger than my dimensions, trailing ones will be added.</param>
+        /// <returns>Integer array containing a copy of dimensions length. 
+        /// Trailing elements outside my dims will be one.</returns>
+        internal int[] ToIntArray (int length) {
+            int[] ret; 
+            ret = new int[length > m_nrDims ? length : m_nrDims];
+            Array.Copy(m_dims,0,ret,0,m_nrDims);
+            for (int i = m_nrDims; i < length; i++) {
+                ret[i] = 1; 
+            }
+            return ret; 
+        }
+        /// <summary>
+        /// return dimension vector, fixed length, for subarray operations
+        /// </summary>
+        /// <param name="length"></param>
+        /// <returns>dimension vector, corresponds to reshaped or unlimited dimensions</returns>
+        internal int[] ToIntArrayEx (int length) {
+            int[] ret; 
+            if (length == m_nrDims) {
+                ret = new int[length];
+                Array.Copy(m_dims,0,ret,0,m_nrDims);
+            } else if (length > m_nrDims) {
+                ret = new int[length];
+                int i = 0; 
+                for (; i < m_dims.Length; i++) {
+                    ret[i] = m_dims[i]; 
+                }
+                for (; i < length; i++) {
+                    ret[i] = 1; 
+                }
+            } else if (length > 0) {
+                ret = new int[length];
+                int i = 0; 
+                for (; i < length; i++) {
+                    ret[i] = m_dims[i]; 
+                }
+                for (int a = i--; a < m_dims.Length; a++) {
+                    ret[i] *= m_dims[a]; 
+                }
+            } else 
+                throw new ILArgumentException("the length parameter must be positive"); 
+            return ret; 
+        }
+        /// <summary>
+        /// Transform indices from int[] System.Array into sequential index of underlying 1dim array 
+        /// </summary>
+        /// <param name="idx">int array of nrDims length, min length: 1, all indices must fit into my dimensions</param>
+        /// <returns>Index pointing to element defined by 'idx'</returns>
+        public int IndexFromArray(int[] idx) {      
+            int ret = idx[0];
+            if (ret < 0 || ret >= m_dims[0]) 
+                throw new ILArgumentException("index out of bounds, dimension # 0");
+            int i = 1, tmp, len = (idx.Length < m_nrDims) ? idx.Length : m_nrDims; 
+            for (; i < len-1; i++) {
+                tmp = idx[i]; 
+                if (tmp >= m_dims[i] || tmp < 0)
+                    throw new ILArgumentException("index out of bounds, dimension # " + i);
+                ret += tmp * SequentialIndexDistance(i); 
+            }
+            if (i < len) {
+                tmp = idx[i];
+                if (tmp < 0 || tmp >= m_dims[i]) throw new ILArgumentException("index out of bounds, dimension # " + i);
+                ret += tmp * SequentialIndexDistance(i);
+            }
+            return ret; 
+        }
+        /// <summary>
+        /// Transform dimension position into sequential index, gather expand 
+        /// information
+        /// </summary>
+        /// <param name="idx">int array of arbitrary length</param>
+        /// <param name="MustExpand">[output] true, if the indices 
+        /// given address an element outside of 
+        /// this dimensions size. In this case, the output parameter 
+        /// 'Dimensions' carry the sizes 
+        /// of new dimensions needed. False otherwise</param>
+        /// <param name="dimensions">sizes of dimension if expansion is needed. 
+        /// Must be predefined to length of max(idx.Length,m_nrDims) at least</param>
+        /// <returns>Index number pointing to the value's position in 
+        /// sequential storage.</returns>
+        /// <remarks>no checks are made for idx to fit inside dimensions! 
+        /// This functions is used for left side assignments. Therefore it 
+        /// computes the destination index also if it lays outside 
+        /// the array bounds.</remarks>
+        internal int IndexFromArray(ref bool MustExpand, ref int[] dimensions, int[] idx) {
+            int tmp; 
+            if (idx.Length < m_nrDims) {
+                #region idx < nrDims
+                // expanding is allowed for all but the last specified dimension
+                // reason: if less than m_nrDims idx entries exist, the array is 
+                // reshaped to that number of dimensions and the index access 
+                // computed according to the reshaped version. Attempts to expand
+                // that last (virtual) dimension is not allowed than since that 
+                // dimension would be ambigous. 
+                #region special case: sequential addressing
+                if (idx.Length < 2) {
+                    if (idx.Length == 1) {
+                        tmp = idx[0]; 
+                        if (tmp >= m_numberOfElements) {
+                            // allowed only for scalars and vectors
+                            if (m_dims[0] == m_numberOfElements) {
+                                dimensions[0] = tmp+1; 
+                                MustExpand = true; 
+                                return tmp; 
+                            } else if (m_dims[1] == m_numberOfElements) {
+                                dimensions[1] = tmp+1; 
+                                MustExpand = true; 
+                                return tmp; 
+                            } else 
+                                throw new ILArgumentException("invalid attempt to expand non vector sized array"); 
+                        } else {
+                            return tmp; 
+                        }
+                    }
+                    throw new ILArgumentException("invalid index specification: must not be empty");
+                }
+                #endregion
+                int d = 0, faktor = 1; 
+                int ret = 0; 
+                tmp = idx[0]; 
+                while (d < idx.Length-1) {
+                    if (tmp < 0)
+                        throw new ILArgumentException("check index at dimension #" + d.ToString() + "!");
+                    if (tmp >= m_dims[d]) {
+                        dimensions[d] = tmp+1; 
+                        MustExpand = true; 
+                        ret += (faktor * tmp); 
+                        faktor *= tmp+1; 
+                    } else {
+                        ret += (faktor * tmp); 
+                        faktor *= m_dims[d]; 
+                    }
+                    tmp = idx[++d];
+                }
+                while (d < m_nrDims) {
+                    ret += faktor * ((tmp % m_dims[d])); 
+                    tmp /= m_dims[d]; 
+                    faktor *= m_dims[d++]; 
+                }
+                if (tmp > 0) 
+                    throw new ILArgumentException("expanding is allowed for explicitly bounded dimensions only! You must specify indices into all existing dimensions."); 
+                return ret;
+                #endregion
+            } else if (idx.Length == m_nrDims) {
+                // expanding is allowed for all dimensions 
+                int d = 0,faktor = 1; 
+                int ret = 0; 
+                while (d < idx.Length) {
+                    tmp = idx[d];
+                    if (tmp < 0)
+                        throw new ILArgumentException("check index at dimension #" + d.ToString() + " !");
+                    if (tmp >= m_dims[d]) {
+                        dimensions[d] = tmp+1; 
+                        MustExpand = true; 
+                        ret += (faktor * tmp); 
+                        faktor *= tmp+1; 
+                    } else {
+                        ret += (faktor * tmp); 
+                        faktor *= m_dims[d]; 
+                    }
+                    d++; 
+                }
+                return ret;
+            } else {
+                // idx dimensions are larger than my dimensions
+                int d = 0, faktor = 1; 
+                int ret = 0;
+                tmp = idx[0]; 
+                while (d < m_nrDims) {
+                    tmp = idx[d];
+                    if (tmp < 0)
+                        throw new ILArgumentException("check index at dimension " + d.ToString() + "!");
+                    if (tmp >= m_dims[d]) {
+                        dimensions[d] = tmp+1; 
+                        MustExpand = true; 
+                        ret += (faktor * tmp); 
+                        faktor *= tmp+1; 
+                   } else { 
+                        ret += (faktor * tmp); 
+                        faktor *= m_dims[d]; 
+                    }
+                    d++; 
+                }
+                while (d < idx.Length) {
+                    tmp = idx[d]; 
+                    if (tmp > 0) {
+                        dimensions[d] = tmp +1; 
+                        MustExpand = true; 
+                    }
+                    d++; 
+                    faktor *= tmp; 
+                    ret += faktor; 
+                }
+                return ret; 
+            }
+        }
+        /// <summary>
+        /// Unshift dimensions of indices from int[] Array 
+        /// and translate to index for sequential storage access 
+        /// in my dimensions </summary>
+        /// <param name="idx">int array of the same length as 
+        /// the number of dimensions of this storage. Indices must 
+        /// lay within my dimensions.</param>
+        /// <param name="unshift">Number of dimensions to unshift 
+        /// idx before computing index</param>
+        /// <returns>Index number pointing to the value's position 
+        /// in sequential storage.</returns>
+        /// <remarks>If idx contains elements (indices) larger than 
+        /// my dimension bounds, an exception will be thrown. If unshift 
+        /// is 0, the length of idx may be smaller than the length of 
+        /// my dimensions. However, with unshift &gt; 0 the result 
+        /// is undefined.</remarks>
+        public int IndexFromArray(int[] idx, int unshift) {
+            unshift %= m_nrDims;
+            int faktor = m_dims[0];
+            int ret = idx[(-unshift) % m_nrDims]; 
+            int d = 1;
+            for (; d<idx.Length; d++) {
+                ret += idx[(-unshift + d) % m_nrDims] * faktor; 
+                faktor *= m_dims[d]; 
+            }
+            return ret; 			
+        }
+        /// <summary>
+        /// Return shifted version
+        /// </summary>
+        /// <param name="shift">Number of dimensions to shift. The value
+        /// will be considered modules the number of dimensions of 
+        /// this size descriptor.</param>
+        /// <returns>Shifted version of this size descriptor object.</returns>
+        public ILSize GetShifted(int shift){ 
+            shift %= m_nrDims; 
+            if (shift < 0) shift += m_nrDims; 
+            int [] tmp = new int [m_nrDims]; 
+            int id;
+            for (int d = 0; d < m_nrDims; d++) {
+                id = (d + shift) % m_nrDims;
+                tmp[d] = m_dims[id];
+            }
+            return new ILSize(tmp);
+        }
+        /// <summary>
+        /// Create dimension sizes for reshaping index adressing
+        /// </summary>
+        /// <param name="dimCount">Needed number of destination array dimensions</param>
+        /// <returns>Dimension sizes, cutted trailing dimensions are multiplied to last dimension returned.</returns>
+        public int[] GetReshapedSize(int dimCount) {
+            dimCount = Math.Max(1,dimCount); 
+            if (dimCount >= m_nrDims) {
+                return ToIntArray(dimCount); 
+            }
+            int[] ret = new int[Math.Max(dimCount,2)];
+            for (int i = 0; i < dimCount; i++) {
+                ret[i] = m_dims[i]; 
+            }
+            for (int i = dimCount; i < m_nrDims; i++) {
+                ret[dimCount - 1] *= m_dims[i]; 
+            }
+            if (dimCount < 2) 
+                ret[1] = 1; 
+            return ret; 
+        }
+        /// <summary>
+        /// Get length for dimension specified (Readonly)
+        /// </summary>
+        /// <param name="idx">Index of dimension</param>
+        /// <returns>Length of dimension specified by idx</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If idx is negative</exception>
+        /// <remarks><para>For idx corresponds to an existing dimension, 
+        /// the length of that dimension is returned. If idx is larger than 
+        /// the number of dimensions 1 is returned. </para>
+        /// </remarks>
+        public int this [int idx] {
+            get {
+                if (idx < 0) 
+                    throw new ArgumentOutOfRangeException("index","Index out of Range!");
+                else if (idx >= m_nrDims) {
+                    return 1; 
+                }
+                return m_dims[idx];
+            }
+        }
+        /// <summary>
+        /// Compares the size of this dimension to another dimension object. 
+        /// </summary>
+        /// <param name="dim2">size descriptor to compare this to.</param>
+        /// <returns>Returns true if the sizes are the same, else returns false. 
+        /// The comparison is made by recognizing singleton dimensions. Therefore 
+        /// only non singleton dimensions are compared in the order of their 
+        /// appearance. </returns>
+        /// <remarks>The function returns true, if the squeezed dimensions of 
+        /// both size descriptors match.</remarks>
+        public bool IsSameSize(ILSize dim2) { 
+            if (dim2.NumberOfElements != m_numberOfElements) return false; 
+            for (int d2 = dim2.NumberOfDimensions,d1 = m_nrDims;d1 >= 0;) {
+                d1--; d2--;
+                while (d1 >= 0 && m_dims[d1]== 1) d1--; 
+                while (d2 >= 0 && dim2[d2]  == 1) d2--; 
+                if (d1 >= 0 && d2 >= 0) {
+                    if (m_dims[d1] != dim2[d2]) 
+                        return false;
+
+                }
+            }
+            return true;
+        }
+        /// <summary>
+        /// Compares the shape of this dimension to another dimension object 
+        /// </summary>
+        /// <param name="dim2">size descriptor to compare this to.</param>
+        /// <returns>Returns true if the shapes are the same, else returns false. </returns>
+        /// <remarks>This function is more strict than IsSameSize. In order 
+        /// for two dimensions to have the same shape, ALL dimensions must match - 
+        /// even singleton dimensions.</remarks>
+        public bool IsSameShape(ILSize dim2) { 
+            if (dim2.NumberOfElements != m_numberOfElements) return false; 
+            if (dim2.NumberOfDimensions != m_nrDims) return false; 
+            for (int d1 = m_nrDims;d1-->0;) { 
+                if (m_dims[d1] != dim2.m_dims[d1]) 
+                    return false;
+            }
+            return true;
+        }
+        /// <summary>
+        /// [deprecated] Create copy of this size descriptor having all singleton 
+        /// dimensions removed.
+        /// </summary>
+        /// <returns>a squeezed copy</returns>
+        /// <remarks>This function is deprecated. Use the ILSize.Squeeze()
+        /// memeber instead. </remarks>
+        [Obsolete("Use the ILSize.Squeeze() instead")]
+        public ILSize GetSqueezed() {
+            return Squeeze();
+        }
+        /// <summary>
+        /// Create and return copy without singleton dimensions
+        /// </summary>
+        /// <returns>Copy of this size descriptor having all singleton dimensions removed.</returns>
+        /// <remarks> This function does not alter this object (since ILSize is 
+        /// immutable).
+        /// <para>All arrays in ILNumerics have at least 2 dimensions. 
+        /// Therefore all but the first two singleton dimensions can be removed.</para>
+        /// </remarks>
+        public ILSize Squeeze() {
+            List<int> tmp = new List<int>(); 
+            foreach (int d in m_dims) {
+                if (d != 1) tmp.Add(d); 
+            }
+            while (tmp.Count < 2) { 
+                tmp.Add(1); 
+            }
+            return new ILSize(tmp.ToArray());
+        }
+        /// <summary>
+        /// Return size descriptor, having trailing singleton dimensions removed
+        /// </summary>
+        /// <returns>Copy without trailing singleton dimensions</returns>
+        /// <remarks>This object will NOT be altered. As usual for all ILArrays, 
+        /// the result wil have at least 2 dimensions.</remarks>
+        public ILSize Trim() {
+            if (m_nrDims == 2 || m_dims[m_nrDims-1] != 1) {
+                return this; 
+            }
+            int i = m_nrDims; 
+            for (; i-->2; ) if (m_dims[i] != 1) break; 
+            int[] newdims = new int[++i]; 
+            System.Array.Copy(m_dims,0,newdims,0,i);
+            return new ILSize(newdims);
+        }
+
+        /// <summary>
+        /// Pretty print dimensions in the format "[a,b,c]"
+        /// </summary>
+        /// <returns>Dimensions as String</returns>
+        public override String ToString (){
+            String s = "[";
+            for (int t = 0; t < m_nrDims; t++) {
+                s = s + m_dims[t];
+                if (t < m_nrDims -1 ) 
+                    s = s + ",";
+            }
+            s = s + "]"; 
+            return s;
+        }
+        /// <summary>
+        /// Generate hash code based on the dimension information 
+        /// </summary>
+        /// <returns>Hash code</returns>
+        public override int GetHashCode() {
+            int ret = m_dims.Length;
+            foreach (int i in m_dims) {
+                ret = ret * 17 + i; 
+            }
+            return ret; 
+        }
+        /// <summary>
+        /// Checks for equaltiy of this dimensions to another dimensions object
+        /// </summary>
+        /// <param name="obj">Dimensions object to compare this instance with</param>
+        /// <returns>true, if both dimensions have the same <b>shape</b></returns>
+        /// <remarks>This is equivalent to <c>IsSameShape((ILSize)obj)</c>.</remarks>
+        public override bool Equals(object obj) {
+            if (object.ReferenceEquals(obj, null)) return false;
+            ILSize objDim = obj as ILSize;
+            if (objDim != null) {
+                return IsSameShape(objDim); 
+            } else {
+                return false; 
+            }
+
+        }
+        #endregion 
+
+        #region private helpers
+        private static int[] convert2int(ILBaseArray[] dimensions) {
+            using (ILScope.Enter(dimensions)) {
+                if (dimensions == null || dimensions.Length == 0) {
+                    return new int[2];
+                }
+                int[] ret = new int[dimensions.Length];
+                if (dimensions.Length > 1) {
+                    for (int i = 0; i < ret.Length; i++) {
+                        ILBaseArray A = dimensions[i];
+                        if (object.Equals(A, null) || !A.IsScalar || !A.IsNumeric) {
+                            throw new ILArgumentException("dimension specifier must be numeric scalars");
+                        }
+                        ret[i] = (int)ILMath.todouble(A).GetValue(0);
+                    }
+                } else {
+                    // if exactly one array was given, it must be a numeric int vector with the dim specification 
+                    ILBaseArray A = dimensions[0];
+                    if (object.Equals(A, null) || !A.IsVector || !A.IsNumeric) {
+                        throw new ILArgumentException("invalid dimension specification"); 
+                    }
+                    ILArray<int> Aint = ILMath.toint32(A); 
+                    Aint.ExportValues(ref ret);  
+                }
+                return ret;
+            }
+        }
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILThreadConfig.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILThreadConfig.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILThreadConfig.cs	(revision 9102)
@@ -0,0 +1,96 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Runtime.InteropServices;
+using System.Diagnostics;
+using System.Threading;
+
+namespace Tester {
+    internal class ILThreadConfig {
+        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+        static extern int GetCurrentThreadId();
+        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+        static extern bool GetProcessAffinityMask(IntPtr currentProcess, ref Int64 lpProcessAffinityMask, ref Int64 lpSystemAffinityMask);
+        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+        public static extern int GetCurrentProcessorNumber();
+
+        static void Main() {
+            Int64 lpProcessAffinityMask = 0, lpSystemAffinityMask = 0;
+            int i = 0, j = 0;
+            Int64 procCount = Environment.ProcessorCount;
+            Thread[] t = new Thread[procCount];
+
+            IntPtr currentProcess = Process.GetCurrentProcess().Handle;
+            Int64 currProcMask;
+
+            GetProcessAffinityMask(currentProcess, ref lpProcessAffinityMask, ref lpSystemAffinityMask);
+
+            Console.WriteLine("ProcessAffintityMask = {0}, SystemAffinityMask ={1}", lpProcessAffinityMask, lpSystemAffinityMask);
+
+            for (i = 0; i < procCount; i++) {
+                currProcMask = lpSystemAffinityMask & (1 << i);
+                if (currProcMask >= 1) {
+                    t[j] = new Thread(new ParameterizedThreadStart(DoWork));
+                    object[] parameters = new object[] { currProcMask };
+                    t[j++].Start(parameters);
+                }
+            }
+            for (i = 0; i < j; i++) {
+                t[i].Join();
+            }
+        }
+
+        static void DoWork(object parameters) {
+
+            object[] parameterArray = (object[])parameters;
+            Int64 currProcMask = (Int64)parameterArray[0];
+
+            foreach (ProcessThread pt in Process.GetCurrentProcess().Threads) {
+                int utid = GetCurrentThreadId();
+                if (utid == pt.Id) {
+                    pt.ProcessorAffinity = (IntPtr)(currProcMask); // Set affinity for this thread to CPU #1
+                    Thread.Sleep(10);
+                    Console.WriteLine("Running on processor {0}", GetCurrentProcessorNumber());
+                }
+            }
+
+        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILThreadPool.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILThreadPool.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Misc/ILThreadPool.cs	(revision 9102)
@@ -0,0 +1,215 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Diagnostics; 
+using System.Runtime.InteropServices; 
+
+namespace ILNumerics.Misc {
+    /// <summary>
+    /// simple thread pool implementation - NOT THREAD SAFE !! 
+    /// </summary>
+    internal partial class ILThreadPool {
+
+        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+        static extern bool GetProcessAffinityMask(IntPtr currentProcess, ref Int64 lpProcessAffinityMask, ref Int64 lpSystemAffinityMask);
+        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+        static extern int GetCurrentThreadId();
+        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+        public static extern int GetCurrentProcessorNumber();
+
+        private static ILThreadPool s_pool = new ILThreadPool(Settings.MaxNumberThreads - 1);
+        public static ILThreadPool Pool {
+            get {
+                return s_pool; 
+            }
+        }
+        private static ILPerformanceCounter s_performanceCounters; 
+        private static object s_lock = new object(); 
+        internal static bool QueueUserWorkItem(int id, Action<object> action, object data) {
+            lock (s_lock) {
+                ILThread thread = s_pool.m_threads[id];
+                ILThreadPoolWorkItem workItem;
+                workItem.Action = action;
+                workItem.Data = data;
+                thread.Queue(workItem);
+                return true;
+            }
+        }
+
+        private int m_maxNumberThreads;
+        public int MaxNumberThreads {
+            get { return m_maxNumberThreads; }
+            set {
+                lock (s_lock) {
+                    while (m_maxNumberThreads > value) {
+                        ILThread thread = m_threads[--m_maxNumberThreads];
+                        thread.End();
+                        m_threads.Remove(thread);
+                    }
+                    while (m_maxNumberThreads < value) {
+                        m_threads.Add(new ILThread(m_maxNumberThreads));
+                        m_maxNumberThreads++; 
+                    }
+                }
+            }
+        }
+        private List<ILThread> m_threads = new List<ILThread>();
+
+        public ILThreadPool(int maxThreads) {
+
+            m_maxNumberThreads = maxThreads; 
+            for (int i = 0; i < m_maxNumberThreads; i++) {
+                m_threads.Add(new ILThread(i)); 
+            }
+            if (Settings.s_useThreadAffinity) {
+                int targetMask = 8;
+                foreach (ProcessThread pt in Process.GetCurrentProcess().Threads) {
+                    int osThreadId = GetCurrentThreadId();
+                    if (osThreadId == pt.Id) {
+                        pt.ProcessorAffinity = (IntPtr)(targetMask);
+                        break;
+                    }
+                }
+                Thread.Sleep(10);
+                Thread.BeginThreadAffinity();
+            }
+            if (Settings.s_measurePerformanceAtRuntime) {
+                s_performanceCounters = new ILPerformanceCounter();
+                s_performanceCounters.PCcurNumberThreadsSet(maxThreads);
+            }
+        }
+        public static void Wait4Workers(ref int workerCount) {
+            //var spinWait = new SpinWait();
+            //while (workerCount > 0) {
+            //    //Thread.MemoryBarrier(); 
+            //    spinWait.SpinOnce();
+            //}
+
+            //System.Threading.SpinWait.SpinUntil(() => {
+            //    Thread.MemoryBarrier();
+            //    return workerCount <= 0;
+            //});
+            long msStart = Stopwatch.GetTimestamp();
+            while (workerCount > 0) {
+                System.Threading.Thread.SpinWait(8);
+            }
+            if (Settings.s_measurePerformanceAtRuntime) 
+                s_performanceCounters.PCwaited4ThreadsSet(Stopwatch.GetTimestamp() - msStart); 
+        }
+
+        public struct ILThreadPoolWorkItem {
+            public Action<object> Action;
+            public object Data; 
+        }
+
+        private class ILThread {
+            private int m_index; 
+            private Thread m_thread;
+            private AutoResetEvent m_resetEvent;
+            private Queue<ILThreadPoolWorkItem> m_queue;
+            private bool m_ending; 
+
+            internal ILThread(int index) {
+                m_index = index; 
+                m_ending = false; 
+                m_resetEvent = new AutoResetEvent(false);
+                m_queue = new Queue<ILThreadPoolWorkItem>();
+                m_thread = new Thread(WorkerFunc);
+                m_thread.Priority = ThreadPriority.AboveNormal;
+                m_thread.IsBackground = true; 
+                m_thread.Start(); 
+            }
+
+            private int Index {
+                get {
+                    return m_index; 
+                }
+            }
+
+            public void End() {
+                lock (s_lock) {
+                    if (m_queue.Count > 0)
+                        throw new Exceptions.ILInvalidOperationException("invalid attempt to remove a thread with pending work items");
+                    m_ending = true;
+                    m_resetEvent.Set();
+                }
+            }
+            public void Queue(ILThreadPoolWorkItem workItem) {
+                m_queue.Enqueue(workItem);
+                m_resetEvent.Set(); 
+            }
+
+            private void WorkerFunc() {
+                if (Settings.s_useThreadAffinity) {
+                    Int64 targetMask = (Index + 1) << (Index + 1);
+                    // TODO: IMPROVE!! 
+                    targetMask = 1; 
+                    foreach (ProcessThread pt in Process.GetCurrentProcess().Threads) {
+                        int osThreadId = GetCurrentThreadId();
+                        if (osThreadId == pt.Id) {
+                            pt.ProcessorAffinity = (IntPtr)(targetMask);
+                            break;
+                        }
+                    }
+                    Thread.Sleep(10);
+                    //Thread.BeginThreadAffinity(); 
+                }
+                while (true) {
+                    //SpinWait.SpinUntil(() => { return m_queue.Count > 0; }); 
+                    m_resetEvent.WaitOne();
+                    while (m_queue.Count > 0) {
+                        //Thread.BeginThreadAffinity(); 
+                        ILThreadPoolWorkItem workItem = m_queue.Dequeue();
+                        workItem.Action(workItem.Data);
+                        //Thread.EndThreadAffinity(); 
+                    }
+                    if (m_ending) break; 
+                }
+
+            }
+        }
+
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Native/FFT/IILFFT.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Native/FFT/IILFFT.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Native/FFT/IILFFT.cs	(revision 9102)
@@ -0,0 +1,185 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using ILNumerics; 
+
+namespace ILNumerics.Native {
+
+    /// <summary>
+    /// Interface for all FFT methods supported
+    /// </summary>
+    public interface IILFFT {
+        /// <summary>
+        /// performs backward n-dimensional fft
+        /// </summary>
+        /// <param name="A">input array</param>
+        /// <param name="nDims">number of dimensions of fft</param>
+        /// <returns>result, same size as A</returns>
+        ILRetArray<complex> FFTBackward(ILInArray<complex> A, int nDims);
+        /// <summary>
+        /// performs backward n-dimensional fft
+        /// </summary>
+        /// <param name="A">input array</param>
+        /// <param name="nDims">number of dimensions of fft</param>
+        /// <returns>result, same size as A</returns>
+        ILRetArray<fcomplex> FFTBackward(ILInArray<fcomplex> A, int nDims);
+        /// <summary>
+        /// performs backward 1-dimensional fft
+        /// </summary>
+        /// <param name="A">input array</param>
+        /// <param name="dim">dimension to perform fft along</param>
+        /// <returns>result, same size as A</returns>
+        ILRetArray<fcomplex> FFTBackward1D(ILInArray<fcomplex> A, int dim);
+        /// <summary>
+        /// performs backward 1-dimensional fft 
+        /// </summary>
+        /// <param name="A">input array</param>
+        /// <param name="dim">dimension to perform fft along</param>
+        /// <returns>result, same size as A</returns>
+        ILRetArray<complex> FFTBackward1D(ILInArray<complex> A, int dim);
+        /// <summary>
+        /// performs backward n-dimensional fft on hermitian sequence
+        /// </summary>
+        /// <param name="A">input array</param>
+        /// <param name="nDims">number of dimensions of fft</param>
+        /// <returns>result, same size as A</returns>
+        /// <remarks>This function brings increased performance if the implementation supports it. 
+        /// If not, the method will be implemented by repeated calls of (inplace) 1D fft.</remarks>
+        ILRetArray<float> FFTBackwSym(ILInArray<fcomplex> A, int nDims);
+        /// <summary>
+        /// performs backward n-dimensional fft on hermitian sequence
+        /// </summary>
+        /// <param name="A">input array</param>
+        /// <param name="nDims">number of dimensions of fft</param>
+        /// <returns>result, same size as A</returns>
+        /// <remarks>This function brings increased performance if the implementation supports it. 
+        /// If not, the method will be implemented by repeated calls of (inplace) 1D fft.</remarks>
+        ILRetArray<double> FFTBackwSym(ILInArray<complex> A, int nDims);
+        /// <summary>
+        /// performs backward 1-dimensional fft on hermitian sequence
+        /// </summary>
+        /// <param name="A">input array</param>
+        /// <param name="dim">dimension to perform fft along</param>
+        /// <returns>result, same size as A</returns>
+        /// <remarks>This function brings increased performance if the implementation supports it. 
+        /// If not, the method will be implemented by repeated calls of (inplace) 1D fft.</remarks>
+        ILRetArray<float> FFTBackwSym1D(ILInArray<fcomplex> A, int dim);
+        /// <summary>
+        /// performs backward 1-dimensional fft on hermitian sequence
+        /// </summary>
+        /// <param name="A">input array</param>
+        /// <param name="dim">dimension to perform fft along</param>
+        /// <returns>result, same size as A</returns>
+        /// <remarks>This function brings increased performance if the implementation supports it. 
+        /// If not, the method will be implemented by repeated calls of (inplace) 1D fft.</remarks>
+        ILRetArray<double> FFTBackwSym1D(ILInArray<complex> A, int dim);
+        /// <summary>
+        /// performs n-dimensional fft
+        /// </summary>
+        /// <param name="A">input array</param>
+        /// <param name="nDims">number of dimension of fft</param>
+        /// <returns>result, same size as A</returns>
+        ILRetArray<fcomplex> FFTForward(ILInArray<fcomplex> A, int nDims);
+        /// <summary>
+        /// performs n-dimensional fft
+        /// </summary>
+        /// <param name="A">input array</param>
+        /// <param name="nDims">number of dimension of fft</param>
+        /// <returns>result, same size as A</returns>
+        ILRetArray<complex> FFTForward(ILInArray<double> A, int nDims);
+        /// <summary>
+        /// performs n-dimensional fft
+        /// </summary>
+        /// <param name="A">input array</param>
+        /// <param name="nDims">number of dimension of fft</param>
+        /// <returns>result, same size as A</returns>
+        ILRetArray<complex> FFTForward(ILInArray<complex> A, int nDims);
+        /// <summary>
+        /// performs n-dimensional fft
+        /// </summary>
+        /// <param name="A">input array</param>
+        /// <param name="nDims">number of dimension of fft</param>
+        /// <returns>result, same size as A</returns>
+        ILRetArray<fcomplex> FFTForward(ILInArray<float> A, int nDims);
+        /// <summary>
+        /// performs 1-dimensional fft
+        /// </summary>
+        /// <param name="A">input array</param>
+        /// <param name="dim">dimension to perform fft along</param>
+        /// <returns>result, same size as A</returns>
+        ILRetArray<complex> FFTForward1D(ILInArray<complex> A, int dim);
+        /// <summary>
+        /// performs 1-dimensional fft
+        /// </summary>
+        /// <param name="A">input array</param>
+        /// <param name="dim">dimension to perform fft along</param>
+        /// <returns>result, same size as A</returns>
+        ILRetArray<complex> FFTForward1D(ILInArray<double> A, int dim);
+        /// <summary>
+        /// performs 1-dimensional fft
+        /// </summary>
+        /// <param name="A">input array</param>
+        /// <param name="dim">dimension to perform fft along</param>
+        /// <returns>result, same size as A</returns>
+        ILRetArray<fcomplex> FFTForward1D(ILInArray<fcomplex> A, int dim);
+        /// <summary>
+        /// performs 1-dimensional fft
+        /// </summary>
+        /// <param name="A">input array</param>
+        /// <param name="dim">dimension to perform fft along</param>
+        /// <returns>result, same size as A</returns>
+        ILRetArray<fcomplex> FFTForward1D(ILInArray<float> A, int dim);
+        /// <summary>
+        /// true, if the implementation caches plans between subsequent calls
+        /// </summary>
+        bool CachePlans { get; }
+        /// <summary>
+        /// Clear all currently cached plans
+        /// </summary>
+        void FreePlans();
+        /// <summary>
+        /// true, if the implementation efficiently transforms from/to hermitian sequences (hermitian symmetry). 
+        /// </summary>
+        /// <remarks>If this property returns 'true', the implementation brings increased performance. 
+        /// If not, the symmetry methods will bring no performance advantage over the 1D transforms. </remarks>
+        bool SpeedyHermitian { get; }
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Native/FFT/ILACMLFFT.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Native/FFT/ILACMLFFT.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Native/FFT/ILACMLFFT.cs	(revision 9102)
@@ -0,0 +1,603 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+#pragma warning disable 1591
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Security; 
+using System.Runtime.InteropServices;
+using ILNumerics.Exceptions; 
+using ILNumerics.Misc; 
+
+namespace ILNumerics.Native {
+    
+    /// <summary>
+    /// Wrapper for FFT interface using ACML ver. 3.6
+    /// </summary>
+    public unsafe class ILACMLFFT : IILFFT, IDisposable {
+
+        #region pinvoke definitions 
+        
+        [DllImport("libacml_dll"),SuppressUnmanagedCodeSecurity]
+		private static extern void zfft1mx(int MODE, double SCALE, int INPL, int NSEQ, int N, IntPtr X, int INCX1, int INCX2, IntPtr Y, int INCY1, int INCY2, IntPtr COMM, ref int INFO);
+        [DllImport("libacml_dll"),SuppressUnmanagedCodeSecurity]
+		private static extern void cfft1mx(int MODE, float SCALE, int INPL, int NSEQ, int N,  IntPtr X, int INCX1, int INCX2, IntPtr Y, int INCY1, int INCY2, IntPtr COMM, ref int INFO);
+        [DllImport("libacml_dll"),SuppressUnmanagedCodeSecurity]
+		private static extern void zfft2dx(int MODE, double SCALE, int LTRANS, int INPL, int M, int N, IntPtr X, int INCX1, int INCX2, IntPtr Y, int INCY1, int INCY2, IntPtr COMM, ref int INFO);
+        [DllImport("libacml_dll"),SuppressUnmanagedCodeSecurity]
+		private static extern void cfft2dx(int MODE, float SCALE,  int LTRANS, int INPL, int M, int N, IntPtr X, int INCX1, int INCX2, IntPtr Y, int INCY1, int INCY2, IntPtr COMM, ref int INFO);
+
+        #endregion
+
+        #region value constants
+        private class ACMLValues {
+            public static readonly int Double = 8; 
+            public static readonly int Single = 4; 
+            public static readonly int Real = 1; 
+            public static readonly int Complex = 2; 
+            public static readonly int Backwards = 1; 
+            public static readonly int Forward = -1; 
+        }
+        #endregion
+
+        #region attributes 
+        Dictionary<string,IntPtr> m_descriptors; 
+        object _lockobject = new object(); 
+        #endregion
+
+        #region constructor 
+        public ILACMLFFT () {
+            m_descriptors = new Dictionary<string,IntPtr>(10); 
+        }
+        #endregion
+
+        #region IILFFT Member - 1-D
+        
+
+
+        public ILRetArray< complex>  FFTForward1D(ILInArray< double> A, int dim) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A, null) || dim < 0)
+                    throw new ILArgumentException("FFTForward1D: invalid parameter!");
+                if (A.IsEmpty) return ILMath.array< complex>(A.Size);
+                if (A.IsScalar || A.Size[dim] == 1)
+                    return  ILMath.tocomplex(A);
+                // prepare output array 
+                ILArray< complex> ret =  ILMath.tocomplex(A);
+                fft1dInplace(dim, ret, ACMLValues.Forward);
+                return ret;
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+
+        public ILRetArray< fcomplex>  FFTBackward1D(ILInArray< fcomplex> A, int dim) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A, null) || dim < 0)
+                    throw new ILArgumentException("FFTForward1D: invalid parameter!");
+                if (A.IsEmpty) return ILMath.array< fcomplex>(A.Size);
+                if (A.IsScalar || A.Size[dim] == 1)
+                    return  A.C;
+                // prepare output array 
+                ILArray< fcomplex> ret =  A.C;
+                fft1dInplace(dim, ret, ACMLValues.Backwards);
+                return ret;
+            }
+        }
+
+        public ILRetArray< complex>  FFTBackward1D(ILInArray< complex> A, int dim) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A, null) || dim < 0)
+                    throw new ILArgumentException("FFTForward1D: invalid parameter!");
+                if (A.IsEmpty) return ILMath.array< complex>(A.Size);
+                if (A.IsScalar || A.Size[dim] == 1)
+                    return  A.C;
+                // prepare output array 
+                ILArray< complex> ret =  A.C;
+                fft1dInplace(dim, ret, ACMLValues.Backwards);
+                return ret;
+            }
+        }
+
+        public ILRetArray< fcomplex>  FFTForward1D(ILInArray< fcomplex> A, int dim) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A, null) || dim < 0)
+                    throw new ILArgumentException("FFTForward1D: invalid parameter!");
+                if (A.IsEmpty) return ILMath.array< fcomplex>(A.Size);
+                if (A.IsScalar || A.Size[dim] == 1)
+                    return  A.C;
+                // prepare output array 
+                ILArray< fcomplex> ret =  A.C;
+                fft1dInplace(dim, ret, ACMLValues.Forward);
+                return ret;
+            }
+        }
+
+        public ILRetArray< fcomplex>  FFTForward1D(ILInArray< float> A, int dim) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A, null) || dim < 0)
+                    throw new ILArgumentException("FFTForward1D: invalid parameter!");
+                if (A.IsEmpty) return ILMath.array< fcomplex>(A.Size);
+                if (A.IsScalar || A.Size[dim] == 1)
+                    return  ILMath.tofcomplex(A);
+                // prepare output array 
+                ILArray< fcomplex> ret =  ILMath.tofcomplex(A);
+                fft1dInplace(dim, ret, ACMLValues.Forward);
+                return ret;
+            }
+        }
+
+        public ILRetArray< complex>  FFTForward1D(ILInArray< complex> A, int dim) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A, null) || dim < 0)
+                    throw new ILArgumentException("FFTForward1D: invalid parameter!");
+                if (A.IsEmpty) return ILMath.array< complex>(A.Size);
+                if (A.IsScalar || A.Size[dim] == 1)
+                    return  A.C;
+                // prepare output array 
+                ILArray< complex> ret =  A.C;
+                fft1dInplace(dim, ret, ACMLValues.Forward);
+                return ret;
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+        public ILRetArray<double> FFTBackwSym1D(ILInArray<complex> A, int dim) {
+            return ILMath.real(FFTBackward1D(A,dim));    
+        }
+
+        public ILRetArray<float> FFTBackwSym1D(ILInArray<fcomplex> A, int dim) {
+            return ILMath.real(FFTBackward1D(A,dim));    
+        }
+
+        #endregion
+
+        #region IILFFT Member n-D
+
+
+
+        public ILRetArray< complex>  FFTForward(ILInArray< double> A, int nDims) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A, null) || nDims <= 0)
+                    throw new ILArgumentException("invalid parameter!");
+                if (A.IsEmpty) return ILMath.array< complex>(A.Size);
+                if (A.IsScalar || (A.Size[0] == 1 && nDims == 1))
+                    return  ILMath.tocomplex(A);
+                if (nDims > A.Size.NumberOfDimensions)
+                    return  FFTForward(A, A.Size.NumberOfDimensions);
+
+                // prepare output array + transform each dimension inplace 
+                ILArray< complex> ret =  ILMath.tocomplex(A);
+                switch (nDims) {
+                    case 2:
+                        fft2dInplace(ret, ACMLValues.Forward);
+                        break;
+                    default:
+                        for (int i = 0; i < nDims; i++) {
+                            fft1dInplace(i, ret, ACMLValues.Forward);
+                        }
+                        break;
+                }
+                return ret;
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+
+        public ILRetArray< fcomplex>  FFTBackward(ILInArray< fcomplex> A, int nDims) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A, null) || nDims <= 0)
+                    throw new ILArgumentException("invalid parameter!");
+                if (A.IsEmpty) return ILMath.array< fcomplex>(A.Size);
+                if (A.IsScalar || (A.Size[0] == 1 && nDims == 1))
+                    return  A.C;
+                if (nDims > A.Size.NumberOfDimensions)
+                    return  FFTBackward(A, A.Size.NumberOfDimensions);
+
+                // prepare output array + transform each dimension inplace 
+                ILArray< fcomplex> ret =  A.C;
+                switch (nDims) {
+                    case 2:
+                        fft2dInplace(ret, ACMLValues.Backwards);
+                        break;
+                    default:
+                        for (int i = 0; i < nDims; i++) {
+                            fft1dInplace(i, ret, ACMLValues.Backwards);
+                        }
+                        break;
+                }
+                return ret;
+            }
+        }
+
+        public ILRetArray< complex>  FFTBackward(ILInArray< complex> A, int nDims) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A, null) || nDims <= 0)
+                    throw new ILArgumentException("invalid parameter!");
+                if (A.IsEmpty) return ILMath.array< complex>(A.Size);
+                if (A.IsScalar || (A.Size[0] == 1 && nDims == 1))
+                    return  A.C;
+                if (nDims > A.Size.NumberOfDimensions)
+                    return  FFTBackward(A, A.Size.NumberOfDimensions);
+
+                // prepare output array + transform each dimension inplace 
+                ILArray< complex> ret =  A.C;
+                switch (nDims) {
+                    case 2:
+                        fft2dInplace(ret, ACMLValues.Backwards);
+                        break;
+                    default:
+                        for (int i = 0; i < nDims; i++) {
+                            fft1dInplace(i, ret, ACMLValues.Backwards);
+                        }
+                        break;
+                }
+                return ret;
+            }
+        }
+
+        public ILRetArray< fcomplex>  FFTForward(ILInArray< fcomplex> A, int nDims) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A, null) || nDims <= 0)
+                    throw new ILArgumentException("invalid parameter!");
+                if (A.IsEmpty) return ILMath.array< fcomplex>(A.Size);
+                if (A.IsScalar || (A.Size[0] == 1 && nDims == 1))
+                    return  A.C;
+                if (nDims > A.Size.NumberOfDimensions)
+                    return  FFTForward(A, A.Size.NumberOfDimensions);
+
+                // prepare output array + transform each dimension inplace 
+                ILArray< fcomplex> ret =  A.C;
+                switch (nDims) {
+                    case 2:
+                        fft2dInplace(ret, ACMLValues.Forward);
+                        break;
+                    default:
+                        for (int i = 0; i < nDims; i++) {
+                            fft1dInplace(i, ret, ACMLValues.Forward);
+                        }
+                        break;
+                }
+                return ret;
+            }
+        }
+
+        public ILRetArray< fcomplex>  FFTForward(ILInArray< float> A, int nDims) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A, null) || nDims <= 0)
+                    throw new ILArgumentException("invalid parameter!");
+                if (A.IsEmpty) return ILMath.array< fcomplex>(A.Size);
+                if (A.IsScalar || (A.Size[0] == 1 && nDims == 1))
+                    return  ILMath.tofcomplex(A);
+                if (nDims > A.Size.NumberOfDimensions)
+                    return  FFTForward(A, A.Size.NumberOfDimensions);
+
+                // prepare output array + transform each dimension inplace 
+                ILArray< fcomplex> ret =  ILMath.tofcomplex(A);
+                switch (nDims) {
+                    case 2:
+                        fft2dInplace(ret, ACMLValues.Forward);
+                        break;
+                    default:
+                        for (int i = 0; i < nDims; i++) {
+                            fft1dInplace(i, ret, ACMLValues.Forward);
+                        }
+                        break;
+                }
+                return ret;
+            }
+        }
+
+        public ILRetArray< complex>  FFTForward(ILInArray< complex> A, int nDims) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A, null) || nDims <= 0)
+                    throw new ILArgumentException("invalid parameter!");
+                if (A.IsEmpty) return ILMath.array< complex>(A.Size);
+                if (A.IsScalar || (A.Size[0] == 1 && nDims == 1))
+                    return  A.C;
+                if (nDims > A.Size.NumberOfDimensions)
+                    return  FFTForward(A, A.Size.NumberOfDimensions);
+
+                // prepare output array + transform each dimension inplace 
+                ILArray< complex> ret =  A.C;
+                switch (nDims) {
+                    case 2:
+                        fft2dInplace(ret, ACMLValues.Forward);
+                        break;
+                    default:
+                        for (int i = 0; i < nDims; i++) {
+                            fft1dInplace(i, ret, ACMLValues.Forward);
+                        }
+                        break;
+                }
+                return ret;
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+        public ILRetArray<float> FFTBackwSym(ILInArray<fcomplex> A, int nDims) {
+            return ILMath.real(FFTBackward(A,nDims)); 
+        }
+
+        public ILRetArray<double> FFTBackwSym(ILInArray<complex> A, int nDims) {
+            return ILMath.real(FFTBackward(A,nDims)); 
+        }
+
+        public bool CachePlans {
+            get { return true; }
+        }
+
+        public void FreePlans() {
+            FreeAllDescriptors();
+        }
+
+        public bool SpeedyHermitian {
+            get { return false; }
+        }
+
+        #endregion
+
+        #region private helper
+
+        private void fft1dInplace(int dim, ILInArray<complex> ret, int mode) {
+            using (ILScope.Enter(ret)) {
+                int N = ret.Size[dim], info = 0;
+                // spacing between elements
+                int incx1 = ret.Size.SequentialIndexDistance(dim);
+                // storage of subsequent transformations
+                int incx2 = incx1 * N;
+                // number of transformations
+                int nseq = ret.Size.NumberOfElements / incx2;
+                double scale = (mode == ACMLValues.Backwards) ? 1.0 / N : 1.0;
+                string hash = hashPlan(ACMLValues.Double, ACMLValues.Complex, N, "zfft1mx");
+                IntPtr descriptor;
+                lock (_lockobject) {
+                    if (!m_descriptors.TryGetValue(hash, out descriptor)) {
+                        int commLength = (3 * N + 100) * ACMLValues.Double * 2;
+                        try {
+                            descriptor = Marshal.AllocCoTaskMem(commLength);
+                            zfft1mx(0, scale, 1, nseq, N, IntPtr.Zero, incx1, incx2, IntPtr.Zero, 0, 0, descriptor, ref info);
+                            if (info != 0)
+                                throw new ILInvalidOperationException("error creating fft-plan");
+                            m_descriptors[hash] = descriptor;
+                        } catch (OutOfMemoryException exc) {
+                            if (m_descriptors.Count > 0) {
+                                FreeAllDescriptors();
+                                descriptor = Marshal.AllocCoTaskMem(commLength);
+                                zfft1mx(0, scale, 1, nseq, N, IntPtr.Zero, incx1, incx2, IntPtr.Zero, 0, 0, descriptor, ref info);
+                                if (info != 0)
+                                    throw new ILInvalidOperationException("error creating fft-plan");
+                                m_descriptors[hash] = descriptor;
+                            }
+                            throw exc;
+                        }
+                    }
+                    // do the transform(s)
+                    fixed (complex* start = ret.GetArrayForWrite()) {
+                        for (int i = 0; i < incx1 && info == 0; i++)
+                            zfft1mx(mode, scale, 1, nseq, N, (IntPtr)(start + i), incx1, incx2, IntPtr.Zero, 0, 0, descriptor, ref info);
+                    }
+                }
+                if (info != 0) {
+                    throw new ILInvalidOperationException(String.Format("error: {0}th parameter was invalid", -info));
+                }
+            }
+        }
+        private void fft2dInplace(ILInArray<complex> ret, int mode) {
+            using (ILScope.Enter(ret)) {
+                System.Diagnostics.Debug.Assert(ret.Size.NumberOfDimensions >= 2);
+                int N = ret.Size[1], M = ret.Size[0], info = 0;
+                int MN = M * N;
+                // number of transformations
+                int nseq = ret.Size.NumberOfElements / (MN);
+                double scale = (mode == ACMLValues.Backwards) ? 1.0 / MN : 1.0;
+                string hash = hashPlan(ACMLValues.Double, ACMLValues.Complex, M, N, "zfft2dx");
+                IntPtr descriptor;
+                lock (_lockobject) {
+                    if (!m_descriptors.TryGetValue(hash, out descriptor)) {
+                        int commLength = (3 * (N + M) + MN + 200) * ACMLValues.Double * 2;
+                        try {
+                            descriptor = Marshal.AllocCoTaskMem(commLength);
+                            zfft2dx(0, scale, 1, 1, M, N, IntPtr.Zero, 1, M, IntPtr.Zero, 0, 0, descriptor, ref info);
+                            if (info != 0)
+                                throw new ILInvalidOperationException("error creating fft-plan");
+                            m_descriptors[hash] = descriptor;
+                        } catch (OutOfMemoryException exc) {
+                            if (m_descriptors.Count > 0) {
+                                FreeAllDescriptors();
+                                descriptor = Marshal.AllocCoTaskMem(commLength);
+                                zfft2dx(0, scale, 1, 1, M, N, IntPtr.Zero, 1, M, IntPtr.Zero, 0, 0, descriptor, ref info);
+                                if (info != 0)
+                                    throw new ILInvalidOperationException("error creating fft-plan");
+                                m_descriptors[hash] = descriptor;
+                            }
+                            throw exc;
+                        }
+                    }
+                    // do the transform(s)
+                    fixed (complex* start = ret.GetArrayForWrite()) {
+                        for (int i = 0; i < nseq && info == 0; i++)
+                            zfft2dx(mode, scale, 1, 1, M, N, (IntPtr)(start + i * MN), 1, M, IntPtr.Zero, 0, 0, descriptor, ref info);
+                    }
+                }
+                if (info != 0) {
+                    throw new ILInvalidOperationException(String.Format("error: {0}th parameter was invalid", -info));
+                }
+            }
+        }
+
+        private void fft1dInplace(int dim, ILInArray<fcomplex> ret, int mode) {
+            using (ILScope.Enter(ret)) {
+                int N = ret.Size[dim], info = 0;
+                // spacing between elements
+                int incx1 = ret.Size.SequentialIndexDistance(dim);
+                // storage of subsequent transformations
+                int incx2 = incx1 * N;
+                // number of transformations
+                int nseq = ret.Size.NumberOfElements / incx2;
+                float scale = (mode == ACMLValues.Backwards) ? 1.0f / N : 1.0f;
+                string hash = hashPlan(ACMLValues.Single, ACMLValues.Complex, N, "cfft1mx");
+                IntPtr descriptor;
+                lock (_lockobject) {
+                    if (!m_descriptors.TryGetValue(hash, out descriptor)) {
+                        int commLength = (3 * N + 100) * ACMLValues.Single * 2;
+                        try {
+                            descriptor = Marshal.AllocCoTaskMem(commLength);
+                            cfft1mx(0, 1.0f, 1, 1, N, IntPtr.Zero, 1, 1, IntPtr.Zero, 0, 0, descriptor, ref info);
+                            if (info != 0)
+                                throw new ILInvalidOperationException("error creating fft-plan");
+                            m_descriptors[hash] = descriptor;
+                        } catch (OutOfMemoryException exc) {
+                            if (m_descriptors.Count > 0) {
+                                FreeAllDescriptors();
+                                descriptor = Marshal.AllocCoTaskMem(commLength);
+                                cfft1mx(0, 1.0f, 1, 1, N, IntPtr.Zero, 1, 1, IntPtr.Zero, 0, 0, descriptor, ref info);
+                                if (info != 0)
+                                    throw new ILInvalidOperationException("error creating fft-plan");
+                                m_descriptors[hash] = descriptor;
+                            }
+                            throw exc;
+                        }
+                    }
+                    // do the transform(s)
+                    fixed (fcomplex* start = ret.GetArrayForWrite()) {
+                        for (int i = 0; i < incx1 && info == 0; i++)
+                            cfft1mx(mode, scale, 1, nseq, N, (IntPtr)(start + i), incx1, incx2, IntPtr.Zero, 0, 0, descriptor, ref info);
+                    }
+                }
+                if (info != 0) {
+                    throw new ILInvalidOperationException(String.Format("error: {0}th parameter was invalid", -info));
+                }
+            }
+        }
+        private void fft2dInplace(ILInArray<fcomplex> ret, int mode) {
+            using (ILScope.Enter(ret)) {
+                System.Diagnostics.Debug.Assert(ret.Size.NumberOfDimensions >= 2);
+                int N = ret.Size[1], M = ret.Size[0], info = 0;
+                int MN = M * N;
+                // number of transformations
+                int nseq = ret.Size.NumberOfElements / (MN);
+                float scale = (mode == ACMLValues.Backwards) ? 1.0f / MN : 1.0f;
+                string hash = hashPlan(ACMLValues.Single, ACMLValues.Complex, M, N, "cfft2dx");
+                IntPtr descriptor;
+                lock (_lockobject) {
+                    if (!m_descriptors.TryGetValue(hash, out descriptor)) {
+                        int commLength = (3 * (N + M) + MN + 200) * ACMLValues.Single * 2;
+                        try {
+                            descriptor = Marshal.AllocCoTaskMem(commLength);
+                            cfft2dx(0, scale, 1, 1, M, N, IntPtr.Zero, 1, M, IntPtr.Zero, 0, 0, descriptor, ref info);
+                            if (info != 0)
+                                throw new ILInvalidOperationException("error creating fft-plan");
+                            m_descriptors[hash] = descriptor;
+                        } catch (OutOfMemoryException exc) {
+                            if (m_descriptors.Count > 0) {
+                                FreeAllDescriptors();
+                                descriptor = Marshal.AllocCoTaskMem(commLength);
+                                cfft2dx(0, scale, 1, 1, M, N, IntPtr.Zero, 1, M, IntPtr.Zero, 0, 0, descriptor, ref info);
+                                if (info != 0)
+                                    throw new ILInvalidOperationException("error creating fft-plan");
+                                m_descriptors[hash] = descriptor;
+                            }
+                            throw exc;
+                        }
+                    }
+                    // do the transform(s)
+                    fixed (fcomplex* start = ret.GetArrayForWrite()) {
+                        for (int i = 0; i < nseq && info == 0; i++)
+                            cfft2dx(mode, scale, 1, 1, M, N, (IntPtr)(start + i * MN), 1, M, IntPtr.Zero, 0, 0, descriptor, ref info);
+                    }
+                }
+                if (info != 0) {
+                    throw new ILInvalidOperationException(String.Format("error: {0}th parameter was invalid", -info));
+                }
+            }
+        }
+
+        private static string hashPlan(int precision, int realcomplex, int N, string funcname) {
+            return hashPlan(precision,realcomplex,0,N,funcname); 
+        }
+        private static string hashPlan(int precision, int realcomplex, int M, int N, string funcname) {
+            return String.Format("{0}|{1}|{2}|{3}|{4}",precision, realcomplex,M,N,funcname); 
+        }
+        private void FreeAllDescriptors() {
+            lock (_lockobject) {
+                if (m_descriptors != null) {
+                    foreach (IntPtr p in m_descriptors.Values) {
+                        if (p != IntPtr.Zero)
+                            Marshal.FreeCoTaskMem(p); 
+                    }
+                    m_descriptors.Clear(); 
+                }
+            }
+        }   
+        
+        #endregion
+
+        #region IDisposable Member
+
+        public void Dispose() {
+            Dispose(true); 
+            /* we cannot supress finalize,since the class will only wipe all 
+             * cached cotask memory. Supsequent calls will again allocate those. 
+             * Therefore the finalizer must check at the end again. 
+             */ 
+            // GC.SuppressFinalize(this); 
+        }
+
+        public virtual void Dispose (bool manual) {
+            if (m_descriptors != null && m_descriptors.Count > 0) {
+                if (manual) {
+                    FreeAllDescriptors();             
+                }
+            }
+        }
+
+        ~ILACMLFFT () {
+            Dispose(true);     
+        }
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Native/FFT/ILFFTW3FFT.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Native/FFT/ILFFTW3FFT.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Native/FFT/ILFFTW3FFT.cs	(revision 9102)
@@ -0,0 +1,731 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+#pragma warning disable 1591
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Security; 
+using System.Runtime.InteropServices;
+using ILNumerics.Exceptions;  
+using ILNumerics.Misc; 
+
+namespace ILNumerics.Native {
+    
+    /// <summary>
+    /// Wrapper for FFT interface using FFTW3 libs
+    /// </summary>
+    public unsafe class ILFFTW3FFT : IILFFT, IDisposable {
+
+        #region pinvoke definitions 
+        
+        /// <summary>
+        /// This struct is used to define (n-dimensional) transform sizes
+        /// </summary>
+        /// <remarks>This struct is only user in C-API. It is NOT used for the Fortran interface (i.e. it's not used in here)!!! </remarks>
+        [StructLayout(LayoutKind.Sequential)]
+        private struct fftw_iodim {
+            /// <summary>
+            /// length of dimension
+            /// </summary>
+            public int n;
+            /// <summary>
+            /// input stride
+            /// </summary>
+            public int iS;
+            /// <summary>
+            /// output stride
+            /// </summary>
+            public int oS;
+        }
+
+        #region DOUBLE PRECISION INTERFACE ********* COMPLEX 
+        [DllImport("libfftw3-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void dfftw_plan_dft_1d_(ref IntPtr plan, ref int n, [In,Out] complex* input, [In,Out] complex* output, ref FFTW_DIRECTION sign, ref FFTW_PLANCREATION flags);
+        [DllImport("libfftw3-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void dfftw_plan_dft_2d_(ref IntPtr plan, ref int nx, ref int ny, [In,Out] complex* input, [In,Out] complex* output, ref FFTW_DIRECTION sign, ref FFTW_PLANCREATION flags);
+        [DllImport("libfftw3-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void dfftw_plan_dft_3d_(ref IntPtr plan, ref int nx, ref int ny, ref int nz, [In,Out] complex* input, [In,Out] complex* output, ref FFTW_DIRECTION sign, ref FFTW_PLANCREATION flags);
+        [DllImport("libfftw3-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void dfftw_plan_dft_(ref IntPtr plan, ref int rank, [In,Out] int[] n, [In,Out] complex* input, [In,Out] complex* output, ref FFTW_DIRECTION sign, ref FFTW_PLANCREATION flags);
+        
+        /****************************************************************** REAL-COMPLEX ***/
+        [DllImport("libfftw3-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void dfftw_plan_dft_r2c_1d_(ref IntPtr plan, ref int n, [In,Out] double* input, [In,Out] complex* output, ref FFTW_PLANCREATION flags);
+        [DllImport("libfftw3-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void dfftw_plan_dft_r2c_2d_(ref IntPtr plan, ref int nx, ref int ny, [In,Out] double* input, [In,Out] complex* output, ref FFTW_PLANCREATION flags);
+        [DllImport("libfftw3-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void dfftw_plan_dft_r2c_3d_(ref IntPtr plan, ref int nx, ref int ny, ref int nz, [In,Out] double* input, [In,Out] complex* output, ref FFTW_PLANCREATION flags);
+        [DllImport("libfftw3-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void dfftw_plan_dft_r2c_(ref IntPtr plan, ref int rank, [In,Out] int[] n, [In,Out] double* input, [In,Out] complex* output, ref FFTW_PLANCREATION flags);
+
+        [DllImport("libfftw3-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void dfftw_plan_dft_c2r_1d_(ref IntPtr plan, ref int n, [In,Out] complex* input, [In,Out] double* output, ref FFTW_PLANCREATION flags);
+        [DllImport("libfftw3-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void dfftw_plan_dft_c2r_2d_(ref IntPtr plan, ref int nx, ref int ny, [In,Out] complex* input, [In,Out] double* output, ref FFTW_PLANCREATION flags);
+        [DllImport("libfftw3-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void dfftw_plan_dft_c2r_3d_(ref IntPtr plan, ref int nx, ref int ny, ref int nz, [In,Out] complex* input, [In,Out] double* output, ref FFTW_PLANCREATION flags);
+        [DllImport("libfftw3-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void dfftw_plan_dft_c2r_(ref IntPtr plan, ref int rank, [In,Out] int[] n, [In,Out] complex* input, [In,Out] double* output, ref FFTW_PLANCREATION flags);
+
+        [DllImport("libfftw3-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void dfftw_plan_r2r_1d_(ref IntPtr plan, ref int n, [In,Out] double* input, [In,Out] double* output,  ref FFTW_PLANCREATION flags);
+        [DllImport("libfftw3-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void dfftw_plan_r2r_2d_(ref IntPtr plan, ref int nx, ref int ny, [In,Out] double* input, [In,Out] double* output, ref FFTW_PLANCREATION flags);
+        [DllImport("libfftw3-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void dfftw_plan_r2r_3d_(ref IntPtr plan, ref int nx, ref int ny, ref int nz, [In,Out] double* input, [In,Out] double* output, ref FFTW_PLANCREATION flags);
+        [DllImport("libfftw3-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void dfftw_plan_r2r_(ref IntPtr plan, ref int rank, [In,Out] int[] n, [In,Out] double* input, [In,Out] double* output, ref FFTW_PLANCREATION flags);
+
+        /************************************ ADVANCED INTERFACE *************************************/
+        [DllImport("libfftw3-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void dfftw_plan_many_dft_(ref IntPtr plan, ref int rank, [In,Out] int[] n, ref int howmany, [In,Out] complex* input, [In,Out] int[] inembed, ref int istride, ref int idist, [In,Out] complex* output, [In,Out] int[] onembed, ref int ostride, ref int odist, ref FFTW_DIRECTION sign, ref FFTW_PLANCREATION flags);		
+        [DllImport("libfftw3-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void dfftw_plan_many_dft_r2c_(ref IntPtr plan, ref int rank, [In,Out] int [] n, ref int howmany, [In,Out] double* input, [In,Out] int[] inembed, ref int istride, ref int idist, [In,Out] complex* output, [In,Out] int[] onembed, ref int ostride, ref int odist, ref FFTW_PLANCREATION flags);        
+        [DllImport("libfftw3-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void dfftw_plan_many_dft_c2r_(ref IntPtr plan, ref int rank, [In,Out] int [] n, ref int howmany, [In,Out] complex* input, [In,Out] int[] inembed, ref int istride, ref int idist, [In,Out] double* output, [In,Out] int[] onembed, ref int ostride, ref int odist, ref FFTW_PLANCREATION flags);        
+        [DllImport("libfftw3-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void dfftw_plan_many_r2r_(    ref IntPtr plan, ref int rank, [In,Out] int [] n, ref int howmany, [In,Out] double [] input, [In,Out] int[] inembed, ref int istride, ref int idist, [In,Out] double* output, [In,Out] int[] onembed, ref int ostride, ref int odist, ref FFTW_KIND kind, ref FFTW_PLANCREATION flags);        
+        
+        /************************************ GURU INTERFACE *************************************/
+        [DllImport("libfftw3-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void dfftw_plan_guru_dft_(ref IntPtr plan, ref int rank, [In,Out] int[] n, [In,Out] int[] iS,  [In,Out] int[] iO, ref int howmany_rank, [In,Out] int[] hn, [In,Out] int[] hiS,  [In,Out] int[] hiO, [In,Out] complex* input, [In,Out] complex* output, ref FFTW_DIRECTION sign, ref FFTW_PLANCREATION flags);
+        [DllImport("libfftw3-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void dfftw_plan_guru_split_dft_(ref IntPtr plan, ref int rank, [In,Out] int[] n, [In,Out] int[] iS,  [In,Out] int[] iO, ref int howmany_rank, [In,Out] int[] hn, [In,Out] int[] hiS,  [In,Out] int[] hiO, [In,Out] double* ri, [In,Out] double* ii, [In,Out] double* ro, [In,Out] double* io, ref FFTW_PLANCREATION flags);
+        [DllImport("libfftw3-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void dfftw_plan_guru_dft_r2c_(ref IntPtr plan, ref int rank, [In,Out] int[] n, [In,Out] int[] iS,  [In,Out] int[] iO, ref int howmany_rank, [In,Out] int[] hn, [In,Out] int[] hiS,  [In,Out] int[] hiO, [In,Out] double* input, [In,Out] complex* output, ref FFTW_PLANCREATION flags);
+        [DllImport("libfftw3-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void dfftw_plan_guru_dft_c2r_(ref IntPtr plan, ref int rank, [In,Out] int[] n, [In,Out] int[] iS,  [In,Out] int[] iO, ref int howmany_rank, [In,Out] int[] hn, [In,Out] int[] hiS,  [In,Out] int[] hiO, [In,Out] complex* input, [In,Out] double* output, ref FFTW_PLANCREATION flags);
+        [DllImport("libfftw3-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void dfftw_plan_guru_split_dft_r2c_(ref IntPtr plan, ref int rank, [In,Out] int[] n, [In,Out] int[] iS,  [In,Out] int[] iO, ref int howmany_rank, [In,Out] int[] hn, [In,Out] int[] hiS,  [In,Out] int[] hiO, [In,Out] double* ri, [In,Out] double* ro, [In,Out] double* io, ref FFTW_PLANCREATION flags);
+        [DllImport("libfftw3-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void dfftw_plan_guru_split_dft_c2r_(ref IntPtr plan, ref int rank, [In,Out] int[] n, [In,Out] int[] iS,  [In,Out] int[] iO, ref int howmany_rank, [In,Out] int[] hn, [In,Out] int[] hiS,  [In,Out] int[] hiO, [In,Out] double* ri, [In,Out] double* ii, [In,Out] double* ro, ref FFTW_PLANCREATION flags);
+        [DllImport("libfftw3-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void dfftw_plan_guru_r2r_(ref IntPtr plan, ref int rank, [In,Out] int[] n, [In,Out] int[] iS,  [In,Out] int[] iO, ref int howmany_rank, [In,Out] int[] hn, [In,Out] int[] hiS,  [In,Out] int[] hiO, [In,Out] double* input, [In,Out] double* output, ref FFTW_KIND kind, ref FFTW_PLANCREATION flags);
+        [DllImport("libfftw3-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void dfftw_execute_dft_(ref IntPtr plan, [In,Out] complex* input, [In,Out] complex* output);
+        [DllImport("libfftw3-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void dfftw_execute_split_dft_(ref IntPtr plan, [In,Out] double* ri, [In,Out] double* ii, [In,Out] double* ro, [In,Out] double* io);
+        [DllImport("libfftw3-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void dfftw_execute_dft_r2c_(ref IntPtr plan, [In,Out] double* ri, [In,Out] complex* ii);
+        [DllImport("libfftw3-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void dfftw_execute_split_dft_r2c_(ref IntPtr plan, [In,Out] double* input, [In,Out] double* ro, [In,Out] double* ri);
+        [DllImport("libfftw3-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void dfftw_execute_dft_c2r_(ref IntPtr plan, [In,Out] complex* input, [In,Out] double* output);
+        [DllImport("libfftw3-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void dfftw_execute_split_dft_c2r_(ref IntPtr plan, [In,Out] double* ri, [In,Out] double* ii, [In,Out] double* output);
+        [DllImport("libfftw3-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void dfftw_execute_r2r_(ref IntPtr plan, [In,Out] double* input, [In,Out] double* output);
+
+        /************************************ BASIC PLAN EXECUTION & MISC ******************************/
+        [DllImport("libfftw3-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void dfftw_execute_(ref IntPtr plan);
+        [DllImport("libfftw3-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void dfftw_destroy_plan_(ref IntPtr plan);
+        [DllImport("libfftw3-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void dfftw_cleanup_();
+        [DllImport("libfftw3-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void fftw_set_timelimit(ref double seconds);
+        #endregion DOUBLE PRECISION INTERFACE 
+
+        #region SINGLE PRECISION INTERFACE
+        [DllImport("libfftw3f-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void sfftw_plan_dft_1d_(ref IntPtr plan, ref int n, [In,Out] fcomplex* input, [In,Out] fcomplex* output, ref FFTW_DIRECTION sign, ref FFTW_PLANCREATION flags);
+        [DllImport("libfftw3f-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void sfftw_plan_dft_2d_(ref IntPtr plan, ref int nx, ref int ny, [In,Out] fcomplex* input, [In,Out] fcomplex* output, ref FFTW_DIRECTION sign, ref FFTW_PLANCREATION flags);
+        [DllImport("libfftw3f-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void sfftw_plan_dft_3d_(ref IntPtr plan, ref int nx, ref int ny, ref int nz, [In,Out] fcomplex* input, [In,Out] fcomplex* output, ref FFTW_DIRECTION sign, ref FFTW_PLANCREATION flags);
+        [DllImport("libfftw3f-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void sfftw_plan_dft_(ref IntPtr plan, ref int rank, [In,Out] int[] n, [In,Out] fcomplex* input, [In,Out] fcomplex* output, ref FFTW_DIRECTION sign, ref FFTW_PLANCREATION flags);
+        
+        /****************************************************************** REAL-COMPLEX ***/
+        [DllImport("libfftw3f-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void sfftw_plan_dft_r2c_1d_(ref IntPtr plan, ref int n, [In,Out] float* input, [In,Out] fcomplex* output, ref FFTW_PLANCREATION flags);
+        [DllImport("libfftw3f-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void sfftw_plan_dft_r2c_2d_(ref IntPtr plan, ref int nx, ref int ny, [In,Out] float* input, [In,Out] fcomplex* output, ref FFTW_PLANCREATION flags);
+        [DllImport("libfftw3f-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void sfftw_plan_dft_r2c_3d_(ref IntPtr plan, ref int nx, ref int ny, ref int nz, [In,Out] float* input, [In,Out] fcomplex* output, ref FFTW_PLANCREATION flags);
+        [DllImport("libfftw3f-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void sfftw_plan_dft_r2c_(ref IntPtr plan, ref int rank, [In,Out] int[] n, [In,Out] float* input, [In,Out] fcomplex* output, ref FFTW_PLANCREATION flags);
+
+        [DllImport("libfftw3f-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void sfftw_plan_dft_c2r_1d_(ref IntPtr plan, ref int n, [In,Out] fcomplex* input, [In,Out] float* output, ref FFTW_PLANCREATION flags);
+        [DllImport("libfftw3f-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void sfftw_plan_dft_c2r_2d_(ref IntPtr plan, ref int nx, ref int ny, [In,Out] fcomplex* input, [In,Out] float* output, ref FFTW_PLANCREATION flags);
+        [DllImport("libfftw3f-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void sfftw_plan_dft_c2r_3d_(ref IntPtr plan, ref int nx, ref int ny, ref int nz, [In,Out] fcomplex* input, [In,Out] float* output, ref FFTW_PLANCREATION flags);
+        [DllImport("libfftw3f-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void sfftw_plan_dft_c2r_(ref IntPtr plan, ref int rank, [In,Out] int[] n, [In,Out] fcomplex* input, [In,Out] float* output, ref FFTW_PLANCREATION flags);
+
+        [DllImport("libfftw3f-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void sfftw_plan_r2r_1d_(ref IntPtr plan, ref int n, [In,Out] float* input, [In,Out] float* output,  ref FFTW_PLANCREATION flags);
+        [DllImport("libfftw3f-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void sfftw_plan_r2r_2d_(ref IntPtr plan, ref int nx, ref int ny, [In,Out] float* input, [In,Out] float* output, ref FFTW_PLANCREATION flags);
+        [DllImport("libfftw3f-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void sfftw_plan_r2r_3d_(ref IntPtr plan, ref int nx, ref int ny, ref int nz, [In,Out] float* input, [In,Out] float* output, ref FFTW_PLANCREATION flags);
+        [DllImport("libfftw3f-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void sfftw_plan_r2r_(ref IntPtr plan, ref int rank, [In,Out] int[] n, [In,Out] float* input, [In,Out] float* output, ref FFTW_PLANCREATION flags);
+
+        /************************************ ADVANCED INTERFACE *************************************/
+        [DllImport("libfftw3f-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void sfftw_plan_many_dft_(ref IntPtr plan, ref int rank, [In,Out] int[] n, ref int howmany, [In,Out] fcomplex* input, [In,Out] int[] inembed, ref int istride, ref int idist, [In,Out] fcomplex* output, [In,Out] int[] onembed, ref int ostride, ref int odist, ref FFTW_DIRECTION sign, ref FFTW_PLANCREATION flags);		
+        [DllImport("libfftw3f-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void sfftw_plan_many_dft_r2c_(ref IntPtr plan, ref int rank, [In,Out] int [] n, ref int howmany, [In,Out] float* input, [In,Out] int[] inembed, ref int istride, ref int idist, [In,Out] fcomplex* output, [In,Out] int[] onembed, ref int ostride, ref int odist, ref FFTW_PLANCREATION flags);        
+        [DllImport("libfftw3f-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void sfftw_plan_many_dft_c2r_(ref IntPtr plan, ref int rank, [In,Out] int [] n, ref int howmany, [In,Out] fcomplex* input, [In,Out] int[] inembed, ref int istride, ref int idist, [In,Out] float* output, [In,Out] int[] onembed, ref int ostride, ref int odist, ref FFTW_PLANCREATION flags);        
+        [DllImport("libfftw3f-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void sfftw_plan_many_r2r_(    ref IntPtr plan, ref int rank, [In,Out] int [] n, ref int howmany, [In,Out] float [] input, [In,Out] int[] inembed, ref int istride, ref int idist, [In,Out] float* output, [In,Out] int[] onembed, ref int ostride, ref int odist, ref FFTW_KIND kind, ref FFTW_PLANCREATION flags);        
+        
+        /************************************ GURU INTERFACE *************************************/
+        [DllImport("libfftw3f-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void sfftw_plan_guru_dft_(ref IntPtr plan, ref int rank, [In,Out] int[] n, [In,Out] int[] iS,  [In,Out] int[] iO, ref int howmany_rank, [In,Out] int[] hn, [In,Out] int[] hiS,  [In,Out] int[] hiO, [In,Out] fcomplex* input, [In,Out] fcomplex* output, ref FFTW_DIRECTION sign, ref FFTW_PLANCREATION flags);
+        [DllImport("libfftw3f-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void sfftw_plan_guru_split_dft_(ref IntPtr plan, ref int rank, [In,Out] int[] n, [In,Out] int[] iS,  [In,Out] int[] iO, ref int howmany_rank, [In,Out] int[] hn, [In,Out] int[] hiS,  [In,Out] int[] hiO, [In,Out] float* ri, [In,Out] float* ii, [In,Out] float* ro, [In,Out] float* io, ref FFTW_PLANCREATION flags);
+        [DllImport("libfftw3f-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void sfftw_plan_guru_dft_r2c_(ref IntPtr plan, ref int rank, [In,Out] int[] n, [In,Out] int[] iS,  [In,Out] int[] iO, ref int howmany_rank, [In,Out] int[] hn, [In,Out] int[] hiS,  [In,Out] int[] hiO, [In,Out] float* input, [In,Out] fcomplex* output, ref FFTW_PLANCREATION flags);
+        [DllImport("libfftw3f-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void sfftw_plan_guru_dft_c2r_(ref IntPtr plan, ref int rank, [In,Out] int[] n, [In,Out] int[] iS,  [In,Out] int[] iO, ref int howmany_rank, [In,Out] int[] hn, [In,Out] int[] hiS,  [In,Out] int[] hiO, [In,Out] fcomplex* input, [In,Out] float* output, ref FFTW_PLANCREATION flags);
+        [DllImport("libfftw3f-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void sfftw_plan_guru_split_dft_r2c_(ref IntPtr plan, ref int rank, [In,Out] int[] n, [In,Out] int[] iS,  [In,Out] int[] iO, ref int howmany_rank, [In,Out] int[] hn, [In,Out] int[] hiS,  [In,Out] int[] hiO, [In,Out] float* ri, [In,Out] float* ro, [In,Out] float* io, ref FFTW_PLANCREATION flags);
+        [DllImport("libfftw3f-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void sfftw_plan_guru_split_dft_c2r_(ref IntPtr plan, ref int rank, [In,Out] int[] n, [In,Out] int[] iS,  [In,Out] int[] iO, ref int howmany_rank, [In,Out] int[] hn, [In,Out] int[] hiS,  [In,Out] int[] hiO, [In,Out] float* ri, [In,Out] float* ii, [In,Out] float* ro, ref FFTW_PLANCREATION flags);
+        [DllImport("libfftw3f-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void sfftw_plan_guru_r2r_(ref IntPtr plan, ref int rank, [In,Out] int[] n, [In,Out] int[] iS,  [In,Out] int[] iO, ref int howmany_rank, [In,Out] int[] hn, [In,Out] int[] hiS,  [In,Out] int[] hiO, [In,Out] float* input, [In,Out] float* output, ref FFTW_KIND kind, ref FFTW_PLANCREATION flags);
+        [DllImport("libfftw3f-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void sfftw_execute_dft_(ref IntPtr plan, [In,Out] fcomplex* input, [In,Out] fcomplex* output);
+        [DllImport("libfftw3f-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void sfftw_execute_split_dft_(ref IntPtr plan, [In,Out] float* ri, [In,Out] float* ii, [In,Out] float* ro, [In,Out] float* io);
+        [DllImport("libfftw3f-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void sfftw_execute_dft_r2c_(ref IntPtr plan, [In,Out] float* ri, [In,Out] fcomplex* ii);
+        [DllImport("libfftw3f-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void sfftw_execute_split_dft_r2c_(ref IntPtr plan, [In,Out] float* input, [In,Out] float* ro, [In,Out] float* ri);
+        [DllImport("libfftw3f-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void sfftw_execute_dft_c2r_(ref IntPtr plan, [In,Out] fcomplex* input, [In,Out] float* output);
+        [DllImport("libfftw3f-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void sfftw_execute_split_dft_c2r_(ref IntPtr plan, [In,Out] float* ri, [In,Out] float* ii, [In,Out] float* output);
+        [DllImport("libfftw3f-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void sfftw_execute_r2r_(ref IntPtr plan, [In,Out] float* input, [In,Out] float* output);
+
+        /************************************ BASIC PLAN EXECUTION & MISC ******************************/
+        [DllImport("libfftw3f-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void sfftw_execute_(ref IntPtr plan);
+        [DllImport("libfftw3f-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void sfftw_destroy_plan_(ref IntPtr plan);
+        [DllImport("libfftw3f-3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		private static extern void sfftw_cleanup_();
+        #endregion SINGLE PRECISION INTERFACE
+        #endregion
+
+        #region FFTW CONSTANTS 
+
+        [FlagsAttribute]
+        public enum FFTW_PLANCREATION : uint {
+            MEASURE = 0u, 
+            DESTROY_INPUT = (1U << 0), 
+            UNALIGNED = (1U << 1), 
+            CONSERVE_MEMORY = (1U << 2), 
+            EXHAUSTIVE = (1U << 3), /* NO_EXHAUSTIVE is default */
+            PRESERVE_INPUT = (1U << 4), /* cancels FFTW_DESTROY_INPUT */
+            PATIENT = (1U << 5), /* IMPATIENT is default */
+            ESTIMATE = (1U << 6)
+        }
+        
+        public enum FFTW_DIRECTION {
+            FORWARD = -1, 
+            BACKWARDS = 1
+        }
+
+        public enum FFTW_KIND {
+            R2HC=0,
+            HC2R=1,
+            DHT=2,
+            REDFT00=3,
+            REDFT01=4,
+            REDFT10=5,
+            REDFT11=6,
+            RODFT00=7,
+            RODFT01=8,
+            RODFT10=9,
+            RODFT11=10
+        }
+        #endregion
+
+        #region attributes
+        object _lockobject = new object(); 
+        int[] m_n,m_is,m_os, m_hn, m_his, m_hos; 
+        //List<int> m_tmpDims = new List<int>(10); 
+        #endregion
+
+        #region constructor 
+        public ILFFTW3FFT () {
+            // fftw internally caches the plans, so ....
+            m_n = new int[10]; 
+            m_is = new int[10]; 
+            m_os = new int[10]; 
+            m_hn = new int[2]; 
+            m_his = new int[2]; 
+            m_hos = new int[2]; 
+        }
+        #endregion
+
+        #region IILFFT Member - 1-D
+
+
+
+        public ILRetArray< complex >  FFTForward1D (ILInArray< double > A, int dim) {
+            return  FFTForward (A,dim,1); 
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+
+        public ILRetArray< fcomplex >  FFTBackward1D (ILInArray< fcomplex > A, int dim) {
+            return  FFTBackward (A,dim,1); 
+        }
+
+        public ILRetArray< complex >  FFTBackward1D (ILInArray< complex > A, int dim) {
+            return  FFTBackward (A,dim,1); 
+        }
+
+        public ILRetArray< fcomplex >  FFTForward1D (ILInArray< fcomplex > A, int dim) {
+            return  FFTForward (A,dim,1); 
+        }
+
+        public ILRetArray< fcomplex >  FFTForward1D (ILInArray< float > A, int dim) {
+            return  FFTForward (A,dim,1); 
+        }
+
+        public ILRetArray< complex >  FFTForward1D (ILInArray< complex > A, int dim) {
+            return  FFTForward (A,dim,1); 
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+
+
+        public ILRetArray< double > FFTBackwSym1D(ILInArray< complex > A, int dim) {
+            return ILMath.real(FFTBackward1D(A,dim)); 
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+
+        public ILRetArray< float > FFTBackwSym1D(ILInArray< fcomplex > A, int dim) {
+            return ILMath.real(FFTBackward1D(A,dim)); 
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+        #endregion
+
+        #region IILFFT Member - n-D
+
+
+
+        public ILRetArray< complex >  FFTForward (ILInArray< double > A, int nDims) {
+            return  FFTForward (A,0,nDims); 
+        }
+
+        public ILRetArray< complex>  FFTForward(ILInArray< double> A, int firstDim, int nDims) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A, null) || nDims < 0 || firstDim < 0)
+                    throw new ILArgumentException("invalid parameter!");
+                if (A.IsEmpty) return ILArray<  complex>.empty(A.Size);
+                if (A.IsScalar || (A.Size[firstDim] == 1 && nDims == 1))
+                    return  ILMath.tocomplex(A);
+                if (nDims > A.Size.NumberOfDimensions)
+                    nDims = A.Size.NumberOfDimensions;
+                // prepare output array 
+                ILArray< complex> ret =  ILMath.tocomplex(A);
+                IntPtr plan = IntPtr.Zero;
+                int hrank = 2;
+                FFTW_DIRECTION dir =  FFTW_DIRECTION.FORWARD;
+                lock (_lockobject) {
+                    FFTW_PLANCREATION flags = FFTW_PLANCREATION.ESTIMATE;
+                    if (nDims > m_n.Length) resizeCache(nDims);
+                    for (int i = 0; i < nDims; i++) {
+                        m_n[i] = A.Size[i + firstDim];
+                        m_is[i] = A.Size.SequentialIndexDistance(i + firstDim);
+                        m_os[i] = m_is[i];
+                    }
+                    m_hn[0] = A.Size.SequentialIndexDistance(firstDim);
+                    m_his[0] = 1;
+                    m_hos[0] = 1;
+                    m_his[1] = A.Size.SequentialIndexDistance(nDims + firstDim);
+                    m_hn[1] = A.Size.NumberOfElements / m_his[1];
+                    m_hos[1] = m_his[1];
+                    fixed ( complex* retArr = ret.GetArrayForWrite()) {
+                        
+                        dfftw_plan_guru_dft_(ref plan, ref nDims, m_n, m_is, m_os,
+                                      ref hrank, m_hn, m_his, m_hos,
+                                      retArr, retArr,
+                                      ref dir, ref flags);
+                    }
+                }
+                if (plan == IntPtr.Zero)
+                    throw new ILInvalidOperationException("error creating plan for fftw3 (guru interface)");
+                dfftw_execute_(ref plan);
+                dfftw_destroy_plan_(ref plan);
+                
+
+                return ret;
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+
+        public ILRetArray< fcomplex >  FFTBackward (ILInArray< fcomplex > A, int nDims) {
+            return  FFTBackward (A,0,nDims); 
+        }
+
+        public ILRetArray< fcomplex>  FFTBackward(ILInArray< fcomplex> A, int firstDim, int nDims) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A, null) || nDims < 0 || firstDim < 0)
+                    throw new ILArgumentException("invalid parameter!");
+                if (A.IsEmpty) return ILArray<  fcomplex>.empty(A.Size);
+                if (A.IsScalar || (A.Size[firstDim] == 1 && nDims == 1))
+                    return  A.C;
+                if (nDims > A.Size.NumberOfDimensions)
+                    nDims = A.Size.NumberOfDimensions;
+                // prepare output array 
+                ILArray< fcomplex> ret =  A.C;
+                IntPtr plan = IntPtr.Zero;
+                int hrank = 2;
+                FFTW_DIRECTION dir =  FFTW_DIRECTION.BACKWARDS;
+                lock (_lockobject) {
+                    FFTW_PLANCREATION flags = FFTW_PLANCREATION.ESTIMATE;
+                    if (nDims > m_n.Length) resizeCache(nDims);
+                    for (int i = 0; i < nDims; i++) {
+                        m_n[i] = A.Size[i + firstDim];
+                        m_is[i] = A.Size.SequentialIndexDistance(i + firstDim);
+                        m_os[i] = m_is[i];
+                    }
+                    m_hn[0] = A.Size.SequentialIndexDistance(firstDim);
+                    m_his[0] = 1;
+                    m_hos[0] = 1;
+                    m_his[1] = A.Size.SequentialIndexDistance(nDims + firstDim);
+                    m_hn[1] = A.Size.NumberOfElements / m_his[1];
+                    m_hos[1] = m_his[1];
+                    fixed ( fcomplex* retArr = ret.GetArrayForWrite()) {
+                       
+                        sfftw_plan_guru_dft_(ref plan, ref nDims, m_n, m_is, m_os,
+                                      ref hrank, m_hn, m_his, m_hos,
+                                      retArr, retArr,
+                                      ref dir, ref flags);
+                    }
+                }
+                if (plan == IntPtr.Zero)
+                    throw new ILInvalidOperationException("error creating plan for fftw3 (guru interface)");
+                dfftw_execute_(ref plan);
+                dfftw_destroy_plan_(ref plan);
+                ret /= new fcomplex(m_his[1]/m_hn[0],0.0f);
+                return ret;
+            }
+        }
+
+        public ILRetArray< complex >  FFTBackward (ILInArray< complex > A, int nDims) {
+            return  FFTBackward (A,0,nDims); 
+        }
+
+        public ILRetArray< complex>  FFTBackward(ILInArray< complex> A, int firstDim, int nDims) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A, null) || nDims < 0 || firstDim < 0)
+                    throw new ILArgumentException("invalid parameter!");
+                if (A.IsEmpty) return ILArray<  complex>.empty(A.Size);
+                if (A.IsScalar || (A.Size[firstDim] == 1 && nDims == 1))
+                    return  A.C;
+                if (nDims > A.Size.NumberOfDimensions)
+                    nDims = A.Size.NumberOfDimensions;
+                // prepare output array 
+                ILArray< complex> ret =  A.C;
+                IntPtr plan = IntPtr.Zero;
+                int hrank = 2;
+                FFTW_DIRECTION dir =  FFTW_DIRECTION.BACKWARDS;
+                lock (_lockobject) {
+                    FFTW_PLANCREATION flags = FFTW_PLANCREATION.ESTIMATE;
+                    if (nDims > m_n.Length) resizeCache(nDims);
+                    for (int i = 0; i < nDims; i++) {
+                        m_n[i] = A.Size[i + firstDim];
+                        m_is[i] = A.Size.SequentialIndexDistance(i + firstDim);
+                        m_os[i] = m_is[i];
+                    }
+                    m_hn[0] = A.Size.SequentialIndexDistance(firstDim);
+                    m_his[0] = 1;
+                    m_hos[0] = 1;
+                    m_his[1] = A.Size.SequentialIndexDistance(nDims + firstDim);
+                    m_hn[1] = A.Size.NumberOfElements / m_his[1];
+                    m_hos[1] = m_his[1];
+                    fixed ( complex* retArr = ret.GetArrayForWrite()) {
+                       
+                        dfftw_plan_guru_dft_(ref plan, ref nDims, m_n, m_is, m_os,
+                                      ref hrank, m_hn, m_his, m_hos,
+                                      retArr, retArr,
+                                      ref dir, ref flags);
+                    }
+                }
+                if (plan == IntPtr.Zero)
+                    throw new ILInvalidOperationException("error creating plan for fftw3 (guru interface)");
+                dfftw_execute_(ref plan);
+                dfftw_destroy_plan_(ref plan);
+                ret /= new complex(m_his[1]/m_hn[0],0.0f);
+                return ret;
+            }
+        }
+
+        public ILRetArray< fcomplex >  FFTForward (ILInArray< fcomplex > A, int nDims) {
+            return  FFTForward (A,0,nDims); 
+        }
+
+        public ILRetArray< fcomplex>  FFTForward(ILInArray< fcomplex> A, int firstDim, int nDims) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A, null) || nDims < 0 || firstDim < 0)
+                    throw new ILArgumentException("invalid parameter!");
+                if (A.IsEmpty) return ILArray<  fcomplex>.empty(A.Size);
+                if (A.IsScalar || (A.Size[firstDim] == 1 && nDims == 1))
+                    return  A.C;
+                if (nDims > A.Size.NumberOfDimensions)
+                    nDims = A.Size.NumberOfDimensions;
+                // prepare output array 
+                ILArray< fcomplex> ret =  A.C;
+                IntPtr plan = IntPtr.Zero;
+                int hrank = 2;
+                FFTW_DIRECTION dir =  FFTW_DIRECTION.FORWARD;
+                lock (_lockobject) {
+                    FFTW_PLANCREATION flags = FFTW_PLANCREATION.ESTIMATE;
+                    if (nDims > m_n.Length) resizeCache(nDims);
+                    for (int i = 0; i < nDims; i++) {
+                        m_n[i] = A.Size[i + firstDim];
+                        m_is[i] = A.Size.SequentialIndexDistance(i + firstDim);
+                        m_os[i] = m_is[i];
+                    }
+                    m_hn[0] = A.Size.SequentialIndexDistance(firstDim);
+                    m_his[0] = 1;
+                    m_hos[0] = 1;
+                    m_his[1] = A.Size.SequentialIndexDistance(nDims + firstDim);
+                    m_hn[1] = A.Size.NumberOfElements / m_his[1];
+                    m_hos[1] = m_his[1];
+                    fixed ( fcomplex* retArr = ret.GetArrayForWrite()) {
+                       
+                        sfftw_plan_guru_dft_(ref plan, ref nDims, m_n, m_is, m_os,
+                                      ref hrank, m_hn, m_his, m_hos,
+                                      retArr, retArr,
+                                      ref dir, ref flags);
+                    }
+                }
+                if (plan == IntPtr.Zero)
+                    throw new ILInvalidOperationException("error creating plan for fftw3 (guru interface)");
+                dfftw_execute_(ref plan);
+                dfftw_destroy_plan_(ref plan);
+                
+                return ret;
+            }
+        }
+
+        public ILRetArray< fcomplex >  FFTForward (ILInArray< float > A, int nDims) {
+            return  FFTForward (A,0,nDims); 
+        }
+
+        public ILRetArray< fcomplex>  FFTForward(ILInArray< float> A, int firstDim, int nDims) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A, null) || nDims < 0 || firstDim < 0)
+                    throw new ILArgumentException("invalid parameter!");
+                if (A.IsEmpty) return ILArray<  fcomplex>.empty(A.Size);
+                if (A.IsScalar || (A.Size[firstDim] == 1 && nDims == 1))
+                    return  ILMath.tofcomplex(A);
+                if (nDims > A.Size.NumberOfDimensions)
+                    nDims = A.Size.NumberOfDimensions;
+                // prepare output array 
+                ILArray< fcomplex> ret =  ILMath.tofcomplex(A);
+                IntPtr plan = IntPtr.Zero;
+                int hrank = 2;
+                FFTW_DIRECTION dir =  FFTW_DIRECTION.FORWARD;
+                lock (_lockobject) {
+                    FFTW_PLANCREATION flags = FFTW_PLANCREATION.ESTIMATE;
+                    if (nDims > m_n.Length) resizeCache(nDims);
+                    for (int i = 0; i < nDims; i++) {
+                        m_n[i] = A.Size[i + firstDim];
+                        m_is[i] = A.Size.SequentialIndexDistance(i + firstDim);
+                        m_os[i] = m_is[i];
+                    }
+                    m_hn[0] = A.Size.SequentialIndexDistance(firstDim);
+                    m_his[0] = 1;
+                    m_hos[0] = 1;
+                    m_his[1] = A.Size.SequentialIndexDistance(nDims + firstDim);
+                    m_hn[1] = A.Size.NumberOfElements / m_his[1];
+                    m_hos[1] = m_his[1];
+                    fixed ( fcomplex* retArr = ret.GetArrayForWrite()) {
+                       
+                        sfftw_plan_guru_dft_(ref plan, ref nDims, m_n, m_is, m_os,
+                                      ref hrank, m_hn, m_his, m_hos,
+                                      retArr, retArr,
+                                      ref dir, ref flags);
+                    }
+                }
+                if (plan == IntPtr.Zero)
+                    throw new ILInvalidOperationException("error creating plan for fftw3 (guru interface)");
+                dfftw_execute_(ref plan);
+                dfftw_destroy_plan_(ref plan);
+                
+                return ret;
+            }
+        }
+
+        public ILRetArray< complex >  FFTForward (ILInArray< complex > A, int nDims) {
+            return  FFTForward (A,0,nDims); 
+        }
+
+        public ILRetArray< complex>  FFTForward(ILInArray< complex> A, int firstDim, int nDims) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A, null) || nDims < 0 || firstDim < 0)
+                    throw new ILArgumentException("invalid parameter!");
+                if (A.IsEmpty) return ILArray<  complex>.empty(A.Size);
+                if (A.IsScalar || (A.Size[firstDim] == 1 && nDims == 1))
+                    return  A.C;
+                if (nDims > A.Size.NumberOfDimensions)
+                    nDims = A.Size.NumberOfDimensions;
+                // prepare output array 
+                ILArray< complex> ret =  A.C;
+                IntPtr plan = IntPtr.Zero;
+                int hrank = 2;
+                FFTW_DIRECTION dir =  FFTW_DIRECTION.FORWARD;
+                lock (_lockobject) {
+                    FFTW_PLANCREATION flags = FFTW_PLANCREATION.ESTIMATE;
+                    if (nDims > m_n.Length) resizeCache(nDims);
+                    for (int i = 0; i < nDims; i++) {
+                        m_n[i] = A.Size[i + firstDim];
+                        m_is[i] = A.Size.SequentialIndexDistance(i + firstDim);
+                        m_os[i] = m_is[i];
+                    }
+                    m_hn[0] = A.Size.SequentialIndexDistance(firstDim);
+                    m_his[0] = 1;
+                    m_hos[0] = 1;
+                    m_his[1] = A.Size.SequentialIndexDistance(nDims + firstDim);
+                    m_hn[1] = A.Size.NumberOfElements / m_his[1];
+                    m_hos[1] = m_his[1];
+                    fixed ( complex* retArr = ret.GetArrayForWrite()) {
+                       
+                        dfftw_plan_guru_dft_(ref plan, ref nDims, m_n, m_is, m_os,
+                                      ref hrank, m_hn, m_his, m_hos,
+                                      retArr, retArr,
+                                      ref dir, ref flags);
+                    }
+                }
+                if (plan == IntPtr.Zero)
+                    throw new ILInvalidOperationException("error creating plan for fftw3 (guru interface)");
+                dfftw_execute_(ref plan);
+                dfftw_destroy_plan_(ref plan);
+                
+                return ret;
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+       
+
+        
+        public ILRetArray< double > FFTBackwSym(ILInArray< complex > A, int nDims) {
+            return ILMath.real(FFTBackward(A,nDims));  
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+       
+        public ILRetArray< float > FFTBackwSym(ILInArray< fcomplex > A, int nDims) {
+            return ILMath.real(FFTBackward(A,nDims));  
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+        #endregion
+        
+        #region IILFFT Member - Misc
+        
+        public bool CachePlans {
+            get {
+                return true; 
+            }
+        }
+
+        public void FreePlans() {
+            FreeAllDescriptors(); 
+        }
+
+        public bool SpeedyHermitian {
+            get { return false; }
+        }
+
+        #endregion
+
+        #region private helper
+        private void FreeAllDescriptors() {
+            try {
+                dfftw_cleanup_();
+                sfftw_cleanup_();
+            } catch (Exception) { }
+        }
+        private void resizeCache(int size) {
+            if (m_n.Length >= size) return;
+            m_n = new int[size];
+            m_is = new int[size];
+            m_os = new int[size];
+        }
+        #endregion
+
+        #region IDisposable Member
+
+        public void Dispose() {
+            Dispose(true); 
+            GC.SuppressFinalize(this); 
+        }
+
+        public virtual void Dispose (bool manual) {
+            if (manual) {
+                FreeAllDescriptors();             
+            }
+        }
+
+        ~ILFFTW3FFT () {
+            Dispose(true);     
+        }
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Native/FFT/ILMKLFFT.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Native/FFT/ILMKLFFT.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Native/FFT/ILMKLFFT.cs	(revision 9102)
@@ -0,0 +1,1107 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+#pragma warning disable 1591
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Security; 
+using System.Runtime.InteropServices;
+using ILNumerics.Exceptions;  
+using ILNumerics.Misc; 
+
+namespace ILNumerics.Native {
+    
+    /// <summary>
+    /// MKL configuration parameters (constant definitions)
+    /// </summary>
+    internal sealed class MKLParameter {
+        /* Domain for forward transform. No default value */
+        public static readonly int FORWARD_DOMAIN = 0;
+
+        /* Dimensionality; or rank. No default value */
+        public static readonly int DIMENSION = 1;
+
+        /* Length(s) of transform. No default value */
+        public static readonly int LENGTHS = 2;
+
+        /* Floating point precision. No default value */
+        public static readonly int PRECISION = 3;
+
+        /* Scale factor for forward transform [1.0] */
+        public static readonly int FORWARD_SCALE  = 4;
+
+        /* Scale factor for backward transform [1.0] */
+        public static readonly int BACKWARD_SCALE = 5;
+
+        /* Exponent sign for forward transform [NEGATIVE]  */
+        /* FORWARD_SIGN = 6; ## NOT IMPLEMENTED */
+
+        /* Number of data sets to be transformed [1] */
+        public static readonly int NUMBER_OF_TRANSFORMS = 7;
+
+        /* Storage of finite complex-valued sequences in complex domain
+           [COMPLEX_COMPLEX] */
+        public static readonly int COMPLEX_STORAGE = 8;
+
+        /* Storage of finite real-valued sequences in real domain
+           [REAL_REAL] */
+        public static readonly int REAL_STORAGE = 9;
+
+        /* Storage of finite complex-valued sequences in conjugate-even
+           domain [COMPLEX_REAL] */
+        public static readonly int CONJUGATE_EVEN_STORAGE = 10;
+
+        /* Placement of result [INPLACE] */
+        public static readonly int PLACEMENT = 11;
+
+        /* Generalized strides for input data layout [tight; row-major for C] */
+        public static readonly int INPUT_STRIDES = 12;
+
+        /* Generalized strides for output data layout [tight; row-major
+           for C] */
+        public static readonly int OUTPUT_STRIDES = 13;
+
+        /* Distance between first input elements for multiple transforms
+           [0] */
+        public static readonly int INPUT_DISTANCE = 14;
+
+        /* Distance between first output elements for multiple transforms
+           [0] */
+        public static readonly int OUTPUT_DISTANCE = 15;
+
+        /* Ordering of the result [ORDERED] */
+        public static readonly int ORDERING = 18;
+
+        /* Possible transposition of result [NONE] */
+        public static readonly int TRANSPOSE = 19;
+
+        /* User-settable descriptor name [""] */
+        public static readonly int DESCRIPTOR_NAME = 20; /* DEPRECATED */
+
+        /* Packing format for COMPLEX_REAL storage of finite
+           conjugate-even sequences [CCS_FORMAT] */
+        public static readonly int PACKED_FORMAT = 21;
+
+        /* Commit status of the descriptor - R/O parameter */
+        public static readonly int COMMIT_STATUS = 22;
+
+        /* Version string for this DFTI implementation - R/O parameter */
+        public static readonly int VERSION = 23;
+
+        /* Number of user threads that share the descriptor [1] */
+        public static readonly int NUMBER_OF_USER_THREADS = 26;
+    }
+    /// <summary>
+    /// MKL configuration values (constant definitions) 
+    /// </summary>
+    internal sealed class MKLValues {
+        public static readonly int MKL_ALL = 0;
+        public static readonly int MKL_BLAS = 1;
+        public static readonly int MKL_FFT = 2;
+        public static readonly int MKL_VML = 3;
+        /* Values of the descriptor configuration parameters */
+        /* COMMIT_STATUS */
+        public static readonly int COMMITTED = 30;
+        public static readonly int UNCOMMITTED = 31;
+
+        /* FORWARD_DOMAIN */
+        public static readonly int COMPLEX = 32;
+        public static readonly int REAL = 33;
+            /* CONJUGATE_EVEN = 34;   ## NOT IMPLEMENTED */
+
+        /* PRECISION */
+        public static readonly int SINGLE = 35;
+        public static readonly int DOUBLE = 36;
+
+        /* COMPLEX_STORAGE and CONJUGATE_EVEN_STORAGE */
+        public static readonly int COMPLEX_COMPLEX = 39;
+        public static readonly int COMPLEX_REAL = 40;
+
+        /* REAL_STORAGE */
+        public static readonly int REAL_COMPLEX = 41;
+        public static readonly int REAL_REAL = 42;
+
+        /* PLACEMENT */
+        public static readonly int INPLACE = 43;          /* Result overwrites input */
+        public static readonly int NOT_INPLACE = 44;      /* Have another place for result */
+
+        /* ORDERING */
+        public static readonly int ORDERED = 48;
+        public static readonly int BACKWARD_SCRAMBLED = 49;
+
+        /* Allow/avoid certain usages */
+        public static readonly int ALLOW = 51;            /* Allow transposition or workspace */
+        public static readonly int NONE = 53;
+
+        /* PACKED_FORMAT (for storing congugate-even finite sequence
+           in real array) */
+        public static readonly int CCS_FORMAT = 54;       /* Complex conjugate-symmetric */
+        public static readonly int PACK_FORMAT = 55;      /* Pack format for real DFT */
+        public static readonly int PERM_FORMAT = 56;      /* Perm format for real DFT */
+        public static readonly int CCE_FORMAT = 57;       /* Complex conjugate-even */
+        
+        /* Error classes */
+        public static readonly int  NO_ERROR = 0; 
+        public static readonly int  MEMORY_ERROR = 1;
+        public static readonly int  INVALID_CONFIGURATION = 2;
+        public static readonly int  INCONSISTENT_CONFIGURATION = 3;
+        public static readonly int  MULTITHREADED_ERROR = 4;
+        public static readonly int  BAD_DESCRIPTOR = 5;
+        public static readonly int  UNIMPLEMENTED = 6;
+        public static readonly int  MKL_INTERNAL_ERROR = 7;
+        public static readonly int  NUMBER_OF_THREADS_ERROR = 8;
+        public static readonly int  ONED_LENGTH_EXCEEDS_INT32 = 9;
+
+        public static readonly int  MAX_MESSAGE_LENGTH = 40; /* Maximum length of error string */
+        public static readonly int  MAX_NAME_LENGTH = 10;    /* Maximum length of descriptor name */
+        public static readonly int  VERSION_LENGTH = 198;    /* Maximum length of MKL version string */
+    }
+    /// <summary>
+    /// import functions (pinvoke)
+    /// </summary>
+    internal sealed class MKLImports {
+
+        #region pinvoke definitions 
+
+#if x64 
+#region 64 bit includes
+        [DllImport("mkl_custom64", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
+        internal static extern int mkl_domain_set_num_threads(ref int num, ref int mask);
+        [DllImport("mkl_custom64", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
+        internal static extern int mkl_domain_get_max_threads(ref int mask);
+        [DllImport("mkl_custom64", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
+        internal static extern void mkl_set_num_threads(int num);
+        [DllImport("mkl_custom64", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
+        internal static extern int mkl_get_max_threads();
+        [DllImport("mkl_custom64", CallingConvention = CallingConvention.Cdecl)]
+        internal static extern void omp_set_num_threads(int num);
+        [DllImport("mkl_custom64", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
+        internal static extern int omp_get_num_threads();
+        
+        [DllImport("mkl_custom64", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
+        internal static extern void mkl_set_dynamic(ref int boolean_value);
+
+        [DllImport("mkl_custom64",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        public static extern int DftiCreateDescriptor(ref IntPtr pDescriptor, int precision, int domain, int dimCount, int dim1);
+        [DllImport("mkl_custom64",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        public static extern int DftiCreateDescriptor(ref IntPtr pDescriptor, int precision, int domain, int dimCount, int[] dims);
+        [DllImport("mkl_custom64",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		public static extern int DftiFreeDescriptor(ref IntPtr pDescriptor);
+        [DllImport("mkl_custom64",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		public static extern int DftiCommitDescriptor(IntPtr pDescriptor);
+        [DllImport("mkl_custom64",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		public static extern int DftiErrorClass(int status, int ERROR_CLASS);
+        [DllImport("mkl_custom64",CallingConvention =CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
+		public static extern int DftiSetValue(IntPtr pDescriptor, int parameter, int value);
+        [DllImport("mkl_custom64",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		public static extern int DftiSetValue(IntPtr pDescriptor, int parameter, double value);
+        [DllImport("mkl_custom64",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		public static extern int DftiSetValue(IntPtr pDescriptor, int parameter, int[] values);
+        [DllImport("mkl_custom64",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		public static extern int DftiGetValue(IntPtr pDescriptor, int parameter, ref int value);
+        [DllImport("mkl_custom64",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		public static extern int DftiGetValue(IntPtr pDescriptor, int parameter, ref double value);
+        [DllImport("mkl_custom64",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		public static extern int DftiComputeForward(IntPtr pDescriptor, IntPtr pArray);
+        [DllImport("mkl_custom64",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        public static extern int DftiComputeForward(IntPtr pDescriptor, IntPtr pInArray, IntPtr pOutArray);
+
+        /** DFTI native DftiComputeForward declaration */
+        [DllImport("mkl_custom64", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true, SetLastError = false)]
+        internal static extern int DftiComputeForward(IntPtr desc, [In] double[] x_in, [Out] double[] x_out);
+
+        [DllImport("mkl_custom64",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		public static extern int DftiComputeBackward(IntPtr pDescriptor, IntPtr pArray);
+        [DllImport("mkl_custom64",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		public static extern int DftiComputeBackward(IntPtr pDescriptor, IntPtr pInArray, IntPtr pOutArray);
+
+        /** DFTI native DftiComputeBackward declaration */
+        [DllImport("mkl_custom64", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true, SetLastError = false)]
+        internal static extern int DftiComputeBackward(IntPtr desc, [In] double[] x_in, [Out] double[] x_out);
+
+        [DllImport("mkl_custom64",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		public static extern string DftiErrorMessage(int errID);
+#endregion
+#else 
+#region 32 bit includes
+        [DllImport("mkl_custom32", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
+        internal static extern int mkl_domain_set_num_threads(ref int num, ref int mask);
+        [DllImport("mkl_custom32", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
+        internal static extern int mkl_domain_get_max_threads(ref int mask);
+
+        [DllImport("mkl_custom32", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
+        internal static extern void mkl_set_num_threads(int num);
+        [DllImport("mkl_custom32", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
+        internal static extern int mkl_get_max_threads();
+        [DllImport("mkl_custom32", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
+        internal static extern void omp_set_num_threads(int num);
+        [DllImport("mkl_custom32", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
+        internal static extern void mkl_set_dynamic(ref int boolean_value);
+        [DllImport("mkl_custom32",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        public static extern int DftiCreateDescriptor(ref IntPtr pDescriptor, int precision, int domain, int dimCount, int dim1);
+        [DllImport("mkl_custom32",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        public static extern int DftiCreateDescriptor(ref IntPtr pDescriptor, int precision, int domain, int dimCount, int[] dims);
+        [DllImport("mkl_custom32",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		public static extern int DftiFreeDescriptor(ref IntPtr pDescriptor);
+        [DllImport("mkl_custom32",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		public static extern int DftiCommitDescriptor(IntPtr pDescriptor);
+        [DllImport("mkl_custom32",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		public static extern int DftiErrorClass(int status, int ERROR_CLASS);
+
+        [DllImport("mkl_custom32",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		public static extern int DftiSetValue(IntPtr pDescriptor, int parameter, int value);
+        [DllImport("mkl_custom32",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		public static extern int DftiSetValue(IntPtr pDescriptor, int parameter, double value);
+        [DllImport("mkl_custom32",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		public static extern int DftiSetValue(IntPtr pDescriptor, int parameter, int[] values);
+        
+        [DllImport("mkl_custom32",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		public static extern int DftiGetValue(IntPtr pDescriptor, int parameter, ref int value);
+        [DllImport("mkl_custom32",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+		public static extern int DftiGetValue(IntPtr pDescriptor, int parameter, ref double value);
+
+        [DllImport("mkl_custom32", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]		
+        public static extern int DftiComputeForward(IntPtr pDescriptor, IntPtr pArray);
+        [DllImport("mkl_custom32", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
+        public static extern int DftiComputeForward(IntPtr pDescriptor, IntPtr pInArray, IntPtr pOutArray);
+        [DllImport("mkl_custom32", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
+		public static extern int DftiComputeBackward(IntPtr pDescriptor, IntPtr pArray);
+        [DllImport("mkl_custom32", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
+		public static extern int DftiComputeBackward(IntPtr pDescriptor, IntPtr pInArray, IntPtr pOutArray);
+        [DllImport("mkl_custom32", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
+		public static extern string DftiErrorMessage(int errID);
+#endregion
+#endif
+        #endregion
+    }
+    
+    internal sealed class MKLDescriptor : IDisposable {
+        private int[] Stride;  
+        private int Precision; 
+        private int RealComplex; 
+        private bool InPlace; 
+        private ILSize Dimension; 
+        private int AlongDimensionIndex; 
+        private IntPtr Descriptor = IntPtr.Zero; 
+        private int Dimensionality; 
+        private int LocalLoopIncrement; 
+        private int LocalLoopLength; 
+
+        public IntPtr GetDescriptor(int precision, int realComplex, int dimensionality, 
+                                    int dim, ILSize dimension, bool inplace,
+                                    out int localLoopLength, out int localLoopIncrement) {
+            // DEBUG: remove "false" for descriptor caching!
+            if (Descriptor != IntPtr.Zero 
+                && precision == Precision 
+                && realComplex == RealComplex 
+                && dimensionality == Dimensionality
+                && dimension.IsSameShape(Dimension)
+                && dim == AlongDimensionIndex
+                && inplace == InPlace) {
+                // reuse old descriptor 
+                localLoopIncrement = LocalLoopIncrement;
+                localLoopLength = LocalLoopLength;
+                return Descriptor; 
+            } else {
+
+                // must create a new one 
+                if (Descriptor != IntPtr.Zero) {
+                    MKLImports.DftiFreeDescriptor(ref Descriptor);
+                }
+                IntPtr tmpDescriptor = IntPtr.Zero; 
+                int error; 
+                if (dimensionality == 1) {
+#region one dimensional transforms
+                    error = MKLImports.DftiCreateDescriptor(ref tmpDescriptor, precision ,realComplex, dimensionality, dimension[dim]);
+                    if (error != 0) {
+                        throw new ILInvalidOperationException ("error creating descriptor: " + MKLImports.DftiErrorMessage(error)); 
+                    }
+
+                    // storage,number of subsequent transformations
+                    int nrTransGlobal = dimension.NumberOfElements / dimension[dim];
+                    int nrTransPerPass; 
+                    if (dim == 0) {
+                        // MKL does all transf. at once 
+                        MKLImports.DftiSetValue(tmpDescriptor,MKLParameter.NUMBER_OF_TRANSFORMS, nrTransGlobal); 
+                        int distances = dimension[0]; 
+                        MKLImports.DftiSetValue(tmpDescriptor,MKLParameter.INPUT_DISTANCE, distances); 
+                        MKLImports.DftiSetValue(tmpDescriptor,MKLParameter.OUTPUT_DISTANCE, distances); 
+                        localLoopIncrement = 1; 
+                        localLoopLength = 1;
+                        nrTransPerPass = 1; 
+                    } else {
+                        nrTransPerPass = dimension.SequentialIndexDistance(dim); 
+                        MKLImports.DftiSetValue(tmpDescriptor,MKLParameter.NUMBER_OF_TRANSFORMS, nrTransPerPass); 
+                        int distances = 1; 
+                        MKLImports.DftiSetValue(tmpDescriptor,MKLParameter.INPUT_DISTANCE, distances); 
+                        MKLImports.DftiSetValue(tmpDescriptor,MKLParameter.OUTPUT_DISTANCE, distances); 
+                        localLoopIncrement = dimension.SequentialIndexDistance(dim) * dimension[dim]; 
+                        localLoopLength = nrTransGlobal / nrTransPerPass; 
+                    }
+
+                    // spacing between elements
+                    if (Stride == null || Stride.Length < 2) {
+                        Stride = new int[10];
+                    }
+                    Stride[1] = nrTransPerPass; 
+                    MKLImports.DftiSetValue(tmpDescriptor, MKLParameter.INPUT_STRIDES, Stride);
+                    error = MKLImports.DftiSetValue(tmpDescriptor, MKLParameter.OUTPUT_STRIDES, Stride);
+                    if (error != 0) {
+                        throw new ILInvalidOperationException("error: " + MKLImports.DftiErrorMessage(error));
+                    }
+#endregion
+                } else {
+#region multidimensional transforms 
+                    int[] tmpDims = dimension.ToIntArray(10); 
+                    error = MKLImports.DftiCreateDescriptor(ref tmpDescriptor, precision ,realComplex, dimensionality, tmpDims);            
+                    // MKL will handle to do all transforms at once 
+                    localLoopIncrement = 1; 
+                    localLoopLength = 1; 
+                    // how many transformations ? 
+                    int nrElementsPerPass = dimension.SequentialIndexDistance(dimensionality); 
+                    MKLImports.DftiSetValue(tmpDescriptor,MKLParameter.NUMBER_OF_TRANSFORMS, dimension.NumberOfElements / nrElementsPerPass); 
+                    MKLImports.DftiSetValue(tmpDescriptor,MKLParameter.INPUT_DISTANCE, nrElementsPerPass); 
+                    MKLImports.DftiSetValue(tmpDescriptor,MKLParameter.OUTPUT_DISTANCE, nrElementsPerPass);
+
+                    // spacing between elements
+                    if (Stride == null || Stride.Length < dimensionality + 1) {
+                        Stride = new int[dimensionality + 1];
+                    }
+                    int[] seqDistances = dimension.GetSequentialIndexDistances(dimensionality);
+                    for (int i = dimensionality; i-- > 0; ) {
+                        Stride[i + 1] = seqDistances[i];
+                    }
+                    //Stride[0] = 0; // should never gotten changed
+                    MKLImports.DftiSetValue(tmpDescriptor, MKLParameter.INPUT_STRIDES, Stride);
+                    error = MKLImports.DftiSetValue(tmpDescriptor, MKLParameter.OUTPUT_STRIDES, Stride);
+                    if (error != 0) {
+                        throw new ILInvalidOperationException("error: " + MKLImports.DftiErrorMessage(error));
+                    }
+#endregion
+                }
+                //// backward scale 
+                //if (!forwardTransform) {
+                //    MKLImports.DftiSetValue(tmpDescriptor,MKLParameter.BACKWARD_SCALE, __arglist(1.0/Dimension[dim]));
+                //}
+                if (!inplace) {
+                    error = MKLImports.DftiSetValue(tmpDescriptor, MKLParameter.PLACEMENT, MKLValues.NOT_INPLACE);
+                    //error = MKLImports.DftiSetValue(tmpDescriptor, MKLParameter.REAL_STORAGE, __arglist(MKLValues.REAL_REAL));
+                    error = MKLImports.DftiSetValue(tmpDescriptor, MKLParameter.CONJUGATE_EVEN_STORAGE, MKLValues.COMPLEX_COMPLEX);
+                }
+                
+                error = MKLImports.DftiCommitDescriptor(tmpDescriptor);
+                if (error != 0) {
+                    throw new ILInvalidOperationException ("error: " + MKLImports.DftiErrorMessage(error)); 
+                }
+                
+                Precision = precision; 
+                RealComplex = realComplex; 
+                Dimensionality = dimensionality; 
+                Dimension = dimension; 
+                AlongDimensionIndex = dim; 
+                Descriptor = tmpDescriptor; 
+                LocalLoopIncrement = localLoopIncrement;
+                LocalLoopLength = localLoopLength;
+                InPlace = inplace; 
+                return Descriptor; 
+            }
+        }
+        public string GetDescriptorInfo() {
+            if (Descriptor != IntPtr.Zero) {
+                return GetDescriptorInfo(Descriptor);
+            } else {
+                return "(no descriptor set)";
+            }
+        }
+        public string GetDescriptorInfo(IntPtr descriptor) {
+            StringBuilder ret = new StringBuilder();
+            int val = 0;
+            MKLImports.DftiGetValue(descriptor, MKLParameter.PRECISION, ref val); ret.Append("Precision: " + val + " " + Environment.NewLine);
+            MKLImports.DftiGetValue(descriptor, MKLParameter.FORWARD_DOMAIN, ref val); ret.Append("ForwDomain: " + val + " " + Environment.NewLine);
+            MKLImports.DftiGetValue(descriptor, MKLParameter.DIMENSION, ref val); ret.Append("DIMENSION: " + val + " " + Environment.NewLine);
+            MKLImports.DftiGetValue(descriptor, MKLParameter.LENGTHS, ref val); ret.Append("Length: " + val + " " + Environment.NewLine);
+            MKLImports.DftiGetValue(descriptor, MKLParameter.PLACEMENT, ref val); ret.Append("PLACEMENT: " + val + " " + Environment.NewLine);
+            MKLImports.DftiGetValue(descriptor, MKLParameter.NUMBER_OF_TRANSFORMS, ref val); ret.Append("NUMBER_OF_TRANSFORMS: " + val + " " + Environment.NewLine);
+            MKLImports.DftiGetValue(descriptor, MKLParameter.COMPLEX_STORAGE, ref val); ret.Append("COMPLEX_STORAGE: " + val + " " + Environment.NewLine);
+            MKLImports.DftiGetValue(descriptor, MKLParameter.CONJUGATE_EVEN_STORAGE, ref val); ret.Append("CONJUGATE_EVEN_STORAGE: " + val + " " + Environment.NewLine);
+            MKLImports.DftiGetValue(descriptor, MKLParameter.INPUT_DISTANCE, ref val); ret.Append("INPUT_DISTANCE: " + val + " " + Environment.NewLine);
+            MKLImports.DftiGetValue(descriptor, MKLParameter.OUTPUT_DISTANCE, ref val); ret.Append("OUTPUT_DISTANCE: " + val + " " + Environment.NewLine);
+            MKLImports.DftiGetValue(descriptor, MKLParameter.INPUT_STRIDES, ref val); ret.Append("INPUT_STRIDES: " + val + " " + Environment.NewLine);
+            MKLImports.DftiGetValue(descriptor, MKLParameter.OUTPUT_STRIDES, ref val); ret.Append("OUTPUT_STRIDES: " + val + " " + Environment.NewLine);
+            return ret.ToString();
+        }
+
+        #region IDisposable Members
+
+        public void Dispose() {
+            lock (this)  
+            if (Descriptor != IntPtr.Zero) {
+                Descriptor = IntPtr.Zero; 
+                MKLImports.DftiFreeDescriptor(ref Descriptor);
+            }
+        }
+        ~MKLDescriptor () {
+            Dispose(); 
+        }
+        #endregion
+    }
+    /// <summary>
+    /// Wrapper for FFT interface using MKL 10_03
+    /// </summary>
+    public class ILMKLFFT : IILFFT {
+
+        public static void Init() {
+            try {
+                // unless the user explicitely configured the number of threads, let omp configure it! 
+                if (Settings.MaxNumberThreadsConfigured) {
+                    SetNumThreads(Settings.MaxNumberThreads); 
+                }
+            } catch (System.IO.FileNotFoundException) {}
+        }
+        public static void SetNumThreads(int numThreads) {
+            int mklfft = MKLValues.MKL_FFT; 
+            MKLImports.mkl_domain_set_num_threads(ref numThreads,ref mklfft); 
+        }
+        public static int GetMaxThreads() {
+            int mklfft = MKLValues.MKL_FFT; 
+            return MKLImports.mkl_domain_get_max_threads(ref mklfft); 
+        }
+        private static void SetDynamicThreads(bool dynamic) {
+            int val = dynamic ? 1 : 0;
+            MKLImports.mkl_set_dynamic(ref val);
+        }
+
+        #region attributes 
+        [ThreadStatic]
+        private static int[] s_strides; 
+        private static int[] Strides {
+            get {
+                if (s_strides == null) {
+                     s_strides = new int[10];
+                }
+                return s_strides; 
+            }
+        }
+        [ThreadStatic]
+        private static MKLDescriptor s_descriptor; 
+        private static MKLDescriptor DescriptorCache {
+            get  {
+                if (s_descriptor == null) {
+                    s_descriptor = new MKLDescriptor(); 
+                }
+                return s_descriptor; 
+            }
+        }
+        #endregion
+
+        #region constructor 
+        public ILMKLFFT () {
+            Init();  
+        }
+        #endregion
+
+        #region IILFFT Member - 1-D
+
+
+
+        public ILRetArray< complex >  FFTForward1D (ILInArray< double > A, int dim) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A,null) || dim < 0) 
+                    throw new ILArgumentException("invalid parameter"); 
+                if (A.IsEmpty) return ILMath.empty< complex >(A.Size); 
+                if (dim >= A.Size.NumberOfDimensions || A.Size[dim] == 1) 
+                    return  ILMath.tocomplex(A); 
+                // prepare output array 
+                ILArray< complex > ret =  ILMath.tocomplex(A) ;
+                int localLoopLength, localLoopIncrement; 
+
+                IntPtr descriptor = DescriptorCache.GetDescriptor( MKLValues.DOUBLE,MKLValues.COMPLEX,1,dim,A.Size,true,
+                                    out localLoopLength, out localLoopIncrement);
+                int error = 0;   
+                // do the transform(s)
+                unsafe {
+                    fixed ( complex * retArr = ret.GetArrayForWrite()) {
+                        for (int i = 0; i < localLoopLength && error == 0; i ++)
+                            error =   MKLImports.DftiComputeForward(descriptor, (IntPtr)(retArr + i * localLoopIncrement));
+                    }
+                }
+                if (isMKLError(error)) {
+                    throw new ILInvalidOperationException ("error: " + MKLImports.DftiErrorMessage(error)); 
+                }
+                
+
+                return ret;
+            }
+        }
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+
+        public ILRetArray< fcomplex >  FFTBackward1D (ILInArray< fcomplex > A, int dim) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A,null) || dim < 0) 
+                    throw new ILArgumentException("invalid parameter"); 
+                if (A.IsEmpty) return ILMath.empty< fcomplex >(A.Size); 
+                if (dim >= A.Size.NumberOfDimensions || A.Size[dim] == 1) 
+                    return  A.C; 
+                // prepare output array 
+                ILArray< fcomplex > ret =  A.C ;
+                int localLoopLength, localLoopIncrement; 
+
+                IntPtr descriptor = DescriptorCache.GetDescriptor( MKLValues.SINGLE,MKLValues.COMPLEX,1,dim,A.Size,true,
+                                    out localLoopLength, out localLoopIncrement);
+                int error = 0;   
+                // do the transform(s)
+                unsafe {
+                    fixed ( fcomplex * retArr = ret.GetArrayForWrite()) {
+                        for (int i = 0; i < localLoopLength && error == 0; i ++)
+                            error =  MKLImports.DftiComputeBackward(descriptor, (IntPtr)(retArr + i * localLoopIncrement));
+                    }
+                }
+                if (isMKLError(error)) {
+                    throw new ILInvalidOperationException ("error: " + MKLImports.DftiErrorMessage(error)); 
+                }
+                ret = ret / new fcomplex(A.D[dim],0);
+                return ret;
+            }
+        }
+
+
+        public ILRetArray< complex >  FFTBackward1D (ILInArray< complex > A, int dim) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A,null) || dim < 0) 
+                    throw new ILArgumentException("invalid parameter"); 
+                if (A.IsEmpty) return ILMath.empty< complex >(A.Size); 
+                if (dim >= A.Size.NumberOfDimensions || A.Size[dim] == 1) 
+                    return  A.C; 
+                // prepare output array 
+                ILArray< complex > ret =  A.C ;
+                int localLoopLength, localLoopIncrement; 
+
+                IntPtr descriptor = DescriptorCache.GetDescriptor( MKLValues.DOUBLE,MKLValues.COMPLEX,1,dim,A.Size,true,
+                                    out localLoopLength, out localLoopIncrement);
+                int error = 0;   
+                // do the transform(s)
+                unsafe {
+                    fixed ( complex * retArr = ret.GetArrayForWrite()) {
+                        for (int i = 0; i < localLoopLength && error == 0; i ++)
+                            error =  MKLImports.DftiComputeBackward(descriptor, (IntPtr)(retArr + i * localLoopIncrement));
+                    }
+                }
+                if (isMKLError(error)) {
+                    throw new ILInvalidOperationException ("error: " + MKLImports.DftiErrorMessage(error)); 
+                }
+                ret = ret / new complex(A.D[dim],0);
+                return ret;
+            }
+        }
+
+
+        public ILRetArray< fcomplex >  FFTForward1D (ILInArray< fcomplex > A, int dim) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A,null) || dim < 0) 
+                    throw new ILArgumentException("invalid parameter"); 
+                if (A.IsEmpty) return ILMath.empty< fcomplex >(A.Size); 
+                if (dim >= A.Size.NumberOfDimensions || A.Size[dim] == 1) 
+                    return  A.C; 
+                // prepare output array 
+                ILArray< fcomplex > ret =  A.C ;
+                int localLoopLength, localLoopIncrement; 
+
+                IntPtr descriptor = DescriptorCache.GetDescriptor( MKLValues.SINGLE,MKLValues.COMPLEX,1,dim,A.Size,true,
+                                    out localLoopLength, out localLoopIncrement);
+                int error = 0;   
+                // do the transform(s)
+                unsafe {
+                    fixed ( fcomplex * retArr = ret.GetArrayForWrite()) {
+                        for (int i = 0; i < localLoopLength && error == 0; i ++)
+                            error =  MKLImports.DftiComputeForward(descriptor, (IntPtr)(retArr + i * localLoopIncrement));
+                    }
+                }
+                if (isMKLError(error)) {
+                    throw new ILInvalidOperationException ("error: " + MKLImports.DftiErrorMessage(error)); 
+                }
+                
+                return ret;
+            }
+        }
+
+
+        public ILRetArray< fcomplex >  FFTForward1D (ILInArray< float > A, int dim) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A,null) || dim < 0) 
+                    throw new ILArgumentException("invalid parameter"); 
+                if (A.IsEmpty) return ILMath.empty< fcomplex >(A.Size); 
+                if (dim >= A.Size.NumberOfDimensions || A.Size[dim] == 1) 
+                    return  ILMath.tofcomplex(A); 
+                // prepare output array 
+                ILArray< fcomplex > ret =  ILMath.tofcomplex(A) ;
+                int localLoopLength, localLoopIncrement; 
+
+                IntPtr descriptor = DescriptorCache.GetDescriptor( MKLValues.SINGLE,MKLValues.COMPLEX,1,dim,A.Size,true,
+                                    out localLoopLength, out localLoopIncrement);
+                int error = 0;   
+                // do the transform(s)
+                unsafe {
+                    fixed ( fcomplex * retArr = ret.GetArrayForWrite()) {
+                        for (int i = 0; i < localLoopLength && error == 0; i ++)
+                            error =  MKLImports.DftiComputeForward(descriptor, (IntPtr)(retArr + i * localLoopIncrement));
+                    }
+                }
+                if (isMKLError(error)) {
+                    throw new ILInvalidOperationException ("error: " + MKLImports.DftiErrorMessage(error)); 
+                }
+                
+                return ret;
+            }
+        }
+
+
+        public ILRetArray< complex >  FFTForward1D (ILInArray< complex > A, int dim) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A,null) || dim < 0) 
+                    throw new ILArgumentException("invalid parameter"); 
+                if (A.IsEmpty) return ILMath.empty< complex >(A.Size); 
+                if (dim >= A.Size.NumberOfDimensions || A.Size[dim] == 1) 
+                    return  A.C; 
+                // prepare output array 
+                ILArray< complex > ret =  A.C ;
+                int localLoopLength, localLoopIncrement; 
+
+                IntPtr descriptor = DescriptorCache.GetDescriptor( MKLValues.DOUBLE,MKLValues.COMPLEX,1,dim,A.Size,true,
+                                    out localLoopLength, out localLoopIncrement);
+                int error = 0;   
+                // do the transform(s)
+                unsafe {
+                    fixed ( complex * retArr = ret.GetArrayForWrite()) {
+                        for (int i = 0; i < localLoopLength && error == 0; i ++)
+                            error =  MKLImports.DftiComputeForward(descriptor, (IntPtr)(retArr + i * localLoopIncrement));
+                    }
+                }
+                if (isMKLError(error)) {
+                    throw new ILInvalidOperationException ("error: " + MKLImports.DftiErrorMessage(error)); 
+                }
+                
+                return ret;
+            }
+        }
+
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+
+
+
+        public ILRetArray< double > FFTBackwSym1D(ILInArray< complex > A, int dim) {
+            using (ILScope.Enter(A)) {  
+                if (object.Equals(A,null) || dim < 0) 
+                    throw new ILArgumentException("invalid parameter"); 
+                if (A.IsEmpty) return ILArray< double >.empty(A.Size); 
+                if (A.IsScalar || A.Size[dim] == 1) 
+                    return ILMath.real(A.C); 
+                // prepare output array, if we query the memory directly from
+                // memory pool, we prevent from clearing the elements since every 
+                // single one will be overwritten by fft anyway
+                int error = 0,inDim = A.Size[dim];   
+                 double [] retArr = ILMemoryPool.Pool.New< double >(A.Size.NumberOfElements); 
+                ILArray< double > ret = ILMath.array< double >(retArr,A.Size); 
+                int localLoopLength, localLoopIncrement; 
+                IntPtr descriptor = DescriptorCache.GetDescriptor( MKLValues.DOUBLE , MKLValues.REAL, 1, dim, A.S, false, 
+                                    out localLoopLength, out localLoopIncrement);
+                // do the transform(s)
+                unsafe {
+                    fixed ( double * retArrP = ret.GetArrayForWrite()) 
+                    fixed ( complex * pA = A.GetArrayForRead()) {
+                        for (int i = 0; i < (localLoopLength * localLoopIncrement) && error == 0; i += localLoopIncrement)
+                            error = MKLImports.DftiComputeBackward(descriptor, (IntPtr)(pA + i), (IntPtr)(retArrP + i));
+                    }
+                }
+                if (isMKLError(error)) {
+                    throw new ILInvalidOperationException ("error: " + MKLImports.DftiErrorMessage(error)); 
+                }
+                return ret / inDim;
+            }
+        }
+
+
+#region HYCALPER AUTO GENERATED CODE
+
+
+
+        public ILRetArray< float > FFTBackwSym1D(ILInArray< fcomplex > A, int dim) {
+            using (ILScope.Enter(A)) {  
+                if (object.Equals(A,null) || dim < 0) 
+                    throw new ILArgumentException("invalid parameter"); 
+                if (A.IsEmpty) return ILArray< float >.empty(A.Size); 
+                if (A.IsScalar || A.Size[dim] == 1) 
+                    return ILMath.real(A.C); 
+                // prepare output array, if we query the memory directly from
+                // memory pool, we prevent from clearing the elements since every 
+                // single one will be overwritten by fft anyway
+                int error = 0,inDim = A.Size[dim];   
+                float [] retArr = ILMemoryPool.Pool.New< float >(A.Size.NumberOfElements); 
+                ILArray< float > ret = ILMath.array< float >(retArr,A.Size); 
+                int localLoopLength, localLoopIncrement; 
+                IntPtr descriptor = DescriptorCache.GetDescriptor( MKLValues.SINGLE , MKLValues.REAL, 1, dim, A.S, false, 
+                                    out localLoopLength, out localLoopIncrement);
+                // do the transform(s)
+                unsafe {
+                    fixed ( float * retArrP = ret.GetArrayForWrite()) 
+                    fixed ( fcomplex * pA = A.GetArrayForRead()) {
+                        for (int i = 0; i < (localLoopLength * localLoopIncrement) && error == 0; i += localLoopIncrement)
+                            error = MKLImports.DftiComputeBackward(descriptor, (IntPtr)(pA + i), (IntPtr)(retArrP + i));
+                    }
+                }
+                if (isMKLError(error)) {
+                    throw new ILInvalidOperationException ("error: " + MKLImports.DftiErrorMessage(error)); 
+                }
+                return ret / inDim;
+            }
+        }
+
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+        #endregion
+
+        #region IILFFT Member - n-D
+
+
+
+        public ILRetArray< complex >  FFTForward (ILInArray< double > A, int nDims) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A, null) || nDims <= 0 ) 
+                    throw new ILArgumentException("invalid argument!");
+                if (A.IsEmpty) return ILArray< complex > .empty(A.Size); 
+                if (A.IsScalar || (A.Size[0] == 1 && nDims == 1)) 
+                    return  ILMath.tocomplex(A) ; 
+                if (nDims > A.Size.NumberOfDimensions) 
+                    nDims = A.Size.NumberOfDimensions; 
+                
+                if (nDims > 3) return FFTForward(ILMath.tocomplex(A),nDims); 
+                // prepare output array 
+                ILArray< complex > ret =  ILMath.tocomplex(A) ;
+                int localLoopLength, localLoopIncrement; 
+                IntPtr descriptor = DescriptorCache.GetDescriptor( MKLValues.DOUBLE , MKLValues.COMPLEX, nDims, 0, A.Size, true,
+                                    out localLoopLength, out localLoopIncrement); 
+                int error = 0;   
+                // do the transform(s)
+                unsafe {
+                    fixed ( complex * retArr = ret.GetArrayForWrite()) {
+                        error =  MKLImports.DftiComputeForward (descriptor, (IntPtr)retArr);
+                    }
+                }
+                if (isMKLError(error)) {
+                    throw new ILInvalidOperationException ("error: " + MKLImports.DftiErrorMessage(error)); 
+                }
+                
+
+                return ret;
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+
+        public ILRetArray< complex >  FFTBackward (ILInArray< complex > A, int nDims) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A, null) || nDims <= 0 ) 
+                    throw new ILArgumentException("invalid argument!");
+                if (A.IsEmpty) return ILArray< complex > .empty(A.Size); 
+                if (A.IsScalar || (A.Size[0] == 1 && nDims == 1)) 
+                    return  A.C ; 
+                if (nDims > A.Size.NumberOfDimensions) 
+                    nDims = A.Size.NumberOfDimensions; 
+                
+                // prepare output array 
+                ILArray< complex > ret =  A.C ;
+                int localLoopLength, localLoopIncrement; 
+                IntPtr descriptor = DescriptorCache.GetDescriptor( MKLValues.DOUBLE , MKLValues.COMPLEX, nDims, 0, A.Size, true,
+                                    out localLoopLength, out localLoopIncrement); 
+                int error = 0;   
+                // do the transform(s)
+                unsafe {
+                    fixed ( complex * retArr = ret.GetArrayForWrite()) {
+                        error =  MKLImports.DftiComputeBackward (descriptor, (IntPtr)retArr);
+                    }
+                }
+                if (isMKLError(error)) {
+                    throw new ILInvalidOperationException ("error: " + MKLImports.DftiErrorMessage(error)); 
+                }
+                ret = ret / new complex(A.D.SequentialIndexDistance(nDims),0);
+                return ret;
+            }
+        }
+
+        public ILRetArray< fcomplex >  FFTBackward (ILInArray< fcomplex > A, int nDims) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A, null) || nDims <= 0 ) 
+                    throw new ILArgumentException("invalid argument!");
+                if (A.IsEmpty) return ILArray< fcomplex > .empty(A.Size); 
+                if (A.IsScalar || (A.Size[0] == 1 && nDims == 1)) 
+                    return  A.C ; 
+                if (nDims > A.Size.NumberOfDimensions) 
+                    nDims = A.Size.NumberOfDimensions; 
+                
+                // prepare output array 
+                ILArray< fcomplex > ret =  A.C ;
+                int localLoopLength, localLoopIncrement; 
+                IntPtr descriptor = DescriptorCache.GetDescriptor( MKLValues.SINGLE , MKLValues.COMPLEX, nDims, 0, A.Size, true,
+                                    out localLoopLength, out localLoopIncrement); 
+                int error = 0;   
+                // do the transform(s)
+                unsafe {
+                    fixed ( fcomplex * retArr = ret.GetArrayForWrite()) {
+                        error =  MKLImports.DftiComputeBackward (descriptor, (IntPtr)retArr);
+                    }
+                }
+                if (isMKLError(error)) {
+                    throw new ILInvalidOperationException ("error: " + MKLImports.DftiErrorMessage(error)); 
+                }
+                ret = ret / new fcomplex(A.D.SequentialIndexDistance(nDims),0);
+                return ret;
+            }
+        }
+
+        public ILRetArray< fcomplex >  FFTForward (ILInArray< fcomplex > A, int nDims) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A, null) || nDims <= 0 ) 
+                    throw new ILArgumentException("invalid argument!");
+                if (A.IsEmpty) return ILArray< fcomplex > .empty(A.Size); 
+                if (A.IsScalar || (A.Size[0] == 1 && nDims == 1)) 
+                    return  A.C ; 
+                if (nDims > A.Size.NumberOfDimensions) 
+                    nDims = A.Size.NumberOfDimensions; 
+                
+                // prepare output array 
+                ILArray< fcomplex > ret =  A.C ;
+                int localLoopLength, localLoopIncrement; 
+                IntPtr descriptor = DescriptorCache.GetDescriptor( MKLValues.SINGLE , MKLValues.COMPLEX, nDims, 0, A.Size, true,
+                                    out localLoopLength, out localLoopIncrement); 
+                int error = 0;   
+                // do the transform(s)
+                unsafe {
+                    fixed ( fcomplex * retArr = ret.GetArrayForWrite()) {
+                        error =  MKLImports.DftiComputeForward (descriptor, (IntPtr)retArr);
+                    }
+                }
+                if (isMKLError(error)) {
+                    throw new ILInvalidOperationException ("error: " + MKLImports.DftiErrorMessage(error)); 
+                }
+                
+                return ret;
+            }
+        }
+
+        public ILRetArray< fcomplex >  FFTForward (ILInArray< float > A, int nDims) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A, null) || nDims <= 0 ) 
+                    throw new ILArgumentException("invalid argument!");
+                if (A.IsEmpty) return ILArray< fcomplex > .empty(A.Size); 
+                if (A.IsScalar || (A.Size[0] == 1 && nDims == 1)) 
+                    return  ILMath.tofcomplex(A) ; 
+                if (nDims > A.Size.NumberOfDimensions) 
+                    nDims = A.Size.NumberOfDimensions; 
+                if (nDims > 3) return FFTForward(ILMath.tofcomplex(A),nDims);
+                // prepare output array 
+                ILArray< fcomplex > ret =  ILMath.tofcomplex(A) ;
+                int localLoopLength, localLoopIncrement; 
+                IntPtr descriptor = DescriptorCache.GetDescriptor( MKLValues.SINGLE , MKLValues.COMPLEX, nDims, 0, A.Size, true,
+                                    out localLoopLength, out localLoopIncrement); 
+                int error = 0;   
+                // do the transform(s)
+                unsafe {
+                    fixed ( fcomplex * retArr = ret.GetArrayForWrite()) {
+                        error =  MKLImports.DftiComputeForward (descriptor, (IntPtr)retArr);
+                    }
+                }
+                if (isMKLError(error)) {
+                    throw new ILInvalidOperationException ("error: " + MKLImports.DftiErrorMessage(error)); 
+                }
+                
+                return ret;
+            }
+        }
+
+        public ILRetArray< complex >  FFTForward (ILInArray< complex > A, int nDims) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A, null) || nDims <= 0 ) 
+                    throw new ILArgumentException("invalid argument!");
+                if (A.IsEmpty) return ILArray< complex > .empty(A.Size); 
+                if (A.IsScalar || (A.Size[0] == 1 && nDims == 1)) 
+                    return  A.C ; 
+                if (nDims > A.Size.NumberOfDimensions) 
+                    nDims = A.Size.NumberOfDimensions; 
+                
+                // prepare output array 
+                ILArray< complex > ret =  A.C ;
+                int localLoopLength, localLoopIncrement; 
+                IntPtr descriptor = DescriptorCache.GetDescriptor( MKLValues.DOUBLE , MKLValues.COMPLEX, nDims, 0, A.Size, true,
+                                    out localLoopLength, out localLoopIncrement); 
+                int error = 0;   
+                // do the transform(s)
+                unsafe {
+                    fixed ( complex * retArr = ret.GetArrayForWrite()) {
+                        error =  MKLImports.DftiComputeForward (descriptor, (IntPtr)retArr);
+                    }
+                }
+                if (isMKLError(error)) {
+                    throw new ILInvalidOperationException ("error: " + MKLImports.DftiErrorMessage(error)); 
+                }
+                
+                return ret;
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+       
+
+        
+        public ILRetArray< double > FFTBackwSym(ILInArray< complex > A, int nDims) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A, null) || nDims <= 0 ) 
+                    throw new ILArgumentException("invalid argument!");
+                if (A.IsEmpty) return ILMath.empty< double > (A.Size); 
+                if (A.IsScalar || (A.Size[0] == 1 && nDims == 1)) 
+                    return ILMath.real(A.C); 
+                if (nDims > A.Size.NumberOfDimensions) 
+                    nDims = A.Size.NumberOfDimensions; 
+                // MKL currently does not handle more than 3 dimensions this way
+                if (nDims > 3) {
+                    return ILMath.real(FFTBackward(A,nDims)); 
+                }
+                // prepare output array, if we query the memory directly from
+                // memory pool, we prevent from clearing the elements since every 
+                // single one will be overwritten by fft anyway
+                 double [] retArr = ILMemoryPool.Pool.New< double >(A.Size.NumberOfElements);
+                ILArray< double> ret = ILMath.array< double>(retArr, A.Size); 
+                int localLoopIncrement, localLoopLength; 
+                IntPtr descriptor = DescriptorCache.GetDescriptor( MKLValues.DOUBLE , MKLValues.REAL,nDims, 0, A.S, false,
+                                    out localLoopIncrement, out localLoopLength); 
+                int error = 0;   
+                // do the transform(s)
+                unsafe {
+                    fixed ( double * retArrP = retArr) 
+                    fixed ( complex * inArr = A.GetArrayForRead()) {
+                        error = MKLImports.DftiComputeBackward(descriptor, (IntPtr)(inArr),(IntPtr)(retArrP));
+                    }
+                }
+                if (isMKLError(error)) {
+                    throw new ILInvalidOperationException ("error: " + MKLImports.DftiErrorMessage(error)); 
+                }
+                ret = ret / A.S.SequentialIndexDistance(nDims);     
+                return ret;
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+       
+        public ILRetArray< float > FFTBackwSym(ILInArray< fcomplex > A, int nDims) {
+            using (ILScope.Enter(A)) {
+                if (object.Equals(A, null) || nDims <= 0 ) 
+                    throw new ILArgumentException("invalid argument!");
+                if (A.IsEmpty) return ILMath.empty< float > (A.Size); 
+                if (A.IsScalar || (A.Size[0] == 1 && nDims == 1)) 
+                    return ILMath.real(A.C); 
+                if (nDims > A.Size.NumberOfDimensions) 
+                    nDims = A.Size.NumberOfDimensions; 
+                // MKL currently does not handle more than 3 dimensions this way
+                if (nDims > 3) {
+                    return ILMath.real(FFTBackward(A,nDims)); 
+                }
+                // prepare output array, if we query the memory directly from
+                // memory pool, we prevent from clearing the elements since every 
+                // single one will be overwritten by fft anyway
+                float [] retArr = ILMemoryPool.Pool.New< float >(A.Size.NumberOfElements);
+                ILArray< float> ret = ILMath.array< float>(retArr, A.Size); 
+                int localLoopIncrement, localLoopLength; 
+                IntPtr descriptor = DescriptorCache.GetDescriptor( MKLValues.SINGLE , MKLValues.REAL,nDims, 0, A.S, false,
+                                    out localLoopIncrement, out localLoopLength); 
+                int error = 0;   
+                // do the transform(s)
+                unsafe {
+                    fixed ( float * retArrP = retArr) 
+                    fixed ( fcomplex * inArr = A.GetArrayForRead()) {
+                        error = MKLImports.DftiComputeBackward(descriptor, (IntPtr)(inArr),(IntPtr)(retArrP));
+                    }
+                }
+                if (isMKLError(error)) {
+                    throw new ILInvalidOperationException ("error: " + MKLImports.DftiErrorMessage(error)); 
+                }
+                ret = ret / A.S.SequentialIndexDistance(nDims);     
+                return ret;
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+        #endregion
+        
+        #region IILFFT Member - Misc
+        
+        public bool CachePlans {
+            get {
+                return true; 
+            }
+        }
+
+        public void FreePlans() {
+            DescriptorCache.Dispose(); 
+        }
+
+        public bool SpeedyHermitian {
+            get { return true; }
+        }
+
+        #endregion
+
+        #region private helper
+        private static bool isMKLError(int error) {
+            // TODO check! only the first 32 bits seem to be relevant for error!
+            //return MKLImports.DftiErrorClass(error, MKLValues.NO_ERROR) != 1;
+            return error != MKLValues.NO_ERROR; 
+        }
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Native/lapack/IILLapack.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Native/lapack/IILLapack.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Native/lapack/IILLapack.cs	(revision 9102)
@@ -0,0 +1,1204 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+#pragma warning disable 1591
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace ILNumerics.Native {
+    /// <summary>
+    /// Interface to all LAPACK/BLAS functions available
+    /// </summary>
+    /// <remarks>Each native module must implement this interface explicitly. Calls 
+    /// to native functions are made virtual by calling functions of this interface.
+    /// Therefore the user can transparently call any function regardless of the 
+    /// plattform the assymbly (currently) runs on. The native modules implementing
+    /// this interface take care of the details of implementation. 
+    /// <para>Usually users of the library will not have to handle with this interface. 
+    /// Its functions will be used from inside built in functions and are therefore wrapped 
+    /// (mainly from inside <see cref="ILNumerics.ILMath">ILNumerics.ILMath</see>).</para>
+    /// <para>Every LAPACK/BLAS function is explicitly implemented for any type supported.
+    /// e.g. IILLapack includes four functions doing general matrix multiply: dgemm, zgemm, cgemm and sgemm - 
+    /// for all four floating point datatypes supported from the LAPACK package.</para>
+    /// <para>LAPACK is an open source linear algebra functions package optimized for 
+    /// use together with highly natively optimized BLAS functions. A LAPACK guide is 
+    /// available in the internet: <see href="http://www.netlib.org/lapack">www.netlib.org</see>.</para>
+    /// </remarks>
+    [System.Security.SuppressUnmanagedCodeSecurity]
+    public interface IILLapack {
+        
+        #region ?GEMM
+
+        /// <summary>
+        /// Wrapper implementiation for ATLAS GeneralMatrixMultiply
+        /// </summary>
+        /// <param name="TransA">Transposition state for matrix A: one of the constants in enum CBlas_Transpose</param>
+        /// <param name="TransB">Transposition state for matrix B: one of the constants in enum CBlas_Transpose</param>
+        /// <param name="M">Number of rows in A</param>
+        /// <param name="N">Number of columns in B</param>
+        /// <param name="K">Number of columns in A and number of rows in B</param>
+        /// <param name="alpha">multiplicationi factor for A</param>
+        /// <param name="A">pointer to array A</param>
+        /// <param name="lda">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix A</param>
+        /// <param name="B">pointer to array B</param>
+        /// <param name="ldb">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix B</param>
+        /// <param name="beta">multiplication faktor for matrix B</param>
+        /// <param name="C">pointer to predefined array C of neccessary length</param>
+        /// <param name="ldc">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix C</param>
+        /// <remarks>All parameters except C are readonly. Only elements of matrix C will be altered. C must be a predefined 
+        /// continous array of size MxN</remarks>
+        void  dgemm (char TransA, char TransB, int M, int N, int K,
+             double alpha,  IntPtr A, int lda,
+            IntPtr B, int ldb,
+             double beta,  double [] C, int ldc);
+
+        /// <summary>
+        /// Wrapper implementiation for ATLAS GeneralMatrixMultiply
+        /// </summary>
+        /// <param name="TransA">Transposition state for matrix A: one of the constants in enum CBlas_Transpose</param>
+        /// <param name="TransB">Transposition state for matrix B: one of the constants in enum CBlas_Transpose</param>
+        /// <param name="M">Number of rows in A</param>
+        /// <param name="N">Number of columns in B</param>
+        /// <param name="K">Number of columns in A and number of rows in B</param>
+        /// <param name="alpha">multiplicationi factor for A</param>
+        /// <param name="A">pointer to array A</param>
+        /// <param name="lda">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix A</param>
+        /// <param name="B">pointer to array B</param>
+        /// <param name="ldb">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix B</param>
+        /// <param name="beta">multiplication faktor for matrix B</param>
+        /// <param name="C">pointer to predefined array C of neccessary length</param>
+        /// <param name="ldc">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix C</param>
+        /// <remarks>All parameters except C are readonly. Only elements of matrix C will be altered. C must be a predefined 
+        /// continous array of size MxN</remarks>
+        void  sgemm (char TransA, char TransB, int M, int N, int K,
+            float alpha,  IntPtr A, int lda,
+            IntPtr B, int ldb,
+            float beta,  float [] C, int ldc);
+       
+
+        /// <summary>
+        /// Wrapper implementiation for ATLAS GeneralMatrixMultiply
+        /// </summary>
+        /// <param name="TransA">Transposition state for matrix A: one of the constants in enum CBlas_Transpose</param>
+        /// <param name="TransB">Transposition state for matrix B: one of the constants in enum CBlas_Transpose</param>
+        /// <param name="M">Number of rows in A</param>
+        /// <param name="N">Number of columns in B</param>
+        /// <param name="K">Number of columns in A and number of rows in B</param>
+        /// <param name="alpha">multiplicationi factor for A</param>
+        /// <param name="A">pointer to array A</param>
+        /// <param name="lda">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix A</param>
+        /// <param name="B">pointer to array B</param>
+        /// <param name="ldb">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix B</param>
+        /// <param name="beta">multiplication faktor for matrix B</param>
+        /// <param name="C">pointer to predefined array C of neccessary length</param>
+        /// <param name="ldc">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix C</param>
+        /// <remarks>All parameters except C are readonly. Only elements of matrix C will be altered. C must be a predefined 
+        /// continous array of size MxN</remarks>
+        void  cgemm (char TransA, char TransB, int M, int N, int K,
+            fcomplex alpha,  IntPtr A, int lda,
+            IntPtr B, int ldb,
+            fcomplex beta,  fcomplex [] C, int ldc);
+       
+
+        /// <summary>
+        /// Wrapper implementiation for ATLAS GeneralMatrixMultiply
+        /// </summary>
+        /// <param name="TransA">Transposition state for matrix A: one of the constants in enum CBlas_Transpose</param>
+        /// <param name="TransB">Transposition state for matrix B: one of the constants in enum CBlas_Transpose</param>
+        /// <param name="M">Number of rows in A</param>
+        /// <param name="N">Number of columns in B</param>
+        /// <param name="K">Number of columns in A and number of rows in B</param>
+        /// <param name="alpha">multiplicationi factor for A</param>
+        /// <param name="A">pointer to array A</param>
+        /// <param name="lda">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix A</param>
+        /// <param name="B">pointer to array B</param>
+        /// <param name="ldb">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix B</param>
+        /// <param name="beta">multiplication faktor for matrix B</param>
+        /// <param name="C">pointer to predefined array C of neccessary length</param>
+        /// <param name="ldc">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix C</param>
+        /// <remarks>All parameters except C are readonly. Only elements of matrix C will be altered. C must be a predefined 
+        /// continous array of size MxN</remarks>
+        void  zgemm (char TransA, char TransB, int M, int N, int K,
+            complex alpha,  IntPtr A, int lda,
+            IntPtr B, int ldb,
+            complex beta,  complex [] C, int ldc);
+
+#endregion 
+
+        #region ?GESDD
+        /// <summary>
+        /// singular value decomposition, new version, more memory needed
+        /// </summary>
+        /// <param name="jobz">Specifies options for computing all or part of the matrix U
+        /// <list type="table">
+        /// <listheader>
+        ///     <term>jobz value</term>
+        ///     <description>... will result in:</description>
+        /// </listheader>
+        ///     <item>
+        ///         <term>A</term>
+        ///         <description>all M columns of U and all N rows of V**T are
+        ///                     returned in the arrays U and VT</description>
+        ///     </item>
+        ///     <item>  <term>S</term>
+        ///             <description>the first min(M,N) columns of U and the first
+        ///              min(M,N) rows of V**T are returned in the arrays U
+        ///              and VT</description>
+        ///     </item>
+        ///     <item> <term>O</term>  
+        ///            <description>If M >= N, the first N columns of U are overwritten
+        ///              on the array A and all rows of V**T are returned in
+        ///              the array VT,
+        ///              otherwise, all columns of U are returned in the
+        ///              array U and the first M rows of V**T are overwritten
+        ///              in the array VT</description>
+        ///     </item>
+        ///     <item> <term>N</term> 
+        ///            <description>no columns of U or rows of V**T are computed.</description>
+        ///     </item>
+        /// </list>
+        /// </param>
+        /// <param name="m">The number of rows of the input matrix A.  M greater or equal to 0.</param>
+        /// <param name="n">The number of columns of the input matrix A.  N greater or equal to 0</param>
+        /// <param name="a">On entry, the M-by-N matrix A.
+        ///          On exit, <list><item>
+        ///          if JOBZ = 'O',  A is overwritten with the first N columns
+        ///                          of U (the left singular vectors, stored
+        ///                          columnwise) if M >= N;
+        ///                          A is overwritten with the first M rows
+        ///                          of V**T (the right singular vectors, stored
+        ///                          rowwise) otherwise.</item>
+        ///          <item>if JOBZ .ne. 'O', the contents of A are destroyed.</item></list></param>
+        /// <param name="lda">The leading dimension of the array A.  LDA ge max(1,M).</param>
+        /// <param name="s">array, dimension (min(M,N)). The singular values of A, sorted so that S(i) ge S(i+1)</param>
+        /// <param name="u">array, dimension (LDU,UCOL)
+        ///          UCOL = M if JOBZ = 'A' or JOBZ = 'O' and M &lt; N;
+        ///          UCOL = min(M,N) if JOBZ = 'S'.
+        ///          If JOBZ = 'A' or JOBZ = 'O' and M &lt; N, U contains the M-by-M
+        ///          orthogonal matrix U;
+        ///          if JOBZ = 'S', U contains the first min(M,N) columns of U
+        ///          (the left singular vectors, stored columnwise);
+        ///          if JOBZ = 'O' and M &gt;= N, or JOBZ = 'N', U is not referenced.</param>
+        /// <param name="ldu">The leading dimension of the array U.  LDU &gt;= 1; if  
+        /// JOBZ = 'S' or 'A' or JOBZ = 'O' and M &lt; N, LDU &gt;= M</param>
+        /// <param name="vt">array, dimension (LDVT,N). If JOBZ = 'A' or JOBZ = 'O' and 
+        /// M >= N, VT contains the N-by-N orthogonal matrix V**T; if JOBZ = 'S', 
+        /// VT contains the first min(M,N) rows of V**T 
+        /// (the right singular vectors, stored rowwise); if JOBZ = 'O' and M &lt; N, 
+        /// or JOBZ = 'N', VT is not referenced</param>
+        /// <param name="ldvt">The leading dimension of the array VT.  LDVT &gt; = 1; 
+        /// if JOBZ = 'A' or JOBZ = 'O' and M &gt; = N, LDVT &gt;= N; 
+        /// if JOBZ = 'S', LDVT &gt; min(M,N).</param>
+        /// <param name="info">
+        /// <list>
+        ///     <item> 0:  successful exit.</item>
+        ///     <item> <![CDATA[< 0]]> :  if INFO = -i, the i-th argument had an illegal value.</item>
+        ///     <item> <![CDATA[> 0]]> :  ?BGSDD did not converge, updating process failed.</item>
+        /// </list>
+        /// </param>
+        /// <remarks>(From the lapack manual):DGESDD computes the singular value decomposition (SVD) of a real
+        ///M-by-N matrix A, optionally computing the left and right singular
+        ///vectors.  If singular vectors are desired, it uses a
+        ///divide-and-conquer algorithm.
+        ///The SVD is written
+        ///    <code>A = U * SIGMA * transpose(V)</code> 
+        ///where SIGMA is an M-by-N matrix which is zero except for its
+        ///min(m,n) diagonal elements, U is an M-by-M orthogonal matrix, and
+        ///V is an N-by-N orthogonal matrix.  The diagonal elements of SIGMA
+        ///are the singular values of A; they are real and non-negative, and
+        ///are returned in descending order.  The first min(m,n) columns of
+        ///U and V are the left and right singular vectors of A.
+        ///Note that the routine returns VT = V**T, not V.
+        ///The divide and conquer algorithm makes very mild assumptions about
+        ///floating point arithmetic. It will work on machines with a guard
+        ///digit in add/subtract, or on those binary machines without guard
+        ///digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or
+        ///Cray-2. It could conceivably fail on hexadecimal or decimal machines
+        ///without guard digits, but we know of none.</remarks>
+        void  dgesdd (char jobz, int m, int n,
+             double [] a, int lda,  double [] s,
+             double [] u, int ldu,  double [] vt,
+                   int ldvt, //double [] work, int lwork, 
+                   // int [] iwork,
+                   ref int info);
+
+        /// <summary>
+        /// singular value decomposition, new version, more memory needed
+        /// </summary>
+        /// <param name="jobz">Specifies options for computing all or part of the matrix U
+        /// <list type="table">
+        /// <listheader>
+        ///     <term>jobz value</term>
+        ///     <description>... will result in:</description>
+        /// </listheader>
+        ///     <item>
+        ///         <term>A</term>
+        ///         <description>all M columns of U and all N rows of V**T are
+        ///                     returned in the arrays U and VT</description>
+        ///     </item>
+        ///     <item>  <term>S</term>
+        ///             <description>the first min(M,N) columns of U and the first
+        ///              min(M,N) rows of V**T are returned in the arrays U
+        ///              and VT</description>
+        ///     </item>
+        ///     <item> <term>O</term>  
+        ///            <description>If M >= N, the first N columns of U are overwritten
+        ///              on the array A and all rows of V**T are returned in
+        ///              the array VT,
+        ///              otherwise, all columns of U are returned in the
+        ///              array U and the first M rows of V**T are overwritten
+        ///              in the array VT</description>
+        ///     </item>
+        ///     <item> <term>N</term> 
+        ///            <description>no columns of U or rows of V**T are computed.</description>
+        ///     </item>
+        /// </list>
+        /// </param>
+        /// <param name="m">The number of rows of the input matrix A.  M greater or equal to 0.</param>
+        /// <param name="n">The number of columns of the input matrix A.  N greater or equal to 0</param>
+        /// <param name="a">On entry, the M-by-N matrix A.
+        ///          On exit, <list><item>
+        ///          if JOBZ = 'O',  A is overwritten with the first N columns
+        ///                          of U (the left singular vectors, stored
+        ///                          columnwise) if M >= N;
+        ///                          A is overwritten with the first M rows
+        ///                          of V**T (the right singular vectors, stored
+        ///                          rowwise) otherwise.</item>
+        ///          <item>if JOBZ .ne. 'O', the contents of A are destroyed.</item></list></param>
+        /// <param name="lda">The leading dimension of the array A.  LDA ge max(1,M).</param>
+        /// <param name="s">array, dimension (min(M,N)). The singular values of A, sorted so that S(i) ge S(i+1)</param>
+        /// <param name="u">array, dimension (LDU,UCOL)
+        ///          UCOL = M if JOBZ = 'A' or JOBZ = 'O' and M &lt; N;
+        ///          UCOL = min(M,N) if JOBZ = 'S'.
+        ///          If JOBZ = 'A' or JOBZ = 'O' and M &lt; N, U contains the M-by-M
+        ///          orthogonal matrix U;
+        ///          if JOBZ = 'S', U contains the first min(M,N) columns of U
+        ///          (the left singular vectors, stored columnwise);
+        ///          if JOBZ = 'O' and M &gt;= N, or JOBZ = 'N', U is not referenced.</param>
+        /// <param name="ldu">The leading dimension of the array U.  LDU &gt;= 1; if  
+        /// JOBZ = 'S' or 'A' or JOBZ = 'O' and M &lt; N, LDU &gt;= M</param>
+        /// <param name="vt">array, dimension (LDVT,N). If JOBZ = 'A' or JOBZ = 'O' and 
+        /// M >= N, VT contains the N-by-N orthogonal matrix V**T; if JOBZ = 'S', 
+        /// VT contains the first min(M,N) rows of V**T 
+        /// (the right singular vectors, stored rowwise); if JOBZ = 'O' and M &lt; N, 
+        /// or JOBZ = 'N', VT is not referenced</param>
+        /// <param name="ldvt">The leading dimension of the array VT.  LDVT &gt; = 1; 
+        /// if JOBZ = 'A' or JOBZ = 'O' and M &gt; = N, LDVT &gt;= N; 
+        /// if JOBZ = 'S', LDVT &gt; min(M,N).</param>
+        /// <param name="info">
+        /// <list>
+        ///     <item> 0:  successful exit.</item>
+        ///     <item> <![CDATA[< 0]]> :  if INFO = -i, the i-th argument had an illegal value.</item>
+        ///     <item> <![CDATA[> 0]]> :  ?BGSDD did not converge, updating process failed.</item>
+        /// </list>
+        /// </param>
+        /// <remarks>(From the lapack manual):DGESDD computes the singular value decomposition (SVD) of a real
+        ///M-by-N matrix A, optionally computing the left and right singular
+        ///vectors.  If singular vectors are desired, it uses a
+        ///divide-and-conquer algorithm.
+        ///The SVD is written
+        ///    <code>A = U * SIGMA * transpose(V)</code> 
+        ///where SIGMA is an M-by-N matrix which is zero except for its
+        ///min(m,n) diagonal elements, U is an M-by-M orthogonal matrix, and
+        ///V is an N-by-N orthogonal matrix.  The diagonal elements of SIGMA
+        ///are the singular values of A; they are real and non-negative, and
+        ///are returned in descending order.  The first min(m,n) columns of
+        ///U and V are the left and right singular vectors of A.
+        ///Note that the routine returns VT = V**T, not V.
+        ///The divide and conquer algorithm makes very mild assumptions about
+        ///floating point arithmetic. It will work on machines with a guard
+        ///digit in add/subtract, or on those binary machines without guard
+        ///digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or
+        ///Cray-2. It could conceivably fail on hexadecimal or decimal machines
+        ///without guard digits, but we know of none.</remarks>
+        void  sgesdd (char jobz, int m, int n,
+            float [] a, int lda,  float [] s,
+            float [] u, int ldu,  float [] vt,
+                   int ldvt, //double [] work, int lwork, 
+                   // int [] iwork,
+                   ref int info);
+       
+        /// <summary>
+        /// singular value decomposition, new version, more memory needed
+        /// </summary>
+        /// <param name="jobz">Specifies options for computing all or part of the matrix U
+        /// <list type="table">
+        /// <listheader>
+        ///     <term>jobz value</term>
+        ///     <description>... will result in:</description>
+        /// </listheader>
+        ///     <item>
+        ///         <term>A</term>
+        ///         <description>all M columns of U and all N rows of V**T are
+        ///                     returned in the arrays U and VT</description>
+        ///     </item>
+        ///     <item>  <term>S</term>
+        ///             <description>the first min(M,N) columns of U and the first
+        ///              min(M,N) rows of V**T are returned in the arrays U
+        ///              and VT</description>
+        ///     </item>
+        ///     <item> <term>O</term>  
+        ///            <description>If M >= N, the first N columns of U are overwritten
+        ///              on the array A and all rows of V**T are returned in
+        ///              the array VT,
+        ///              otherwise, all columns of U are returned in the
+        ///              array U and the first M rows of V**T are overwritten
+        ///              in the array VT</description>
+        ///     </item>
+        ///     <item> <term>N</term> 
+        ///            <description>no columns of U or rows of V**T are computed.</description>
+        ///     </item>
+        /// </list>
+        /// </param>
+        /// <param name="m">The number of rows of the input matrix A.  M greater or equal to 0.</param>
+        /// <param name="n">The number of columns of the input matrix A.  N greater or equal to 0</param>
+        /// <param name="a">On entry, the M-by-N matrix A.
+        ///          On exit, <list><item>
+        ///          if JOBZ = 'O',  A is overwritten with the first N columns
+        ///                          of U (the left singular vectors, stored
+        ///                          columnwise) if M >= N;
+        ///                          A is overwritten with the first M rows
+        ///                          of V**T (the right singular vectors, stored
+        ///                          rowwise) otherwise.</item>
+        ///          <item>if JOBZ .ne. 'O', the contents of A are destroyed.</item></list></param>
+        /// <param name="lda">The leading dimension of the array A.  LDA ge max(1,M).</param>
+        /// <param name="s">array, dimension (min(M,N)). The singular values of A, sorted so that S(i) ge S(i+1)</param>
+        /// <param name="u">array, dimension (LDU,UCOL)
+        ///          UCOL = M if JOBZ = 'A' or JOBZ = 'O' and M &lt; N;
+        ///          UCOL = min(M,N) if JOBZ = 'S'.
+        ///          If JOBZ = 'A' or JOBZ = 'O' and M &lt; N, U contains the M-by-M
+        ///          orthogonal matrix U;
+        ///          if JOBZ = 'S', U contains the first min(M,N) columns of U
+        ///          (the left singular vectors, stored columnwise);
+        ///          if JOBZ = 'O' and M &gt;= N, or JOBZ = 'N', U is not referenced.</param>
+        /// <param name="ldu">The leading dimension of the array U.  LDU &gt;= 1; if  
+        /// JOBZ = 'S' or 'A' or JOBZ = 'O' and M &lt; N, LDU &gt;= M</param>
+        /// <param name="vt">array, dimension (LDVT,N). If JOBZ = 'A' or JOBZ = 'O' and 
+        /// M >= N, VT contains the N-by-N orthogonal matrix V**T; if JOBZ = 'S', 
+        /// VT contains the first min(M,N) rows of V**T 
+        /// (the right singular vectors, stored rowwise); if JOBZ = 'O' and M &lt; N, 
+        /// or JOBZ = 'N', VT is not referenced</param>
+        /// <param name="ldvt">The leading dimension of the array VT.  LDVT &gt; = 1; 
+        /// if JOBZ = 'A' or JOBZ = 'O' and M &gt; = N, LDVT &gt;= N; 
+        /// if JOBZ = 'S', LDVT &gt; min(M,N).</param>
+        /// <param name="info">
+        /// <list>
+        ///     <item> 0:  successful exit.</item>
+        ///     <item> <![CDATA[< 0]]> :  if INFO = -i, the i-th argument had an illegal value.</item>
+        ///     <item> <![CDATA[> 0]]> :  ?BGSDD did not converge, updating process failed.</item>
+        /// </list>
+        /// </param>
+        /// <remarks>(From the lapack manual):DGESDD computes the singular value decomposition (SVD) of a real
+        ///M-by-N matrix A, optionally computing the left and right singular
+        ///vectors.  If singular vectors are desired, it uses a
+        ///divide-and-conquer algorithm.
+        ///The SVD is written
+        ///    <code>A = U * SIGMA * transpose(V)</code> 
+        ///where SIGMA is an M-by-N matrix which is zero except for its
+        ///min(m,n) diagonal elements, U is an M-by-M orthogonal matrix, and
+        ///V is an N-by-N orthogonal matrix.  The diagonal elements of SIGMA
+        ///are the singular values of A; they are real and non-negative, and
+        ///are returned in descending order.  The first min(m,n) columns of
+        ///U and V are the left and right singular vectors of A.
+        ///Note that the routine returns VT = V**T, not V.
+        ///The divide and conquer algorithm makes very mild assumptions about
+        ///floating point arithmetic. It will work on machines with a guard
+        ///digit in add/subtract, or on those binary machines without guard
+        ///digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or
+        ///Cray-2. It could conceivably fail on hexadecimal or decimal machines
+        ///without guard digits, but we know of none.</remarks>
+        void  cgesdd (char jobz, int m, int n,
+            fcomplex [] a, int lda,  float [] s,
+            fcomplex [] u, int ldu,  fcomplex [] vt,
+                   int ldvt, //double [] work, int lwork, 
+                   // int [] iwork,
+                   ref int info);
+       
+        /// <summary>
+        /// singular value decomposition, new version, more memory needed
+        /// </summary>
+        /// <param name="jobz">Specifies options for computing all or part of the matrix U
+        /// <list type="table">
+        /// <listheader>
+        ///     <term>jobz value</term>
+        ///     <description>... will result in:</description>
+        /// </listheader>
+        ///     <item>
+        ///         <term>A</term>
+        ///         <description>all M columns of U and all N rows of V**T are
+        ///                     returned in the arrays U and VT</description>
+        ///     </item>
+        ///     <item>  <term>S</term>
+        ///             <description>the first min(M,N) columns of U and the first
+        ///              min(M,N) rows of V**T are returned in the arrays U
+        ///              and VT</description>
+        ///     </item>
+        ///     <item> <term>O</term>  
+        ///            <description>If M >= N, the first N columns of U are overwritten
+        ///              on the array A and all rows of V**T are returned in
+        ///              the array VT,
+        ///              otherwise, all columns of U are returned in the
+        ///              array U and the first M rows of V**T are overwritten
+        ///              in the array VT</description>
+        ///     </item>
+        ///     <item> <term>N</term> 
+        ///            <description>no columns of U or rows of V**T are computed.</description>
+        ///     </item>
+        /// </list>
+        /// </param>
+        /// <param name="m">The number of rows of the input matrix A.  M greater or equal to 0.</param>
+        /// <param name="n">The number of columns of the input matrix A.  N greater or equal to 0</param>
+        /// <param name="a">On entry, the M-by-N matrix A.
+        ///          On exit, <list><item>
+        ///          if JOBZ = 'O',  A is overwritten with the first N columns
+        ///                          of U (the left singular vectors, stored
+        ///                          columnwise) if M >= N;
+        ///                          A is overwritten with the first M rows
+        ///                          of V**T (the right singular vectors, stored
+        ///                          rowwise) otherwise.</item>
+        ///          <item>if JOBZ .ne. 'O', the contents of A are destroyed.</item></list></param>
+        /// <param name="lda">The leading dimension of the array A.  LDA ge max(1,M).</param>
+        /// <param name="s">array, dimension (min(M,N)). The singular values of A, sorted so that S(i) ge S(i+1)</param>
+        /// <param name="u">array, dimension (LDU,UCOL)
+        ///          UCOL = M if JOBZ = 'A' or JOBZ = 'O' and M &lt; N;
+        ///          UCOL = min(M,N) if JOBZ = 'S'.
+        ///          If JOBZ = 'A' or JOBZ = 'O' and M &lt; N, U contains the M-by-M
+        ///          orthogonal matrix U;
+        ///          if JOBZ = 'S', U contains the first min(M,N) columns of U
+        ///          (the left singular vectors, stored columnwise);
+        ///          if JOBZ = 'O' and M &gt;= N, or JOBZ = 'N', U is not referenced.</param>
+        /// <param name="ldu">The leading dimension of the array U.  LDU &gt;= 1; if  
+        /// JOBZ = 'S' or 'A' or JOBZ = 'O' and M &lt; N, LDU &gt;= M</param>
+        /// <param name="vt">array, dimension (LDVT,N). If JOBZ = 'A' or JOBZ = 'O' and 
+        /// M >= N, VT contains the N-by-N orthogonal matrix V**T; if JOBZ = 'S', 
+        /// VT contains the first min(M,N) rows of V**T 
+        /// (the right singular vectors, stored rowwise); if JOBZ = 'O' and M &lt; N, 
+        /// or JOBZ = 'N', VT is not referenced</param>
+        /// <param name="ldvt">The leading dimension of the array VT.  LDVT &gt; = 1; 
+        /// if JOBZ = 'A' or JOBZ = 'O' and M &gt; = N, LDVT &gt;= N; 
+        /// if JOBZ = 'S', LDVT &gt; min(M,N).</param>
+        /// <param name="info">
+        /// <list>
+        ///     <item> 0:  successful exit.</item>
+        ///     <item> <![CDATA[< 0]]> :  if INFO = -i, the i-th argument had an illegal value.</item>
+        ///     <item> <![CDATA[> 0]]> :  ?BGSDD did not converge, updating process failed.</item>
+        /// </list>
+        /// </param>
+        /// <remarks>(From the lapack manual):DGESDD computes the singular value decomposition (SVD) of a real
+        ///M-by-N matrix A, optionally computing the left and right singular
+        ///vectors.  If singular vectors are desired, it uses a
+        ///divide-and-conquer algorithm.
+        ///The SVD is written
+        ///    <code>A = U * SIGMA * transpose(V)</code> 
+        ///where SIGMA is an M-by-N matrix which is zero except for its
+        ///min(m,n) diagonal elements, U is an M-by-M orthogonal matrix, and
+        ///V is an N-by-N orthogonal matrix.  The diagonal elements of SIGMA
+        ///are the singular values of A; they are real and non-negative, and
+        ///are returned in descending order.  The first min(m,n) columns of
+        ///U and V are the left and right singular vectors of A.
+        ///Note that the routine returns VT = V**T, not V.
+        ///The divide and conquer algorithm makes very mild assumptions about
+        ///floating point arithmetic. It will work on machines with a guard
+        ///digit in add/subtract, or on those binary machines without guard
+        ///digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or
+        ///Cray-2. It could conceivably fail on hexadecimal or decimal machines
+        ///without guard digits, but we know of none.</remarks>
+        void  zgesdd (char jobz, int m, int n,
+            complex [] a, int lda,  double [] s,
+            complex [] u, int ldu,  complex [] vt,
+                   int ldvt, //double [] work, int lwork, 
+                   // int [] iwork,
+                   ref int info);
+
+#endregion 
+
+        #region ?GESVD
+        /// <summary>
+        /// singular value decomposition, older version, less memory needed 
+        /// </summary>
+        /// <param name="jobz">Specifies options for computing all or part of the matrix U
+        /// <list type="bullet"><item>= 'A':  all M columns of U and all N rows of V**T are
+        ///returned in the arrays U and VT</item>
+        ///     <item> = 'S':  the first min(M,N) columns of U and the first
+        ///              min(M,N) rows of V**T are returned in the arrays U
+        ///              and VT</item>
+        ///     <item> = 'O':  If M >= N, the first N columns of U are overwritten
+        ///              on the array A and all rows of V**T are returned in
+        ///              the array VT. Otherwise, all columns of U are returned in the
+        ///              array U and the first M rows of V**T are overwritten
+        ///              in the array VT</item>
+        ///     <item> = 'N':  no columns of U or rows of V**T are computed.</item>
+        ///        </list>
+        /// </param>
+        /// <param name="m">The number of rows of the input matrix A.  M greater or equal to 0.</param>
+        /// <param name="n">The number of columns of the input matrix A.  N greater or equal to 0</param>
+        /// <param name="a">On entry, the M-by-N matrix A.
+        ///          On exit, <list><item>
+        ///          if JOBZ = 'O',  A is overwritten with the first N columns
+        ///                          of U (the left singular vectors, stored
+        ///                          columnwise) if M >= N;
+        ///                          A is overwritten with the first M rows
+        ///                          of V**T (the right singular vectors, stored
+        ///                          rowwise) otherwise.</item>
+        ///          <item>if JOBZ .ne. 'O', the contents of A are destroyed.</item></list></param>
+        /// <param name="lda">The leading dimension of the array A.  LDA ge max(1,M).</param>
+        /// <param name="s">array, dimension (min(M,N)). The singular values of A, sorted so that S(i) ge S(i+1)</param>
+        /// <param name="u">array, dimension (LDU,UCOL)
+        ///          UCOL = M if JOBZ = 'A' or JOBZ = 'O' and M &lt; N;
+        ///          UCOL = min(M,N) if JOBZ = 'S'.
+        ///          If JOBZ = 'A' or JOBZ = 'O' and M &lt; N, U contains the M-by-M
+        ///          orthogonal matrix U;
+        ///          if JOBZ = 'S', U contains the first min(M,N) columns of U
+        ///          (the left singular vectors, stored columnwise);
+        ///          if JOBZ = 'O' and M &gt;= N, or JOBZ = 'N', U is not referenced.</param>
+        /// <param name="ldu">The leading dimension of the array U.  LDU &gt;= 1; if  
+        /// JOBZ = 'S' or 'A' or JOBZ = 'O' and M &lt; N, LDU &gt;= M</param>
+        /// <param name="vt">array, dimension (LDVT,N). If JOBZ = 'A' or JOBZ = 'O' and 
+        /// M >= N, VT contains the N-by-N orthogonal matrix V**T; if JOBZ = 'S', 
+        /// VT contains the first min(M,N) rows of V**T 
+        /// (the right singular vectors, stored rowwise); if JOBZ = 'O' and M &lt; N, 
+        /// or JOBZ = 'N', VT is not referenced</param>
+        /// <param name="ldvt">The leading dimension of the array VT.  LDVT &gt; = 1; 
+        /// if JOBZ = 'A' or JOBZ = 'O' and M &gt; = N, LDVT &gt;= N; 
+        /// if JOBZ = 'S', LDVT &gt; min(M,N).</param>
+        /// <param name="info">
+        /// <list>
+        ///     <item> 0:  successful exit.</item>
+        ///     <item> lower 0:  if INFO = -i, the i-th argument had an illegal value.</item>
+        ///     <item> greater 0:  DBDSDC did not converge, updating process failed.</item>
+        /// </list>
+        /// </param>
+        /// <remarks>(From the lapack manual):DGESDD computes the singular value decomposition (SVD) of a real
+        ///M-by-N matrix A, optionally computing the left and right singular
+        ///vectors.  If singular vectors are desired, it uses a
+        ///divide-and-conquer algorithm.
+        ///The SVD is written
+        ///    <br>A = U * SIGMA * transpose(V)</br> 
+        ///where SIGMA is an M-by-N matrix which is zero except for its
+        ///min(m,n) diagonal elements, U is an M-by-M orthogonal matrix, and
+        ///V is an N-by-N orthogonal matrix.  The diagonal elements of SIGMA
+        ///are the singular values of A; they are real and non-negative, and
+        ///are returned in descending order.  The first min(m,n) columns of
+        ///U and V are the left and right singular vectors of A.
+        ///Note that the routine returns VT = V**T, not V.
+        ///The divide and conquer algorithm makes very mild assumptions about
+        ///floating point arithmetic. It will work on machines with a guard
+        ///digit in add/subtract, or on those binary machines without guard
+        ///digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or
+        ///Cray-2. It could conceivably fail on hexadecimal or decimal machines
+        ///without guard digits, but we know of none.</remarks>
+        void  dgesvd (char jobz, int m, int n,  double [] a, int lda,
+             double [] s,  double [] u, int ldu, 
+             double [] vt, int ldvt, ref int info);
+
+        /// <summary>
+        /// singular value decomposition, older version, less memory needed 
+        /// </summary>
+        /// <param name="jobz">Specifies options for computing all or part of the matrix U
+        /// <list type="bullet"><item>= 'A':  all M columns of U and all N rows of V**T are
+        ///returned in the arrays U and VT</item>
+        ///     <item> = 'S':  the first min(M,N) columns of U and the first
+        ///              min(M,N) rows of V**T are returned in the arrays U
+        ///              and VT</item>
+        ///     <item> = 'O':  If M >= N, the first N columns of U are overwritten
+        ///              on the array A and all rows of V**T are returned in
+        ///              the array VT. Otherwise, all columns of U are returned in the
+        ///              array U and the first M rows of V**T are overwritten
+        ///              in the array VT</item>
+        ///     <item> = 'N':  no columns of U or rows of V**T are computed.</item>
+        ///        </list>
+        /// </param>
+        /// <param name="m">The number of rows of the input matrix A.  M greater or equal to 0.</param>
+        /// <param name="n">The number of columns of the input matrix A.  N greater or equal to 0</param>
+        /// <param name="a">On entry, the M-by-N matrix A.
+        ///          On exit, <list><item>
+        ///          if JOBZ = 'O',  A is overwritten with the first N columns
+        ///                          of U (the left singular vectors, stored
+        ///                          columnwise) if M >= N;
+        ///                          A is overwritten with the first M rows
+        ///                          of V**T (the right singular vectors, stored
+        ///                          rowwise) otherwise.</item>
+        ///          <item>if JOBZ .ne. 'O', the contents of A are destroyed.</item></list></param>
+        /// <param name="lda">The leading dimension of the array A.  LDA ge max(1,M).</param>
+        /// <param name="s">array, dimension (min(M,N)). The singular values of A, sorted so that S(i) ge S(i+1)</param>
+        /// <param name="u">array, dimension (LDU,UCOL)
+        ///          UCOL = M if JOBZ = 'A' or JOBZ = 'O' and M &lt; N;
+        ///          UCOL = min(M,N) if JOBZ = 'S'.
+        ///          If JOBZ = 'A' or JOBZ = 'O' and M &lt; N, U contains the M-by-M
+        ///          orthogonal matrix U;
+        ///          if JOBZ = 'S', U contains the first min(M,N) columns of U
+        ///          (the left singular vectors, stored columnwise);
+        ///          if JOBZ = 'O' and M &gt;= N, or JOBZ = 'N', U is not referenced.</param>
+        /// <param name="ldu">The leading dimension of the array U.  LDU &gt;= 1; if  
+        /// JOBZ = 'S' or 'A' or JOBZ = 'O' and M &lt; N, LDU &gt;= M</param>
+        /// <param name="vt">array, dimension (LDVT,N). If JOBZ = 'A' or JOBZ = 'O' and 
+        /// M >= N, VT contains the N-by-N orthogonal matrix V**T; if JOBZ = 'S', 
+        /// VT contains the first min(M,N) rows of V**T 
+        /// (the right singular vectors, stored rowwise); if JOBZ = 'O' and M &lt; N, 
+        /// or JOBZ = 'N', VT is not referenced</param>
+        /// <param name="ldvt">The leading dimension of the array VT.  LDVT &gt; = 1; 
+        /// if JOBZ = 'A' or JOBZ = 'O' and M &gt; = N, LDVT &gt;= N; 
+        /// if JOBZ = 'S', LDVT &gt; min(M,N).</param>
+        /// <param name="info">
+        /// <list>
+        ///     <item> 0:  successful exit.</item>
+        ///     <item> lower 0:  if INFO = -i, the i-th argument had an illegal value.</item>
+        ///     <item> greater 0:  DBDSDC did not converge, updating process failed.</item>
+        /// </list>
+        /// </param>
+        /// <remarks>(From the lapack manual):DGESDD computes the singular value decomposition (SVD) of a real
+        ///M-by-N matrix A, optionally computing the left and right singular
+        ///vectors.  If singular vectors are desired, it uses a
+        ///divide-and-conquer algorithm.
+        ///The SVD is written
+        ///    <br>A = U * SIGMA * transpose(V)</br> 
+        ///where SIGMA is an M-by-N matrix which is zero except for its
+        ///min(m,n) diagonal elements, U is an M-by-M orthogonal matrix, and
+        ///V is an N-by-N orthogonal matrix.  The diagonal elements of SIGMA
+        ///are the singular values of A; they are real and non-negative, and
+        ///are returned in descending order.  The first min(m,n) columns of
+        ///U and V are the left and right singular vectors of A.
+        ///Note that the routine returns VT = V**T, not V.
+        ///The divide and conquer algorithm makes very mild assumptions about
+        ///floating point arithmetic. It will work on machines with a guard
+        ///digit in add/subtract, or on those binary machines without guard
+        ///digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or
+        ///Cray-2. It could conceivably fail on hexadecimal or decimal machines
+        ///without guard digits, but we know of none.</remarks>
+        void  sgesvd (char jobz, int m, int n,  float [] a, int lda,
+            float [] s,  float [] u, int ldu, 
+            float [] vt, int ldvt, ref int info);
+
+       
+        /// <summary>
+        /// singular value decomposition, older version, less memory needed 
+        /// </summary>
+        /// <param name="jobz">Specifies options for computing all or part of the matrix U
+        /// <list type="bullet"><item>= 'A':  all M columns of U and all N rows of V**T are
+        ///returned in the arrays U and VT</item>
+        ///     <item> = 'S':  the first min(M,N) columns of U and the first
+        ///              min(M,N) rows of V**T are returned in the arrays U
+        ///              and VT</item>
+        ///     <item> = 'O':  If M >= N, the first N columns of U are overwritten
+        ///              on the array A and all rows of V**T are returned in
+        ///              the array VT. Otherwise, all columns of U are returned in the
+        ///              array U and the first M rows of V**T are overwritten
+        ///              in the array VT</item>
+        ///     <item> = 'N':  no columns of U or rows of V**T are computed.</item>
+        ///        </list>
+        /// </param>
+        /// <param name="m">The number of rows of the input matrix A.  M greater or equal to 0.</param>
+        /// <param name="n">The number of columns of the input matrix A.  N greater or equal to 0</param>
+        /// <param name="a">On entry, the M-by-N matrix A.
+        ///          On exit, <list><item>
+        ///          if JOBZ = 'O',  A is overwritten with the first N columns
+        ///                          of U (the left singular vectors, stored
+        ///                          columnwise) if M >= N;
+        ///                          A is overwritten with the first M rows
+        ///                          of V**T (the right singular vectors, stored
+        ///                          rowwise) otherwise.</item>
+        ///          <item>if JOBZ .ne. 'O', the contents of A are destroyed.</item></list></param>
+        /// <param name="lda">The leading dimension of the array A.  LDA ge max(1,M).</param>
+        /// <param name="s">array, dimension (min(M,N)). The singular values of A, sorted so that S(i) ge S(i+1)</param>
+        /// <param name="u">array, dimension (LDU,UCOL)
+        ///          UCOL = M if JOBZ = 'A' or JOBZ = 'O' and M &lt; N;
+        ///          UCOL = min(M,N) if JOBZ = 'S'.
+        ///          If JOBZ = 'A' or JOBZ = 'O' and M &lt; N, U contains the M-by-M
+        ///          orthogonal matrix U;
+        ///          if JOBZ = 'S', U contains the first min(M,N) columns of U
+        ///          (the left singular vectors, stored columnwise);
+        ///          if JOBZ = 'O' and M &gt;= N, or JOBZ = 'N', U is not referenced.</param>
+        /// <param name="ldu">The leading dimension of the array U.  LDU &gt;= 1; if  
+        /// JOBZ = 'S' or 'A' or JOBZ = 'O' and M &lt; N, LDU &gt;= M</param>
+        /// <param name="vt">array, dimension (LDVT,N). If JOBZ = 'A' or JOBZ = 'O' and 
+        /// M >= N, VT contains the N-by-N orthogonal matrix V**T; if JOBZ = 'S', 
+        /// VT contains the first min(M,N) rows of V**T 
+        /// (the right singular vectors, stored rowwise); if JOBZ = 'O' and M &lt; N, 
+        /// or JOBZ = 'N', VT is not referenced</param>
+        /// <param name="ldvt">The leading dimension of the array VT.  LDVT &gt; = 1; 
+        /// if JOBZ = 'A' or JOBZ = 'O' and M &gt; = N, LDVT &gt;= N; 
+        /// if JOBZ = 'S', LDVT &gt; min(M,N).</param>
+        /// <param name="info">
+        /// <list>
+        ///     <item> 0:  successful exit.</item>
+        ///     <item> lower 0:  if INFO = -i, the i-th argument had an illegal value.</item>
+        ///     <item> greater 0:  DBDSDC did not converge, updating process failed.</item>
+        /// </list>
+        /// </param>
+        /// <remarks>(From the lapack manual):DGESDD computes the singular value decomposition (SVD) of a real
+        ///M-by-N matrix A, optionally computing the left and right singular
+        ///vectors.  If singular vectors are desired, it uses a
+        ///divide-and-conquer algorithm.
+        ///The SVD is written
+        ///    <br>A = U * SIGMA * transpose(V)</br> 
+        ///where SIGMA is an M-by-N matrix which is zero except for its
+        ///min(m,n) diagonal elements, U is an M-by-M orthogonal matrix, and
+        ///V is an N-by-N orthogonal matrix.  The diagonal elements of SIGMA
+        ///are the singular values of A; they are real and non-negative, and
+        ///are returned in descending order.  The first min(m,n) columns of
+        ///U and V are the left and right singular vectors of A.
+        ///Note that the routine returns VT = V**T, not V.
+        ///The divide and conquer algorithm makes very mild assumptions about
+        ///floating point arithmetic. It will work on machines with a guard
+        ///digit in add/subtract, or on those binary machines without guard
+        ///digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or
+        ///Cray-2. It could conceivably fail on hexadecimal or decimal machines
+        ///without guard digits, but we know of none.</remarks>
+        void  cgesvd (char jobz, int m, int n,  fcomplex [] a, int lda,
+            float [] s,  fcomplex [] u, int ldu, 
+            fcomplex [] vt, int ldvt, ref int info);
+
+       
+        /// <summary>
+        /// singular value decomposition, older version, less memory needed 
+        /// </summary>
+        /// <param name="jobz">Specifies options for computing all or part of the matrix U
+        /// <list type="bullet"><item>= 'A':  all M columns of U and all N rows of V**T are
+        ///returned in the arrays U and VT</item>
+        ///     <item> = 'S':  the first min(M,N) columns of U and the first
+        ///              min(M,N) rows of V**T are returned in the arrays U
+        ///              and VT</item>
+        ///     <item> = 'O':  If M >= N, the first N columns of U are overwritten
+        ///              on the array A and all rows of V**T are returned in
+        ///              the array VT. Otherwise, all columns of U are returned in the
+        ///              array U and the first M rows of V**T are overwritten
+        ///              in the array VT</item>
+        ///     <item> = 'N':  no columns of U or rows of V**T are computed.</item>
+        ///        </list>
+        /// </param>
+        /// <param name="m">The number of rows of the input matrix A.  M greater or equal to 0.</param>
+        /// <param name="n">The number of columns of the input matrix A.  N greater or equal to 0</param>
+        /// <param name="a">On entry, the M-by-N matrix A.
+        ///          On exit, <list><item>
+        ///          if JOBZ = 'O',  A is overwritten with the first N columns
+        ///                          of U (the left singular vectors, stored
+        ///                          columnwise) if M >= N;
+        ///                          A is overwritten with the first M rows
+        ///                          of V**T (the right singular vectors, stored
+        ///                          rowwise) otherwise.</item>
+        ///          <item>if JOBZ .ne. 'O', the contents of A are destroyed.</item></list></param>
+        /// <param name="lda">The leading dimension of the array A.  LDA ge max(1,M).</param>
+        /// <param name="s">array, dimension (min(M,N)). The singular values of A, sorted so that S(i) ge S(i+1)</param>
+        /// <param name="u">array, dimension (LDU,UCOL)
+        ///          UCOL = M if JOBZ = 'A' or JOBZ = 'O' and M &lt; N;
+        ///          UCOL = min(M,N) if JOBZ = 'S'.
+        ///          If JOBZ = 'A' or JOBZ = 'O' and M &lt; N, U contains the M-by-M
+        ///          orthogonal matrix U;
+        ///          if JOBZ = 'S', U contains the first min(M,N) columns of U
+        ///          (the left singular vectors, stored columnwise);
+        ///          if JOBZ = 'O' and M &gt;= N, or JOBZ = 'N', U is not referenced.</param>
+        /// <param name="ldu">The leading dimension of the array U.  LDU &gt;= 1; if  
+        /// JOBZ = 'S' or 'A' or JOBZ = 'O' and M &lt; N, LDU &gt;= M</param>
+        /// <param name="vt">array, dimension (LDVT,N). If JOBZ = 'A' or JOBZ = 'O' and 
+        /// M >= N, VT contains the N-by-N orthogonal matrix V**T; if JOBZ = 'S', 
+        /// VT contains the first min(M,N) rows of V**T 
+        /// (the right singular vectors, stored rowwise); if JOBZ = 'O' and M &lt; N, 
+        /// or JOBZ = 'N', VT is not referenced</param>
+        /// <param name="ldvt">The leading dimension of the array VT.  LDVT &gt; = 1; 
+        /// if JOBZ = 'A' or JOBZ = 'O' and M &gt; = N, LDVT &gt;= N; 
+        /// if JOBZ = 'S', LDVT &gt; min(M,N).</param>
+        /// <param name="info">
+        /// <list>
+        ///     <item> 0:  successful exit.</item>
+        ///     <item> lower 0:  if INFO = -i, the i-th argument had an illegal value.</item>
+        ///     <item> greater 0:  DBDSDC did not converge, updating process failed.</item>
+        /// </list>
+        /// </param>
+        /// <remarks>(From the lapack manual):DGESDD computes the singular value decomposition (SVD) of a real
+        ///M-by-N matrix A, optionally computing the left and right singular
+        ///vectors.  If singular vectors are desired, it uses a
+        ///divide-and-conquer algorithm.
+        ///The SVD is written
+        ///    <br>A = U * SIGMA * transpose(V)</br> 
+        ///where SIGMA is an M-by-N matrix which is zero except for its
+        ///min(m,n) diagonal elements, U is an M-by-M orthogonal matrix, and
+        ///V is an N-by-N orthogonal matrix.  The diagonal elements of SIGMA
+        ///are the singular values of A; they are real and non-negative, and
+        ///are returned in descending order.  The first min(m,n) columns of
+        ///U and V are the left and right singular vectors of A.
+        ///Note that the routine returns VT = V**T, not V.
+        ///The divide and conquer algorithm makes very mild assumptions about
+        ///floating point arithmetic. It will work on machines with a guard
+        ///digit in add/subtract, or on those binary machines without guard
+        ///digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or
+        ///Cray-2. It could conceivably fail on hexadecimal or decimal machines
+        ///without guard digits, but we know of none.</remarks>
+        void  zgesvd (char jobz, int m, int n,  complex [] a, int lda,
+            double [] s,  complex [] u, int ldu, 
+            complex [] vt, int ldvt, ref int info);
+        #endregion 
+        
+        #region ?POTRF - cholesky factorization
+        /// <summary>
+        /// cholesky factorization 
+        /// </summary>
+        void  dpotrf (char uplo, int n,  double [] A, int lda, ref int info);
+        /// <summary>
+        /// cholesky factorization 
+        /// </summary>
+        void  spotrf (char uplo, int n,  float [] A, int lda, ref int info);
+       
+        /// <summary>
+        /// cholesky factorization 
+        /// </summary>
+        void  cpotrf (char uplo, int n,  fcomplex [] A, int lda, ref int info);
+       
+        /// <summary>
+        /// cholesky factorization 
+        /// </summary>
+        void  zpotrf (char uplo, int n,  complex [] A, int lda, ref int info);
+#endregion 
+
+        #region ?POTRI - inverse via cholesky factorization
+        /// <summary>
+        /// matrix inverse via cholesky factorization (?potrf)
+        /// </summary>
+        void  dpotri (char uplo, int n,  double [] A, int lda,ref int info);
+        /// <summary>
+        /// matrix inverse via cholesky factorization (?potrf)
+        /// </summary>
+        void  spotri (char uplo, int n,  float [] A, int lda,ref int info);
+       
+        /// <summary>
+        /// matrix inverse via cholesky factorization (?potrf)
+        /// </summary>
+        void  cpotri (char uplo, int n,  fcomplex [] A, int lda,ref int info);
+       
+        /// <summary>
+        /// matrix inverse via cholesky factorization (?potrf)
+        /// </summary>
+        void  zpotri (char uplo, int n,  complex [] A, int lda,ref int info);
+
+#endregion 
+
+        #region ?POTRS - Solve via cholesky factors
+        /// <summary>
+        /// solve equation system via cholesky factorization (?potrs)
+        /// </summary>
+        void dpotrs (char uplo, int n, int nrhs, double [] A, int lda, double [] B, int ldb, ref int info);
+        /// <summary>
+        /// solve equation system via cholesky factorization (?potrs)
+        /// </summary>
+        void  spotrs (char uplo, int n, int nrhs, float [] A, int lda, float [] B, int ldb, ref int info);
+        /// <summary>
+        /// solve equation system via cholesky factorization (?potrs)
+        /// </summary>
+        void  cpotrs (char uplo, int n, int nrhs, fcomplex [] A, int lda, fcomplex [] B, int ldb, ref int info);
+        /// <summary>
+        /// solve equation system via cholesky factorization (?potrs)
+        /// </summary>
+        void  zpotrs (char uplo, int n, int nrhs, complex [] A, int lda, complex [] B, int ldb, ref int info);
+#endregion
+
+        #region ?getrf - LU factorization
+        /// <summary>
+        /// LU factorization of general matrix
+        /// </summary>
+        void  dgetrf (int M, int N,  double [] A, int LDA, int [] IPIV, ref int info);
+        /// <summary>
+        /// LU factorization of general matrix
+        /// </summary>
+        void  sgetrf (int M, int N,  float [] A, int LDA, int [] IPIV, ref int info);
+       
+        /// <summary>
+        /// LU factorization of general matrix
+        /// </summary>
+        void  cgetrf (int M, int N,  fcomplex [] A, int LDA, int [] IPIV, ref int info);
+       
+        /// <summary>
+        /// LU factorization of general matrix
+        /// </summary>
+        void  zgetrf (int M, int N,  complex [] A, int LDA, int [] IPIV, ref int info);
+        #endregion 
+        
+        #region ?getri - inverse via LU factorization
+        /// <summary>
+        /// inverse of a matrix via LU factorization
+        /// </summary>
+        void  dgetri (int N,  double [] A, int LDA, int [] IPIV, ref int info);
+        /// <summary>
+        /// inverse of a matrix via LU factorization
+        /// </summary>
+        void  sgetri (int N,  float [] A, int LDA, int [] IPIV, ref int info);
+       
+        /// <summary>
+        /// inverse of a matrix via LU factorization
+        /// </summary>
+        void  cgetri (int N,  fcomplex [] A, int LDA, int [] IPIV, ref int info);
+       
+        /// <summary>
+        /// inverse of a matrix via LU factorization
+        /// </summary>
+        void  zgetri (int N,  complex [] A, int LDA, int [] IPIV, ref int info);
+        #endregion 
+
+        #region ORGQR
+        /// <summary>
+        /// QR factor extraction
+        /// </summary>
+        void  dorgqr (int M, int N, int K,  double [] A, int lda,  double [] tau, ref int info);
+        /// <summary>
+        /// QR factor extraction
+        /// </summary>
+        void  sorgqr (int M, int N, int K,  float [] A, int lda,  float [] tau, ref int info);
+        /// <summary>
+        /// QR factor extraction
+        /// </summary>
+        void  cungqr (int M, int N, int K,  fcomplex [] A, int lda,  fcomplex [] tau, ref int info);
+        /// <summary>
+        /// QR factor extraction
+        /// </summary>
+        void  zungqr (int M, int N, int K,  complex [] A, int lda,  complex [] tau, ref int info);
+        #endregion
+
+        #region ?geqrf - QR factorization
+        /// <summary>
+        /// QR factorization
+        /// </summary>
+        void  dgeqrf (int M, int N,  double [] A, int lda,  double [] tau, ref int info);
+        /// <summary>
+        /// QR factorization
+        /// </summary>
+        void  sgeqrf (int M, int N,  float [] A, int lda,  float [] tau, ref int info);
+        /// <summary>
+        /// QR factorization
+        /// </summary>
+        void  cgeqrf (int M, int N,  fcomplex [] A, int lda,  fcomplex [] tau, ref int info);
+        /// <summary>
+        /// QR factorization
+        /// </summary>
+        void  zgeqrf (int M, int N,  complex [] A, int lda,  complex [] tau, ref int info);
+        #endregion 
+
+        #region GEQP3
+        /// <summary>
+        /// QR factorisation with column pivoting
+        /// </summary>
+        void dgeqp3 (int M, int N, double [] A, int LDA, int [] JPVT, double [] tau, ref int info);
+        /// <summary>
+        /// QR factorisation with column pivoting
+        /// </summary>
+        void sgeqp3 (int M, int N, float [] A, int LDA, int [] JPVT, float [] tau, ref int info);
+        /// <summary>
+        /// QR factorisation with column pivoting
+        /// </summary>
+        void cgeqp3 (int M, int N, fcomplex [] A, int LDA, int [] JPVT, fcomplex [] tau, ref int info);
+        /// <summary>
+        /// QR factorisation with column pivoting
+        /// </summary>
+        void zgeqp3 (int M, int N, complex [] A, int LDA, int [] JPVT, complex [] tau, ref int info);
+        #endregion
+
+        #region ?ormqr - mmult of QR factorization result
+        /// <summary>
+        /// multipliation for general matrix with QR decomposition factor
+        /// </summary>
+        void  dormqr (char side, char trans, int m, int n, int k,  double [] A, int lda,  double [] tau,  double [] C, int LDC, ref int info);
+        /// <summary>
+        /// multipliation for general matrix with QR decomposition factor
+        /// </summary>
+        void  sormqr (char side, char trans, int m, int n, int k,  float [] A, int lda,  float [] tau,  float [] C, int LDC, ref int info);
+
+        #endregion 
+        
+        #region DTRTRS 
+        /// <summary>
+        /// Solve triangular system of linear equations (forward-/ backward substitution)
+        /// </summary>
+        /// <param name="uplo">'U': A is upper triangular, 'L': A is lower triangular</param>
+        /// <param name="transA">'N':  A * X = B  (No transpose); 'T':  A**T * X = B  (Transpose), 'T':  A**T * X = B  (Transpose)</param>
+        /// <param name="diag">'N' arbitrary diagonal elements, 'U' unit diagonal</param>
+        /// <param name="N">order of A</param>
+        /// <param name="nrhs">number of right hand sides - columns of matrix B</param>
+        /// <param name="A">square matrix A</param>
+        /// <param name="LDA">spacing between columns for A</param>
+        /// <param name="B">(input/output) on input: right hand side, on output: solution x </param>
+        /// <param name="LDB">spacing between columns for B</param>
+        /// <param name="info">(output) 0: success; &lt; 0: illigal argument, &gt; 0: A is sinular having a zero on the i-th diagonal element. No solution will be computed than. </param>
+        void dtrtrs (char uplo, char transA, char diag, int N, int nrhs, IntPtr A, int LDA, IntPtr B, int LDB, ref int info); 
+        /// <summary>
+        /// Solve triangular system of linear equations (forward-/ backward substitution)
+        /// </summary>
+        /// <param name="uplo">'U': A is upper triangular, 'L': A is lower triangular</param>
+        /// <param name="transA">'N':  A * X = B  (No transpose); 'T':  A**T * X = B  (Transpose), 'T':  A**T * X = B  (Transpose)</param>
+        /// <param name="diag">'N' arbitrary diagonal elements, 'U' unit diagonal</param>
+        /// <param name="N">order of A</param>
+        /// <param name="nrhs">number of right hand sides - columns of matrix B</param>
+        /// <param name="A">square matrix A</param>
+        /// <param name="LDA">spacing between columns for A</param>
+        /// <param name="B">(input/output) on input: right hand side, on output: solution x </param>
+        /// <param name="LDB">spacing between columns for B</param>
+        /// <param name="info">(output) 0: success; &lt; 0: illigal argument, &gt; 0: A is sinular having a zero on the i-th diagonal element. No solution will be computed than. </param>
+        void strtrs (char uplo, char transA, char diag, int N, int nrhs, IntPtr A, int LDA, IntPtr B, int LDB, ref int info); 
+        /// <summary>
+        /// Solve triangular system of linear equations (forward-/ backward substitution)
+        /// </summary>
+        /// <param name="uplo">'U': A is upper triangular, 'L': A is lower triangular</param>
+        /// <param name="transA">'N':  A * X = B  (No transpose); 'T':  A**T * X = B  (Transpose), 'T':  A**T * X = B  (Transpose)</param>
+        /// <param name="diag">'N' arbitrary diagonal elements, 'U' unit diagonal</param>
+        /// <param name="N">order of A</param>
+        /// <param name="nrhs">number of right hand sides - columns of matrix B</param>
+        /// <param name="A">square matrix A</param>
+        /// <param name="LDA">spacing between columns for A</param>
+        /// <param name="B">(input/output) on input: right hand side, on output: solution x </param>
+        /// <param name="LDB">spacing between columns for B</param>
+        /// <param name="info">(output) 0: success; &lt; 0: illigal argument, &gt; 0: A is sinular having a zero on the i-th diagonal element. No solution will be computed than. </param>
+        void ctrtrs (char uplo, char transA, char diag, int N, int nrhs, IntPtr A, int LDA, IntPtr B, int LDB, ref int info); 
+        /// <summary>
+        /// Solve triangular system of linear equations (forward-/ backward substitution)
+        /// </summary>
+        /// <param name="uplo">'U': A is upper triangular, 'L': A is lower triangular</param>
+        /// <param name="transA">'N':  A * X = B  (No transpose); 'T':  A**T * X = B  (Transpose), 'T':  A**T * X = B  (Transpose)</param>
+        /// <param name="diag">'N' arbitrary diagonal elements, 'U' unit diagonal</param>
+        /// <param name="N">order of A</param>
+        /// <param name="nrhs">number of right hand sides - columns of matrix B</param>
+        /// <param name="A">square matrix A</param>
+        /// <param name="LDA">spacing between columns for A</param>
+        /// <param name="B">(input/output) on input: right hand side, on output: solution x </param>
+        /// <param name="LDB">spacing between columns for B</param>
+        /// <param name="info">(output) 0: success; &lt; 0: illigal argument, &gt; 0: A is sinular having a zero on the i-th diagonal element. No solution will be computed than. </param>
+        void ztrtrs (char uplo, char transA, char diag, int N, int nrhs, IntPtr A, int LDA, IntPtr B, int LDB, ref int info); 
+        #endregion
+
+        #region ?GETRS
+        /// <summary>
+        /// solve system of linear equations by triangular matrices
+        /// </summary>
+        /// <param name="trans">transpose before work?</param>
+        /// <param name="N">number rows</param>
+        /// <param name="NRHS">number right hand sides</param>
+        /// <param name="A">matrix A</param>
+        /// <param name="LDA">spacing between columns: A</param>
+        /// <param name="IPIV">pivoting indices</param>
+        /// <param name="B">matrix B</param>
+        /// <param name="LDB">spacing between columns: B</param>
+        /// <param name="info">success info</param>
+        void dgetrs (char trans, int N, int NRHS, double [] A, int LDA, int [] IPIV, double [] B, int LDB, ref int info); 
+        /// <summary>
+        /// solve system of linear equations by triangular matrices
+        /// </summary>
+        /// <param name="trans">transpose before work?</param>
+        /// <param name="N">number rows</param>
+        /// <param name="NRHS">number right hand sides</param>
+        /// <param name="A">matrix A</param>
+        /// <param name="LDA">spacing between columns: A</param>
+        /// <param name="IPIV">pivoting indices</param>
+        /// <param name="B">matrix B</param>
+        /// <param name="LDB">spacing between columns: B</param>
+        /// <param name="info">success info</param>
+        void sgetrs (char trans, int N, int NRHS, float [] A, int LDA, int [] IPIV, float [] B, int LDB, ref int info); 
+        /// <summary>
+        /// solve system of linear equations by triangular matrices
+        /// </summary>
+        /// <param name="trans">transpose before work?</param>
+        /// <param name="N">number rows</param>
+        /// <param name="NRHS">number right hand sides</param>
+        /// <param name="A">matrix A</param>
+        /// <param name="LDA">spacing between columns: A</param>
+        /// <param name="IPIV">pivoting indices</param>
+        /// <param name="B">matrix B</param>
+        /// <param name="LDB">spacing between columns: B</param>
+        /// <param name="info">success info</param>
+        void cgetrs (char trans, int N, int NRHS, fcomplex [] A, int LDA, int [] IPIV, fcomplex [] B, int LDB, ref int info); 
+        /// <summary>
+        /// solve system of linear equations by triangular matrices
+        /// </summary>
+        /// <param name="trans">transpose before work?</param>
+        /// <param name="N">number rows</param>
+        /// <param name="NRHS">number right hand sides</param>
+        /// <param name="A">matrix A</param>
+        /// <param name="LDA">spacing between columns: A</param>
+        /// <param name="IPIV">pivoting indices</param>
+        /// <param name="B">matrix B</param>
+        /// <param name="LDB">spacing between columns: B</param>
+        /// <param name="info">success info</param>
+        void zgetrs (char trans, int N, int NRHS, complex [] A, int LDA, int [] IPIV, complex [] B, int LDB, ref int info); 
+        #endregion 
+
+        #region ?GELSD - least square solution, SVD - divide & conquer
+        void dgelsd (int m, int n, int nrhs, double[] A, int lda, double[] B, int ldb, double[] S, double RCond, ref int rank, ref int info); 
+        void sgelsd (int m, int n, int nrhs, float[] A, int lda, float[] B, int ldb, float[] S, float RCond, ref int rank, ref int info); 
+        void cgelsd (int m, int n, int nrhs, fcomplex[] A, int lda, fcomplex[] B, int ldb, float[] S, float RCond, ref int rank, ref int info); 
+        void zgelsd (int m, int n, int nrhs, complex[] A, int lda, complex[] B, int ldb, double[] S, double RCond, ref int rank, ref int info); 
+        #endregion 
+
+        #region ?GELSY - least square solution, QRP
+        void dgelsy (int m,int n,int nrhs, double[] A,int lda, double[] B,int ldb, int[] JPVT0, double RCond, ref int rank, ref int info); 
+        void sgelsy (int m,int n,int nrhs, float[] A,int lda, float[] B,int ldb, int[] JPVT0, float RCond, ref int rank, ref int info); 
+        void cgelsy (int m,int n,int nrhs, fcomplex[] A,int lda, fcomplex[] B,int ldb, int[] JPVT0, float RCond, ref int rank, ref int info); 
+        void zgelsy (int m,int n,int nrhs, complex[] A,int lda, complex[] B,int ldb, int[] JPVT0, double RCond, ref int rank, ref int info); 
+        #endregion 
+
+        #region ?GEEVX - eigenvectors & -values, nonsymmetric A 
+        void dgeevx (char balance, char jobvl, char jobvr, char sense, int n, double[] A, int lda, double[] wr, double[] wi, double[] vl, int ldvl, double[] vr, int ldvr, ref int ilo, ref int ihi, double[] scale, ref double abnrm, double[] rconde, double[] rcondv, ref int info); 
+        void sgeevx (char balance, char jobvl, char jobvr, char sense, int n, float[] A, int lda, float[] wr, float[] wi, float[] vl, int ldvl, float[] vr, int ldvr, ref int ilo, ref int ihi, float[] scale, ref float abnrm, float[] rconde, float[] rcondv, ref int info); 
+        void cgeevx (char balance, char jobvl, char jobvr, char sense, int n, fcomplex[] A, int lda, fcomplex[] w, fcomplex[] vl, int ldvl, fcomplex[] vr, int ldvr, ref int ilo, ref int ihi, float[] scale, ref float abnrm, float[] rconde, float[] rcondv, ref int info);
+        void zgeevx (char balance, char jobvl, char jobvr, char sense, int n, complex[] A, int lda, complex[] w, complex[] vl, int ldvl, complex[] vr, int ldvr, ref int ilo, ref int ihi, double[] scale, ref double abnrm, double[] rconde, double[] rcondv, ref int info);
+        #endregion 
+
+        #region ?GEEVR - eigenvectors & -values, symmetric/hermitian A 
+        void dsyevr (char jobz, char range, char uplo, int n, double  [] A, int lda, double vl, double vu, int il, int iu, double abstol, ref int m, double[] w, double  [] z, int ldz, int[] isuppz, ref int info); 
+        void ssyevr (char jobz, char range, char uplo, int n, float   [] A, int lda, float  vl, float  vu, int il, int iu, float  abstol, ref int m, float [] w, float   [] z, int ldz, int[] isuppz, ref int info); 
+        void cheevr (char jobz, char range, char uplo, int n, fcomplex[] A, int lda, float  vl, float  vu, int il, int iu, float  abstol, ref int m, float [] w, fcomplex[] z, int ldz, int[] isuppz, ref int info); 
+        void zheevr (char jobz, char range, char uplo, int n, complex [] A, int lda, double vl, double vu, int il, int iu, double abstol, ref int m, double[] w, complex [] z, int ldz, int[] isuppz, ref int info); 
+        #endregion 
+        
+        #region ?SYGV - eigenvectors & -values, symmetric/hermitian A and B, pos.def.B 
+        void dsygv (int itype, char jobz, char uplo, int n, double  [] A, int lda, double  [] B, int ldb, double [] w, ref int info); 
+        void ssygv (int itype, char jobz, char uplo, int n, float   [] A, int lda, float   [] B, int ldb, float  [] w, ref int info); 
+        void chegv (int itype, char jobz, char uplo, int n, fcomplex[] A, int lda, fcomplex[] B, int ldb, float  [] w, ref int info); 
+        void zhegv (int itype, char jobz, char uplo, int n, complex [] A, int lda, complex [] B, int ldb, double [] w, ref int info); 
+        #endregion 
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Native/lapack/ILACML4_1.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Native/lapack/ILACML4_1.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Native/lapack/ILACML4_1.cs	(revision 9102)
@@ -0,0 +1,501 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+#pragma warning disable 1591
+
+using System;
+using System.Runtime.InteropServices;
+using ILNumerics.Storage;
+using ILNumerics.Misc;
+using ILNumerics;
+using System.Security;
+
+namespace ILNumerics.Native {
+    
+	/// <summary>
+	/// LAPACK implementation for AMD processors
+	/// </summary>
+    /// <remarks>By using this module, you will have to make sure,
+    /// you placed all runtime binaries for AMD's performance library 
+    /// into the binary output dir accessable for ILNumerics assemblies. 
+    /// Those modules must be donwloaded seperately, since it is not 
+    /// permitted to distribute them among with LGPL code. However, 
+    /// developing and redistributing of products with ACML is possible though. 
+    /// AMD currently does not charge money for a redistributable 
+    /// license, given that one signs a license agreement with AMD 
+    /// individually.</remarks>
+    public class ILACML4_1 : IILLapack {
+
+        #region constructor 
+        public ILACML4_1 () {}
+        #endregion
+
+        #region DLL IMPORTS
+        ////////////////////////////////////  DOUBLE LAPACK //////////////////
+        [DllImport("libacml_dll", EntryPoint = "dgemm"),SuppressUnmanagedCodeSecurity]
+		private static extern void acml_dgemm(char TransA, char TransB, int M, int N, int K, double alpha, IntPtr A, int lda, IntPtr B, int ldb, double beta, double[] C, int ldc);
+        [DllImport("libacml_dll", EntryPoint = "sgemm"),SuppressUnmanagedCodeSecurity]
+		private static extern void acml_sgemm(char TransA, char TransB, int M,  int N, int K, float alpha, IntPtr A, int lda, IntPtr B, int ldb, float beta, float[] C, int ldc);
+        [DllImport("lapack_gen", EntryPoint = "cgemm"),SuppressUnmanagedCodeSecurity]
+		private static extern void acml_cgemm(ref char TransA, ref char TransB, ref int M, ref int N, ref int K, ref fcomplex alpha, IntPtr A, ref int lda, IntPtr B, ref int ldb, ref fcomplex beta, [In, Out] fcomplex[] C, ref int ldc);
+        [DllImport("lapack_gen", EntryPoint = "zgemm"),SuppressUnmanagedCodeSecurity]
+		private static extern void acml_zgemm(ref char TransA, ref char TransB, ref int M, ref int N, ref int K, ref complex alpha, IntPtr A, ref int lda, IntPtr B, ref int ldb, ref complex beta, [In, Out] complex[] C, ref int ldc);
+
+        [DllImport("libacml_dll", EntryPoint = "dgesdd",CallingConvention = CallingConvention.StdCall)]
+		private static extern void acml_dgesdd(char jobz, int m, int n, double[] a, int lda, double[] s, double[] u, int ldu, double[] vt, int ldvt, ref int info);
+        [DllImport("libacml_dll", EntryPoint = "sgesdd"),SuppressUnmanagedCodeSecurity]
+		private static extern void acml_sgesdd(char jobz, int m, int n, float[] a, int lda, float[] s,  float[] u, int ldu, float[] vt, int ldvt, ref int info);
+        [DllImport("libacml_dll", EntryPoint = "cgesdd"),SuppressUnmanagedCodeSecurity]
+		private static extern void acml_cgesdd(char jobz, int m, int n, [In,Out] fcomplex[] a, int lda, float[] s, [In,Out] fcomplex[] u, int ldu, [In,Out] fcomplex[] vt, int ldvt, ref int info);
+        [DllImport("libacml_dll", EntryPoint = "zgesdd"),SuppressUnmanagedCodeSecurity]
+		private static extern void acml_zgesdd(char jobz, int m, int n, [In,Out] complex[] a, int lda, double[] s, [In,Out] complex[] u, int ldu, [In,Out] complex[] vt, int ldvt, ref int info);
+
+        [DllImport("libacml_dll", EntryPoint = "dgesvd"),SuppressUnmanagedCodeSecurity]
+		private static extern void acml_dgesvd(char jobu, char jobvt, int m, int n,  double[] a, int lda, double[] s, double[] u, int ldu, double[] vt, int ldvt, ref int info);
+        [DllImport("libacml_dll", EntryPoint = "sgesvd"),SuppressUnmanagedCodeSecurity]
+		private static extern void acml_sgesvd(char jobu, char jobvt, int m, int n, float[] a, int lda, float[] s, float[] u, int ldu, float[] vt, int ldvt, ref int info);
+        [DllImport("libacml_dll", EntryPoint = "cgesvd"),SuppressUnmanagedCodeSecurity]
+		private static extern void acml_cgesvd(char jobu, char jobvt, int m, int n, [In,Out] fcomplex[] a, int lda, float[] s, [In,Out] fcomplex[] u, int ldu, [In,Out] fcomplex[] vt,  int ldvt, ref int info);
+        [DllImport("libacml_dll", EntryPoint = "zgesvd"),SuppressUnmanagedCodeSecurity]
+		private static extern void acml_zgesvd(char jobu, char jobvt, int m, int n, [In,Out] complex[] a, int lda, double[] s, [In,Out] complex[] u, int ldu, [In,Out] complex[] vt, int ldvt,  ref int info);
+            
+        [DllImport("libacml_dll", EntryPoint = "dpotrf"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_dpotrf (char uplo, int n, double [] A, int lda, ref int info);
+        [DllImport("libacml_dll", EntryPoint = "spotrf"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_spotrf (char uplo, int n, float [] A, int lda, ref int info);
+        [DllImport("libacml_dll", EntryPoint = "cpotrf"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_cpotrf (char uplo, int n, [In,Out] fcomplex [] A, int lda, ref int info);
+        [DllImport("libacml_dll", EntryPoint = "zpotrf"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_zpotrf (char uplo, int n, [In,Out] complex [] A, int lda, ref int info);
+        
+        [DllImport("libacml_dll", EntryPoint = "dpotri"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_dpotri (char uplo, int n, double [] A, int lda,ref int info);
+        [DllImport("libacml_dll", EntryPoint = "spotri"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_spotri (char uplo, int n, float [] A, int lda,ref int info);
+        [DllImport("libacml_dll", EntryPoint = "cpotri"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_cpotri (char uplo, int n, [In,Out] fcomplex [] A, int lda,ref int info);
+        [DllImport("libacml_dll", EntryPoint = "zpotri"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_zpotri (char uplo, int n, [In,Out] complex [] A, int lda,ref int info);
+
+        [DllImport("libacml_dll", EntryPoint = "dpotrs"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_dpotrs (char uplo, int n, int nrhs, double[] A, int lda, double[] B, int ldb, ref int info);
+        [DllImport("libacml_dll", EntryPoint = "spotrs"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_spotrs (char uplo, int n, int nrhs, float[] A, int lda, float[] B, int ldb, ref int info);
+        [DllImport("libacml_dll", EntryPoint = "cpotrs"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_cpotrs (char uplo, int n, int nrhs, [In,Out] fcomplex[] A, int lda, [In,Out] fcomplex[] B, int ldb, ref int info);
+        [DllImport("libacml_dll", EntryPoint = "zpotrs"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_zpotrs (char uplo, int n, int nrhs, [In,Out] complex[] A, int lda, [In,Out] complex[] B, int ldb, ref int info);
+
+        [DllImport("libacml_dll", EntryPoint = "dgetrf"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_dgetrf (int M, int N, double [] A, int LDA, int [] IPIV, ref int info);
+        [DllImport("libacml_dll", EntryPoint = "sgetrf"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_sgetrf (int M, int N, float [] A, int LDA, int [] IPIV, ref int info);
+        [DllImport("libacml_dll", EntryPoint = "cgetrf"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_cgetrf (int M, int N, [In,Out] fcomplex [] A, int LDA, int [] IPIV, ref int info);
+        [DllImport("libacml_dll", EntryPoint = "zgetrf"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_zgetrf (int M, int N, [In,Out] complex [] A, int LDA, int [] IPIV, ref int info);
+
+        [DllImport("libacml_dll", EntryPoint = "dgetri"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_dgetri (int N, double [] A, int LDA, int [] IPIV, ref int info);
+        [DllImport("libacml_dll", EntryPoint = "sgetri"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_sgetri (int N, float [] A, int LDA, int [] IPIV, ref int info);
+        [DllImport("libacml_dll", EntryPoint = "cgetri"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_cgetri (int N, [In,Out] fcomplex [] A, int LDA, int [] IPIV, ref int info);
+        [DllImport("libacml_dll", EntryPoint = "zgetri"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_zgetri (int N, [In,Out] complex [] A, int LDA, int [] IPIV, ref int info);
+
+        [DllImport("libacml_dll", EntryPoint = "dgeqp3"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_dgeqp3 (int M, int N, double [] A, int lda, int [] JPVT, double [] tau, ref int info);
+        [DllImport("libacml_dll", EntryPoint = "sgeqp3"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_sgeqp3 (int M, int N, float [] A, int lda, int [] JPVT, float [] tau, ref int info);
+        [DllImport("libacml_dll", EntryPoint = "cgeqp3"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_cgeqp3 (int M, int N, [In,Out] fcomplex [] A, int lda, int [] JPVT, [In,Out] fcomplex [] tau, ref int info);
+        [DllImport("libacml_dll", EntryPoint = "zgeqp3"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_zgeqp3 (int M, int N, [In,Out] complex [] A, int lda, int [] JPVT, [In,Out] complex [] tau, ref int info);
+        
+        [DllImport("libacml_dll", EntryPoint = "dgeqrf"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_dgeqrf (int M, int N, double [] A, int lda, double [] tau, ref int info);
+        [DllImport("libacml_dll", EntryPoint = "sgeqrf"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_sgeqrf (int M, int N, float [] A, int lda, float [] tau, ref int info);
+        [DllImport("libacml_dll", EntryPoint = "cgeqrf"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_cgeqrf (int M, int N, [In,Out] fcomplex [] A, int lda, [In,Out] fcomplex[] tau, ref int info);
+        [DllImport("libacml_dll", EntryPoint = "zgeqrf"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_zgeqrf (int M, int N, [In,Out] complex [] A, int lda, [In,Out] complex[] tau, ref int info);
+
+        [DllImport("libacml_dll", EntryPoint = "dormqr"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_dormqr (char side, char trans, int m, int n, int k, double [] A, int lda, double [] tau , double [] C, int ldc, ref int info);
+        [DllImport("libacml_dll", EntryPoint = "sormqr"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_sormqr (char side, char trans, int m, int n, int k, float [] A, int lda, float [] tau ,  float [] C, int ldc, ref int info);
+        
+        [DllImport("libacml_dll", EntryPoint = "dorgqr"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_dorgqr (int M, int N, int K, double [] A, int lda, double [] tau, ref int info);
+        [DllImport("libacml_dll", EntryPoint = "sorgqr"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_sorgqr (int M, int N, int K, float [] A, int lda, float [] tau, ref int info);
+        [DllImport("libacml_dll", EntryPoint = "cungqr"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_cungqr (int M, int N, int K, [In,Out] fcomplex [] A, int lda, [In,Out] fcomplex [] tau, ref int info);
+        [DllImport("libacml_dll", EntryPoint = "zungqr"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_zungqr (int M, int N, int K, [In,Out] complex  [] A, int lda, [In,Out] complex [] tau, ref int info);
+        
+        [DllImport("libacml_dll", EntryPoint = "dtrtrs"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_dtrtrs (char uplo, char transA, char diag, int N, int nrhs, IntPtr A, int LDA, IntPtr B, int LDB, ref int info);
+        [DllImport("libacml_dll", EntryPoint = "strtrs"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_strtrs (char uplo, char transA, char diag, int N, int nrhs, IntPtr A, int LDA, IntPtr B, int LDB, ref int info);
+        [DllImport("libacml_dll", EntryPoint = "ctrtrs"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_ctrtrs (char uplo, char transA, char diag, int N, int nrhs, IntPtr A, int LDA, IntPtr B, int LDB, ref int info);
+        [DllImport("libacml_dll", EntryPoint = "ztrtrs"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_ztrtrs (char uplo, char transA, char diag, int N, int nrhs, IntPtr A, int LDA, IntPtr B, int LDB, ref int info);
+        
+        [DllImport("libacml_dll", EntryPoint = "dgetrs"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_dgetrs (char trans, int N, int NRHS, double [] A, int LDA, int [] IPIV, double [] B, int LDB, ref int info); 
+        [DllImport("libacml_dll", EntryPoint = "sgetrs"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_sgetrs (char trans, int N, int NRHS, float [] A, int LDA, int [] IPIV, float [] B, int LDB, ref int info); 
+        [DllImport("libacml_dll", EntryPoint = "cgetrs"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_cgetrs (char trans, int N, int NRHS, [In,Out] fcomplex [] A, int LDA, int [] IPIV, [In,Out] fcomplex [] B, int LDB, ref int info); 
+        [DllImport("libacml_dll", EntryPoint = "zgetrs"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_zgetrs (char trans, int N, int NRHS, [In,Out] complex [] A, int LDA, int [] IPIV, [In,Out] complex [] B, int LDB, ref int info); 
+        
+        [DllImport("libacml_dll", EntryPoint = "dgelsd"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_dgelsd (int m, int n, int nrhs, double[] A, int lda, double[] B, int ldb, double[] S, double RCond, ref int rank, ref int info); 
+        [DllImport("libacml_dll", EntryPoint = "sgelsd"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_sgelsd (int m, int n, int nrhs, float[] A, int lda, float[] B, int ldb, float[] S, float RCond, ref int rank, ref int info); 
+        [DllImport("libacml_dll", EntryPoint = "cgelsd"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_cgelsd (int m, int n, int nrhs, [In,Out] fcomplex[] A, int lda, [In,Out] fcomplex[] B, int ldb, float[] S, float RCond, ref int rank, ref int info); 
+        [DllImport("libacml_dll", EntryPoint = "zgelsd"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_zgelsd (int m, int n, int nrhs, [In,Out] complex[] A, int lda,[In,Out] complex[] B, int ldb, double[] S, double RCond, ref int rank, ref int info);  
+        
+        [DllImport("libacml_dll", EntryPoint = "dgelsy"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_dgelsy (int m, int n, int nrhs, double[] A, int lda, double[] B, int ldb, int[] IPOV0, double RCond, ref int rank, ref int info); 
+        [DllImport("libacml_dll", EntryPoint = "sgelsy"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_sgelsy (int m, int n, int nrhs, float[] A, int lda, float[] B, int ldb, int[] IPOV0, float RCond, ref int rank, ref int info); 
+        [DllImport("libacml_dll", EntryPoint = "cgelsy"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_cgelsy (int m, int n, int nrhs, [In,Out] fcomplex[] A, int lda, [In,Out] fcomplex[] B, int ldb, int[] IPOV0, float RCond, ref int rank, ref int info); 
+        [DllImport("libacml_dll", EntryPoint = "zgelsy"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_zgelsy (int m, int n, int nrhs, [In,Out] complex[] A, int lda,[In,Out] complex[] B, int ldb, int[] IPOV0, double RCond, ref int rank, ref int info);  
+        
+        [DllImport("libacml_dll", EntryPoint = "dgeevx"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_dgeevx (char balance, char jobvl, char jobvr, char sense, int n, double[] A, int lda, double[] wr, double[] wi, double[] vl, int ldvl, double[] vr, int ldvr, ref int ilo, ref int ihi, double[] scale, ref double abnrm, double[] rconde, double[] rcondv, ref int info); 
+        [DllImport("libacml_dll", EntryPoint = "sgeevx"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_sgeevx (char balance, char jobvl, char jobvr, char sense, int n, float[] A, int lda, float[] wr, float[] wi, float[] vl, int ldvl, float[] vr, int ldvr, ref int ilo, ref int ihi, float[] scale, ref float abnrm, float[] rconde, float[] rcondv, ref int info); 
+        [DllImport("libacml_dll", EntryPoint = "cgeevx"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_cgeevx (char balance, char jobvl, char jobvr, char sense, int n,[In,Out] fcomplex[] A, int lda, [In,Out] fcomplex[] w, [In,Out] fcomplex[] vl, int ldvl, [In,Out] fcomplex[] vr, int ldvr, ref int ilo, ref int ihi, float[] scale, ref float abnrm, float[] rconde, float[] rcondv, ref int info);
+        [DllImport("libacml_dll", EntryPoint = "zgeevx"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_zgeevx (char balance, char jobvl, char jobvr, char sense, int n, [In,Out] complex[] A, int lda, [In,Out] complex[] w, [In,Out] complex[] vl, int ldvl, [In,Out] complex[] vr, int ldvr, ref int ilo, ref int ihi, double[] scale, ref double abnrm, double[] rconde, double[] rcondv, ref int info);
+
+        [DllImport("libacml_dll", EntryPoint = "dsyevr"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_dsyevr (char jobz, char range, char uplo, int n, double  [] A, int lda, double vl, double vu, int il, int iu, double abstol, ref int m, double[] w, double  [] z, int ldz, int[] isuppz, ref int info); 
+        [DllImport("libacml_dll", EntryPoint = "ssyevr"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_ssyevr (char jobz, char range, char uplo, int n, float   [] A, int lda, float  vl, float  vu, int il, int iu, float  abstol, ref int m, float [] w, float   [] z, int ldz, int[] isuppz, ref int info); 
+        [DllImport("libacml_dll", EntryPoint = "cheevr"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_cheevr (char jobz, char range, char uplo, int n, [In,Out] fcomplex[] A, int lda, float  vl, float  vu, int il, int iu, float  abstol, ref int m, float [] w, [In,Out] fcomplex[] z, int ldz, int[] isuppz, ref int info); 
+        [DllImport("libacml_dll", EntryPoint = "zheevr"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_zheevr (char jobz, char range, char uplo, int n, [In,Out] complex [] A, int lda, double vl, double vu, int il, int iu, double abstol, ref int m, double[] w, [In,Out] complex [] z, int ldz, int[] isuppz, ref int info); 
+
+        [DllImport("libacml_dll", EntryPoint = "dsygv"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_dsygv (int itype, char jobz, char uplo, int n, double  [] A, int lda, double  [] B, int ldb, double [] w, ref int info); 
+        [DllImport("libacml_dll", EntryPoint = "ssygv"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_ssygv (int itype, char jobz, char uplo, int n, float   [] A, int lda, float  [] B, int ldb, float [] w, ref int info); 
+        [DllImport("libacml_dll", EntryPoint = "chegv"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_chegv (int itype, char jobz, char uplo, int n, [In,Out] fcomplex[] A, int lda, [In,Out] fcomplex [] B, int ldb, float  [] w, ref int info); 
+        [DllImport("libacml_dll", EntryPoint = "zhegv"),SuppressUnmanagedCodeSecurity]
+        private static extern void acml_zhegv (int itype, char jobz, char uplo, int n, [In,Out] complex [] A, int lda, [In,Out] complex  [] B, int ldb, double [] w, ref int info); 
+
+
+#endregion DLL_IMPORTS 
+
+        #region IILLapack_INTERFACE
+        public void dgemm(char TransA, char TransB, int M, int N, int K, double alpha, IntPtr A, int lda, IntPtr B, int ldb, double beta, double[] C, int ldc) {
+            acml_dgemm(TransA, TransB, M, N, K, alpha, A, lda, B, ldb, beta, C, ldc);
+        }
+        public void sgemm(char TransA, char TransB, int M, int N, int K, float alpha, IntPtr A, int lda, IntPtr B, int ldb, float beta, float[] C, int ldc) {
+            acml_sgemm(TransA, TransB, M, N, K, alpha, A, lda, B, ldb, beta, C, ldc);
+        }
+        public void zgemm(char TransA, char TransB, int M, int N, int K, complex alpha, IntPtr A, int lda, IntPtr B, int ldb, complex beta, complex[] C, int ldc) {
+            acml_zgemm(ref TransA, ref TransB, ref M, ref N, ref K, ref alpha, A, ref lda, B, ref ldb, ref beta, C, ref ldc);
+        }
+        public void cgemm(char TransA, char TransB, int M, int N, int K, fcomplex alpha, IntPtr A, int lda, IntPtr B, int ldb, fcomplex beta, fcomplex [] C, int ldc) {
+            acml_cgemm(ref TransA, ref TransB, ref M, ref N, ref K, ref alpha, A, ref lda, B, ref ldb, ref beta, C, ref ldc);
+        }
+
+
+        public void dgesdd(char jobz, int m, int n, double[] a, int lda, double[] s, double[] u, int ldu, double[] vt, int ldvt, ref int info) {
+            acml_dgesdd(jobz, m, n, a, lda, s, u, ldu, vt, ldvt, ref info);
+        }
+        public void sgesdd(char jobz, int m, int n, float[] a, int lda, float[] s, float[] u, int ldu, float[] vt, int ldvt, ref int info) {
+            acml_sgesdd(jobz, m, n, a, lda, s, u, ldu, vt, ldvt, ref info);
+        }
+        public void zgesdd(char jobz, int m, int n, complex[] a, int lda, double[] s, complex[] u, int ldu, complex[] vt, int ldvt, ref int info) {
+            acml_zgesdd(jobz, m, n, a, lda, s, u, ldu, vt, ldvt, ref info);
+        }
+        public void cgesdd(char jobz, int m, int n, fcomplex[] a, int lda, float[] s, fcomplex[] u, int ldu, fcomplex[] vt, int ldvt, ref int info) {
+            acml_cgesdd(jobz, m, n, a, lda, s, u, ldu, vt, ldvt, ref info);
+        }
+
+        public void dgesvd(char jobz, int m, int n, double[] a, int lda, double[] s, double[] u, int ldu, double[] vt, int ldvt, ref int info) {
+            acml_dgesvd(jobz, jobz, m, n, a, lda, s, u, ldu, vt, ldvt, ref info);
+        }
+        public void sgesvd(char jobz, int m, int n, float[] a, int lda, float[] s, float[] u, int ldu, float[] vt, int ldvt, ref int info) {
+            acml_sgesvd(jobz, jobz, m, n, a, lda, s, u, ldu, vt, ldvt, ref info);
+        }
+        public void zgesvd(char jobz, int m, int n, complex[] a, int lda, double[] s, complex[] u, int ldu, complex[] vt, int ldvt, ref int info) {
+            acml_zgesvd(jobz, jobz, m, n, a, lda, s, u, ldu, vt, ldvt, ref info);
+        }
+        public void cgesvd(char jobz, int m, int n, fcomplex[] a, int lda, float[] s, fcomplex[] u, int ldu, fcomplex[] vt, int ldvt, ref int info) {
+            acml_cgesvd(jobz, jobz, m, n, a, lda, s, u, ldu, vt, ldvt, ref info);
+        }
+
+        public void dpotrf(char uplo, int n, double[] A, int lda, ref int info) {
+            acml_dpotrf(uplo,n, A, lda, ref info); 
+        }
+        public void spotrf(char uplo, int n, float[] A, int lda, ref int info) {
+            acml_spotrf(uplo,n, A, lda, ref info);
+        }
+        public void cpotrf(char uplo, int n, fcomplex[] A, int lda, ref int info) {
+            acml_cpotrf(uplo,n, A, lda, ref info);
+        }
+        public void zpotrf(char uplo, int n, complex[] A, int lda, ref int info) {
+            acml_zpotrf(uplo,n, A, lda, ref info);
+        }
+
+        public void dpotri(char uplo, int n, double[] A, int lda, ref int info) {
+            acml_dpotri(uplo,n, A, lda, ref info); 
+        }
+        public void spotri(char uplo, int n, float[] A, int lda, ref int info) {
+            acml_spotri(uplo,n,A, lda, ref info);
+        }
+        public void cpotri(char uplo, int n, fcomplex[] A, int lda, ref int info) {
+            acml_cpotri(uplo,n, A, lda, ref info);
+        }
+        public void zpotri(char uplo, int n, complex[] A, int lda, ref int info) {
+            acml_zpotri(uplo,n, A, lda, ref info);
+        }
+
+        public void dgetrf(int M, int N, double[] A, int LDA, int[] IPIV, ref int info) {
+            acml_dgetrf(M, N,  A, LDA, IPIV, ref info);
+        }
+        public void sgetrf(int M, int N, float[] A, int LDA, int[] IPIV, ref int info) {
+            acml_sgetrf(M, N,  A, LDA, IPIV, ref info);
+        }
+
+        public void cgetrf(int M, int N, fcomplex[] A, int LDA, int[] IPIV, ref int info) {
+            acml_cgetrf(M, N,  A, LDA, IPIV, ref info);
+        }
+        public void zgetrf(int M, int N, complex[] A, int LDA, int[] IPIV, ref int info) {
+            acml_zgetrf(M, N,  A, LDA,  IPIV, ref info);
+        }
+
+        public void dgetri(int N, double[] A, int LDA, int[] IPIV, ref int info) {
+            acml_dgetri(N, A, LDA, IPIV, ref info);
+        }
+        public void sgetri(int N, float[] A, int LDA, int[] IPIV, ref int info) {
+            acml_sgetri(N, A, LDA, IPIV, ref info);
+        }
+
+        public void cgetri(int N, fcomplex[] A, int LDA, int[] IPIV, ref int info) {
+            acml_cgetri(N, A, LDA, IPIV, ref info);
+        }
+        public void zgetri(int N, complex[] A, int LDA, int[] IPIV, ref int info) {
+            acml_zgetri(N, A, LDA, IPIV, ref info);
+        }
+
+        public void dgeqrf(int M, int N, double[] A, int lda, double [] tau, ref int info) {
+            acml_dgeqrf(M, N, A, lda, tau, ref info);
+        }
+        public void sgeqrf(int M, int N, float[] A, int lda, float [] tau, ref int info) {
+            acml_sgeqrf(M, N, A, lda, tau, ref info);
+        }
+        public void cgeqrf(int M, int N, fcomplex[] A, int lda, fcomplex [] tau, ref int info) {
+            acml_cgeqrf(M, N, A, lda, tau, ref info);
+        }
+        public void zgeqrf(int M, int N, complex[] A, int lda, complex [] tau, ref int info) {
+            acml_zgeqrf(M, N, A, lda, tau, ref info);
+        }
+
+        public void dormqr(char side, char trans, int m, int n, int k, double [] A, int lda, double [] tau, double [] C, int ldc, ref int info) {
+            acml_dormqr(side, trans, m,n,k, A, lda, tau, C,ldc, ref info);
+        }
+        public void sormqr(char side, char trans, int m, int n, int k, float [] A, int lda, float [] tau, float [] C, int ldc, ref int info) {
+            acml_sormqr(side, trans, m,n,k, A, lda, tau, C,ldc, ref info);
+        }
+
+        public void dorgqr(int M, int N, int K, double[] A, int lda, double[] tau, ref int info) {
+            acml_dorgqr(M,N,K,A,lda,tau,ref info); 
+        }
+        public void sorgqr(int M, int N, int K, float[] A, int lda, float[] tau, ref int info) {
+            acml_sorgqr(M,N,K,A,lda,tau,ref info); 
+        }
+        public void cungqr(int M, int N, int K, fcomplex[] A, int lda, fcomplex[] tau, ref int info) {
+            acml_cungqr(M,N,K,A,lda,tau,ref info); 
+        }
+        public void zungqr(int M, int N, int K, complex[] A, int lda, complex[] tau, ref int info) {
+            acml_zungqr(M,N,K,A,lda,tau,ref info); 
+        }
+
+        public void dgeqp3 ( int M,int N,double [] A,int LDA,int [] JPVT,double [] tau,ref int info ) {
+            acml_dgeqp3(M,N,A,LDA,JPVT,tau,ref info);
+        }
+
+        public void sgeqp3 ( int M,int N,float [] A,int LDA,int [] JPVT,float [] tau,ref int info ) {
+            acml_sgeqp3(M,N,A,LDA,JPVT,tau,ref info);
+        }
+
+        public void cgeqp3 ( int M,int N,fcomplex [] A,int LDA,int [] JPVT,fcomplex [] tau,ref int info ) {
+            acml_cgeqp3(M,N,A,LDA,JPVT,tau,ref info);
+        }
+
+        public void zgeqp3 ( int M,int N,complex [] A,int LDA,int [] JPVT,complex [] tau,ref int info ) {
+            acml_zgeqp3(M,N,A,LDA,JPVT,tau,ref info);
+        }
+
+        public void dtrtrs(char uplo, char transA, char diag, int N, int nrhs, IntPtr A, int LDA, IntPtr B, int LDB, ref int info) {
+            acml_dtrtrs (uplo, transA, diag, N, nrhs, A, LDA, B, LDB, ref info);
+        }
+        public void strtrs(char uplo, char transA, char diag, int N, int nrhs, IntPtr A, int LDA, IntPtr B, int LDB, ref int info) {
+            acml_strtrs (uplo, transA, diag, N, nrhs, A, LDA, B, LDB, ref info);
+        }
+        public void ctrtrs(char uplo, char transA, char diag, int N, int nrhs, IntPtr A, int LDA, IntPtr B, int LDB, ref int info) {
+            acml_ctrtrs (uplo, transA, diag, N, nrhs, A, LDA, B, LDB, ref info);
+        }
+        public void ztrtrs(char uplo, char transA, char diag, int N, int nrhs, IntPtr A, int LDA, IntPtr B, int LDB, ref int info) {
+            acml_ztrtrs (uplo, transA, diag, N, nrhs, A, LDA, B, LDB, ref info);
+        }
+
+        public void dgetrs(char trans, int N, int NRHS, double[] A, int LDA, int[] IPIV, double[] B, int LDB, ref int info) {
+            acml_dgetrs(trans,N,NRHS,A,LDA,IPIV,B,LDB,ref info); 
+        }
+
+        public void sgetrs(char trans, int N, int NRHS, float[] A, int LDA, int[] IPIV, float[] B, int LDB, ref int info) {
+            acml_sgetrs(trans,N,NRHS,A,LDA,IPIV,B,LDB,ref info); 
+        }
+
+        public void cgetrs(char trans, int N, int NRHS, fcomplex[] A, int LDA, int[] IPIV, fcomplex[] B, int LDB, ref int info) {
+            acml_cgetrs(trans,N,NRHS,A,LDA,IPIV,B,LDB,ref info); 
+        }
+
+        public void zgetrs(char trans, int N, int NRHS, complex[] A, int LDA, int[] IPIV, complex[] B, int LDB, ref int info) {
+            acml_zgetrs(trans,N,NRHS,A,LDA,IPIV,B,LDB,ref info); 
+        }
+
+        public void dpotrs(char uplo, int n, int nrhs, double[] A, int lda, double[] B, int ldb, ref int info) {
+            acml_dpotrs(uplo,n,nrhs,A,lda,B,ldb,ref info); 
+        }
+        public void spotrs(char uplo, int n, int nrhs, float[] A, int lda, float[] B, int ldb, ref int info) {
+            acml_spotrs(uplo,n,nrhs,A,lda,B,ldb,ref info); 
+        }
+        public void cpotrs(char uplo, int n, int nrhs, fcomplex[] A, int lda, fcomplex[] B, int ldb, ref int info) {
+            acml_cpotrs(uplo,n,nrhs,A,lda,B,ldb,ref info); 
+        }
+        public void zpotrs(char uplo, int n, int nrhs, complex[] A, int lda, complex[] B, int ldb, ref int info) {
+            acml_zpotrs(uplo,n,nrhs,A,lda,B,ldb,ref info); 
+        }
+ 
+        public void dgelsd(int m, int n, int nrhs, double[] A, int lda, double[] B, int ldb, double[] S, double RCond, ref int rank, ref int info) {
+            dgelsd (m, n, nrhs, A, lda, B, ldb, S, RCond, ref rank, ref info); 
+        }
+        public void sgelsd(int m, int n, int nrhs, float[] A, int lda, float[] B, int ldb, float[] S, float RCond, ref int rank, ref int info) {
+            sgelsd (m, n, nrhs, A, lda, B, ldb, S, RCond, ref rank, ref info); 
+        }
+        public void cgelsd(int m, int n, int nrhs, fcomplex[] A, int lda, fcomplex[] B, int ldb, float[] S, float RCond, ref int rank, ref int info) {
+            cgelsd (m, n, nrhs, A, lda, B, ldb, S, RCond, ref rank, ref info); 
+        }
+        public void zgelsd(int m, int n, int nrhs, complex[] A, int lda, complex[] B, int ldb, double[] S, double RCond, ref int rank, ref int info) {
+            zgelsd (m, n, nrhs, A, lda, B, ldb, S, RCond, ref rank, ref info); 
+        }
+
+        public void dgelsy(int m, int n, int nrhs, double[] A, int lda, double[] B, int ldb, int[] JPVT0, double RCond, ref int rank, ref int info) {
+            acml_dgelsy(m,n,nrhs,A,lda,B,ldb,JPVT0,RCond,ref rank,ref info); 
+        }
+        public void sgelsy(int m, int n, int nrhs, float[] A, int lda, float[] B, int ldb, int[] JPVT0, float RCond, ref int rank, ref int info) {
+            acml_sgelsy(m,n,nrhs,A,lda,B,ldb,JPVT0,RCond,ref rank,ref info);
+        }
+        public void cgelsy(int m, int n, int nrhs, fcomplex[] A, int lda, fcomplex[] B, int ldb, int[] JPVT0, float RCond, ref int rank, ref int info) {
+            acml_cgelsy(m,n,nrhs,A,lda,B,ldb,JPVT0,RCond,ref rank,ref info);
+        }
+        public void zgelsy(int m, int n, int nrhs, complex[] A, int lda, complex[] B, int ldb, int[] JPVT0, double RCond, ref int rank, ref int info) {
+            acml_zgelsy(m,n,nrhs,A,lda,B,ldb,JPVT0,RCond,ref rank,ref info);
+        }
+
+        public void dgeevx(char balance, char jobvl, char jobvr, char sense, int n, double[] A, int lda, double[] wr, double[] wi, double[] vl, int ldvl, double[] vr, int ldvr, ref int ilo, ref int ihi, double[] scale, ref double abnrm, double[] rconde, double[] rcondv, ref int info) {
+            acml_dgeevx(balance,jobvl,jobvr,sense,n,A,lda,wr,wi,vl,ldvl,vr,ldvr,ref ilo,ref ihi,scale,ref abnrm,rconde,rcondv,ref info); 
+        }
+
+        public void sgeevx(char balance, char jobvl, char jobvr, char sense, int n, float[] A, int lda, float[] wr, float[] wi, float[] vl, int ldvl, float[] vr, int ldvr, ref int ilo, ref int ihi, float[] scale, ref float abnrm, float[] rconde, float[] rcondv, ref int info) {
+            acml_sgeevx(balance,jobvl,jobvr,sense,n,A,lda,wr,wi,vl,ldvl,vr,ldvr,ref ilo,ref ihi,scale,ref abnrm,rconde,rcondv,ref info); 
+        }
+
+        public void cgeevx(char balance, char jobvl, char jobvr, char sense, int n, fcomplex[] A, int lda, fcomplex[] w, fcomplex[] vl, int ldvl, fcomplex[] vr, int ldvr, ref int ilo, ref int ihi, float[] scale, ref float abnrm, float[] rconde, float[] rcondv, ref int info) {
+            acml_cgeevx(balance,jobvl,jobvr,sense,n,A,lda,w,vl,ldvl,vr,ldvr,ref ilo,ref ihi,scale,ref abnrm,rconde,rcondv,ref info); 
+        }
+
+        public void zgeevx(char balance, char jobvl, char jobvr, char sense, int n, complex[] A, int lda, complex[] w, complex[] vl, int ldvl, complex[] vr, int ldvr, ref int ilo, ref int ihi, double[] scale, ref double abnrm, double[] rconde, double[] rcondv, ref int info) {
+            acml_zgeevx(balance,jobvl,jobvr,sense,n,A,lda,w,vl,ldvl,vr,ldvr,ref ilo,ref ihi,scale,ref abnrm,rconde,rcondv,ref info); 
+        }
+
+        public void dsyevr(char jobz, char range, char uplo, int n, double[] A, int lda, double vl, double vu, int il, int iu, double abstol, ref int m, double[] w, double[] z, int ldz, int[] isuppz, ref int info) {
+            acml_dsyevr(jobz,range,uplo,n,A,lda,vl,vu,il,iu,abstol,ref m,w,z,ldz,isuppz,ref info); 
+        }
+
+        public void ssyevr(char jobz, char range, char uplo, int n, float[] A, int lda, float vl, float vu, int il, int iu, float abstol, ref int m, float[] w, float[] z, int ldz, int[] isuppz, ref int info) {
+            acml_ssyevr(jobz,range,uplo,n,A,lda,vl,vu,il,iu,abstol,ref m,w,z,ldz,isuppz,ref info); 
+        }
+
+        public void cheevr(char jobz, char range, char uplo, int n, fcomplex[] A, int lda, float vl, float vu, int il, int iu, float abstol, ref int m, float[] w, fcomplex[] z, int ldz, int[] isuppz, ref int info) {
+            acml_cheevr(jobz,range,uplo,n,A,lda,vl,vu,il,iu,abstol,ref m,w,z,ldz,isuppz,ref info); 
+        }
+
+        public void zheevr(char jobz, char range, char uplo, int n, complex[] A, int lda, double vl, double vu, int il, int iu, double abstol, ref int m, double[] w, complex[] z, int ldz, int[] isuppz, ref int info) {
+            acml_zheevr(jobz,range,uplo,n,A,lda,vl,vu,il,iu,abstol,ref m,w,z,ldz,isuppz,ref info); 
+        }
+
+        // generalized eigenproblem: symmetric
+        public void dsygv (int itype, char jobz, char uplo, int n, double  [] A, int lda, double  [] B, int ldb, double [] w, ref int info) {
+            acml_dsygv (itype, jobz, uplo, n, A, lda, B, ldb, w, ref info); 
+        }        
+        public void ssygv (int itype, char jobz, char uplo, int n, float   [] A, int lda, float   [] B, int ldb, float  [] w, ref int info) {
+            acml_ssygv (itype, jobz, uplo, n, A, lda, B, ldb, w, ref info); 
+        }
+        public void chegv (int itype, char jobz, char uplo, int n, fcomplex[] A, int lda, fcomplex[] B, int ldb, float  [] w, ref int info) {
+            acml_chegv (itype, jobz, uplo, n, A, lda, B, ldb, w, ref info); 
+        }
+        public void zhegv (int itype, char jobz, char uplo, int n, complex [] A, int lda, complex [] B, int ldb, double [] w, ref int info) { 
+            acml_zhegv (itype, jobz, uplo, n, A, lda, B, ldb, w, ref info); 
+        }
+
+        #endregion
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Native/lapack/ILLapackGenLinux.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Native/lapack/ILLapackGenLinux.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Native/lapack/ILLapackGenLinux.cs	(revision 9102)
@@ -0,0 +1,1297 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+#pragma warning disable 1570, 1591
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.InteropServices;
+using System.Security; 
+using ILNumerics.Native;
+using ILNumerics.Misc; 
+using ILNumerics.Exceptions;
+
+namespace ILNumerics.Native  {
+    /// <summary>
+    /// Generic LAPACK implementation, unsupported processor types
+    /// </summary>
+	public class ILLapackGenLinux : IILLapack {
+
+        #region DLL INCLUDES 
+        [DllImport("liblapack.so", EntryPoint = "ilaenv_"),SuppressUnmanagedCodeSecurity]
+        private static extern int lapack_ilaenv(ref int ispec, ref string name, ref string opts, ref int n1, ref int n2, ref int n3, ref int n4);
+
+        ///////////////////////////   DOUBLE LAPACK /////////////////////////////////
+        [DllImport("liblapack.so", EntryPoint = "dgemm_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dgemm(ref char TransA, ref char TransB, ref int M,ref int N, ref int K, ref  double alpha, IntPtr A, ref int lda, IntPtr B, ref int ldb, ref double beta, double[] C, ref int ldc);
+        [DllImport("liblapack.so", EntryPoint = "sgemm_"),SuppressUnmanagedCodeSecurity]
+		private static extern void lapack_sgemm(ref char TransA, ref char TransB, ref int M,ref int N, ref int K, ref float alpha, IntPtr A,ref int lda, IntPtr B, ref int ldb, ref float beta,float[] C, ref int ldc);
+        [DllImport("liblapack.so", EntryPoint = "cgemm_"),SuppressUnmanagedCodeSecurity]
+		private static extern void lapack_cgemm(ref char TransA, ref char TransB, ref int M,ref int N, ref int K, ref fcomplex alpha, IntPtr A, ref int lda, IntPtr B, ref int ldb, ref fcomplex beta,[In,Out] fcomplex [] C, ref int ldc);
+        [DllImport("liblapack.so", EntryPoint = "zgemm_"),SuppressUnmanagedCodeSecurity]
+		private static extern void lapack_zgemm(ref char TransA, ref char TransB, ref int M, ref int N, ref int K, ref complex alpha, IntPtr A, ref int lda, IntPtr B, ref int ldb, ref complex beta,[In,Out] complex [] C, ref int ldc);
+
+        [DllImport("liblapack.so", EntryPoint = "dgesdd_"),SuppressUnmanagedCodeSecurity]
+		private static extern void lapack_dgesdd(ref char jobz, ref int m, ref int n,double[] a, ref int lda, double[] s,double[] u, ref int ldu, double[] vt,ref int ldvt, double[] work, ref int lwork,int[] iwork, ref int info);
+        [DllImport("liblapack.so", EntryPoint = "sgesdd_"),SuppressUnmanagedCodeSecurity]
+		private static extern void lapack_sgesdd(ref char jobz, ref int m, ref int n,float[] a, ref int lda, float[] s,float[] u, ref int ldu, float[] vt, ref int ldvt, float[] work, ref int lwork,int[] iwork, ref int info);
+        [DllImport("liblapack.so", EntryPoint = "cgesdd_"),SuppressUnmanagedCodeSecurity]
+		private static extern void lapack_cgesdd(ref char jobz, ref int m, ref int n,[In, Out] fcomplex[] a, ref int lda, float[] s,[In, Out] fcomplex[] u, ref int ldu, [In, Out]  fcomplex[] vt, ref int ldvt, [In, Out] fcomplex[] work, ref int lwork,[In,Out] float[] rwork, int[] iwork, ref int info);
+        [DllImport("liblapack.so", EntryPoint = "zgesdd_"),SuppressUnmanagedCodeSecurity]
+		private static extern void lapack_zgesdd(ref char jobz, ref int m, ref int n,[In, Out] complex[] a, ref int lda, double[] s,[In, Out] complex[] u, ref int ldu, [In, Out] complex[] vt,ref int ldvt, [In, Out] complex[] work, ref int lwork,[In,Out] double[] rwork, int[] iwork, ref int info);
+
+        [DllImport("liblapack.so", EntryPoint = "dgesvd_"),SuppressUnmanagedCodeSecurity]
+		private static extern void lapack_dgesvd(ref char jobu, ref  char jobvt, ref int m, ref int n,double[] a, ref int lda, double[] s,double[] u, ref int ldu, double[] vt,ref int ldvt, double[] work, ref int lwork,int[] iwork,ref int info);
+        [DllImport("liblapack.so", EntryPoint = "sgesvd_"),SuppressUnmanagedCodeSecurity]
+		private static extern void lapack_sgesvd(ref char jobu, ref  char jobvt, ref int m, ref int n, float[] a, ref int lda, float[] s,float[] u, ref int ldu, float[] vt,ref int ldvt, float[] work, ref int lwork,int[] iwork, ref int info);
+        [DllImport("liblapack.so", EntryPoint = "cgesvd_"),SuppressUnmanagedCodeSecurity]
+		private static extern void lapack_cgesvd(ref char jobu, ref  char jobvt, ref int m, ref int n,[In, Out] fcomplex[] a, ref int lda, float[] s,[In, Out] fcomplex[] u, ref int ldu,[In,Out] fcomplex[] vt,ref int ldvt, [In, Out]  fcomplex[] work, ref int lwork,int[] iwork,ref int info);
+        [DllImport("liblapack.so", EntryPoint = "zgesvd_"),SuppressUnmanagedCodeSecurity]
+		private static extern void lapack_zgesvd(ref char jobu, ref  char jobvt, ref int m, ref int n,[In, Out] complex[] a, ref int lda, double[] s,[In, Out] complex[] u, ref int ldu, [In, Out] complex[] vt,ref int ldvt, [In, Out]  complex[] work, ref int lwork,int[] iwork,ref int info);
+
+        [DllImport("liblapack.so", EntryPoint = "dpotrf_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dpotrf (ref char uplo, ref int n, double [] A, ref int lda, ref int info);
+        [DllImport("liblapack.so", EntryPoint = "spotrf_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_spotrf (ref char uplo, ref int n, float [] A, ref int lda, ref int info);
+        [DllImport("liblapack.so", EntryPoint = "cpotrf_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_cpotrf (ref char uplo, ref int n,[In,Out] fcomplex [] A, ref int lda, ref int info);
+        [DllImport("liblapack.so", EntryPoint = "zpotrf_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_zpotrf (ref char uplo, ref int n, [In,Out] complex [] A, ref int lda, ref int info);
+        
+        [DllImport("liblapack.so", EntryPoint = "dpotri_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dpotri (ref char uplo,ref  int n, double [] A, ref int lda, ref int info);
+        [DllImport("liblapack.so", EntryPoint = "spotri_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_spotri (ref char uplo, ref int n, float [] A, ref int lda, ref int info);
+        [DllImport("liblapack.so", EntryPoint = "cpotri_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_cpotri (ref char uplo, ref int n,[In,Out] fcomplex [] A, ref int lda,ref int info);
+        [DllImport("liblapack.so", EntryPoint = "zpotri_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_zpotri (ref char uplo, ref int n, [In,Out] complex [] A, ref int lda,ref int info);
+
+        [DllImport("liblapack.so", EntryPoint = "dpotrs_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dpotrs (ref char uplo,ref  int n, ref int NRHS, double [] A, ref int lda, double[] B, ref int ldb, ref int info);
+        [DllImport("liblapack.so", EntryPoint = "spotrs_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_spotrs (ref char uplo,ref  int n, ref int NRHS, float [] A, ref int lda, float[] B, ref int ldb, ref int info);
+        [DllImport("liblapack.so", EntryPoint = "cpotrs_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_cpotrs (ref char uplo,ref  int n, ref int NRHS, [In,Out] fcomplex [] A, ref int lda, [In,Out] fcomplex[] B, ref int ldb, ref int info);
+        [DllImport("liblapack.so", EntryPoint = "zpotrs_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_zpotrs (ref char uplo,ref  int n, ref int NRHS, [In,Out] complex [] A, ref int lda, [In,Out] complex[] B, ref int ldb, ref int info);
+
+        [DllImport("liblapack.so", EntryPoint = "dgetrf_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dgetrf (ref int M, ref int N, double [] A, ref int LDA, int[] IPIV, ref int info);
+        [DllImport("liblapack.so", EntryPoint = "sgetrf_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_sgetrf (ref int M, ref int N, float[] A, ref int LDA, int [] IPIV, ref int info);
+        [DllImport("liblapack.so", EntryPoint = "cgetrf_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_cgetrf (ref int M, ref int N, [In,Out] fcomplex [] A, ref int LDA, int [] IPIV, ref int info);
+        [DllImport("liblapack.so", EntryPoint = "zgetrf_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_zgetrf (ref int M, ref int N, [In,Out] complex [] A, ref int LDA, int [] IPIV, ref int info);
+
+        [DllImport("liblapack.so", EntryPoint = "dgetri_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dgetri (ref int N, double[] A,ref  int LDA, int[] IPIV, double[] work, ref int lwork, ref int info);
+        [DllImport("liblapack.so", EntryPoint = "sgetri_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_sgetri (ref int N, float [] A, ref int LDA, int [] IPIV, float[] work, ref int lwork, ref int info);
+        [DllImport("liblapack.so", EntryPoint = "cgetri_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_cgetri (ref int N, [In,Out] fcomplex [] A, ref int LDA,[In,Out] int [] IPIV, [In,Out] fcomplex[] work, ref int lwork, ref int info);
+        [DllImport("liblapack.so", EntryPoint = "zgetri_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_zgetri (ref int N, [In,Out] complex [] A, ref int LDA, int [] IPIV, [In,Out] complex[] work, ref int lwork, ref int info);
+
+        [DllImport("liblapack.so", EntryPoint = "dgeqrf_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dgeqrf (ref int M, ref int N, double [] A, ref int lda, double [] tau, double[] work, ref int lwork, ref int info);
+        [DllImport("liblapack.so", EntryPoint = "sgeqrf_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_sgeqrf (ref int M, ref int N, float [] A, ref int lda, float [] tau, float[] work, ref int lwork,  ref int info);
+        [DllImport("liblapack.so", EntryPoint = "cgeqrf_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_cgeqrf (ref int M, ref int N, [In,Out] fcomplex [] A, ref int lda, [In,Out] fcomplex [] tau, [In,Out] fcomplex[] work, ref int lwork, ref int info);
+        [DllImport("liblapack.so", EntryPoint = "zgeqrf_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_zgeqrf (ref int M, ref int N, [In,Out] complex [] A, ref int lda, [In,Out] complex [] tau, [In,Out] complex[] work, ref int lwork,  ref int info);
+
+        [DllImport("liblapack.so", EntryPoint = "dgeqp3_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dgeqp3 (ref int M, ref int N, double [] A, ref int LDA, int [] JPVT, double [] tau, double [] work, ref int lwork, ref int info );
+        [DllImport("liblapack.so", EntryPoint = "sgeqp3_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_sgeqp3 (ref int M, ref int N, float [] A, ref int LDA, int [] JPVT, float [] tau, float [] work, ref int lwork, ref int info );
+        [DllImport("liblapack.so", EntryPoint = "cgeqp3_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_cgeqp3 (ref int M, ref int N,[In,Out] fcomplex [] A, ref int LDA,[In,Out] int [] JPVT, [In,Out] fcomplex [] tau, [In,Out] fcomplex [] work, ref int lwork,[In,Out] float [] rwork, ref int info );
+        [DllImport("liblapack.so", EntryPoint = "zgeqp3_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_zgeqp3 (ref int M, ref int N, [In,Out] complex [] A, ref int LDA, [In,Out] int [] JPVT, [In,Out] complex [] tau, [In,Out] complex [] work, ref int lwork, [In,Out] double [] rwork, ref int info );
+
+        [DllImport("liblapack.so", EntryPoint = "dormqr_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dormqr (ref char side, ref char trans, ref int m, ref int n, ref int k, double[] A, int lda, double[] tau, double[] C, ref int ldc, ref int info);
+        [DllImport("liblapack.so", EntryPoint = "sormqr_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_sormqr (ref char side, ref char trans, ref int m, ref int n, ref int k, float [] A, ref int lda, float [] tau , float [] C, ref int ldc, ref int info);
+        
+        [DllImport("liblapack.so", EntryPoint = "dorgqr_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dorgqr (ref int m, ref int n, ref int k, double[] A,ref int lda, double[] tau, double[] work, ref int lwork, ref int info);
+        [DllImport("liblapack.so", EntryPoint = "sorgqr_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_sorgqr (ref int m, ref int n, ref int k, float [] A, ref int lda, float [] tau , float[] work, ref int lwork,  ref int info);
+        [DllImport("liblapack.so", EntryPoint = "cungqr_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_cungqr (ref int m, ref int n, ref int k, [In,Out] fcomplex[] A,ref int lda, [In,Out] fcomplex[] tau, [In,Out] fcomplex[] work, ref int lwork, ref int info);
+        [DllImport("liblapack.so", EntryPoint = "zungqr_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_zungqr (ref int m, ref int n, ref int k, [In,Out] complex[] A,ref int lda, [In,Out] complex[] tau, [In,Out] complex[] work, ref int lwork, ref int info);
+        
+        [DllImport("liblapack.so", EntryPoint = "dtrtrs_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dtrtrs (ref char uplo, ref char transA, ref char diag, ref int N, ref int nrhs, IntPtr A, ref int LDA, IntPtr B, ref int LDB, ref int info);
+        [DllImport("liblapack.so", EntryPoint = "strtrs_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_strtrs (ref char uplo, ref char transA, ref char diag, ref int N, ref int nrhs, IntPtr A, ref int LDA, IntPtr B, ref int LDB, ref int info);
+        [DllImport("liblapack.so", EntryPoint = "ctrtrs_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_ctrtrs (ref char uplo, ref char transA, ref char diag, ref int N, ref int nrhs, IntPtr A, ref int LDA, IntPtr B, ref int LDB, ref int info);
+        [DllImport("liblapack.so", EntryPoint = "ztrtrs_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_ztrtrs (ref char uplo, ref char transA, ref char diag, ref int N, ref int nrhs, IntPtr A, ref int LDA, IntPtr B, ref int LDB, ref int info);
+        
+        [DllImport("liblapack.so", EntryPoint = "dgetrs_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dgetrs(ref char trans, ref int N, ref int NRHS, double[] A, ref int LDA, int[] IPIV, double[] B, ref int LDB, ref int info);
+        [DllImport("liblapack.so", EntryPoint = "sgetrs_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_sgetrs(ref char trans, ref int N, ref int NRHS, float[] A, ref int LDA, int[] IPIV, float[] B, ref int LDB, ref int info);
+        [DllImport("liblapack.so", EntryPoint = "cgetrs_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_cgetrs(ref char trans, ref int N, ref int NRHS, [In,Out] fcomplex[] A, ref int LDA, int[] IPIV, [In,Out] fcomplex[] B, ref int LDB, ref int info);
+        [DllImport("liblapack.so", EntryPoint = "zgetrs_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_zgetrs(ref char trans, ref int N, ref int NRHS, [In,Out] complex[] A, ref int LDA, int[] IPIV, [In,Out] complex[] B, ref int LDB, ref int info);
+
+        [DllImport("liblapack.so", EntryPoint = "dgelsd_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dgelsd (ref int m,ref int n,ref int nrhs, double[] A,ref int lda, double[] B,ref int ldb, double[] S, ref double RCond, ref int rank, double[] work,ref int lwork, int[] iwork, ref int info); 
+        [DllImport("liblapack.so", EntryPoint = "sgelsd_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_sgelsd (ref int m,ref int n,ref int nrhs, float[] A,ref int lda, float[] B,ref int ldb, float[] S, ref float RCond, ref int rank, float[] work,ref int lwork, int[] iwork, ref int info); 
+        [DllImport("liblapack.so", EntryPoint = "cgelsd_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_cgelsd (ref int m,ref int n,ref int nrhs, [In,Out] fcomplex[] A,ref int lda, [In,Out] fcomplex[] B,ref int ldb, float[] S , ref float RCond, ref int rank, [In,Out] fcomplex[] work, ref int lwork, float[] rwork, int[] iwork, ref int info); 
+        [DllImport("liblapack.so", EntryPoint = "zgelsd_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_zgelsd (ref int m,ref int n,ref int nrhs, [In,Out] complex[] A,ref int lda, [In,Out] complex[] B,ref int ldb, double[] S, ref double RCond, ref int rank, [In,Out]  complex[] work,ref int lwork, double[] rwork, int[] iwork, ref int info); 
+        
+        [DllImport("liblapack.so", EntryPoint = "dgelsy_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dgelsy (ref int m,ref int n,ref int nrhs, double[] A,ref int lda, double[] B,ref int ldb, int[] JPVT0, ref double RCond, ref int rank, double[] work, ref int lwork, ref int info); 
+        [DllImport("liblapack.so", EntryPoint = "dgelsy_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_sgelsy (ref int m,ref int n,ref int nrhs, float[] A,ref int lda, float[] B,ref int ldb, int[] JPVT0, ref float RCond, ref int rank, float[] work,ref int lwork, ref int info); 
+        [DllImport("liblapack.so", EntryPoint = "dgelsy_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_cgelsy (ref int m,ref int n,ref int nrhs, [In,Out] fcomplex[] A,ref int lda, [In,Out] fcomplex[] B,ref int ldb, int[] JPVT0, ref float RCond, ref int rank, [In,Out] fcomplex[] work, ref int lwork, float[] rwork, ref int info); 
+        [DllImport("liblapack.so", EntryPoint = "dgelsy_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_zgelsy (ref int m,ref int n,ref int nrhs, [In,Out] complex[] A,ref int lda, [In,Out] complex[] B,ref int ldb, int[] JPVT0, ref double RCond, ref int rank, [In,Out]  complex[] work, ref int lwork, double[] rwork, ref int info); 
+        
+        [DllImport("liblapack.so", EntryPoint = "dgeevx_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dgeevx (ref char balance, ref char jobvl, ref char jobvr, ref char sense, ref int n,            double[] A, ref int lda,          double[] wr, double[] wi, double[] vl, ref int ldvl,            double[] vr, ref int ldvr, ref int ilo, ref int ihi, double[] scale, ref double abnrm, double[] rconde, double[] rcondv, double[] work, ref int lwork, int [] iwork, ref int info); 
+        [DllImport("liblapack.so", EntryPoint = "sgeevx_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_sgeevx (ref char balance, ref char jobvl, ref char jobvr, ref char sense, ref int n,             float[] A, ref int lda,             float[] wr, float[] wi, float[] vl, ref int ldvl,             float[] vr, ref int ldvr, ref int ilo, ref int ihi, float[]  scale, ref float  abnrm, float[]  rconde, float[]  rcondv, float [] work, ref int lwork, int [] iwork, ref int info); 
+        [DllImport("liblapack.so", EntryPoint = "cgeevx_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_cgeevx (ref char balance, ref char jobvl, ref char jobvr, ref char sense, ref int n, [In,Out] fcomplex[] A, ref int lda, [In,Out] fcomplex[] w,  [In,Out] fcomplex[] vl, ref int ldvl, [In,Out] fcomplex[] vr, ref int ldvr, ref int ilo, ref int ihi, float[]  scale, ref float  abnrm, float[]  rconde, float[]  rcondv, [In,Out] fcomplex[] work, ref int lwork, float[] rwork, ref int info);
+        [DllImport("liblapack.so", EntryPoint = "zgeevx_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_zgeevx (ref char balance, ref char jobvl, ref char jobvr, ref char sense, ref int n, [In,Out]  complex[] A, ref int lda, [In,Out] complex[]  w,   [In,Out] complex[] vl, ref int ldvl, [In,Out]  complex[] vr, ref int ldvr, ref int ilo, ref int ihi, double[] scale, ref double abnrm, double[] rconde, double[] rcondv, [In,Out] complex[] work, ref int lwork, double[] rwork, ref int info);
+
+        [DllImport("liblapack.so", EntryPoint = "dsyevr_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dsyevr (ref char jobz, ref char range, ref char uplo, ref int n,          double  [] A, ref int lda, ref double vl, ref double vu, ref int il, ref int iu, ref double abstol, ref int m, double[] w,          double  [] z, ref int ldz, int[] isuppz, double[] work, ref int lwork, int[] iwork, ref int liwork, ref int info); 
+        [DllImport("liblapack.so", EntryPoint = "ssyevr_"),SuppressUnmanagedCodeSecurity]                                                                                                                                                                                                                                         
+        private static extern void lapack_ssyevr (ref char jobz, ref char range, ref char uplo, ref int n,          float   [] A, ref int lda, ref float  vl, ref float  vu, ref int il, ref int iu, ref float  abstol, ref int m, float [] w,          float   [] z, ref int ldz, int[] isuppz, float [] work, ref int lwork, int[] iwork, ref int liwork, ref int info); 
+        [DllImport("liblapack.so", EntryPoint = "cheevr_"),SuppressUnmanagedCodeSecurity]                                                                                                                                                                                                                                         
+        private static extern void lapack_cheevr (ref char jobz, ref char range, ref char uplo, ref int n, [In,Out] fcomplex[] A, ref int lda, ref float  vl, ref float  vu, ref int il, ref int iu, ref float  abstol, ref int m, float [] w, [In,Out] fcomplex[] z, ref int ldz, int[] isuppz, [In,Out] fcomplex[] work, ref int lwork, float[] rwork, ref int lrwork, int[] iwork, ref int liwork, ref int info);
+        [DllImport("liblapack.so", EntryPoint = "zheevr_"),SuppressUnmanagedCodeSecurity]                                                                                                                                                                                                                                         
+        private static extern void lapack_zheevr (ref char jobz, ref char range, ref char uplo, ref int n, [In,Out] complex [] A, ref int lda, ref double vl, ref double vu, ref int il, ref int iu, ref double abstol, ref int m, double[] w, [In,Out] complex [] z, ref int ldz, int[] isuppz, [In,Out] complex[] work, ref int lwork, double[] rwork, ref int lrwork, int[] iwork, ref int liwork, ref int info);
+
+        [DllImport("liblapack.so", EntryPoint = "dsygv_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dsygv (ref int itype, ref char jobz, ref char uplo, ref int n, double  [] A, ref int lda, double  [] B, ref int ldb, double [] w, double [] work, ref int lwork, ref int info); 
+        [DllImport("liblapack.so", EntryPoint = "ssygv_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_ssygv (ref int itype, ref char jobz, ref char uplo, ref int n, float   [] A, ref int lda, float   [] B, ref int ldb, float [] w,  float  [] work, ref int lwork, ref int info); 
+        [DllImport("liblapack.so", EntryPoint = "chegv_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_chegv (ref int itype, ref char jobz, ref char uplo, ref int n, [In,Out] fcomplex[] A, ref int lda, [In,Out] fcomplex [] B, ref int ldb, float  [] w, [In,Out] fcomplex[] work , ref int lwork, float[] rwork, ref int info); 
+        [DllImport("liblapack.so", EntryPoint = "zhegv_"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_zhegv (ref int itype, ref char jobz, ref char uplo, ref int n, [In,Out] complex [] A, ref int lda, [In,Out] complex  [] B, ref int ldb, double [] w, [In,Out]  complex[] work , ref int lwork, double[] rwork, ref int info); 
+
+#endregion DLL INCLUDES 
+
+        #region ILLAPACK INTERFACE 
+
+        private int ILAENV (int ispec, string name, string opts, int n1, int n2, int n3, int n4) {
+            return lapack_ilaenv(ref ispec, ref name, ref opts, ref n1, ref n2, ref n3, ref n4); 
+        }
+
+        /// <summary>
+        /// Implement wrapper for ATLAS GeneralMatrixMultiply
+        /// </summary>
+        /// <param name="TransA">Transposition state for matrix A: one of the constants in enum CBlas_Transpose</param>
+        /// <param name="TransB">Transposition state for matrix B: one of the constants in enum CBlas_Transpose</param>
+        /// <param name="M">Number of rows in A</param>
+        /// <param name="N">Number of columns in B</param>
+        /// <param name="K">Number of columns in A and number of rows in B</param>
+        /// <param name="alpha">multiplicationi factor for A</param>
+        /// <param name="A">pointer to double array A</param>
+        /// <param name="lda">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix B</param>
+        /// <param name="B">pointer to double array B</param>
+        /// <param name="ldb">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix A</param>
+        /// <param name="beta">multiplication faktor for matrix B</param>
+        /// <param name="C">pointer to predefined double array C of neccessary length</param>
+        /// <param name="ldc">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix C</param>
+        /// <remarks>All parameters except C are readonly. Only elements of matrix C will be altered. C must be a predefined 
+        /// continous double array of size MxN</remarks>
+        public void dgemm(char TransA, char TransB, int M, int N, int K, double alpha, IntPtr A, int lda, IntPtr B, int ldb, double beta, double[] C, int ldc) {
+            lapack_dgemm(ref TransA, ref TransB, ref M, ref  N, ref  K, ref  alpha, A, ref lda, B, ref ldb, ref  beta, C, ref  ldc);
+        }
+        /// <summary>
+        /// Implement wrapper for ATLAS GeneralMatrixMultiply
+        /// </summary>
+        /// <param name="TransA">Transposition state for matrix A: one of the constants in enum CBlas_Transpose</param>
+        /// <param name="TransB">Transposition state for matrix B: one of the constants in enum CBlas_Transpose</param>
+        /// <param name="M">Number of rows in A</param>
+        /// <param name="N">Number of columns in B</param>
+        /// <param name="K">Number of columns in A and number of rows in B</param>
+        /// <param name="alpha">multiplicationi factor for A</param>
+        /// <param name="A">pointer to double array A</param>
+        /// <param name="lda">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix B</param>
+        /// <param name="B">pointer to double array B</param>
+        /// <param name="ldb">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix A</param>
+        /// <param name="beta">multiplication faktor for matrix B</param>
+        /// <param name="C">pointer to predefined double array C of neccessary length</param>
+        /// <param name="ldc">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix C</param>
+        /// <remarks>All parameters except C are readonly. Only elements of matrix C will be altered. C must be a predefined 
+        /// continous double array of size MxN</remarks>
+        public void sgemm(char TransA, char TransB, int M, int N, int K, float alpha, IntPtr A, int lda, IntPtr B, int ldb, float beta, float[] C, int ldc) {
+            lapack_sgemm(ref TransA, ref TransB, ref M, ref  N, ref  K, ref  alpha, A, ref lda, B, ref ldb, ref  beta, C, ref  ldc);
+        }
+        /// <summary>
+        /// Implement wrapper for ATLAS GeneralMatrixMultiply
+        /// </summary>
+        /// <param name="TransA">Transposition state for matrix A: one of the constants in enum CBlas_Transpose</param>
+        /// <param name="TransB">Transposition state for matrix B: one of the constants in enum CBlas_Transpose</param>
+        /// <param name="M">Number of rows in A</param>
+        /// <param name="N">Number of columns in B</param>
+        /// <param name="K">Number of columns in A and number of rows in B</param>
+        /// <param name="alpha">multiplicationi factor for A</param>
+        /// <param name="A">pointer to double array A</param>
+        /// <param name="lda">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix B</param>
+        /// <param name="B">pointer to double array B</param>
+        /// <param name="ldb">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix A</param>
+        /// <param name="beta">multiplication faktor for matrix B</param>
+        /// <param name="C">pointer to predefined double array C of neccessary length</param>
+        /// <param name="ldc">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix C</param>
+        /// <remarks>All parameters except C are readonly. Only elements of matrix C will be altered. C must be a predefined 
+        /// continous double array of size MxN</remarks>
+        public void cgemm(char TransA, char TransB, int M, int N, int K, fcomplex alpha, IntPtr A, int lda, IntPtr B, int ldb, fcomplex beta, fcomplex[] C, int ldc) {
+            lapack_cgemm(ref TransA, ref TransB, ref M, ref  N, ref  K, ref  alpha, A, ref lda, B, ref ldb, ref  beta, C, ref  ldc);
+        }
+        /// <summary>
+        /// Implement wrapper for ATLAS GeneralMatrixMultiply
+        /// </summary>
+        /// <param name="TransA">Transposition state for matrix A: one of the constants in enum CBlas_Transpose</param>
+        /// <param name="TransB">Transposition state for matrix B: one of the constants in enum CBlas_Transpose</param>
+        /// <param name="M">Number of rows in A</param>
+        /// <param name="N">Number of columns in B</param>
+        /// <param name="K">Number of columns in A and number of rows in B</param>
+        /// <param name="alpha">multiplicationi factor for A</param>
+        /// <param name="A">pointer to double array A</param>
+        /// <param name="lda">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix B</param>
+        /// <param name="B">pointer to double array B</param>
+        /// <param name="ldb">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix A</param>
+        /// <param name="beta">multiplication faktor for matrix B</param>
+        /// <param name="C">pointer to predefined double array C of neccessary length</param>
+        /// <param name="ldc">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix C</param>
+        /// <remarks>All parameters except C are readonly. Only elements of matrix C will be altered. C must be a predefined 
+        /// continous double array of size MxN</remarks>
+        public void zgemm(char TransA, char TransB, int M, int N, int K, complex alpha, IntPtr A, int lda, IntPtr B, int ldb, complex beta, complex[] C, int ldc) {
+            lapack_zgemm(ref TransA, ref TransB, ref M, ref  N, ref  K, ref  alpha, A, ref lda, B, ref ldb, ref  beta, C, ref  ldc);
+        }
+
+
+        
+        public void  dgesdd (char jobz, int m, int n,  double [] a, int lda,  double [] s,  double [] u, int ldu,  double [] vt, int ldvt, ref int info) {
+            try {
+                 double [] work = new  double [1] { ( double )0.0 };
+                int lwork = -1;
+                int[] iwork = new int[((m < n) ? m : n) * 8];
+                 lapack_dgesdd (ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, iwork, ref info);
+                if (work[0] != 0) {
+                    work = new  double [(int)work[0]];
+                    lwork = work.Length;
+                     lapack_dgesdd (ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, iwork, ref info);
+                }
+            } catch (Exception e) {
+                if (e is OutOfMemoryException) {
+                     dgesvd (jobz, m, n, a, lda, s, u, ldu, vt, ldvt, ref info); 
+                }
+                throw new ILException("Unable to do " +  "dgesdd"  + ".", e); 
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+       
+        public void  sgesdd (char jobz, int m, int n,  float [] a, int lda,  float [] s,  float [] u, int ldu,  float [] vt, int ldvt, ref int info) {
+            try {
+                float [] work = new  float [1] { ( float )0.0 };
+                int lwork = -1;
+                int[] iwork = new int[((m < n) ? m : n) * 8];
+                lapack_sgesdd (ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, iwork, ref info);
+                if (work[0] != 0) {
+                    work = new  float [(int)work[0]];
+                    lwork = work.Length;
+                    lapack_sgesdd (ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, iwork, ref info);
+                }
+            } catch (Exception e) {
+                if (e is OutOfMemoryException) {
+                    sgesvd (jobz, m, n, a, lda, s, u, ldu, vt, ldvt, ref info); 
+                }
+                throw new ILException("Unable to do " +  "sgesdd"  + ".", e); 
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+
+
+        public void  zgesdd (char jobz, int m, int n,  complex [] a, int lda,  double [] s,  complex [] u, int ldu, complex [] vt, int ldvt, ref int info)
+        {
+            try {
+                 complex [] work = new  complex [1] { (  complex )0.0 };
+                 double [] rwork; 
+                int minMN = (m < n) ? m : n;
+                if (jobz == 'N') {
+                    rwork = new  double [minMN * 7];  
+                } else {
+                    rwork = new  double [5 * minMN * minMN + 5 * minMN];  
+                }
+                int lwork = -1;
+                int[] iwork = new int[minMN * 8];
+                 lapack_zgesdd (ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, rwork, iwork, ref info);
+                if (work[0] != 0) {
+                    work = new  complex [(int)work[0].real];
+                    lwork = work.Length;
+                     lapack_zgesdd (ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork,rwork, iwork, ref info);
+                }
+            } catch (Exception e) {
+                if (e is OutOfMemoryException) {
+                     zgesvd (jobz, m, n, a, lda, s, u, ldu, vt, ldvt, ref info); 
+                }
+                throw new ILException("Unable to do " +  "zgesdd"  + ".", e); 
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+
+        public void  cgesdd (char jobz, int m, int n,  fcomplex [] a, int lda,  float [] s,  fcomplex [] u, int ldu, fcomplex [] vt, int ldvt, ref int info)
+        {
+            try {
+                fcomplex [] work = new  fcomplex [1] { (  fcomplex )0.0 };
+                float [] rwork; 
+                int minMN = (m < n) ? m : n;
+                if (jobz == 'N') {
+                    rwork = new  float [minMN * 7];  
+                } else {
+                    rwork = new  float [5 * minMN * minMN + 5 * minMN];  
+                }
+                int lwork = -1;
+                int[] iwork = new int[minMN * 8];
+                lapack_cgesdd (ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, rwork, iwork, ref info);
+                if (work[0] != 0) {
+                    work = new  fcomplex [(int)work[0].real];
+                    lwork = work.Length;
+                    lapack_cgesdd (ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork,rwork, iwork, ref info);
+                }
+            } catch (Exception e) {
+                if (e is OutOfMemoryException) {
+                    cgesvd (jobz, m, n, a, lda, s, u, ldu, vt, ldvt, ref info); 
+                }
+                throw new ILException("Unable to do " +  "zgesdd"  + ".", e); 
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+
+        
+
+        /// <summary>
+        /// singular value decomposition
+        /// </summary>
+        /// <param name="jobz"></param>
+        /// <param name="m"></param>
+        /// <param name="n"></param>
+        /// <param name="a"></param>
+        /// <param name="lda"></param>
+        /// <param name="s"></param>
+        /// <param name="u"></param>
+        /// <param name="ldu"></param>
+        /// <param name="vt"></param>
+        /// <param name="ldvt"></param>
+        /// <param name="info"></param>
+        public void  dgesvd (char jobz, int m, int n,  double [] a, int lda,
+                            double [] s,  double [] u, int ldu,  double [] vt, int ldvt, ref int info) {
+            if (jobz != 'A' && jobz != 'S' && jobz != 'N')
+                throw new ILArgumentException("Argument jobz must be one of 'A','S' or 'N'"); 
+            try {
+                 double [] work = new  double [1] { ( double )0.0 };
+                int lwork = -1;
+                int[] iwork = new int[((m < n) ? m : n) * 8];
+                 lapack_dgesvd (ref jobz, ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, iwork, ref info);
+                if (work[0] != 0) {
+                    work = new  double [(int)work[0]];
+                    lwork = work.Length; 
+                     lapack_dgesvd (ref jobz, ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, iwork, ref info);
+                }
+            } catch (Exception e) {
+                if (e is OutOfMemoryException) {
+                    throw new ILMemoryException("Not enough memory for given arguments."); 
+                }
+                throw new ILException("Unable to do gesvd.", e);
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+       
+
+        /// <summary>
+        /// singular value decomposition
+        /// </summary>
+        /// <param name="jobz"></param>
+        /// <param name="m"></param>
+        /// <param name="n"></param>
+        /// <param name="a"></param>
+        /// <param name="lda"></param>
+        /// <param name="s"></param>
+        /// <param name="u"></param>
+        /// <param name="ldu"></param>
+        /// <param name="vt"></param>
+        /// <param name="ldvt"></param>
+        /// <param name="info"></param>
+        public void  sgesvd (char jobz, int m, int n,  float [] a, int lda,
+                           float [] s,  float [] u, int ldu,  float [] vt, int ldvt, ref int info) {
+            if (jobz != 'A' && jobz != 'S' && jobz != 'N')
+                throw new ILArgumentException("Argument jobz must be one of 'A','S' or 'N'"); 
+            try {
+                float [] work = new  float [1] { ( float )0.0 };
+                int lwork = -1;
+                int[] iwork = new int[((m < n) ? m : n) * 8];
+                lapack_sgesvd (ref jobz, ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, iwork, ref info);
+                if (work[0] != 0) {
+                    work = new  float [(int)work[0]];
+                    lwork = work.Length; 
+                    lapack_sgesvd (ref jobz, ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, iwork, ref info);
+                }
+            } catch (Exception e) {
+                if (e is OutOfMemoryException) {
+                    throw new ILMemoryException("Not enough memory for given arguments."); 
+                }
+                throw new ILException("Unable to do gesvd.", e);
+            }
+        }
+       
+
+        /// <summary>
+        /// singular value decomposition
+        /// </summary>
+        /// <param name="jobz"></param>
+        /// <param name="m"></param>
+        /// <param name="n"></param>
+        /// <param name="a"></param>
+        /// <param name="lda"></param>
+        /// <param name="s"></param>
+        /// <param name="u"></param>
+        /// <param name="ldu"></param>
+        /// <param name="vt"></param>
+        /// <param name="ldvt"></param>
+        /// <param name="info"></param>
+        public void  zgesvd (char jobz, int m, int n,  complex [] a, int lda,
+                           double [] s,  complex [] u, int ldu,  complex [] vt, int ldvt, ref int info) {
+            if (jobz != 'A' && jobz != 'S' && jobz != 'N')
+                throw new ILArgumentException("Argument jobz must be one of 'A','S' or 'N'"); 
+            try {
+                complex [] work = new  complex [1] { ( complex )0.0 };
+                int lwork = -1;
+                int[] iwork = new int[((m < n) ? m : n) * 8];
+                lapack_zgesvd (ref jobz, ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, iwork, ref info);
+                if (work[0] != 0) {
+                    work = new  complex [(int)work[0]];
+                    lwork = work.Length; 
+                    lapack_zgesvd (ref jobz, ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, iwork, ref info);
+                }
+            } catch (Exception e) {
+                if (e is OutOfMemoryException) {
+                    throw new ILMemoryException("Not enough memory for given arguments."); 
+                }
+                throw new ILException("Unable to do gesvd.", e);
+            }
+        }
+       
+
+        /// <summary>
+        /// singular value decomposition
+        /// </summary>
+        /// <param name="jobz"></param>
+        /// <param name="m"></param>
+        /// <param name="n"></param>
+        /// <param name="a"></param>
+        /// <param name="lda"></param>
+        /// <param name="s"></param>
+        /// <param name="u"></param>
+        /// <param name="ldu"></param>
+        /// <param name="vt"></param>
+        /// <param name="ldvt"></param>
+        /// <param name="info"></param>
+        public void  cgesvd (char jobz, int m, int n,  fcomplex [] a, int lda,
+                           float [] s,  fcomplex [] u, int ldu,  fcomplex [] vt, int ldvt, ref int info) {
+            if (jobz != 'A' && jobz != 'S' && jobz != 'N')
+                throw new ILArgumentException("Argument jobz must be one of 'A','S' or 'N'"); 
+            try {
+                fcomplex [] work = new  fcomplex [1] { ( fcomplex )0.0 };
+                int lwork = -1;
+                int[] iwork = new int[((m < n) ? m : n) * 8];
+                lapack_cgesvd (ref jobz, ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, iwork, ref info);
+                if (work[0] != 0) {
+                    work = new  fcomplex [(int)work[0]];
+                    lwork = work.Length; 
+                    lapack_cgesvd (ref jobz, ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, iwork, ref info);
+                }
+            } catch (Exception e) {
+                if (e is OutOfMemoryException) {
+                    throw new ILMemoryException("Not enough memory for given arguments."); 
+                }
+                throw new ILException("Unable to do gesvd.", e);
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+        public void dpotrf(char uplo, int n, double[] A, int lda, ref int info) {
+            lapack_dpotrf(ref uplo, ref n, A, ref lda, ref info);
+        }
+        public void spotrf(char uplo, int n, float[] A, int lda, ref int info) {
+            lapack_spotrf(ref uplo, ref n, A, ref lda, ref info);
+        }
+        public void cpotrf(char uplo, int n, fcomplex[] A, int lda, ref int info) {
+            lapack_cpotrf(ref uplo, ref n, A, ref lda, ref info);
+        }
+        public void zpotrf(char uplo, int n, complex[] A, int lda, ref int info) {
+            lapack_zpotrf(ref uplo, ref n, A, ref lda, ref info);
+        }
+
+
+        public void dpotri(char uplo, int n, double[] A, int lda, ref int info) {
+            lapack_dpotri(ref uplo, ref n, A, ref lda, ref info);
+        }
+        public void spotri(char uplo, int n, float[] A, int lda, ref int info) {
+            lapack_spotri(ref uplo, ref n, A, ref lda, ref info);
+        }
+        public void cpotri(char uplo, int n, fcomplex[] A, int lda, ref int info) {
+            lapack_cpotri(ref uplo, ref n, A, ref lda, ref info);
+        }
+        public void zpotri(char uplo, int n, complex[] A, int lda, ref int info) {
+            lapack_zpotri(ref uplo, ref n, A, ref lda, ref info);
+        }
+
+
+        public void dgetrf(int M, int N, double[] A, int LDA, int[] IPIV, ref int info) {
+            lapack_dgetrf(ref M, ref N, A, ref LDA, IPIV, ref info);
+        }
+        public void sgetrf(int M, int N, float[] A, int LDA, int[] IPIV, ref int info) {
+            lapack_sgetrf(ref M, ref N, A, ref LDA, IPIV, ref info);
+        }
+        public void cgetrf(int M, int N, fcomplex[] A, int LDA, int[] IPIV, ref int info) {
+            lapack_cgetrf(ref M, ref N, A, ref LDA, IPIV, ref info);
+        }
+        public void zgetrf(int M, int N, complex[] A, int LDA, int[] IPIV, ref int info) {
+            lapack_zgetrf(ref M, ref N, A, ref LDA, IPIV, ref info);
+        }
+
+
+        
+        public void  dgetri (int N,  double [] A, int LDA, int[] IPIV, ref int info) {
+             double [] work = new  double [1];  
+            int lwork = -1; 
+            try {
+                 lapack_dgetri (ref N, A, ref LDA, IPIV, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  double [lwork]; 
+                     lapack_dgetri (ref N, A, ref LDA, IPIV, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in lapack_dgetri"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on dgetri. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+       
+        public void  sgetri (int N,  float [] A, int LDA, int[] IPIV, ref int info) {
+            float [] work = new  float [1];  
+            int lwork = -1; 
+            try {
+                lapack_sgetri (ref N, A, ref LDA, IPIV, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  float [lwork]; 
+                    lapack_sgetri (ref N, A, ref LDA, IPIV, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in lapack_dgetri"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on dgetri. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+       
+        public void  zgetri (int N,  complex [] A, int LDA, int[] IPIV, ref int info) {
+            complex [] work = new  complex [1];  
+            int lwork = -1; 
+            try {
+                lapack_zgetri (ref N, A, ref LDA, IPIV, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  complex [lwork]; 
+                    lapack_zgetri (ref N, A, ref LDA, IPIV, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in lapack_dgetri"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on dgetri. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+       
+        public void  cgetri (int N,  fcomplex [] A, int LDA, int[] IPIV, ref int info) {
+            fcomplex [] work = new  fcomplex [1];  
+            int lwork = -1; 
+            try {
+                lapack_cgetri (ref N, A, ref LDA, IPIV, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  fcomplex [lwork]; 
+                    lapack_cgetri (ref N, A, ref LDA, IPIV, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in lapack_dgetri"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on dgetri. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+
+        
+        public void  dgeqrf (int M, int N,  double [] A, int lda,  double [] tau, ref int info) {
+             double [] work = new  double [1];  
+            int lwork = -1; 
+            try {
+                 lapack_dgeqrf (ref M, ref N, A, ref lda, tau, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  double [lwork]; 
+                     lapack_dgeqrf (ref M, ref N, A, ref lda, tau, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in lapack_?geqrf"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on ?geqrf. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+       
+        public void  sgeqrf (int M, int N,  float [] A, int lda,  float [] tau, ref int info) {
+            float [] work = new  float [1];  
+            int lwork = -1; 
+            try {
+                lapack_sgeqrf (ref M, ref N, A, ref lda, tau, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  float [lwork]; 
+                    lapack_sgeqrf (ref M, ref N, A, ref lda, tau, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in lapack_?geqrf"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on ?geqrf. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+       
+        public void  zgeqrf (int M, int N,  complex [] A, int lda,  complex [] tau, ref int info) {
+            complex [] work = new  complex [1];  
+            int lwork = -1; 
+            try {
+                lapack_zgeqrf (ref M, ref N, A, ref lda, tau, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  complex [lwork]; 
+                    lapack_zgeqrf (ref M, ref N, A, ref lda, tau, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in lapack_?geqrf"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on ?geqrf. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+       
+        public void  cgeqrf (int M, int N,  fcomplex [] A, int lda,  fcomplex [] tau, ref int info) {
+            fcomplex [] work = new  fcomplex [1];  
+            int lwork = -1; 
+            try {
+                lapack_cgeqrf (ref M, ref N, A, ref lda, tau, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  fcomplex [lwork]; 
+                    lapack_cgeqrf (ref M, ref N, A, ref lda, tau, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in lapack_?geqrf"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on ?geqrf. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+        public void dormqr(char side, char trans, int m, int n, int k, double[] A, int lda, double[] tau, double[] C, int LDC, ref int info) {
+            throw new Exception("The method or operation is not implemented.");
+        }
+        public void sormqr(char side, char trans, int m, int n, int k, float[] A, int lda, float[] tau, float[] C, int LDC, ref int info) {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+
+        
+        public void  dorgqr (int M, int N, int K,  double [] A, int lda,  double [] tau, ref int info) {
+             double [] work = new  double [1];  
+            int lwork = -1; 
+            try {
+                /*!HC:lapack_***gqr*/ lapack_dorgqr (ref M, ref N, ref K, A, ref lda, tau, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  double [lwork]; 
+                    /*!HC:lapack_***gqr*/ lapack_dorgqr (ref M, ref N, ref K, A, ref lda, tau, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in lapack_?[un/or]gqr"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on ?[un/or]gqr. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+       
+        public void  sorgqr (int M, int N, int K,  float [] A, int lda,  float [] tau, ref int info) {
+            float [] work = new  float [1];  
+            int lwork = -1; 
+            try {
+                lapack_sorgqr (ref M, ref N, ref K, A, ref lda, tau, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  float [lwork]; 
+                    lapack_sorgqr (ref M, ref N, ref K, A, ref lda, tau, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in lapack_?[un/or]gqr"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on ?[un/or]gqr. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+       
+        public void  zungqr (int M, int N, int K,  complex [] A, int lda,  complex [] tau, ref int info) {
+            complex [] work = new  complex [1];  
+            int lwork = -1; 
+            try {
+                lapack_zungqr (ref M, ref N, ref K, A, ref lda, tau, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  complex [lwork]; 
+                    lapack_zungqr (ref M, ref N, ref K, A, ref lda, tau, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in lapack_?[un/or]gqr"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on ?[un/or]gqr. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+       
+        public void  cungqr (int M, int N, int K,  fcomplex [] A, int lda,  fcomplex [] tau, ref int info) {
+            fcomplex [] work = new  fcomplex [1];  
+            int lwork = -1; 
+            try {
+                lapack_cungqr (ref M, ref N, ref K, A, ref lda, tau, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  fcomplex [lwork]; 
+                    lapack_cungqr (ref M, ref N, ref K, A, ref lda, tau, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in lapack_?[un/or]gqr"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on ?[un/or]gqr. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+
+        
+        public void  dgeqp3 ( int M,int N, double [] A,int LDA,int [] JPVT, double [] tau, ref int info ) {
+             double [] work = new  double [1];
+            int lwork = -1; 
+            try {
+                 
+                /*dummy*/
+                 
+                lapack_dgeqp3 (ref M, ref N, A, ref LDA, JPVT, tau, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  double [lwork]; 
+                     
+                    lapack_dgeqp3 (ref M, ref N, A, ref LDA, JPVT, tau, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in lapack_?geqp3"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on ?geqp3. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+       
+        public void  sgeqp3 ( int M,int N, float [] A,int LDA,int [] JPVT, float [] tau, ref int info ) {
+            float [] work = new  float [1];
+            int lwork = -1; 
+            try {
+                
+                lapack_sgeqp3 (ref M, ref N, A, ref LDA, JPVT, tau, work, ref lwork, ref info);
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  float [lwork]; 
+                    lapack_sgeqp3 (ref M, ref N, A, ref LDA, JPVT, tau, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in lapack_?geqp3"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on ?geqp3. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+       
+        public void  zgeqp3 ( int M,int N, complex [] A,int LDA,int [] JPVT, complex [] tau, ref int info ) {
+            complex [] work = new  complex [1];
+            int lwork = -1; 
+            try {
+                double[] rwork = new double[2 * N];
+                lapack_zgeqp3 (ref M, ref N, A, ref LDA, JPVT, tau, work, ref lwork, rwork, ref info);
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  complex [lwork]; 
+                    lapack_zgeqp3 (ref M, ref N, A, ref LDA, JPVT, tau, work, ref lwork, rwork, ref info);
+                } else {
+                    throw new ILException("error in lapack_?geqp3"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on ?geqp3. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+       
+        public void  cgeqp3 ( int M,int N, fcomplex [] A,int LDA,int [] JPVT, fcomplex [] tau, ref int info ) {
+            fcomplex [] work = new  fcomplex [1];
+            int lwork = -1; 
+            try {
+                float[] rwork = new float[2 * N];
+                lapack_cgeqp3 (ref M, ref N, A, ref LDA, JPVT, tau, work, ref lwork, rwork, ref info);
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  fcomplex [lwork]; 
+                    lapack_cgeqp3 (ref M, ref N, A, ref LDA, JPVT, tau, work, ref lwork, rwork, ref info);
+                } else {
+                    throw new ILException("error in lapack_?geqp3"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on ?geqp3. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+        public void dtrtrs(char uplo, char transA, char diag, int N, int nrhs, IntPtr A, int LDA, IntPtr B, int LDB, ref int info) {
+            lapack_dtrtrs(ref uplo, ref transA, ref diag, ref N, ref nrhs, A, ref LDA, B, ref LDB, ref info); 
+        }
+        public void strtrs(char uplo, char transA, char diag, int N, int nrhs, IntPtr A, int LDA, IntPtr B, int LDB, ref int info) {
+            lapack_strtrs(ref uplo, ref transA, ref diag, ref N, ref nrhs, A, ref LDA, B, ref LDB, ref info); 
+        }
+        public void ctrtrs(char uplo, char transA, char diag, int N, int nrhs, IntPtr A, int LDA, IntPtr B, int LDB, ref int info) {
+            lapack_ctrtrs(ref uplo, ref transA, ref diag, ref N, ref nrhs, A, ref LDA, B, ref LDB, ref info); 
+        }
+        public void ztrtrs(char uplo, char transA, char diag, int N, int nrhs, IntPtr A, int LDA, IntPtr B, int LDB, ref int info) {
+            lapack_ztrtrs(ref uplo, ref transA, ref diag, ref N, ref nrhs, A, ref LDA, B, ref LDB, ref info); 
+        }
+
+        public void dgetrs(char trans, int N, int NRHS, double[] A, int LDA, int[] IPIV, double[] B, int LDB, ref int info) {
+            lapack_dgetrs(ref trans,ref N,ref NRHS, A, ref LDA, IPIV, B, ref LDB, ref info);     
+        }
+
+        public void sgetrs(char trans, int N, int NRHS, float[] A, int LDA, int[] IPIV, float[] B, int LDB, ref int info) {
+            lapack_sgetrs(ref trans,ref N,ref NRHS, A, ref LDA, IPIV, B, ref LDB, ref info);     
+        }
+
+        public void cgetrs(char trans, int N, int NRHS, fcomplex[] A, int LDA, int[] IPIV, fcomplex[] B, int LDB, ref int info) {
+            lapack_cgetrs(ref trans,ref N,ref NRHS, A, ref LDA, IPIV, B, ref LDB, ref info);     
+        }
+
+        public void zgetrs(char trans, int N, int NRHS, complex[] A, int LDA, int[] IPIV, complex[] B, int LDB, ref int info) {
+            lapack_zgetrs(ref trans,ref N,ref NRHS, A, ref LDA, IPIV, B, ref LDB, ref info);
+        }
+        
+        public void dpotrs(char uplo, int n, int nrhs, double[] A, int lda, double[] B, int ldb, ref int info) {
+            lapack_dpotrs(ref uplo, ref n, ref nrhs, A, ref lda, B, ref ldb, ref info); 
+        }
+
+        public void spotrs(char uplo, int n, int nrhs, float[] A, int lda, float[] B, int ldb, ref int info) {
+            lapack_spotrs(ref uplo, ref n, ref nrhs, A, ref lda, B, ref ldb, ref info); 
+        }
+
+        public void cpotrs(char uplo, int n, int nrhs, fcomplex[] A, int lda, fcomplex[] B, int ldb, ref int info) {
+            lapack_cpotrs(ref uplo, ref n, ref nrhs, A, ref lda, B, ref ldb, ref info); 
+        }
+
+        public void zpotrs(char uplo, int n, int nrhs, complex[] A, int lda, complex[] B, int ldb, ref int info) {
+            lapack_zpotrs(ref uplo, ref n, ref nrhs, A, ref lda, B, ref ldb, ref info); 
+        }
+
+
+        
+        public void  dgelsd (int m, int n, int nrhs,  double [] A, int lda,  double [] B, int ldb,  double [] S,  double RCond, ref int rank, ref int info) {
+             double [] work = new  double [1]; 
+            int [] iwork = new int[1]; 
+            int lwork = -1; 
+            /*HC:HycalpTag1*/
+            lapack_dgelsd (ref m, ref n, ref nrhs, A, ref lda, B, ref ldb, S,ref RCond, ref rank, work, ref lwork, iwork, ref info);
+            if (info != 0) 
+                throw new ILArgumentException("dgelsd: invalid parameter: #" + (-info).ToString());
+            lwork = ILAENV(9, "dgelsd", " ",0,0,0,0); 
+            if (lwork <= 0)
+                throw new ILArgumentException("dgelsd: unknown error determining working size liwork");
+            iwork = new int[lwork];
+            lwork = (int)work[0];
+            work = new  double [lwork]; 
+            /*HC:HycalpTag2*/
+            lapack_dgelsd (ref m, ref n, ref nrhs, A, ref lda, B, ref ldb, S,ref RCond, ref rank, work, ref lwork, iwork, ref info);
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+       
+        public void  sgelsd  (int m, int n, int nrhs,  float [] A, int lda,  float [] B, int ldb,  float [] S,  float RCond, ref int rank, ref int info) {
+            float [] work = new  float [1]; 
+            int [] iwork = new int[1]; 
+            int lwork = -1; 
+            lapack_sgelsd (ref m, ref n, ref nrhs, A, ref lda, B, ref ldb, S,ref RCond, ref rank, work, ref lwork, iwork, ref info);
+            if (info != 0) 
+                throw new ILArgumentException("dgelsd: invalid parameter: #" + (-info).ToString());
+            lwork = ILAENV(9, "dgelsd", " ",0,0,0,0); 
+            if (lwork <= 0)
+                throw new ILArgumentException("dgelsd: unknown error determining working size liwork");
+            iwork = new int[lwork];
+            lwork = (int)work[0];
+            work = new  float [lwork]; 
+            lapack_sgelsd (ref m, ref n, ref nrhs, A, ref lda, B, ref ldb, S,ref RCond, ref rank, work, ref lwork, iwork, ref info);
+        }
+       
+        public void  zgelsd  (int m, int n, int nrhs,  complex [] A, int lda,  complex [] B, int ldb,  double [] S,  double RCond, ref int rank, ref int info) {
+            complex [] work = new  complex [1]; 
+            int [] iwork = new int[1]; 
+            int lwork = -1; 
+            double [] rwork = new double [1];  lapack_zgelsd (ref m, ref n, ref nrhs, A, ref lda, B, ref ldb, S,ref RCond, ref rank, work, ref lwork, rwork, iwork, ref info);
+            if (info != 0) 
+                throw new ILArgumentException("dgelsd: invalid parameter: #" + (-info).ToString());
+            lwork = ILAENV(9, "dgelsd", " ",0,0,0,0); 
+            if (lwork <= 0)
+                throw new ILArgumentException("dgelsd: unknown error determining working size liwork");
+            iwork = new int[lwork];
+            lwork = (int)work[0];
+            work = new  complex [lwork]; 
+            rwork = new double [(int)rwork[0]];  lapack_zgelsd (ref m, ref n, ref nrhs, A, ref lda, B, ref ldb, S,ref RCond, ref rank, work, ref lwork, rwork, iwork, ref info);
+        }
+       
+        public void  cgelsd  (int m, int n, int nrhs,  fcomplex [] A, int lda,  fcomplex [] B, int ldb,  float [] S,  float RCond, ref int rank, ref int info) {
+            fcomplex [] work = new  fcomplex [1]; 
+            int [] iwork = new int[1]; 
+            int lwork = -1; 
+            float [] rwork = new float [1];  lapack_cgelsd (ref m, ref n, ref nrhs, A, ref lda, B, ref ldb, S,ref RCond, ref rank, work, ref lwork, rwork, iwork, ref info);
+            if (info != 0) 
+                throw new ILArgumentException("dgelsd: invalid parameter: #" + (-info).ToString());
+            lwork = ILAENV(9, "dgelsd", " ",0,0,0,0); 
+            if (lwork <= 0)
+                throw new ILArgumentException("dgelsd: unknown error determining working size liwork");
+            iwork = new int[lwork];
+            lwork = (int)work[0];
+            work = new  fcomplex [lwork]; 
+            rwork = new float [(int)rwork[0]];  lapack_cgelsd (ref m, ref n, ref nrhs, A, ref lda, B, ref ldb, S,ref RCond, ref rank, work, ref lwork, rwork, iwork, ref info);
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+
+        
+        public void  dgelsy (int m, int n, int nrhs,  double [] A, int lda,  double [] B, int ldb, int[] JPVT0,  double RCond, ref int rank, ref int info) {
+            int lwork = -1;
+             double [] work = new  double [1]; 
+             //
+            /*!HC:lapack_?gelsy*/ 
+            lapack_dgelsy (ref m,ref n,ref nrhs,A,ref lda,B,ref ldb,JPVT0,ref RCond,ref rank,work,ref lwork,ref info);
+            if (info != 0)
+                throw new ILArgumentException("?gelsy: unable to determine optimal block size. cancelling...");
+            lwork = (int) work[0];
+            work = new  double [lwork];
+             //
+            /*!HC:lapack_?gelsy*/ 
+            lapack_dgelsy (ref m,ref n,ref nrhs,A,ref lda,B,ref ldb,JPVT0,ref RCond,ref rank,work,ref lwork,ref info);
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+       
+        public void  sgelsy  (int m, int n, int nrhs,  float [] A, int lda,  float [] B, int ldb, int[] JPVT0,  float RCond, ref int rank, ref int info) {
+            int lwork = -1;
+            float [] work = new  float [1]; 
+            
+            lapack_sgelsy (ref m,ref n,ref nrhs,A,ref lda,B,ref ldb,JPVT0,ref RCond,ref rank,work,ref lwork,ref info);
+            if (info != 0)
+                throw new ILArgumentException("?gelsy: unable to determine optimal block size. cancelling...");
+            lwork = (int) work[0];
+            work = new  float [lwork];
+            
+            lapack_sgelsy (ref m,ref n,ref nrhs,A,ref lda,B,ref ldb,JPVT0,ref RCond,ref rank,work,ref lwork,ref info);
+        }
+       
+        public void  zgelsy  (int m, int n, int nrhs,  complex [] A, int lda,  complex [] B, int ldb, int[] JPVT0,  double RCond, ref int rank, ref int info) {
+            int lwork = -1;
+            complex [] work = new  complex [1]; 
+            double[] rwork = new double[1];
+            lapack_zgelsy (ref m,ref n,ref nrhs,A,ref lda,B,ref ldb,JPVT0,ref RCond,ref rank,work,ref lwork, rwork, ref info);
+            if (info != 0)
+                throw new ILArgumentException("?gelsy: unable to determine optimal block size. cancelling...");
+            lwork = (int) work[0];
+            work = new  complex [lwork];
+            rwork = new double[lwork];
+            lapack_zgelsy (ref m,ref n,ref nrhs,A,ref lda,B,ref ldb,JPVT0,ref RCond,ref rank,work,ref lwork, rwork, ref info);
+        }
+       
+        public void  cgelsy  (int m, int n, int nrhs,  fcomplex [] A, int lda,  fcomplex [] B, int ldb, int[] JPVT0,  float RCond, ref int rank, ref int info) {
+            int lwork = -1;
+            fcomplex [] work = new  fcomplex [1]; 
+            float[] rwork = new float[1];
+            lapack_cgelsy (ref m,ref n,ref nrhs,A,ref lda,B,ref ldb,JPVT0,ref RCond,ref rank,work,ref lwork, rwork, ref info);
+            if (info != 0)
+                throw new ILArgumentException("?gelsy: unable to determine optimal block size. cancelling...");
+            lwork = (int) work[0];
+            work = new  fcomplex [lwork];
+            rwork = new float[lwork];
+            lapack_cgelsy (ref m,ref n,ref nrhs,A,ref lda,B,ref ldb,JPVT0,ref RCond,ref rank,work,ref lwork, rwork, ref info);
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+        #region ?GEEVX
+        public void dgeevx(char balance, char jobvl, char jobvr, char sense, int n, double[] A, int lda, double[] wr, double[] wi, double[] vl, int ldvl, double[] vr, int ldvr, ref int ilo, ref int ihi, double[] scale, ref double abnrm, double[] rconde, double[] rcondv, ref int info) {
+            double [] work = new double[1]; 
+            int lwork = -1;
+            int [] iwork = new int[2 * n - 2];
+            lapack_dgeevx(ref balance, ref jobvl, ref jobvr, ref sense, ref n, A, ref lda, wr, wi, vl, ref ldvl, vr, ref ldvr, ref ilo, ref ihi, scale, ref abnrm, rconde, rcondv, work, ref lwork, iwork, ref info);
+            if (info != 0) 
+                throw new ILArgumentException("error in lapack call: ?geevx. (" + info + ")");
+            lwork = (int)work[0]; 
+            work = new double[lwork]; 
+            lapack_dgeevx(ref balance, ref jobvl, ref jobvr, ref sense, ref n, A, ref lda, wr, wi, vl, ref ldvl, vr, ref ldvr, ref ilo, ref ihi, scale, ref abnrm, rconde, rcondv, work, ref lwork, iwork, ref info);
+        }
+        public void sgeevx(char balance, char jobvl, char jobvr, char sense, int n, float[] A, int lda, float[] wr, float[] wi, float[] vl, int ldvl, float[] vr, int ldvr, ref int ilo, ref int ihi, float[] scale, ref float abnrm, float[] rconde, float[] rcondv, ref int info) {
+            float [] work = new float[1]; 
+            int lwork = -1;
+            int [] iwork = new int[2 * n - 2];
+            lapack_sgeevx(ref balance, ref jobvl, ref jobvr, ref sense, ref n, A, ref lda, wr, wi, vl, ref ldvl, vr, ref ldvr, ref ilo, ref ihi, scale, ref abnrm, rconde, rcondv, work, ref lwork, iwork, ref info);
+            if (info != 0) 
+                throw new ILArgumentException("error in lapack call: ?geevx. (" + info + ")");
+            lwork = (int)work[0]; 
+            work = new float[lwork]; 
+            lapack_sgeevx(ref balance, ref jobvl, ref jobvr, ref sense, ref n, A, ref lda, wr, wi, vl, ref ldvl, vr, ref ldvr, ref ilo, ref ihi, scale, ref abnrm, rconde, rcondv, work, ref lwork, iwork, ref info);
+        }
+        public void cgeevx(char balance, char jobvl, char jobvr, char sense, int n, fcomplex[] A, int lda, fcomplex[] w, fcomplex[] vl, int ldvl, fcomplex[] vr, int ldvr, ref int ilo, ref int ihi, float[] scale, ref float abnrm, float[] rconde, float[] rcondv, ref int info) {
+            fcomplex [] work = new fcomplex[1]; 
+            int lwork = -1;
+            float[] rwork = new float[2 * n]; 
+            lapack_cgeevx(ref balance, ref jobvl, ref jobvr, ref sense, ref n, A, ref lda, w, vl, ref ldvl, vr, ref ldvr, ref ilo, ref ihi, scale, ref abnrm, rconde, rcondv, work, ref lwork, rwork, ref info);
+            if (info != 0) 
+                throw new ILArgumentException("error in lapack call: ?geevx. (" + info + ")");
+            lwork = (int)work[0]; 
+            work = new fcomplex[lwork]; 
+            lapack_cgeevx(ref balance, ref jobvl, ref jobvr, ref sense, ref n, A, ref lda, w, vl, ref ldvl, vr, ref ldvr, ref ilo, ref ihi, scale, ref abnrm, rconde, rcondv, work, ref lwork, rwork, ref info);
+        }
+        public void zgeevx(char balance, char jobvl, char jobvr, char sense, int n, complex[] A, int lda, complex[] w, complex[] vl, int ldvl, complex[] vr, int ldvr, ref int ilo, ref int ihi, double[] scale, ref double abnrm, double[] rconde, double[] rcondv, ref int info) {
+            complex [] work = new complex[1]; 
+            int lwork = -1;
+            double[] rwork = new double[2 * n]; 
+            lapack_zgeevx(ref balance, ref jobvl, ref jobvr, ref sense, ref n, A, ref lda, w, vl, ref ldvl, vr, ref ldvr, ref ilo, ref ihi, scale, ref abnrm, rconde, rcondv, work, ref lwork, rwork, ref info);
+            if (info != 0) 
+                throw new ILArgumentException("error in lapack call: ?geevx. (" + info + ")");
+            lwork = (int)work[0]; 
+            work = new complex[lwork]; 
+            lapack_zgeevx(ref balance, ref jobvl, ref jobvr, ref sense, ref n, A, ref lda, w, vl, ref ldvl, vr, ref ldvr, ref ilo, ref ihi, scale, ref abnrm, rconde, rcondv, work, ref lwork, rwork, ref info);
+        }
+        #endregion
+
+        #region ?SYEVR
+        public void dsyevr(char jobz, char range, char uplo, int n, double[] A, int lda, double vl, double vu, int il, int iu, double abstol, ref int m, double[] w, double[] z, int ldz, int[] isuppz, ref int info) {
+            double [] work = new double[1]; 
+            int lwork = -1, liwork = -1; 
+            int [] iwork = new int[1]; 
+            lapack_dsyevr(ref jobz,ref range,ref uplo,ref n, A,ref lda, ref vl, ref vu, ref il, ref iu, ref abstol,ref m, w,z,ref ldz,isuppz, work,ref lwork,iwork,ref liwork,ref info);
+            if (info != 0) {
+                throw new ILArgumentException("?syevr: error returned from lapack: " + info);
+            }
+            lwork = (int)work[0]; 
+            work = new double[lwork];
+            liwork = (int) iwork[0]; 
+            iwork = new int[liwork]; 
+            lapack_dsyevr(ref jobz,ref range,ref uplo,ref n, A,ref lda, ref vl, ref vu, ref il, ref iu, ref abstol,ref m, w,z,ref ldz,isuppz, work,ref lwork,iwork,ref liwork,ref info);
+        }
+        public void ssyevr(char jobz, char range, char uplo, int n, float[] A, int lda, float vl, float vu, int il, int iu, float abstol, ref int m, float[] w, float[] z, int ldz, int[] isuppz, ref int info) {
+            float [] work = new float[1]; 
+            int lwork = -1, liwork = -1; 
+            int [] iwork = new int[1]; 
+            lapack_ssyevr(ref jobz,ref range,ref uplo,ref n, A,ref lda, ref vl, ref vu, ref il, ref iu, ref abstol,ref m, w,z,ref ldz,isuppz, work,ref lwork,iwork,ref liwork,ref info);
+            if (info != 0) {
+                throw new ILArgumentException("?syevr: error returned from lapack: " + info);
+            }
+            lwork = (int)work[0]; 
+            work = new float[lwork];
+            liwork = (int) iwork[0]; 
+            iwork = new int[liwork]; 
+            lapack_ssyevr(ref jobz,ref range,ref uplo,ref n, A,ref lda, ref vl, ref vu, ref il, ref iu, ref abstol,ref m, w,z,ref ldz,isuppz, work,ref lwork,iwork,ref liwork,ref info);
+        }
+        public void cheevr(char jobz, char range, char uplo, int n, fcomplex[] A, int lda, float vl, float vu, int il, int iu, float abstol, ref int m, float[] w, fcomplex[] z, int ldz, int[] isuppz, ref int info) {
+            fcomplex[] work = new fcomplex[1]; 
+            float [] rwork = new float[1]; 
+            int [] iwork = new int[1]; 
+            int lrwork = -1, liwork = -1, lwork = -1; 
+            lapack_cheevr(ref jobz,ref range,ref uplo,ref n, A,ref lda, ref vl, ref vu, ref il, ref iu, ref abstol,ref m, w,z,ref ldz,isuppz, work,ref lwork,rwork,ref lrwork, iwork,ref liwork,ref info);
+            if (info != 0) {
+                throw new ILArgumentException("?syevr: error returned from lapack: " + info);
+            }
+            lrwork = (int)rwork[0]; 
+            rwork = new float[lrwork];
+            lwork = (int) work[0]; 
+            work = new fcomplex[lwork]; 
+            liwork = (int) iwork[0]; 
+            iwork = new int[liwork]; 
+            lapack_cheevr(ref jobz,ref range,ref uplo,ref n, A,ref lda, ref vl, ref vu, ref il, ref iu, ref abstol,ref m, w,z,ref ldz,isuppz, work,ref lwork,rwork,ref lrwork,iwork,ref liwork,ref info);
+        }
+        public void zheevr(char jobz, char range, char uplo, int n, complex[] A, int lda, double vl, double vu, int il, int iu, double abstol, ref int m, double[] w, complex[] z, int ldz, int[] isuppz, ref int info) {
+            complex[] work = new complex[1]; 
+            double [] rwork = new double[1]; 
+            int [] iwork = new int[1]; 
+            int lrwork = -1, liwork = -1, lwork = -1; 
+            lapack_zheevr(ref jobz,ref range,ref uplo,ref n, A,ref lda, ref vl, ref vu, ref il, ref iu, ref abstol,ref m, w,z,ref ldz,isuppz, work,ref lwork,rwork,ref lrwork, iwork,ref liwork,ref info);
+            if (info != 0) {
+                throw new ILArgumentException("?syevr: error returned from lapack: " + info);
+            }
+            lrwork = (int)rwork[0]; 
+            rwork = new double[lrwork];
+            lwork = (int) work[0]; 
+            work = new complex[lwork]; 
+            liwork = (int) iwork[0]; 
+            iwork = new int[liwork]; 
+            lapack_zheevr(ref jobz,ref range,ref uplo,ref n, A,ref lda, ref vl, ref vu, ref il, ref iu, ref abstol,ref m, w,z,ref ldz,isuppz, work,ref lwork,rwork,ref lrwork,iwork,ref liwork,ref info);
+        }
+        #endregion
+
+        #region ?[he/sy]gv - generalized eigenproblem
+        public void dsygv (int itype, char jobz, char uplo, int n, double  [] A, int lda, double  [] B, int ldb, double [] w, ref int info) {
+            // query workspace 
+            int lwork = -1; 
+            double [] work = new double[1] {0.0}; 
+            lapack_dsygv (ref itype,ref jobz,ref uplo,ref n, A,ref lda, B,ref ldb, w, work, ref lwork, ref info); 
+            if (info != 0 || work[0] <= 0.0) return; 
+            // create temporary array(s)
+            lwork = (int) work[0]; 
+            work = ILMemoryPool.Pool.New<double>(lwork); 
+            lapack_dsygv (ref itype,ref jobz,ref uplo,ref n, A,ref lda, B,ref ldb, w, work, ref lwork, ref info); 
+            ILMemoryPool.Pool.Free(work); 
+        }        
+        public void ssygv (int itype, char jobz, char uplo, int n, float   [] A, int lda, float   [] B, int ldb, float  [] w, ref int info) {
+            // query workspace 
+            int lwork = -1; 
+            float [] work = new float[1] {0.0f}; 
+            lapack_ssygv (ref itype,ref jobz,ref uplo,ref n, A,ref lda, B,ref ldb, w, work, ref lwork, ref info); 
+            if (info != 0 || work[0] <= 0.0) return; 
+            // create temporary array(s)
+            lwork = (int) work[0]; 
+            work = ILMemoryPool.Pool.New<float>(lwork); 
+            lapack_ssygv (ref itype,ref jobz,ref uplo,ref n, A,ref lda, B,ref ldb, w, work, ref lwork, ref info); 
+            ILMemoryPool.Pool.Free(work); 
+        }
+        public void chegv (int itype, char jobz, char uplo, int n, fcomplex[] A, int lda, fcomplex[] B, int ldb, float  [] w, ref int info) {
+            // query workspace 
+            int lwork = -1; 
+            fcomplex [] work = new fcomplex[1] {0.0f}; 
+            float [] rwork = ILMemoryPool.Pool.New<float>(Math.Max(1,3*n-2)); 
+            lapack_chegv(ref itype,ref  jobz,ref  uplo,ref  n, A,ref  lda, B,ref  ldb, w, work, ref lwork, rwork, ref info); 
+            if (info != 0 || work[0] <= 0.0) return; 
+            // create temporary array(s)
+            lwork = (int) work[0]; 
+            work = ILMemoryPool.Pool.New<fcomplex>(lwork); 
+            lapack_chegv (ref itype,ref  jobz,ref  uplo,ref  n, A,ref  lda, B,ref  ldb, w, work, ref lwork, rwork, ref info); 
+            ILMemoryPool.Pool.Free(rwork); 
+            ILMemoryPool.Pool.Free(work); 
+        }
+        public void zhegv (int itype, char jobz, char uplo, int n, complex [] A, int lda, complex [] B, int ldb, double [] w, ref int info) { 
+            // query workspace 
+            int lwork = -1; 
+            complex [] work = new complex[1] {0.0f}; 
+            double [] rwork = ILMemoryPool.Pool.New<double>(Math.Max(1,3*n-2)); 
+            lapack_zhegv(ref itype,ref  jobz,ref  uplo,ref  n, A,ref  lda, B,ref  ldb, w, work, ref lwork, rwork, ref info); 
+            if (info != 0 || work[0] <= 0.0) return; 
+            // create temporary array(s)
+            lwork = (int) work[0]; 
+            work = ILMemoryPool.Pool.New<complex>(lwork); 
+            lapack_zhegv (ref itype,ref  jobz,ref  uplo,ref  n, A,ref  lda, B,ref  ldb, w, work, ref lwork, rwork, ref info); 
+            ILMemoryPool.Pool.Free(rwork); 
+            ILMemoryPool.Pool.Free(work); 
+        }
+        #endregion 
+
+        #endregion
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Native/lapack/ILLapackGeneric.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Native/lapack/ILLapackGeneric.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Native/lapack/ILLapackGeneric.cs	(revision 9102)
@@ -0,0 +1,1314 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+#pragma warning disable 1591
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Native;
+using System.Runtime.InteropServices;
+using ILNumerics.Exceptions;
+using System.Security; 
+using ILNumerics.Misc; 
+
+namespace ILNumerics.Native  {
+    /// <summary>
+    /// Generic LAPACK implementation, unsupported processor types
+    /// </summary>
+	public class ILLapackGeneric : IILLapack {
+
+        #region DLL INCLUDES 
+        [DllImport("lapack_gen", EntryPoint = "ilaenv"),SuppressUnmanagedCodeSecurity]
+        private static extern int lapack_ilaenv(ref int ispec, ref string name, ref string opts, ref int n1, ref int n2, ref int n3, ref int n4);
+
+        ///////////////////////////   DOUBLE LAPACK /////////////////////////////////
+        [DllImport("lapack_gen", EntryPoint = "dgemm"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dgemm(ref char TransA, ref char TransB, ref int M,ref int N, ref int K, ref  double alpha, IntPtr A, ref int lda, IntPtr B, ref int ldb, ref double beta, double[] C, ref int ldc);
+        [DllImport("lapack_gen", EntryPoint = "sgemm"),SuppressUnmanagedCodeSecurity]
+		private static extern void lapack_sgemm(ref char TransA, ref char TransB, ref int M,ref int N, ref int K, ref float alpha, IntPtr A,ref int lda, IntPtr B, ref int ldb, ref float beta,float[] C, ref int ldc);
+        [DllImport("lapack_gen", EntryPoint = "cgemm"),SuppressUnmanagedCodeSecurity]
+		private static extern void lapack_cgemm(ref char TransA, ref char TransB, ref int M,ref int N, ref int K, ref fcomplex alpha, IntPtr A, ref int lda, IntPtr B, ref int ldb, ref fcomplex beta,[In,Out] fcomplex [] C, ref int ldc);
+        [DllImport("lapack_gen", EntryPoint = "zgemm"),SuppressUnmanagedCodeSecurity]
+		private static extern void lapack_zgemm(ref char TransA, ref char TransB, ref int M, ref int N, ref int K, ref complex alpha, IntPtr A, ref int lda, IntPtr B, ref int ldb, ref complex beta,[In,Out] complex [] C, ref int ldc);
+
+        [DllImport("lapack_gen", EntryPoint = "dgesdd"),SuppressUnmanagedCodeSecurity]
+		private static extern void lapack_dgesdd(ref char jobz, ref int m, ref int n,double[] a, ref int lda, double[] s,double[] u, ref int ldu, double[] vt,ref int ldvt, double[] work, ref int lwork,int[] iwork, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "sgesdd"),SuppressUnmanagedCodeSecurity]
+		private static extern void lapack_sgesdd(ref char jobz, ref int m, ref int n,float[] a, ref int lda, float[] s,float[] u, ref int ldu, float[] vt, ref int ldvt, float[] work, ref int lwork,int[] iwork, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "cgesdd"),SuppressUnmanagedCodeSecurity]
+		private static extern void lapack_cgesdd(ref char jobz, ref int m, ref int n,[In, Out] fcomplex[] a, ref int lda, float[] s,[In, Out] fcomplex[] u, ref int ldu, [In, Out]  fcomplex[] vt, ref int ldvt, [In, Out] fcomplex[] work, ref int lwork,[In,Out] float[] rwork, int[] iwork, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "zgesdd"),SuppressUnmanagedCodeSecurity]
+		private static extern void lapack_zgesdd(ref char jobz, ref int m, ref int n,[In, Out] complex[] a, ref int lda, double[] s,[In, Out] complex[] u, ref int ldu, [In, Out] complex[] vt,ref int ldvt, [In, Out] complex[] work, ref int lwork,[In,Out] double[] rwork, int[] iwork, ref int info);
+
+        [DllImport("lapack_gen", EntryPoint = "dgesvd"),SuppressUnmanagedCodeSecurity]
+		private static extern void lapack_dgesvd(ref char jobu, ref  char jobvt, ref int m, ref int n,double[] a, ref int lda, double[] s,double[] u, ref int ldu, double[] vt,ref int ldvt, double[] work, ref int lwork,int[] iwork,ref int info);
+        [DllImport("lapack_gen", EntryPoint = "sgesvd"),SuppressUnmanagedCodeSecurity]
+		private static extern void lapack_sgesvd(ref char jobu, ref  char jobvt, ref int m, ref int n, float[] a, ref int lda, float[] s,float[] u, ref int ldu, float[] vt,ref int ldvt, float[] work, ref int lwork,int[] iwork, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "cgesvd"),SuppressUnmanagedCodeSecurity]
+		private static extern void lapack_cgesvd(ref char jobu, ref  char jobvt, ref int m, ref int n,[In, Out] fcomplex[] a, ref int lda, float[] s,[In, Out] fcomplex[] u, ref int ldu,[In,Out] fcomplex[] vt,ref int ldvt, [In, Out]  fcomplex[] work, ref int lwork,int[] iwork,ref int info);
+        [DllImport("lapack_gen", EntryPoint = "zgesvd"),SuppressUnmanagedCodeSecurity]
+		private static extern void lapack_zgesvd(ref char jobu, ref  char jobvt, ref int m, ref int n,[In, Out] complex[] a, ref int lda, double[] s,[In, Out] complex[] u, ref int ldu, [In, Out] complex[] vt,ref int ldvt, [In, Out]  complex[] work, ref int lwork,int[] iwork,ref int info);
+
+        [DllImport("lapack_gen", EntryPoint = "dpotrf"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dpotrf (ref char uplo, ref int n, double [] A, ref int lda, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "spotrf"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_spotrf (ref char uplo, ref int n, float [] A, ref int lda, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "cpotrf"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_cpotrf (ref char uplo, ref int n,[In,Out] fcomplex [] A, ref int lda, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "zpotrf"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_zpotrf (ref char uplo, ref int n, [In,Out] complex [] A, ref int lda, ref int info);
+        
+        [DllImport("lapack_gen", EntryPoint = "dpotri"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dpotri (ref char uplo,ref  int n, double [] A, ref int lda, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "spotri"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_spotri (ref char uplo, ref int n, float [] A, ref int lda, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "cpotri"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_cpotri (ref char uplo, ref int n,[In,Out] fcomplex [] A, ref int lda,ref int info);
+        [DllImport("lapack_gen", EntryPoint = "zpotri"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_zpotri (ref char uplo, ref int n, [In,Out] complex [] A, ref int lda,ref int info);
+
+        [DllImport("lapack_gen", EntryPoint = "dpotrs"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dpotrs (ref char uplo,ref  int n, ref int NRHS, double [] A, ref int lda, double[] B, ref int ldb, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "spotrs"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_spotrs (ref char uplo,ref  int n, ref int NRHS, float [] A, ref int lda, float[] B, ref int ldb, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "cpotrs"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_cpotrs (ref char uplo,ref  int n, ref int NRHS, [In,Out] fcomplex [] A, ref int lda, [In,Out] fcomplex[] B, ref int ldb, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "zpotrs"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_zpotrs (ref char uplo,ref  int n, ref int NRHS, [In,Out] complex [] A, ref int lda, [In,Out] complex[] B, ref int ldb, ref int info);
+
+        [DllImport("lapack_gen", EntryPoint = "dgetrf"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dgetrf (ref int M, ref int N, double [] A, ref int LDA, int[] IPIV, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "sgetrf"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_sgetrf (ref int M, ref int N, float[] A, ref int LDA, int [] IPIV, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "cgetrf"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_cgetrf (ref int M, ref int N, [In,Out] fcomplex [] A, ref int LDA, int [] IPIV, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "zgetrf"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_zgetrf (ref int M, ref int N, [In,Out] complex [] A, ref int LDA, int [] IPIV, ref int info);
+
+        [DllImport("lapack_gen", EntryPoint = "dgetri"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dgetri (ref int N, double[] A,ref  int LDA, int[] IPIV, double[] work, ref int lwork, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "sgetri"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_sgetri (ref int N, float [] A, ref int LDA, int [] IPIV, float[] work, ref int lwork, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "cgetri"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_cgetri (ref int N, [In,Out] fcomplex [] A, ref int LDA,[In,Out] int [] IPIV, [In,Out] fcomplex[] work, ref int lwork, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "zgetri"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_zgetri (ref int N, [In,Out] complex [] A, ref int LDA, int [] IPIV, [In,Out] complex[] work, ref int lwork, ref int info);
+
+        [DllImport("lapack_gen", EntryPoint = "dgeqrf"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dgeqrf (ref int M, ref int N, double [] A, ref int lda, double [] tau, double[] work, ref int lwork, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "sgeqrf"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_sgeqrf (ref int M, ref int N, float [] A, ref int lda, float [] tau, float[] work, ref int lwork,  ref int info);
+        [DllImport("lapack_gen", EntryPoint = "cgeqrf"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_cgeqrf (ref int M, ref int N, [In,Out] fcomplex [] A, ref int lda, [In,Out] fcomplex [] tau, [In,Out] fcomplex[] work, ref int lwork, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "zgeqrf"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_zgeqrf (ref int M, ref int N, [In,Out] complex [] A, ref int lda, [In,Out] complex [] tau, [In,Out] complex[] work, ref int lwork,  ref int info);
+
+        [DllImport("lapack_gen", EntryPoint = "dgeqp3"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dgeqp3 (ref int M, ref int N, double [] A, ref int LDA, int [] JPVT, double [] tau, double [] work, ref int lwork, ref int info );
+        [DllImport("lapack_gen", EntryPoint = "sgeqp3"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_sgeqp3 (ref int M, ref int N, float [] A, ref int LDA, int [] JPVT, float [] tau, float [] work, ref int lwork, ref int info );
+        [DllImport("lapack_gen", EntryPoint = "cgeqp3"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_cgeqp3 (ref int M, ref int N,[In,Out] fcomplex [] A, ref int LDA,[In,Out] int [] JPVT, [In,Out] fcomplex [] tau, [In,Out] fcomplex [] work, ref int lwork,[In,Out] float [] rwork, ref int info );
+        [DllImport("lapack_gen", EntryPoint = "zgeqp3"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_zgeqp3 (ref int M, ref int N, [In,Out] complex [] A, ref int LDA, [In,Out] int [] JPVT, [In,Out] complex [] tau, [In,Out] complex [] work, ref int lwork, [In,Out] double [] rwork, ref int info );
+
+        [DllImport("lapack_gen", EntryPoint = "dormqr"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dormqr (ref char side, ref char trans, ref int m, ref int n, ref int k, double[] A, int lda, double[] tau, double[] C, ref int ldc, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "sormqr"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_sormqr (ref char side, ref char trans, ref int m, ref int n, ref int k, float [] A, ref int lda, float [] tau , float [] C, ref int ldc, ref int info);
+        
+        [DllImport("lapack_gen", EntryPoint = "dorgqr"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dorgqr (ref int m, ref int n, ref int k, double[] A,ref int lda, double[] tau, double[] work, ref int lwork, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "sorgqr"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_sorgqr (ref int m, ref int n, ref int k, float [] A, ref int lda, float [] tau , float[] work, ref int lwork,  ref int info);
+        [DllImport("lapack_gen", EntryPoint = "cungqr"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_cungqr (ref int m, ref int n, ref int k, [In,Out] fcomplex[] A,ref int lda, [In,Out] fcomplex[] tau, [In,Out] fcomplex[] work, ref int lwork, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "zungqr"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_zungqr (ref int m, ref int n, ref int k, [In,Out] complex[] A,ref int lda, [In,Out] complex[] tau, [In,Out] complex[] work, ref int lwork, ref int info);
+        
+        [DllImport("lapack_gen", EntryPoint = "dtrtrs"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dtrtrs (ref char uplo, ref char transA, ref char diag, ref int N, ref int nrhs, IntPtr A, ref int LDA, IntPtr B, ref int LDB, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "strtrs"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_strtrs (ref char uplo, ref char transA, ref char diag, ref int N, ref int nrhs, IntPtr A, ref int LDA, IntPtr B, ref int LDB, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "ctrtrs"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_ctrtrs (ref char uplo, ref char transA, ref char diag, ref int N, ref int nrhs, IntPtr A, ref int LDA, IntPtr B, ref int LDB, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "ztrtrs"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_ztrtrs (ref char uplo, ref char transA, ref char diag, ref int N, ref int nrhs, IntPtr A, ref int LDA, IntPtr B, ref int LDB, ref int info);
+        
+        [DllImport("lapack_gen", EntryPoint = "dgetrs"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dgetrs(ref char trans, ref int N, ref int NRHS, double[] A, ref int LDA, int[] IPIV, double[] B, ref int LDB, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "sgetrs"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_sgetrs(ref char trans, ref int N, ref int NRHS, float[] A, ref int LDA, int[] IPIV, float[] B, ref int LDB, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "cgetrs"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_cgetrs(ref char trans, ref int N, ref int NRHS, [In,Out] fcomplex[] A, ref int LDA, int[] IPIV, [In,Out] fcomplex[] B, ref int LDB, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "zgetrs"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_zgetrs(ref char trans, ref int N, ref int NRHS, [In,Out] complex[] A, ref int LDA, int[] IPIV, [In,Out] complex[] B, ref int LDB, ref int info);
+
+        [DllImport("lapack_gen", EntryPoint = "dgelsd"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dgelsd (ref int m,ref int n,ref int nrhs, double[] A,ref int lda, double[] B,ref int ldb, double[] S, ref double RCond, ref int rank, double[] work,ref int lwork, int[] iwork, ref int info); 
+        [DllImport("lapack_gen", EntryPoint = "sgelsd"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_sgelsd (ref int m,ref int n,ref int nrhs, float[] A,ref int lda, float[] B,ref int ldb, float[] S, ref float RCond, ref int rank, float[] work,ref int lwork, int[] iwork, ref int info); 
+        [DllImport("lapack_gen", EntryPoint = "cgelsd"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_cgelsd (ref int m,ref int n,ref int nrhs, [In,Out] fcomplex[] A,ref int lda, [In,Out] fcomplex[] B,ref int ldb, float[] S , ref float RCond, ref int rank, [In,Out] fcomplex[] work, ref int lwork, float[] rwork, int[] iwork, ref int info); 
+        [DllImport("lapack_gen", EntryPoint = "zgelsd"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_zgelsd (ref int m,ref int n,ref int nrhs, [In,Out] complex[] A,ref int lda, [In,Out] complex[] B,ref int ldb, double[] S, ref double RCond, ref int rank, [In,Out]  complex[] work,ref int lwork, double[] rwork, int[] iwork, ref int info); 
+        
+        [DllImport("lapack_gen", EntryPoint = "dgelsy"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dgelsy (ref int m,ref int n,ref int nrhs, double[] A,ref int lda, double[] B,ref int ldb, int[] JPVT0, ref double RCond, ref int rank, double[] work, ref int lwork, ref int info); 
+        [DllImport("lapack_gen", EntryPoint = "sgelsy"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_sgelsy (ref int m,ref int n,ref int nrhs, float[] A,ref int lda, float[] B,ref int ldb, int[] JPVT0, ref float RCond, ref int rank, float[] work,ref int lwork, ref int info); 
+        [DllImport("lapack_gen", EntryPoint = "cgelsy"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_cgelsy (ref int m,ref int n,ref int nrhs, [In,Out] fcomplex[] A,ref int lda, [In,Out] fcomplex[] B,ref int ldb, int[] JPVT0, ref float RCond, ref int rank, [In,Out] fcomplex[] work, ref int lwork, float[] rwork, ref int info); 
+        [DllImport("lapack_gen", EntryPoint = "zgelsy"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_zgelsy (ref int m,ref int n,ref int nrhs, [In,Out] complex[] A,ref int lda, [In,Out] complex[] B,ref int ldb, int[] JPVT0, ref double RCond, ref int rank, [In,Out]  complex[] work, ref int lwork, double[] rwork, ref int info); 
+        
+        [DllImport("lapack_gen", EntryPoint = "dgeevx"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dgeevx (ref char balance, ref char jobvl, ref char jobvr, ref char sense, ref int n,            double[] A, ref int lda,          double[] wr, double[] wi, double[] vl, ref int ldvl,            double[] vr, ref int ldvr, ref int ilo, ref int ihi, double[] scale, ref double abnrm, double[] rconde, double[] rcondv, double[] work, ref int lwork, int [] iwork, ref int info); 
+        [DllImport("lapack_gen", EntryPoint = "sgeevx"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_sgeevx (ref char balance, ref char jobvl, ref char jobvr, ref char sense, ref int n,             float[] A, ref int lda,             float[] wr, float[] wi, float[] vl, ref int ldvl,             float[] vr, ref int ldvr, ref int ilo, ref int ihi, float[]  scale, ref float  abnrm, float[]  rconde, float[]  rcondv, float [] work, ref int lwork, int [] iwork, ref int info); 
+        [DllImport("lapack_gen", EntryPoint = "cgeevx"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_cgeevx (ref char balance, ref char jobvl, ref char jobvr, ref char sense, ref int n, [In,Out] fcomplex[] A, ref int lda, [In,Out] fcomplex[] w,  [In,Out] fcomplex[] vl, ref int ldvl, [In,Out] fcomplex[] vr, ref int ldvr, ref int ilo, ref int ihi, float[]  scale, ref float  abnrm, float[]  rconde, float[]  rcondv, [In,Out] fcomplex[] work, ref int lwork, float[] rwork, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "zgeevx"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_zgeevx (ref char balance, ref char jobvl, ref char jobvr, ref char sense, ref int n, [In,Out]  complex[] A, ref int lda, [In,Out] complex[]  w,   [In,Out] complex[] vl, ref int ldvl, [In,Out]  complex[] vr, ref int ldvr, ref int ilo, ref int ihi, double[] scale, ref double abnrm, double[] rconde, double[] rcondv, [In,Out] complex[] work, ref int lwork, double[] rwork, ref int info);
+
+        [DllImport("lapack_gen", EntryPoint = "dsyevr"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dsyevr (ref char jobz, ref char range, ref char uplo, ref int n,          double  [] A, ref int lda, ref double vl, ref double vu, ref int il, ref int iu, ref double abstol, ref int m, double[] w,          double  [] z, ref int ldz, int[] isuppz, double[] work, ref int lwork, int[] iwork, ref int liwork, ref int info); 
+        [DllImport("lapack_gen", EntryPoint = "ssyevr"),SuppressUnmanagedCodeSecurity]                                                                                                                                                                                                                                         
+        private static extern void lapack_ssyevr (ref char jobz, ref char range, ref char uplo, ref int n,          float   [] A, ref int lda, ref float  vl, ref float  vu, ref int il, ref int iu, ref float  abstol, ref int m, float [] w,          float   [] z, ref int ldz, int[] isuppz, float [] work, ref int lwork, int[] iwork, ref int liwork, ref int info); 
+        [DllImport("lapack_gen", EntryPoint = "cheevr"),SuppressUnmanagedCodeSecurity]                                                                                                                                                                                                                                         
+        private static extern void lapack_cheevr (ref char jobz, ref char range, ref char uplo, ref int n, [In,Out] fcomplex[] A, ref int lda, ref float  vl, ref float  vu, ref int il, ref int iu, ref float  abstol, ref int m, float [] w, [In,Out] fcomplex[] z, ref int ldz, int[] isuppz, [In,Out] fcomplex[] work, ref int lwork, float[] rwork, ref int lrwork, int[] iwork, ref int liwork, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "zheevr"),SuppressUnmanagedCodeSecurity]                                                                                                                                                                                                                                         
+        private static extern void lapack_zheevr (ref char jobz, ref char range, ref char uplo, ref int n, [In,Out] complex [] A, ref int lda, ref double vl, ref double vu, ref int il, ref int iu, ref double abstol, ref int m, double[] w, [In,Out] complex [] z, ref int ldz, int[] isuppz, [In,Out] complex[] work, ref int lwork, double[] rwork, ref int lrwork, int[] iwork, ref int liwork, ref int info);
+
+        [DllImport("lapack_gen", EntryPoint = "dsygv"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dsygv (ref int itype, ref char jobz, ref char uplo, ref int n, double  [] A, ref int lda, double  [] B, ref int ldb, double [] w, double [] work, ref int lwork, ref int info); 
+        [DllImport("lapack_gen", EntryPoint = "ssygv"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_ssygv (ref int itype, ref char jobz, ref char uplo, ref int n, float   [] A, ref int lda, float   [] B, ref int ldb, float [] w,  float  [] work, ref int lwork, ref int info); 
+        [DllImport("lapack_gen", EntryPoint = "chegv"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_chegv (ref int itype, ref char jobz, ref char uplo, ref int n, [In,Out] fcomplex[] A, ref int lda, [In,Out] fcomplex [] B, ref int ldb, float  [] w, [In,Out] fcomplex[] work , ref int lwork, float[] rwork, ref int info); 
+        [DllImport("lapack_gen", EntryPoint = "zhegv"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_zhegv (ref int itype, ref char jobz, ref char uplo, ref int n, [In,Out] complex [] A, ref int lda, [In,Out] complex  [] B, ref int ldb, double [] w, [In,Out]  complex[] work , ref int lwork, double[] rwork, ref int info); 
+
+#endregion DLL INCLUDES 
+
+        #region ILLAPACK INTERFACE 
+
+        private int ILAENV (int ispec, string name, string opts, int n1, int n2, int n3, int n4) {
+            return lapack_ilaenv(ref ispec, ref name, ref opts, ref n1, ref n2, ref n3, ref n4); 
+        }
+
+        /// <summary>
+        /// Implement wrapper for ATLAS GeneralMatrixMultiply
+        /// </summary>
+        /// <param name="TransA">Transposition state for matrix A: one of the constants in enum CBlas_Transpose</param>
+        /// <param name="TransB">Transposition state for matrix B: one of the constants in enum CBlas_Transpose</param>
+        /// <param name="M">Number of rows in A</param>
+        /// <param name="N">Number of columns in B</param>
+        /// <param name="K">Number of columns in A and number of rows in B</param>
+        /// <param name="alpha">multiplicationi factor for A</param>
+        /// <param name="A">pointer to double array A</param>
+        /// <param name="lda">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix B</param>
+        /// <param name="B">pointer to double array B</param>
+        /// <param name="ldb">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix A</param>
+        /// <param name="beta">multiplication faktor for matrix B</param>
+        /// <param name="C">pointer to predefined double array C of neccessary length</param>
+        /// <param name="ldc">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix C</param>
+        /// <remarks>All parameters except C are readonly. Only elements of matrix C will be altered. C must be a predefined 
+        /// continous double array of size MxN</remarks>
+        public void dgemm(char TransA, char TransB, int M, int N, int K, double alpha, IntPtr A, int lda, IntPtr B, int ldb, double beta, double[] C, int ldc) {
+            lapack_dgemm(ref TransA, ref TransB, ref M, ref  N, ref  K, ref  alpha, A, ref lda, B, ref ldb, ref  beta, C, ref  ldc);
+        }
+        /// <summary>
+        /// Implement wrapper for ATLAS GeneralMatrixMultiply
+        /// </summary>
+        /// <param name="TransA">Transposition state for matrix A: one of the constants in enum CBlas_Transpose</param>
+        /// <param name="TransB">Transposition state for matrix B: one of the constants in enum CBlas_Transpose</param>
+        /// <param name="M">Number of rows in A</param>
+        /// <param name="N">Number of columns in B</param>
+        /// <param name="K">Number of columns in A and number of rows in B</param>
+        /// <param name="alpha">multiplicationi factor for A</param>
+        /// <param name="A">pointer to double array A</param>
+        /// <param name="lda">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix B</param>
+        /// <param name="B">pointer to double array B</param>
+        /// <param name="ldb">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix A</param>
+        /// <param name="beta">multiplication faktor for matrix B</param>
+        /// <param name="C">pointer to predefined double array C of neccessary length</param>
+        /// <param name="ldc">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix C</param>
+        /// <remarks>All parameters except C are readonly. Only elements of matrix C will be altered. C must be a predefined 
+        /// continous double array of size MxN</remarks>
+        public void sgemm(char TransA, char TransB, int M, int N, int K, float alpha, IntPtr A, int lda, IntPtr B, int ldb, float beta, float[] C, int ldc) {
+            lapack_sgemm(ref TransA, ref TransB, ref M, ref  N, ref  K, ref  alpha, A, ref lda, B, ref ldb, ref  beta, C, ref  ldc);
+        }
+        /// <summary>
+        /// Implement wrapper for ATLAS GeneralMatrixMultiply
+        /// </summary>
+        /// <param name="TransA">Transposition state for matrix A: one of the constants in enum CBlas_Transpose</param>
+        /// <param name="TransB">Transposition state for matrix B: one of the constants in enum CBlas_Transpose</param>
+        /// <param name="M">Number of rows in A</param>
+        /// <param name="N">Number of columns in B</param>
+        /// <param name="K">Number of columns in A and number of rows in B</param>
+        /// <param name="alpha">multiplicationi factor for A</param>
+        /// <param name="A">pointer to double array A</param>
+        /// <param name="lda">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix B</param>
+        /// <param name="B">pointer to double array B</param>
+        /// <param name="ldb">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix A</param>
+        /// <param name="beta">multiplication faktor for matrix B</param>
+        /// <param name="C">pointer to predefined double array C of neccessary length</param>
+        /// <param name="ldc">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix C</param>
+        /// <remarks>All parameters except C are readonly. Only elements of matrix C will be altered. C must be a predefined 
+        /// continous double array of size MxN</remarks>
+        public void cgemm(char TransA, char TransB, int M, int N, int K, fcomplex alpha, IntPtr A, int lda, IntPtr B, int ldb, fcomplex beta, fcomplex[] C, int ldc) {
+            lapack_cgemm(ref TransA, ref TransB, ref M, ref  N, ref  K, ref  alpha, A, ref lda, B, ref ldb, ref  beta, C, ref  ldc);
+        }
+        /// <summary>
+        /// Implement wrapper for ATLAS GeneralMatrixMultiply
+        /// </summary>
+        /// <param name="TransA">Transposition state for matrix A: one of the constants in enum CBlas_Transpose</param>
+        /// <param name="TransB">Transposition state for matrix B: one of the constants in enum CBlas_Transpose</param>
+        /// <param name="M">Number of rows in A</param>
+        /// <param name="N">Number of columns in B</param>
+        /// <param name="K">Number of columns in A and number of rows in B</param>
+        /// <param name="alpha">multiplicationi factor for A</param>
+        /// <param name="A">pointer to double array A</param>
+        /// <param name="lda">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix B</param>
+        /// <param name="B">pointer to double array B</param>
+        /// <param name="ldb">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix A</param>
+        /// <param name="beta">multiplication faktor for matrix B</param>
+        /// <param name="C">pointer to predefined double array C of neccessary length</param>
+        /// <param name="ldc">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix C</param>
+        /// <remarks>All parameters except C are readonly. Only elements of matrix C will be altered. C must be a predefined 
+        /// continous double array of size MxN</remarks>
+        public void zgemm(char TransA, char TransB, int M, int N, int K, complex alpha, IntPtr A, int lda, IntPtr B, int ldb, complex beta, complex[] C, int ldc) {
+            lapack_zgemm(ref TransA, ref TransB, ref M, ref  N, ref  K, ref  alpha, A, ref lda, B, ref ldb, ref  beta, C, ref  ldc);
+        }
+
+
+        
+        public void  dgesdd (char jobz, int m, int n,  double [] a, int lda,  double [] s,  double [] u, int ldu,  double [] vt, int ldvt, ref int info) {
+            try {
+                 double [] work = new  double [1] { ( double )0.0 };
+                int lwork = -1;
+                int[] iwork = new int[((m < n) ? m : n) * 8];
+                 lapack_dgesdd (ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, iwork, ref info);
+                if (work[0] != 0) {
+                    work = new  double [(int)work[0]];
+                    lwork = work.Length;
+                     lapack_dgesdd (ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, iwork, ref info);
+                }
+            } catch (Exception e) {
+                if (e is OutOfMemoryException) {
+                     dgesvd (jobz, m, n, a, lda, s, u, ldu, vt, ldvt, ref info); 
+                }
+                throw new ILException("Unable to do " +  "dgesdd"  + ".", e); 
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+       
+        public void  sgesdd (char jobz, int m, int n,  float [] a, int lda,  float [] s,  float [] u, int ldu,  float [] vt, int ldvt, ref int info) {
+            try {
+                float [] work = new  float [1] { ( float )0.0 };
+                int lwork = -1;
+                int[] iwork = new int[((m < n) ? m : n) * 8];
+                lapack_sgesdd (ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, iwork, ref info);
+                if (work[0] != 0) {
+                    work = new  float [(int)work[0]];
+                    lwork = work.Length;
+                    lapack_sgesdd (ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, iwork, ref info);
+                }
+            } catch (Exception e) {
+                if (e is OutOfMemoryException) {
+                    sgesvd (jobz, m, n, a, lda, s, u, ldu, vt, ldvt, ref info); 
+                }
+                throw new ILException("Unable to do " +  "sgesdd"  + ".", e); 
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+
+
+        public void  zgesdd (char jobz, int m, int n,  complex [] a, int lda,  double [] s,  complex [] u, int ldu, complex [] vt, int ldvt, ref int info)
+        {
+            try {
+                 complex [] work = new  complex [1] { (  complex )0.0 };
+                 double [] rwork; 
+                int minMN = (m < n) ? m : n;
+                if (jobz == 'N') {
+                    rwork = new  double [minMN * 7];  
+                } else {
+                    rwork = new  double [5 * minMN * minMN + 5 * minMN];  
+                }
+                int lwork = -1;
+                int[] iwork = new int[minMN * 8];
+                 lapack_zgesdd (ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, rwork, iwork, ref info);
+                if (work[0] != 0) {
+                    work = new  complex [(int)work[0].real];
+                    lwork = work.Length;
+                     lapack_zgesdd (ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork,rwork, iwork, ref info);
+                }
+            } catch (Exception e) {
+                if (e is OutOfMemoryException) {
+                     zgesvd (jobz, m, n, a, lda, s, u, ldu, vt, ldvt, ref info); 
+                }
+                throw new ILException("Unable to do " +  "zgesdd"  + ".", e); 
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+
+        public void  cgesdd (char jobz, int m, int n,  fcomplex [] a, int lda,  float [] s,  fcomplex [] u, int ldu, fcomplex [] vt, int ldvt, ref int info)
+        {
+            try {
+                fcomplex [] work = new  fcomplex [1] { (  fcomplex )0.0 };
+                float [] rwork; 
+                int minMN = (m < n) ? m : n;
+                if (jobz == 'N') {
+                    rwork = new  float [minMN * 7];  
+                } else {
+                    rwork = new  float [5 * minMN * minMN + 5 * minMN];  
+                }
+                int lwork = -1;
+                int[] iwork = new int[minMN * 8];
+                lapack_cgesdd (ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, rwork, iwork, ref info);
+                if (work[0] != 0) {
+                    work = new  fcomplex [(int)work[0].real];
+                    lwork = work.Length;
+                    lapack_cgesdd (ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork,rwork, iwork, ref info);
+                }
+            } catch (Exception e) {
+                if (e is OutOfMemoryException) {
+                    cgesvd (jobz, m, n, a, lda, s, u, ldu, vt, ldvt, ref info); 
+                }
+                throw new ILException("Unable to do " +  "zgesdd"  + ".", e); 
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+
+        
+
+        /// <summary>
+        /// singular value decomposition
+        /// </summary>
+        /// <param name="jobz"></param>
+        /// <param name="m"></param>
+        /// <param name="n"></param>
+        /// <param name="a"></param>
+        /// <param name="lda"></param>
+        /// <param name="s"></param>
+        /// <param name="u"></param>
+        /// <param name="ldu"></param>
+        /// <param name="vt"></param>
+        /// <param name="ldvt"></param>
+        /// <param name="info"></param>
+        public void  dgesvd (char jobz, int m, int n,  double [] a, int lda,
+                            double [] s,  double [] u, int ldu,  double [] vt, int ldvt, ref int info) {
+            if (jobz != 'A' && jobz != 'S' && jobz != 'N')
+                throw new ILArgumentException("Argument jobz must be one of 'A','S' or 'N'"); 
+            try {
+                 double [] work = new  double [1] { ( double )0.0 };
+                int lwork = -1;
+                int[] iwork = new int[((m < n) ? m : n) * 8];
+                 lapack_dgesvd (ref jobz, ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, iwork, ref info);
+                if (work[0] != 0) {
+                    work = new  double [(int)work[0]];
+                    lwork = work.Length; 
+                     lapack_dgesvd (ref jobz, ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, iwork, ref info);
+                }
+            } catch (Exception e) {
+                if (e is OutOfMemoryException) {
+                    throw new ILMemoryException("Not enough memory for given arguments."); 
+                }
+                throw new ILException("Unable to do gesvd.", e);
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+       
+
+        /// <summary>
+        /// singular value decomposition
+        /// </summary>
+        /// <param name="jobz"></param>
+        /// <param name="m"></param>
+        /// <param name="n"></param>
+        /// <param name="a"></param>
+        /// <param name="lda"></param>
+        /// <param name="s"></param>
+        /// <param name="u"></param>
+        /// <param name="ldu"></param>
+        /// <param name="vt"></param>
+        /// <param name="ldvt"></param>
+        /// <param name="info"></param>
+        public void  sgesvd (char jobz, int m, int n,  float [] a, int lda,
+                           float [] s,  float [] u, int ldu,  float [] vt, int ldvt, ref int info) {
+            if (jobz != 'A' && jobz != 'S' && jobz != 'N')
+                throw new ILArgumentException("Argument jobz must be one of 'A','S' or 'N'"); 
+            try {
+                float [] work = new  float [1] { ( float )0.0 };
+                int lwork = -1;
+                int[] iwork = new int[((m < n) ? m : n) * 8];
+                lapack_sgesvd (ref jobz, ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, iwork, ref info);
+                if (work[0] != 0) {
+                    work = new  float [(int)work[0]];
+                    lwork = work.Length; 
+                    lapack_sgesvd (ref jobz, ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, iwork, ref info);
+                }
+            } catch (Exception e) {
+                if (e is OutOfMemoryException) {
+                    throw new ILMemoryException("Not enough memory for given arguments."); 
+                }
+                throw new ILException("Unable to do gesvd.", e);
+            }
+        }
+       
+
+        /// <summary>
+        /// singular value decomposition
+        /// </summary>
+        /// <param name="jobz"></param>
+        /// <param name="m"></param>
+        /// <param name="n"></param>
+        /// <param name="a"></param>
+        /// <param name="lda"></param>
+        /// <param name="s"></param>
+        /// <param name="u"></param>
+        /// <param name="ldu"></param>
+        /// <param name="vt"></param>
+        /// <param name="ldvt"></param>
+        /// <param name="info"></param>
+        public void  zgesvd (char jobz, int m, int n,  complex [] a, int lda,
+                           double [] s,  complex [] u, int ldu,  complex [] vt, int ldvt, ref int info) {
+            if (jobz != 'A' && jobz != 'S' && jobz != 'N')
+                throw new ILArgumentException("Argument jobz must be one of 'A','S' or 'N'"); 
+            try {
+                complex [] work = new  complex [1] { ( complex )0.0 };
+                int lwork = -1;
+                int[] iwork = new int[((m < n) ? m : n) * 8];
+                lapack_zgesvd (ref jobz, ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, iwork, ref info);
+                if (work[0] != 0) {
+                    work = new  complex [(int)work[0]];
+                    lwork = work.Length; 
+                    lapack_zgesvd (ref jobz, ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, iwork, ref info);
+                }
+            } catch (Exception e) {
+                if (e is OutOfMemoryException) {
+                    throw new ILMemoryException("Not enough memory for given arguments."); 
+                }
+                throw new ILException("Unable to do gesvd.", e);
+            }
+        }
+       
+
+        /// <summary>
+        /// singular value decomposition
+        /// </summary>
+        /// <param name="jobz"></param>
+        /// <param name="m"></param>
+        /// <param name="n"></param>
+        /// <param name="a"></param>
+        /// <param name="lda"></param>
+        /// <param name="s"></param>
+        /// <param name="u"></param>
+        /// <param name="ldu"></param>
+        /// <param name="vt"></param>
+        /// <param name="ldvt"></param>
+        /// <param name="info"></param>
+        public void  cgesvd (char jobz, int m, int n,  fcomplex [] a, int lda,
+                           float [] s,  fcomplex [] u, int ldu,  fcomplex [] vt, int ldvt, ref int info) {
+            if (jobz != 'A' && jobz != 'S' && jobz != 'N')
+                throw new ILArgumentException("Argument jobz must be one of 'A','S' or 'N'"); 
+            try {
+                fcomplex [] work = new  fcomplex [1] { ( fcomplex )0.0 };
+                int lwork = -1;
+                int[] iwork = new int[((m < n) ? m : n) * 8];
+                lapack_cgesvd (ref jobz, ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, iwork, ref info);
+                if (work[0] != 0) {
+                    work = new  fcomplex [(int)work[0]];
+                    lwork = work.Length; 
+                    lapack_cgesvd (ref jobz, ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, iwork, ref info);
+                }
+            } catch (Exception e) {
+                if (e is OutOfMemoryException) {
+                    throw new ILMemoryException("Not enough memory for given arguments."); 
+                }
+                throw new ILException("Unable to do gesvd.", e);
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+        public void dpotrf(char uplo, int n, double[] A, int lda, ref int info) {
+            lapack_dpotrf(ref uplo, ref n, A, ref lda, ref info);
+        }
+        public void spotrf(char uplo, int n, float[] A, int lda, ref int info) {
+            lapack_spotrf(ref uplo, ref n, A, ref lda, ref info);
+        }
+        public void cpotrf(char uplo, int n, fcomplex[] A, int lda, ref int info) {
+            lapack_cpotrf(ref uplo, ref n, A, ref lda, ref info);
+        }
+        public void zpotrf(char uplo, int n, complex[] A, int lda, ref int info) {
+            lapack_zpotrf(ref uplo, ref n, A, ref lda, ref info);
+        }
+
+
+        public void dpotri(char uplo, int n, double[] A, int lda, ref int info) {
+            lapack_dpotri(ref uplo, ref n, A, ref lda, ref info);
+        }
+        public void spotri(char uplo, int n, float[] A, int lda, ref int info) {
+            lapack_spotri(ref uplo, ref n, A, ref lda, ref info);
+        }
+        public void cpotri(char uplo, int n, fcomplex[] A, int lda, ref int info) {
+            lapack_cpotri(ref uplo, ref n, A, ref lda, ref info);
+        }
+        public void zpotri(char uplo, int n, complex[] A, int lda, ref int info) {
+            lapack_zpotri(ref uplo, ref n, A, ref lda, ref info);
+        }
+
+
+        public void dgetrf(int M, int N, double[] A, int LDA, int[] IPIV, ref int info) {
+            lapack_dgetrf(ref M, ref N, A, ref LDA, IPIV, ref info);
+        }
+        public void sgetrf(int M, int N, float[] A, int LDA, int[] IPIV, ref int info) {
+            lapack_sgetrf(ref M, ref N, A, ref LDA, IPIV, ref info);
+        }
+        public void cgetrf(int M, int N, fcomplex[] A, int LDA, int[] IPIV, ref int info) {
+            lapack_cgetrf(ref M, ref N, A, ref LDA, IPIV, ref info);
+        }
+        public void zgetrf(int M, int N, complex[] A, int LDA, int[] IPIV, ref int info) {
+            lapack_zgetrf(ref M, ref N, A, ref LDA, IPIV, ref info);
+        }
+
+
+        
+        public void  dgetri (int N,  double [] A, int LDA, int[] IPIV, ref int info) {
+             double [] work = new  double [1];  
+            int lwork = -1; 
+            try {
+                 lapack_dgetri (ref N, A, ref LDA, IPIV, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  double [lwork]; 
+                     lapack_dgetri (ref N, A, ref LDA, IPIV, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in lapack_dgetri"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on dgetri. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+       
+        public void  sgetri (int N,  float [] A, int LDA, int[] IPIV, ref int info) {
+            float [] work = new  float [1];  
+            int lwork = -1; 
+            try {
+                lapack_sgetri (ref N, A, ref LDA, IPIV, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  float [lwork]; 
+                    lapack_sgetri (ref N, A, ref LDA, IPIV, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in lapack_dgetri"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on dgetri. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+       
+        public void  zgetri (int N,  complex [] A, int LDA, int[] IPIV, ref int info) {
+            complex [] work = new  complex [1];  
+            int lwork = -1; 
+            try {
+                lapack_zgetri (ref N, A, ref LDA, IPIV, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  complex [lwork]; 
+                    lapack_zgetri (ref N, A, ref LDA, IPIV, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in lapack_dgetri"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on dgetri. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+       
+        public void  cgetri (int N,  fcomplex [] A, int LDA, int[] IPIV, ref int info) {
+            fcomplex [] work = new  fcomplex [1];  
+            int lwork = -1; 
+            try {
+                lapack_cgetri (ref N, A, ref LDA, IPIV, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  fcomplex [lwork]; 
+                    lapack_cgetri (ref N, A, ref LDA, IPIV, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in lapack_dgetri"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on dgetri. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+
+        
+        public void  dgeqrf (int M, int N,  double [] A, int lda,  double [] tau, ref int info) {
+             double [] work = new  double [1];  
+            int lwork = -1; 
+            try {
+                 lapack_dgeqrf (ref M, ref N, A, ref lda, tau, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  double [lwork]; 
+                     lapack_dgeqrf (ref M, ref N, A, ref lda, tau, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in lapack_?geqrf"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on ?geqrf. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+       
+        public void  sgeqrf (int M, int N,  float [] A, int lda,  float [] tau, ref int info) {
+            float [] work = new  float [1];  
+            int lwork = -1; 
+            try {
+                lapack_sgeqrf (ref M, ref N, A, ref lda, tau, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  float [lwork]; 
+                    lapack_sgeqrf (ref M, ref N, A, ref lda, tau, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in lapack_?geqrf"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on ?geqrf. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+       
+        public void  zgeqrf (int M, int N,  complex [] A, int lda,  complex [] tau, ref int info) {
+            complex [] work = new  complex [1];  
+            int lwork = -1; 
+            try {
+                lapack_zgeqrf (ref M, ref N, A, ref lda, tau, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  complex [lwork]; 
+                    lapack_zgeqrf (ref M, ref N, A, ref lda, tau, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in lapack_?geqrf"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on ?geqrf. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+       
+        public void  cgeqrf (int M, int N,  fcomplex [] A, int lda,  fcomplex [] tau, ref int info) {
+            fcomplex [] work = new  fcomplex [1];  
+            int lwork = -1; 
+            try {
+                lapack_cgeqrf (ref M, ref N, A, ref lda, tau, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  fcomplex [lwork]; 
+                    lapack_cgeqrf (ref M, ref N, A, ref lda, tau, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in lapack_?geqrf"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on ?geqrf. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+        public void dormqr(char side, char trans, int m, int n, int k, double[] A, int lda, double[] tau, double[] C, int LDC, ref int info) {
+            throw new Exception("The method or operation is not implemented.");
+        }
+        public void sormqr(char side, char trans, int m, int n, int k, float[] A, int lda, float[] tau, float[] C, int LDC, ref int info) {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+
+        
+        public void  dorgqr (int M, int N, int K,  double [] A, int lda,  double [] tau, ref int info) {
+             double [] work = new  double [1];  
+            int lwork = -1; 
+            try {
+                /*!HC:lapack_***gqr*/ lapack_dorgqr (ref M, ref N, ref K, A, ref lda, tau, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  double [lwork]; 
+                    /*!HC:lapack_***gqr*/ lapack_dorgqr (ref M, ref N, ref K, A, ref lda, tau, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in lapack_?[un/or]gqr"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on ?[un/or]gqr. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+       
+        public void  sorgqr (int M, int N, int K,  float [] A, int lda,  float [] tau, ref int info) {
+            float [] work = new  float [1];  
+            int lwork = -1; 
+            try {
+                lapack_sorgqr (ref M, ref N, ref K, A, ref lda, tau, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  float [lwork]; 
+                    lapack_sorgqr (ref M, ref N, ref K, A, ref lda, tau, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in lapack_?[un/or]gqr"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on ?[un/or]gqr. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+       
+        public void  zungqr (int M, int N, int K,  complex [] A, int lda,  complex [] tau, ref int info) {
+            complex [] work = new  complex [1];  
+            int lwork = -1; 
+            try {
+                lapack_zungqr (ref M, ref N, ref K, A, ref lda, tau, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  complex [lwork]; 
+                    lapack_zungqr (ref M, ref N, ref K, A, ref lda, tau, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in lapack_?[un/or]gqr"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on ?[un/or]gqr. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+       
+        public void  cungqr (int M, int N, int K,  fcomplex [] A, int lda,  fcomplex [] tau, ref int info) {
+            fcomplex [] work = new  fcomplex [1];  
+            int lwork = -1; 
+            try {
+                lapack_cungqr (ref M, ref N, ref K, A, ref lda, tau, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  fcomplex [lwork]; 
+                    lapack_cungqr (ref M, ref N, ref K, A, ref lda, tau, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in lapack_?[un/or]gqr"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on ?[un/or]gqr. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+
+        
+        public void  dgeqp3 ( int M,int N, double [] A,int LDA,int [] JPVT, double [] tau, ref int info ) {
+             double [] work = new  double [1];
+            int lwork = -1; 
+            try {
+                 
+                /*dummy*/
+                 
+                lapack_dgeqp3 (ref M, ref N, A, ref LDA, JPVT, tau, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  double [lwork]; 
+                     
+                    lapack_dgeqp3 (ref M, ref N, A, ref LDA, JPVT, tau, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in lapack_?geqp3"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on ?geqp3. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+       
+        public void  sgeqp3 ( int M,int N, float [] A,int LDA,int [] JPVT, float [] tau, ref int info ) {
+            float [] work = new  float [1];
+            int lwork = -1; 
+            try {
+                
+                lapack_sgeqp3 (ref M, ref N, A, ref LDA, JPVT, tau, work, ref lwork, ref info);
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  float [lwork]; 
+                    lapack_sgeqp3 (ref M, ref N, A, ref LDA, JPVT, tau, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in lapack_?geqp3"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on ?geqp3. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+       
+        public void  zgeqp3 ( int M,int N, complex [] A,int LDA,int [] JPVT, complex [] tau, ref int info ) {
+            complex [] work = new  complex [1];
+            int lwork = -1; 
+            try {
+                double[] rwork = new double[2 * N];
+                lapack_zgeqp3 (ref M, ref N, A, ref LDA, JPVT, tau, work, ref lwork, rwork, ref info);
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  complex [lwork]; 
+                    lapack_zgeqp3 (ref M, ref N, A, ref LDA, JPVT, tau, work, ref lwork, rwork, ref info);
+                } else {
+                    throw new ILException("error in lapack_?geqp3"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on ?geqp3. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+       
+        public void  cgeqp3 ( int M,int N, fcomplex [] A,int LDA,int [] JPVT, fcomplex [] tau, ref int info ) {
+            fcomplex [] work = new  fcomplex [1];
+            int lwork = -1; 
+            try {
+                float[] rwork = new float[2 * N];
+                lapack_cgeqp3 (ref M, ref N, A, ref LDA, JPVT, tau, work, ref lwork, rwork, ref info);
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  fcomplex [lwork]; 
+                    lapack_cgeqp3 (ref M, ref N, A, ref LDA, JPVT, tau, work, ref lwork, rwork, ref info);
+                } else {
+                    throw new ILException("error in lapack_?geqp3"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on ?geqp3. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+        public void dtrtrs(char uplo, char transA, char diag, int N, int nrhs, IntPtr A, int LDA, IntPtr B, int LDB, ref int info) {
+            lapack_dtrtrs(ref uplo, ref transA, ref diag, ref N, ref nrhs, A, ref LDA, B, ref LDB, ref info); 
+        }
+        public void strtrs(char uplo, char transA, char diag, int N, int nrhs, IntPtr A, int LDA, IntPtr B, int LDB, ref int info) {
+            lapack_strtrs(ref uplo, ref transA, ref diag, ref N, ref nrhs, A, ref LDA, B, ref LDB, ref info); 
+        }
+        public void ctrtrs(char uplo, char transA, char diag, int N, int nrhs, IntPtr A, int LDA, IntPtr B, int LDB, ref int info) {
+            lapack_ctrtrs(ref uplo, ref transA, ref diag, ref N, ref nrhs, A, ref LDA, B, ref LDB, ref info); 
+        }
+        public void ztrtrs(char uplo, char transA, char diag, int N, int nrhs, IntPtr A, int LDA, IntPtr B, int LDB, ref int info) {
+            lapack_ztrtrs(ref uplo, ref transA, ref diag, ref N, ref nrhs, A, ref LDA, B, ref LDB, ref info); 
+        }
+
+        public void dgetrs(char trans, int N, int NRHS, double[] A, int LDA, int[] IPIV, double[] B, int LDB, ref int info) {
+            lapack_dgetrs(ref trans,ref N,ref NRHS, A, ref LDA, IPIV, B, ref LDB, ref info);     
+        }
+
+        public void sgetrs(char trans, int N, int NRHS, float[] A, int LDA, int[] IPIV, float[] B, int LDB, ref int info) {
+            lapack_sgetrs(ref trans,ref N,ref NRHS, A, ref LDA, IPIV, B, ref LDB, ref info);     
+        }
+
+        public void cgetrs(char trans, int N, int NRHS, fcomplex[] A, int LDA, int[] IPIV, fcomplex[] B, int LDB, ref int info) {
+            lapack_cgetrs(ref trans,ref N,ref NRHS, A, ref LDA, IPIV, B, ref LDB, ref info);     
+        }
+
+        public void zgetrs(char trans, int N, int NRHS, complex[] A, int LDA, int[] IPIV, complex[] B, int LDB, ref int info) {
+            lapack_zgetrs(ref trans,ref N,ref NRHS, A, ref LDA, IPIV, B, ref LDB, ref info);
+        }
+        
+        public void dpotrs(char uplo, int n, int nrhs, double[] A, int lda, double[] B, int ldb, ref int info) {
+            lapack_dpotrs(ref uplo, ref n, ref nrhs, A, ref lda, B, ref ldb, ref info); 
+        }
+
+        public void spotrs(char uplo, int n, int nrhs, float[] A, int lda, float[] B, int ldb, ref int info) {
+            lapack_spotrs(ref uplo, ref n, ref nrhs, A, ref lda, B, ref ldb, ref info); 
+        }
+
+        public void cpotrs(char uplo, int n, int nrhs, fcomplex[] A, int lda, fcomplex[] B, int ldb, ref int info) {
+            lapack_cpotrs(ref uplo, ref n, ref nrhs, A, ref lda, B, ref ldb, ref info); 
+        }
+
+        public void zpotrs(char uplo, int n, int nrhs, complex[] A, int lda, complex[] B, int ldb, ref int info) {
+            lapack_zpotrs(ref uplo, ref n, ref nrhs, A, ref lda, B, ref ldb, ref info); 
+        }
+
+
+        
+        public void  dgelsd (int m, int n, int nrhs,  double [] A, int lda,  double [] B, int ldb,  double [] S,  double RCond, ref int rank, ref int info) {
+             double [] work = new  double [1]; 
+            int [] iwork = new int[1]; 
+            int lwork = -1; 
+            /*HC:HycalpTag1*/
+            lapack_dgelsd (ref m, ref n, ref nrhs, A, ref lda, B, ref ldb, S,ref RCond, ref rank, work, ref lwork, iwork, ref info);
+            if (info != 0) 
+                throw new ILArgumentException("dgelsd: invalid parameter: #" + (-info).ToString());
+            lwork = ILAENV(9, "dgelsd", " ",0,0,0,0); 
+            if (lwork <= 0)
+                throw new ILArgumentException("dgelsd: unknown error determining working size liwork");
+            iwork = new int[lwork];
+            lwork = (int)work[0];
+            work = new  double [lwork]; 
+            /*HC:HycalpTag2*/
+            lapack_dgelsd (ref m, ref n, ref nrhs, A, ref lda, B, ref ldb, S,ref RCond, ref rank, work, ref lwork, iwork, ref info);
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+       
+        public void  sgelsd  (int m, int n, int nrhs,  float [] A, int lda,  float [] B, int ldb,  float [] S,  float RCond, ref int rank, ref int info) {
+            float [] work = new  float [1]; 
+            int [] iwork = new int[1]; 
+            int lwork = -1; 
+            lapack_sgelsd (ref m, ref n, ref nrhs, A, ref lda, B, ref ldb, S,ref RCond, ref rank, work, ref lwork, iwork, ref info);
+            if (info != 0) 
+                throw new ILArgumentException("dgelsd: invalid parameter: #" + (-info).ToString());
+            lwork = ILAENV(9, "dgelsd", " ",0,0,0,0); 
+            if (lwork <= 0)
+                throw new ILArgumentException("dgelsd: unknown error determining working size liwork");
+            iwork = new int[lwork];
+            lwork = (int)work[0];
+            work = new  float [lwork]; 
+            lapack_sgelsd (ref m, ref n, ref nrhs, A, ref lda, B, ref ldb, S,ref RCond, ref rank, work, ref lwork, iwork, ref info);
+        }
+       
+        public void  zgelsd  (int m, int n, int nrhs,  complex [] A, int lda,  complex [] B, int ldb,  double [] S,  double RCond, ref int rank, ref int info) {
+            complex [] work = new  complex [1]; 
+            int [] iwork = new int[1]; 
+            int lwork = -1; 
+            double [] rwork = new double [1];  lapack_zgelsd (ref m, ref n, ref nrhs, A, ref lda, B, ref ldb, S,ref RCond, ref rank, work, ref lwork, rwork, iwork, ref info);
+            if (info != 0) 
+                throw new ILArgumentException("dgelsd: invalid parameter: #" + (-info).ToString());
+            lwork = ILAENV(9, "dgelsd", " ",0,0,0,0); 
+            if (lwork <= 0)
+                throw new ILArgumentException("dgelsd: unknown error determining working size liwork");
+            iwork = new int[lwork];
+            lwork = (int)work[0];
+            work = new  complex [lwork]; 
+            rwork = new double [(int)rwork[0]];  lapack_zgelsd (ref m, ref n, ref nrhs, A, ref lda, B, ref ldb, S,ref RCond, ref rank, work, ref lwork, rwork, iwork, ref info);
+        }
+       
+        public void  cgelsd  (int m, int n, int nrhs,  fcomplex [] A, int lda,  fcomplex [] B, int ldb,  float [] S,  float RCond, ref int rank, ref int info) {
+            fcomplex [] work = new  fcomplex [1]; 
+            int [] iwork = new int[1]; 
+            int lwork = -1; 
+            float [] rwork = new float [1];  lapack_cgelsd (ref m, ref n, ref nrhs, A, ref lda, B, ref ldb, S,ref RCond, ref rank, work, ref lwork, rwork, iwork, ref info);
+            if (info != 0) 
+                throw new ILArgumentException("dgelsd: invalid parameter: #" + (-info).ToString());
+            lwork = ILAENV(9, "dgelsd", " ",0,0,0,0); 
+            if (lwork <= 0)
+                throw new ILArgumentException("dgelsd: unknown error determining working size liwork");
+            iwork = new int[lwork];
+            lwork = (int)work[0];
+            work = new  fcomplex [lwork]; 
+            rwork = new float [(int)rwork[0]];  lapack_cgelsd (ref m, ref n, ref nrhs, A, ref lda, B, ref ldb, S,ref RCond, ref rank, work, ref lwork, rwork, iwork, ref info);
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+
+        
+        public void  dgelsy (int m, int n, int nrhs,  double [] A, int lda,  double [] B, int ldb, int[] JPVT0,  double RCond, ref int rank, ref int info) {
+            int lwork = -1;
+             double [] work = new  double [1]; 
+             //
+            /*!HC:lapack_?gelsy*/ 
+            lapack_dgelsy (ref m,ref n,ref nrhs,A,ref lda,B,ref ldb,JPVT0,ref RCond,ref rank,work,ref lwork,ref info);
+            if (info != 0)
+                throw new ILArgumentException("?gelsy: unable to determine optimal block size. cancelling...");
+            lwork = (int) work[0];
+            work = new  double [lwork];
+             //
+            /*!HC:lapack_?gelsy*/ 
+            lapack_dgelsy (ref m,ref n,ref nrhs,A,ref lda,B,ref ldb,JPVT0,ref RCond,ref rank,work,ref lwork,ref info);
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+       
+        public void  sgelsy  (int m, int n, int nrhs,  float [] A, int lda,  float [] B, int ldb, int[] JPVT0,  float RCond, ref int rank, ref int info) {
+            int lwork = -1;
+            float [] work = new  float [1]; 
+            
+            lapack_sgelsy (ref m,ref n,ref nrhs,A,ref lda,B,ref ldb,JPVT0,ref RCond,ref rank,work,ref lwork,ref info);
+            if (info != 0)
+                throw new ILArgumentException("?gelsy: unable to determine optimal block size. cancelling...");
+            lwork = (int) work[0];
+            work = new  float [lwork];
+            
+            lapack_sgelsy (ref m,ref n,ref nrhs,A,ref lda,B,ref ldb,JPVT0,ref RCond,ref rank,work,ref lwork,ref info);
+        }
+       
+        public void  zgelsy  (int m, int n, int nrhs,  complex [] A, int lda,  complex [] B, int ldb, int[] JPVT0,  double RCond, ref int rank, ref int info) {
+            int lwork = -1;
+            complex [] work = new  complex [1]; 
+            double[] rwork = new double[1];
+            lapack_zgelsy (ref m,ref n,ref nrhs,A,ref lda,B,ref ldb,JPVT0,ref RCond,ref rank,work,ref lwork, rwork, ref info);
+            if (info != 0)
+                throw new ILArgumentException("?gelsy: unable to determine optimal block size. cancelling...");
+            lwork = (int) work[0];
+            work = new  complex [lwork];
+            rwork = new double[lwork];
+            lapack_zgelsy (ref m,ref n,ref nrhs,A,ref lda,B,ref ldb,JPVT0,ref RCond,ref rank,work,ref lwork, rwork, ref info);
+        }
+       
+        public void  cgelsy  (int m, int n, int nrhs,  fcomplex [] A, int lda,  fcomplex [] B, int ldb, int[] JPVT0,  float RCond, ref int rank, ref int info) {
+            int lwork = -1;
+            fcomplex [] work = new  fcomplex [1]; 
+            float[] rwork = new float[1];
+            lapack_cgelsy (ref m,ref n,ref nrhs,A,ref lda,B,ref ldb,JPVT0,ref RCond,ref rank,work,ref lwork, rwork, ref info);
+            if (info != 0)
+                throw new ILArgumentException("?gelsy: unable to determine optimal block size. cancelling...");
+            lwork = (int) work[0];
+            work = new  fcomplex [lwork];
+            rwork = new float[lwork];
+            lapack_cgelsy (ref m,ref n,ref nrhs,A,ref lda,B,ref ldb,JPVT0,ref RCond,ref rank,work,ref lwork, rwork, ref info);
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+        #region ?GEEVX
+        public void dgeevx(char balance, char jobvl, char jobvr, char sense, int n, double[] A, int lda, double[] wr, double[] wi, double[] vl, int ldvl, double[] vr, int ldvr, ref int ilo, ref int ihi, double[] scale, ref double abnrm, double[] rconde, double[] rcondv, ref int info) {
+            double [] work = new double[1]; 
+            int lwork = -1;
+            int [] iwork = new int[2 * n - 2];
+            lapack_dgeevx(ref balance, ref jobvl, ref jobvr, ref sense, ref n, A, ref lda, wr, wi, vl, ref ldvl, vr, ref ldvr, ref ilo, ref ihi, scale, ref abnrm, rconde, rcondv, work, ref lwork, iwork, ref info);
+            if (info != 0) 
+                throw new ILArgumentException("error in lapack call: ?geevx. (" + info + ")");
+            lwork = (int)work[0]; 
+            work = new double[lwork]; 
+            lapack_dgeevx(ref balance, ref jobvl, ref jobvr, ref sense, ref n, A, ref lda, wr, wi, vl, ref ldvl, vr, ref ldvr, ref ilo, ref ihi, scale, ref abnrm, rconde, rcondv, work, ref lwork, iwork, ref info);
+        }
+        public void sgeevx(char balance, char jobvl, char jobvr, char sense, int n, float[] A, int lda, float[] wr, float[] wi, float[] vl, int ldvl, float[] vr, int ldvr, ref int ilo, ref int ihi, float[] scale, ref float abnrm, float[] rconde, float[] rcondv, ref int info) {
+            float [] work = new float[1]; 
+            int lwork = -1;
+            int [] iwork = new int[2 * n - 2];
+            lapack_sgeevx(ref balance, ref jobvl, ref jobvr, ref sense, ref n, A, ref lda, wr, wi, vl, ref ldvl, vr, ref ldvr, ref ilo, ref ihi, scale, ref abnrm, rconde, rcondv, work, ref lwork, iwork, ref info);
+            if (info != 0) 
+                throw new ILArgumentException("error in lapack call: ?geevx. (" + info + ")");
+            lwork = (int)work[0]; 
+            work = new float[lwork]; 
+            lapack_sgeevx(ref balance, ref jobvl, ref jobvr, ref sense, ref n, A, ref lda, wr, wi, vl, ref ldvl, vr, ref ldvr, ref ilo, ref ihi, scale, ref abnrm, rconde, rcondv, work, ref lwork, iwork, ref info);
+        }
+        public void cgeevx(char balance, char jobvl, char jobvr, char sense, int n, fcomplex[] A, int lda, fcomplex[] w, fcomplex[] vl, int ldvl, fcomplex[] vr, int ldvr, ref int ilo, ref int ihi, float[] scale, ref float abnrm, float[] rconde, float[] rcondv, ref int info) {
+            fcomplex [] work = new fcomplex[1]; 
+            int lwork = -1;
+            float[] rwork = new float[2 * n]; 
+            lapack_cgeevx(ref balance, ref jobvl, ref jobvr, ref sense, ref n, A, ref lda, w, vl, ref ldvl, vr, ref ldvr, ref ilo, ref ihi, scale, ref abnrm, rconde, rcondv, work, ref lwork, rwork, ref info);
+            if (info != 0) 
+                throw new ILArgumentException("error in lapack call: ?geevx. (" + info + ")");
+            lwork = (int)work[0]; 
+            work = new fcomplex[lwork]; 
+            lapack_cgeevx(ref balance, ref jobvl, ref jobvr, ref sense, ref n, A, ref lda, w, vl, ref ldvl, vr, ref ldvr, ref ilo, ref ihi, scale, ref abnrm, rconde, rcondv, work, ref lwork, rwork, ref info);
+        }
+        public void zgeevx(char balance, char jobvl, char jobvr, char sense, int n, complex[] A, int lda, complex[] w, complex[] vl, int ldvl, complex[] vr, int ldvr, ref int ilo, ref int ihi, double[] scale, ref double abnrm, double[] rconde, double[] rcondv, ref int info) {
+            complex [] work = new complex[1]; 
+            int lwork = -1;
+            double[] rwork = new double[2 * n]; 
+            lapack_zgeevx(ref balance, ref jobvl, ref jobvr, ref sense, ref n, A, ref lda, w, vl, ref ldvl, vr, ref ldvr, ref ilo, ref ihi, scale, ref abnrm, rconde, rcondv, work, ref lwork, rwork, ref info);
+            if (info != 0) 
+                throw new ILArgumentException("error in lapack call: ?geevx. (" + info + ")");
+            lwork = (int)work[0]; 
+            work = new complex[lwork]; 
+            lapack_zgeevx(ref balance, ref jobvl, ref jobvr, ref sense, ref n, A, ref lda, w, vl, ref ldvl, vr, ref ldvr, ref ilo, ref ihi, scale, ref abnrm, rconde, rcondv, work, ref lwork, rwork, ref info);
+        }
+        #endregion
+
+        #region ?SYEVR
+        public void dsyevr(char jobz, char range, char uplo, int n, double[] A, int lda, double vl, double vu, int il, int iu, double abstol, ref int m, double[] w, double[] z, int ldz, int[] isuppz, ref int info) {
+            double [] work = new double[1]; 
+            int lwork = -1, liwork = -1; 
+            int [] iwork = new int[1]; 
+            lapack_dsyevr(ref jobz,ref range,ref uplo,ref n, A,ref lda, ref vl, ref vu, ref il, ref iu, ref abstol,ref m, w,z,ref ldz,isuppz, work,ref lwork,iwork,ref liwork,ref info);
+            if (info != 0) {
+                throw new ILArgumentException("?syevr: error returned from lapack: " + info);
+            }
+            lwork = (int)work[0]; 
+            liwork = (int) iwork[0]; 
+            //work = ILMemoryPool.Pool.New<double>(lwork);
+            //iwork = ILMemoryPool.Pool.New<int>(liwork); 
+            work = new double[lwork];
+            iwork = new int[liwork]; 
+            lapack_dsyevr(ref jobz,ref range,ref uplo,ref n, A,ref lda, ref vl, ref vu, ref il, ref iu, ref abstol,ref m, w,z,ref ldz,isuppz, work,ref lwork,iwork,ref liwork,ref info);
+            //ILMemoryPool.Pool.RegisterObject(work);
+            //ILMemoryPool.Pool.RegisterObject(iwork);
+            if (info != 0) {
+                throw new ILArgumentException("?syevr: error returned from lapack: " + info);
+            }
+        }
+        public void ssyevr(char jobz, char range, char uplo, int n, float[] A, int lda, float vl, float vu, int il, int iu, float abstol, ref int m, float[] w, float[] z, int ldz, int[] isuppz, ref int info) {
+            float [] work = new float[1]; 
+            int lwork = -1, liwork = -1; 
+            int [] iwork = new int[1]; 
+            lapack_ssyevr(ref jobz,ref range,ref uplo,ref n, A,ref lda, ref vl, ref vu, ref il, ref iu, ref abstol,ref m, w,z,ref ldz,isuppz, work,ref lwork,iwork,ref liwork,ref info);
+            if (info != 0) {
+                throw new ILArgumentException("?syevr: error returned from lapack: " + info);
+            }
+            lwork = (int)work[0]; 
+            work = ILMemoryPool.Pool.New<float>(lwork);
+            liwork = (int) iwork[0]; 
+            iwork = ILMemoryPool.Pool.New<int>(liwork); 
+            lapack_ssyevr(ref jobz,ref range,ref uplo,ref n, A,ref lda, ref vl, ref vu, ref il, ref iu, ref abstol,ref m, w,z,ref ldz,isuppz, work,ref lwork,iwork,ref liwork,ref info);
+            ILMemoryPool.Pool.Free(work);
+            ILMemoryPool.Pool.Free(iwork);
+            if (info != 0) {
+                throw new ILArgumentException("?syevr: error returned from lapack: " + info);
+            }
+        }
+        public void cheevr(char jobz, char range, char uplo, int n, fcomplex[] A, int lda, float vl, float vu, int il, int iu, float abstol, ref int m, float[] w, fcomplex[] z, int ldz, int[] isuppz, ref int info) {
+            fcomplex[] work = new fcomplex[1]; 
+            float [] rwork = new float[1]; 
+            int [] iwork = new int[1]; 
+            int lrwork = -1, liwork = -1, lwork = -1; 
+            lapack_cheevr(ref jobz,ref range,ref uplo,ref n, A,ref lda, ref vl, ref vu, ref il, ref iu, ref abstol,ref m, w,z,ref ldz,isuppz, work,ref lwork,rwork,ref lrwork, iwork,ref liwork,ref info);
+            if (info != 0) {
+                throw new ILArgumentException("?chevr: error returned from lapack: " + info);
+            }
+            lrwork = (int)rwork[0]; 
+            rwork = ILMemoryPool.Pool.New<float>(lrwork);
+            lwork = (int) work[0]; 
+            work = ILMemoryPool.Pool.New<fcomplex>(lwork); 
+            liwork = (int) iwork[0]; 
+            iwork = ILMemoryPool.Pool.New<int>(liwork); 
+            lapack_cheevr(ref jobz,ref range,ref uplo,ref n, A,ref lda, ref vl, ref vu, ref il, ref iu, ref abstol,ref m, w,z,ref ldz,isuppz, work,ref lwork,rwork,ref lrwork,iwork,ref liwork,ref info);
+            ILMemoryPool.Pool.Free(rwork);
+            ILMemoryPool.Pool.Free(work);
+            ILMemoryPool.Pool.Free(iwork);
+            if (info != 0) {
+                throw new ILArgumentException("?syevr: error returned from lapack: " + info);
+            }
+        }
+        public void zheevr(char jobz, char range, char uplo, int n, complex[] A, int lda, double vl, double vu, int il, int iu, double abstol, ref int m, double[] w, complex[] z, int ldz, int[] isuppz, ref int info) {
+            complex[] work = new complex[1]; 
+            double [] rwork = new double[1]; 
+            int [] iwork = new int[1]; 
+            int lrwork = -1, liwork = -1, lwork = -1; 
+            lapack_zheevr(ref jobz,ref range,ref uplo,ref n, A,ref lda, ref vl, ref vu, ref il, ref iu, ref abstol,ref m, w,z,ref ldz,isuppz, work,ref lwork,rwork,ref lrwork, iwork,ref liwork,ref info);
+            if (info != 0) {
+                throw new ILArgumentException("?heevr: error returned from lapack: " + info);
+            }
+            lrwork = (int)rwork[0]; 
+            rwork = ILMemoryPool.Pool.New<double>(lrwork);
+            lwork = (int) work[0]; 
+            work = ILMemoryPool.Pool.New<complex>(lwork); 
+            liwork = (int) iwork[0]; 
+            iwork = ILMemoryPool.Pool.New<int>(liwork); 
+            lapack_zheevr(ref jobz,ref range,ref uplo,ref n, A,ref lda, ref vl, ref vu, ref il, ref iu, ref abstol,ref m, w,z,ref ldz,isuppz, work,ref lwork,rwork,ref lrwork,iwork,ref liwork,ref info);
+            ILMemoryPool.Pool.Free(rwork);
+            ILMemoryPool.Pool.Free(work);
+            ILMemoryPool.Pool.Free(iwork);
+            if (info != 0) {
+                throw new ILArgumentException("?syevr: error returned from lapack: " + info);
+            }
+        }
+        #endregion
+
+        #region ?[he/sy]gv - generalized eigenproblem
+        public void dsygv (int itype, char jobz, char uplo, int n, double  [] A, int lda, double  [] B, int ldb, double [] w, ref int info) {
+            // query workspace 
+            int lwork = -1; 
+            double [] work = new double[1] {0.0}; 
+            lapack_dsygv (ref itype,ref jobz,ref uplo,ref n, A,ref lda, B,ref ldb, w, work, ref lwork, ref info); 
+            if (info != 0 || work[0] <= 0.0) return; 
+            // create temporary array(s)
+            lwork = (int) work[0]; 
+            work = ILMemoryPool.Pool.New<double>(lwork); 
+            lapack_dsygv (ref itype,ref jobz,ref uplo,ref n, A,ref lda, B,ref ldb, w, work, ref lwork, ref info); 
+            ILMemoryPool.Pool.Free(work); 
+        }        
+        public void ssygv (int itype, char jobz, char uplo, int n, float   [] A, int lda, float   [] B, int ldb, float  [] w, ref int info) {
+            // query workspace 
+            int lwork = -1; 
+            float [] work = new float[1] {0.0f}; 
+            lapack_ssygv (ref itype,ref jobz,ref uplo,ref n, A,ref lda, B,ref ldb, w, work, ref lwork, ref info); 
+            if (info != 0 || work[0] <= 0.0) return; 
+            // create temporary array(s)
+            lwork = (int) work[0]; 
+            work = ILMemoryPool.Pool.New<float>(lwork); 
+            lapack_ssygv (ref itype,ref jobz,ref uplo,ref n, A,ref lda, B,ref ldb, w, work, ref lwork, ref info); 
+            ILMemoryPool.Pool.Free(work); 
+        }
+        public void chegv (int itype, char jobz, char uplo, int n, fcomplex[] A, int lda, fcomplex[] B, int ldb, float  [] w, ref int info) {
+            int lwork = (int)Math.Max(1,2*n-1); bool dummy; 
+            float [] rwork = ILMemoryPool.Pool.New<float>(Math.Max(1,3*n-2),false, out dummy); 
+            fcomplex [] work = ILMemoryPool.Pool.New<fcomplex>(lwork,false, out dummy); 
+            // NOTE: this implementation of LAPACK (netlib.org, not optimized) seems to overwrite B even if only a workspace query is assumed. 
+            // therefore this hack uses the (may not optimal efficiently) working size 2*n-1 for computation.
+            lapack_chegv(ref itype,ref  jobz,ref  uplo,ref  n, A,ref  lda, B,ref  ldb, w, work, ref lwork, rwork, ref info); 
+            ILMemoryPool.Pool.Free(rwork); 
+            ILMemoryPool.Pool.Free(work); 
+        }
+        public void zhegv (int itype, char jobz, char uplo, int n, complex [] A, int lda, complex [] B, int ldb, double [] w, ref int info) { 
+            // NOTE: this implementation of LAPACK (netlib.org, not optimized) seems to overwrite B even if only a workspace query is assumed. 
+            // therefore this hack uses the (may not optimal efficiently) working size 2*n-1 for computation.
+            int lwork = (int)Math.Max(1,2*n-1); bool dummy; 
+            double [] rwork = ILMemoryPool.Pool.New<double>(Math.Max(1,3*n-2)); 
+            complex [] work = ILMemoryPool.Pool.New<complex>(lwork,false, out dummy); 
+            lapack_zhegv(ref itype,ref  jobz,ref  uplo,ref  n, A,ref  lda, B,ref  ldb, w, work, ref lwork, rwork, ref info); 
+            ILMemoryPool.Pool.Free(rwork); 
+            ILMemoryPool.Pool.Free(work); 
+        }
+        #endregion
+
+        #endregion
+   }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Native/lapack/ILLapackMKL10.0C.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Native/lapack/ILLapackMKL10.0C.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Native/lapack/ILLapackMKL10.0C.cs	(revision 9102)
@@ -0,0 +1,1556 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+#pragma warning disable 1570, 1591
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Native;
+using System.Runtime.InteropServices;
+using ILNumerics.Exceptions;
+using System.Security; 
+using ILNumerics.Misc; 
+
+namespace ILNumerics.Native  {
+    /// <summary>
+    /// Generic LAPACK implementation, unsupported processor types
+    /// </summary>
+    public class ILLapackMKL10_0 : IILLapack {
+
+        #region DLL INCLUDES 
+#if x64
+        #region 64 bit includes
+        [DllImport("mkl_custom64", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
+        internal static extern int mkl_domain_set_num_threads(ref int num, ref int mask);
+        [DllImport("mkl_custom64", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
+        internal static extern int mkl_domain_get_max_threads(ref int mask);
+        [DllImport("mkl_custom64", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 
+        internal static extern void mkl_set_num_threads(int num);
+        [DllImport("mkl_custom64", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
+        internal static extern void omp_set_num_threads(int num);
+        [DllImport("mkl_custom64", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
+        internal static extern int mkl_get_max_threads();
+        [DllImport("mkl_custom64", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
+        internal static extern void mkl_set_dynamic(ref int boolean_value);
+
+        [DllImport("mkl_custom64", EntryPoint = "ilaenv",CallingConvention = CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern int mkl_ilaenv(ref int ispec, ref string name, ref string opts, ref int n1, ref int n2, ref int n3, ref int n4);
+
+        ///////////////////////////   DOUBLE LAPACK /////////////////////////////////
+        [DllImport("mkl_custom64", EntryPoint = "DGEMM",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_dgemm(ref char TransA, ref char TransB, ref int M,ref int N, ref int K, ref  double alpha, IntPtr A, ref int lda, IntPtr B, ref int ldb, ref double beta, double[] C, ref int ldc);
+        [DllImport("mkl_custom64", EntryPoint = "SGEMM",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_sgemm(ref char TransA, ref char TransB, ref int M,ref int N, ref int K, ref float alpha, IntPtr A,ref int lda, IntPtr B, ref int ldb, ref float beta,float[] C, ref int ldc);
+        [DllImport("mkl_custom64", EntryPoint = "CGEMM",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_cgemm(ref char TransA, ref char TransB, ref int M,ref int N, ref int K, ref fcomplex alpha, IntPtr A, ref int lda, IntPtr B, ref int ldb, ref fcomplex beta,[In,Out] fcomplex [] C, ref int ldc);
+        [DllImport("mkl_custom64", EntryPoint = "ZGEMM",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_zgemm(ref char TransA, ref char TransB, ref int M, ref int N, ref int K, ref complex alpha, IntPtr A, ref int lda, IntPtr B, ref int ldb, ref complex beta,[In,Out] complex [] C, ref int ldc);
+
+        [DllImport("mkl_custom64", EntryPoint = "DGESDD",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_dgesdd(ref char jobz, ref int m, ref int n,double[] a, ref int lda, double[] s,double[] u, ref int ldu, double[] vt,ref int ldvt, double[] work, ref int lwork,int[] iwork, ref int info);
+        [DllImport("mkl_custom64", EntryPoint = "SGESDD",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_sgesdd(ref char jobz, ref int m, ref int n,float[] a, ref int lda, float[] s,float[] u, ref int ldu, float[] vt, ref int ldvt, float[] work, ref int lwork,int[] iwork, ref int info);
+        [DllImport("mkl_custom64", EntryPoint = "CGESDD",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_cgesdd(ref char jobz, ref int m, ref int n,[In, Out] fcomplex[] a, ref int lda, float[] s,[In, Out] fcomplex[] u, ref int ldu, [In, Out]  fcomplex[] vt, ref int ldvt, [In, Out] fcomplex[] work, ref int lwork,[In,Out] float[] rwork, int[] iwork, ref int info);
+        [DllImport("mkl_custom64", EntryPoint = "ZGESDD",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_zgesdd(ref char jobz, ref int m, ref int n,[In, Out] complex[] a, ref int lda, double[] s,[In, Out] complex[] u, ref int ldu, [In, Out] complex[] vt,ref int ldvt, [In, Out] complex[] work, ref int lwork,[In,Out] double[] rwork, int[] iwork, ref int info);
+
+        [DllImport("mkl_custom64", EntryPoint = "DGESVD",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_dgesvd(ref char jobu, ref  char jobvt, ref int m, ref int n,double[] a, ref int lda, double[] s,double[] u, ref int ldu, double[] vt,ref int ldvt, double[] work, ref int lwork,int[] iwork,ref int info);
+        [DllImport("mkl_custom64", EntryPoint = "SGESVD",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_sgesvd(ref char jobu, ref  char jobvt, ref int m, ref int n, float[] a, ref int lda, float[] s,float[] u, ref int ldu, float[] vt,ref int ldvt, float[] work, ref int lwork,int[] iwork, ref int info);
+        [DllImport("mkl_custom64", EntryPoint = "CGESVD",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_cgesvd(ref char jobu, ref  char jobvt, ref int m, ref int n,[In, Out] fcomplex[] a, ref int lda, float[] s,[In, Out] fcomplex[] u, ref int ldu,[In,Out] fcomplex[] vt,ref int ldvt, [In, Out]  fcomplex[] work, ref int lwork,int[] iwork,ref int info);
+        [DllImport("mkl_custom64", EntryPoint = "ZGESVD",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_zgesvd(ref char jobu, ref  char jobvt, ref int m, ref int n,[In, Out] complex[] a, ref int lda, double[] s,[In, Out] complex[] u, ref int ldu, [In, Out] complex[] vt,ref int ldvt, [In, Out]  complex[] work, ref int lwork,int[] iwork,ref int info);
+
+        [DllImport("mkl_custom64", EntryPoint = "DPOTRF",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_dpotrf (ref char uplo, ref int n, double [] A, ref int lda, ref int info);
+        [DllImport("mkl_custom64", EntryPoint = "SPOTRF",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_spotrf (ref char uplo, ref int n, float [] A, ref int lda, ref int info);
+        [DllImport("mkl_custom64", EntryPoint = "CPOTRF",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_cpotrf (ref char uplo, ref int n,[In,Out] fcomplex [] A, ref int lda, ref int info);
+        [DllImport("mkl_custom64", EntryPoint = "ZPOTRF",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_zpotrf (ref char uplo, ref int n, [In,Out] complex [] A, ref int lda, ref int info);
+        
+        [DllImport("mkl_custom64", EntryPoint = "DPOTRI",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_dpotri (ref char uplo,ref  int n, double [] A, ref int lda, ref int info);
+        [DllImport("mkl_custom64", EntryPoint = "SPOTRI",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_spotri (ref char uplo, ref int n, float [] A, ref int lda, ref int info);
+        [DllImport("mkl_custom64", EntryPoint = "CPOTRI",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_cpotri (ref char uplo, ref int n,[In,Out] fcomplex [] A, ref int lda,ref int info);
+        [DllImport("mkl_custom64", EntryPoint = "ZPOTRI",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_zpotri (ref char uplo, ref int n, [In,Out] complex [] A, ref int lda,ref int info);
+
+        [DllImport("mkl_custom64", EntryPoint = "DPOTRS",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_dpotrs (ref char uplo,ref  int n, ref int NRHS, double [] A, ref int lda, double[] B, ref int ldb, ref int info);
+        [DllImport("mkl_custom64", EntryPoint = "SPOTRS",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_spotrs (ref char uplo,ref  int n, ref int NRHS, float [] A, ref int lda, float[] B, ref int ldb, ref int info);
+        [DllImport("mkl_custom64", EntryPoint = "CPOTRS",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_cpotrs (ref char uplo,ref  int n, ref int NRHS, [In,Out] fcomplex [] A, ref int lda, [In,Out] fcomplex[] B, ref int ldb, ref int info);
+        [DllImport("mkl_custom64", EntryPoint = "ZPOTRS",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_zpotrs (ref char uplo,ref  int n, ref int NRHS, [In,Out] complex [] A, ref int lda, [In,Out] complex[] B, ref int ldb, ref int info);
+
+        [DllImport("mkl_custom64", EntryPoint = "DGETRF",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_dgetrf (ref int M, ref int N, double [] A, ref int LDA, int[] IPIV, ref int info);
+        [DllImport("mkl_custom64", EntryPoint = "SGETRF",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_sgetrf (ref int M, ref int N, float[] A, ref int LDA, int [] IPIV, ref int info);
+        [DllImport("mkl_custom64", EntryPoint = "CGETRF",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_cgetrf (ref int M, ref int N, [In,Out] fcomplex [] A, ref int LDA, int [] IPIV, ref int info);
+        [DllImport("mkl_custom64", EntryPoint = "ZGETRF",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_zgetrf (ref int M, ref int N, [In,Out] complex [] A, ref int LDA, int [] IPIV, ref int info);
+
+        [DllImport("mkl_custom64", EntryPoint = "DGETRI",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_dgetri (ref int N, double[] A,ref  int LDA, int[] IPIV, double[] work, ref int lwork, ref int info);
+        [DllImport("mkl_custom64", EntryPoint = "SGETRI",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_sgetri (ref int N, float [] A, ref int LDA, int [] IPIV, float[] work, ref int lwork, ref int info);
+        [DllImport("mkl_custom64", EntryPoint = "CGETRI",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_cgetri (ref int N, [In,Out] fcomplex [] A, ref int LDA,[In,Out] int [] IPIV, [In,Out] fcomplex[] work, ref int lwork, ref int info);
+        [DllImport("mkl_custom64", EntryPoint = "ZGETRI",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_zgetri (ref int N, [In,Out] complex [] A, ref int LDA, int [] IPIV, [In,Out] complex[] work, ref int lwork, ref int info);
+
+        [DllImport("mkl_custom64", EntryPoint = "DGEQRF",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_dgeqrf (ref int M, ref int N, double [] A, ref int lda, double [] tau, double[] work, ref int lwork, ref int info);
+        [DllImport("mkl_custom64", EntryPoint = "SGEQRF",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_sgeqrf (ref int M, ref int N, float [] A, ref int lda, float [] tau, float[] work, ref int lwork,  ref int info);
+        [DllImport("mkl_custom64", EntryPoint = "CGEQRF",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_cgeqrf (ref int M, ref int N, [In,Out] fcomplex [] A, ref int lda, [In,Out] fcomplex [] tau, [In,Out] fcomplex[] work, ref int lwork, ref int info);
+        [DllImport("mkl_custom64", EntryPoint = "ZGEQRF",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_zgeqrf (ref int M, ref int N, [In,Out] complex [] A, ref int lda, [In,Out] complex [] tau, [In,Out] complex[] work, ref int lwork,  ref int info);
+
+        [DllImport("mkl_custom64", EntryPoint = "DGEQP3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_dgeqp3 (ref int M, ref int N, double [] A, ref int LDA, int [] JPVT, double [] tau, double [] work, ref int lwork, ref int info );
+        [DllImport("mkl_custom64", EntryPoint = "SGEQP3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_sgeqp3 (ref int M, ref int N, float [] A, ref int LDA, int [] JPVT, float [] tau, float [] work, ref int lwork, ref int info );
+        [DllImport("mkl_custom64", EntryPoint = "CGEQP3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_cgeqp3 (ref int M, ref int N,[In,Out] fcomplex [] A, ref int LDA,[In,Out] int [] JPVT, [In,Out] fcomplex [] tau, [In,Out] fcomplex [] work, ref int lwork,[In,Out] float [] rwork, ref int info );
+        [DllImport("mkl_custom64", EntryPoint = "ZGEQP3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_zgeqp3 (ref int M, ref int N, [In,Out] complex [] A, ref int LDA, [In,Out] int [] JPVT, [In,Out] complex [] tau, [In,Out] complex [] work, ref int lwork, [In,Out] double [] rwork, ref int info );
+
+        [DllImport("mkl_custom64", EntryPoint = "DORMQR",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_dormqr (ref char side, ref char trans, ref int m, ref int n, ref int k, double[] A, int lda, double[] tau, double[] C, ref int ldc, ref int info);
+        [DllImport("mkl_custom64", EntryPoint = "SORMQR",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_sormqr (ref char side, ref char trans, ref int m, ref int n, ref int k, float [] A, ref int lda, float [] tau , float [] C, ref int ldc, ref int info);
+        
+        [DllImport("mkl_custom64", EntryPoint = "DORGQR",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_dorgqr (ref int m, ref int n, ref int k, double[] A,ref int lda, double[] tau, double[] work, ref int lwork, ref int info);
+        [DllImport("mkl_custom64", EntryPoint = "SORGQR",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_sorgqr (ref int m, ref int n, ref int k, float [] A, ref int lda, float [] tau , float[] work, ref int lwork,  ref int info);
+        [DllImport("mkl_custom64", EntryPoint = "CUNGQR",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_cungqr (ref int m, ref int n, ref int k, [In,Out] fcomplex[] A,ref int lda, [In,Out] fcomplex[] tau, [In,Out] fcomplex[] work, ref int lwork, ref int info);
+        [DllImport("mkl_custom64", EntryPoint = "ZUNGQR",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_zungqr (ref int m, ref int n, ref int k, [In,Out] complex[] A,ref int lda, [In,Out] complex[] tau, [In,Out] complex[] work, ref int lwork, ref int info);
+        
+        [DllImport("mkl_custom64", EntryPoint = "DTRTRS", ExactSpelling = false, CallingConvention = CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_dtrtrs (ref char uplo, ref char transA, ref char diag, ref int N, ref int nrhs, IntPtr A, ref int LDA, IntPtr B, ref int LDB, ref int info);
+        [DllImport("mkl_custom64", EntryPoint = "STRTRS",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_strtrs (ref char uplo, ref char transA, ref char diag, ref int N, ref int nrhs, IntPtr A, ref int LDA, IntPtr B, ref int LDB, ref int info);
+        [DllImport("mkl_custom64", EntryPoint = "CTRTRS",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_ctrtrs (ref char uplo, ref char transA, ref char diag, ref int N, ref int nrhs, IntPtr A, ref int LDA, IntPtr B, ref int LDB, ref int info);
+        [DllImport("mkl_custom64", EntryPoint = "ZTRTRS",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_ztrtrs (ref char uplo, ref char transA, ref char diag, ref int N, ref int nrhs, IntPtr A, ref int LDA, IntPtr B, ref int LDB, ref int info);
+        
+        [DllImport("mkl_custom64", EntryPoint = "DGETRS",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_dgetrs(ref char trans, ref int N, ref int NRHS, double[] A, ref int LDA, int[] IPIV, double[] B, ref int LDB, ref int info);
+        [DllImport("mkl_custom64", EntryPoint = "SGETRS",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_sgetrs(ref char trans, ref int N, ref int NRHS, float[] A, ref int LDA, int[] IPIV, float[] B, ref int LDB, ref int info);
+        [DllImport("mkl_custom64", EntryPoint = "CGETRS",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_cgetrs(ref char trans, ref int N, ref int NRHS, [In,Out] fcomplex[] A, ref int LDA, int[] IPIV, [In,Out] fcomplex[] B, ref int LDB, ref int info);
+        [DllImport("mkl_custom64", EntryPoint = "ZGETRS",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_zgetrs(ref char trans, ref int N, ref int NRHS, [In,Out] complex[] A, ref int LDA, int[] IPIV, [In,Out] complex[] B, ref int LDB, ref int info);
+
+        [DllImport("mkl_custom64", EntryPoint = "DGELSD",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_dgelsd (ref int m,ref int n,ref int nrhs, double[] A,ref int lda, double[] B,ref int ldb, double[] S, ref double RCond, ref int rank, double[] work,ref int lwork, int[] iwork, ref int info); 
+        [DllImport("mkl_custom64", EntryPoint = "SGELSD",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_sgelsd (ref int m,ref int n,ref int nrhs, float[] A,ref int lda, float[] B,ref int ldb, float[] S, ref float RCond, ref int rank, float[] work,ref int lwork, int[] iwork, ref int info); 
+        [DllImport("mkl_custom64", EntryPoint = "CGELSD",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_cgelsd (ref int m,ref int n,ref int nrhs, [In,Out] fcomplex[] A,ref int lda, [In,Out] fcomplex[] B,ref int ldb, float[] S , ref float RCond, ref int rank, [In,Out] fcomplex[] work, ref int lwork, float[] rwork, int[] iwork, ref int info); 
+        [DllImport("mkl_custom64", EntryPoint = "ZGELSD",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_zgelsd (ref int m,ref int n,ref int nrhs, [In,Out] complex[] A,ref int lda, [In,Out] complex[] B,ref int ldb, double[] S, ref double RCond, ref int rank, [In,Out]  complex[] work,ref int lwork, double[] rwork, int[] iwork, ref int info); 
+        
+        [DllImport("mkl_custom64", EntryPoint = "DGELSY",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_dgelsy (ref int m,ref int n,ref int nrhs, double[] A,ref int lda, double[] B,ref int ldb, int[] JPVT0, ref double RCond, ref int rank, double[] work, ref int lwork, ref int info); 
+        [DllImport("mkl_custom64", EntryPoint = "SGELSY",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_sgelsy (ref int m,ref int n,ref int nrhs, float[] A,ref int lda, float[] B,ref int ldb, int[] JPVT0, ref float RCond, ref int rank, float[] work,ref int lwork, ref int info); 
+        [DllImport("mkl_custom64", EntryPoint = "CGELSY",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_cgelsy (ref int m,ref int n,ref int nrhs, [In,Out] fcomplex[] A,ref int lda, [In,Out] fcomplex[] B,ref int ldb, int[] JPVT0, ref float RCond, ref int rank, [In,Out] fcomplex[] work, ref int lwork, float[] rwork, ref int info); 
+        [DllImport("mkl_custom64", EntryPoint = "ZGELSY",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_zgelsy (ref int m,ref int n,ref int nrhs, [In,Out] complex[] A,ref int lda, [In,Out] complex[] B,ref int ldb, int[] JPVT0, ref double RCond, ref int rank, [In,Out]  complex[] work, ref int lwork, double[] rwork, ref int info); 
+        
+        [DllImport("mkl_custom64", EntryPoint = "DGEEVX",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_dgeevx (ref char balance, ref char jobvl, ref char jobvr, ref char sense, ref int n,            double[] A, ref int lda,          double[] wr, double[] wi, double[] vl, ref int ldvl,            double[] vr, ref int ldvr, ref int ilo, ref int ihi, double[] scale, ref double abnrm, double[] rconde, double[] rcondv, double[] work, ref int lwork, int [] iwork, ref int info); 
+        [DllImport("mkl_custom64", EntryPoint = "SGEEVX",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]       
+        private static extern void mkl_sgeevx (ref char balance, ref char jobvl, ref char jobvr, ref char sense, ref int n,             float[] A, ref int lda,             float[] wr, float[] wi, float[] vl, ref int ldvl,             float[] vr, ref int ldvr, ref int ilo, ref int ihi, float[]  scale, ref float  abnrm, float[]  rconde, float[]  rcondv, float [] work, ref int lwork, int [] iwork, ref int info); 
+        [DllImport("mkl_custom64", EntryPoint = "CGEEVX",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]       
+        private static extern void mkl_cgeevx (ref char balance, ref char jobvl, ref char jobvr, ref char sense, ref int n, [In,Out] fcomplex[] A, ref int lda, [In,Out] fcomplex[] w,  [In,Out] fcomplex[] vl, ref int ldvl, [In,Out] fcomplex[] vr, ref int ldvr, ref int ilo, ref int ihi, float[]  scale, ref float  abnrm, float[]  rconde, float[]  rcondv, [In,Out] fcomplex[] work, ref int lwork, float[] rwork, ref int info);
+        [DllImport("mkl_custom64", EntryPoint = "ZGEEVX",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]       
+        private static extern void mkl_zgeevx (ref char balance, ref char jobvl, ref char jobvr, ref char sense, ref int n, [In,Out]  complex[] A, ref int lda, [In,Out] complex[]  w,   [In,Out] complex[] vl, ref int ldvl, [In,Out]  complex[] vr, ref int ldvr, ref int ilo, ref int ihi, double[] scale, ref double abnrm, double[] rconde, double[] rcondv, [In,Out] complex[] work, ref int lwork, double[] rwork, ref int info);
+
+        [DllImport("mkl_custom64", EntryPoint = "DSYEVR",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_dsyevr (ref char jobz, ref char range, ref char uplo, ref int n,          double  [] A, ref int lda, ref double vl, ref double vu, ref int il, ref int iu, ref double abstol, ref int m, double[] w,          double  [] z, ref int ldz, int[] isuppz, double[] work, ref int lwork, int[] iwork, ref int liwork, ref int info); 
+        //[DllImport("mkl_custom64", EntryPoint = "DSYEVR",CallingConvention =CallingConvention.Cdecl)]
+        //private static extern void mkl_dsyevr (ref char jobz, ref char range, ref char uplo, ref int n,          double  [] A, ref int lda, ref double vl, ref double vu, ref int il, ref int iu, ref double abstol, ref int m, double[] w,          double  [] z, ref int ldz, int[] isuppz, double[] work, ref int lwork, int[] iwork, ref int liwork, ref int info); 
+        [DllImport("mkl_custom64", EntryPoint = "SSYEVR",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_ssyevr (ref char jobz, ref char range, ref char uplo, ref int n,          float   [] A, ref int lda, ref float  vl, ref float  vu, ref int il, ref int iu, ref float  abstol, ref int m, float [] w,          float   [] z, ref int ldz, int[] isuppz, float [] work, ref int lwork, int[] iwork, ref int liwork, ref int info); 
+        [DllImport("mkl_custom64", EntryPoint = "CHEEVR",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_cheevr (ref char jobz, ref char range, ref char uplo, ref int n, [In,Out] fcomplex[] A, ref int lda, ref float  vl, ref float  vu, ref int il, ref int iu, ref float  abstol, ref int m, float [] w, [In,Out] fcomplex[] z, ref int ldz, int[] isuppz, [In,Out] fcomplex[] work, ref int lwork, float[] rwork, ref int lrwork, int[] iwork, ref int liwork, ref int info); 
+        [DllImport("mkl_custom64", EntryPoint = "ZHEEVR",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_zheevr (ref char jobz, ref char range, ref char uplo, ref int n, [In,Out] complex [] A, ref int lda, ref double vl, ref double vu, ref int il, ref int iu, ref double abstol, ref int m, double[] w, [In,Out] complex [] z, ref int ldz, int[] isuppz, [In,Out] complex[] work, ref int lwork, double[] rwork, ref int lrwork, int[] iwork, ref int liwork, ref int info); 
+
+        [DllImport("mkl_custom64", EntryPoint = "DSYGV",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_dsygv (ref int itype, ref char jobz, ref char uplo, ref int n, double  [] A, ref int lda, double  [] B, ref int ldb, double [] w, double [] work, ref int lwork, ref int info); 
+        [DllImport("mkl_custom64", EntryPoint = "SSYGV",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_ssygv (ref int itype, ref char jobz, ref char uplo, ref int n, float   [] A, ref int lda, float   [] B, ref int ldb, float [] w,  float  [] work, ref int lwork, ref int info); 
+        [DllImport("mkl_custom64", EntryPoint = "CHEGV",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_chegv (ref int itype, ref char jobz, ref char uplo, ref int n, [In,Out] fcomplex[] A, ref int lda, [In,Out] fcomplex [] B, ref int ldb, float  [] w, [In,Out] fcomplex[] work , ref int lwork, float[] rwork, ref int info); 
+        [DllImport("mkl_custom64", EntryPoint = "ZHEGV",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_zhegv (ref int itype, ref char jobz, ref char uplo, ref int n, [In,Out] complex [] A, ref int lda, [In,Out] complex  [] B, ref int ldb, double [] w, [In,Out]  complex[] work , ref int lwork, double[] rwork, ref int info); 
+        #endregion
+#else 
+        #region 32 bit includes
+        [DllImport("mkl_custom32", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
+        internal static extern int mkl_domain_set_num_threads(ref int num, ref int mask);
+        [DllImport("mkl_custom32", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
+        internal static extern int mkl_domain_get_max_threads(ref int mask);
+        [DllImport("mkl_custom32", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 
+        internal static extern void mkl_set_num_threads(int num);
+        [DllImport("mkl_custom32", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
+        internal static extern void omp_set_num_threads(int num);
+        [DllImport("mkl_custom32", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
+        internal static extern int mkl_get_max_threads();
+        [DllImport("mkl_custom32", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
+        internal static extern void mkl_set_dynamic(ref int boolean_value);
+
+        [DllImport("mkl_custom32", EntryPoint = "ilaenv",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern int mkl_ilaenv(ref int ispec, ref string name, ref string opts, ref int n1, ref int n2, ref int n3, ref int n4);
+
+        ///////////////////////////   DOUBLE LAPACK /////////////////////////////////
+        [DllImport("mkl_custom32", EntryPoint = "DGEMM",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_dgemm(ref char TransA, ref char TransB, ref int M,ref int N, ref int K, ref  double alpha, IntPtr A, ref int lda, IntPtr B, ref int ldb, ref double beta, double[] C, ref int ldc);
+        [DllImport("mkl_custom32", EntryPoint = "SGEMM",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_sgemm(ref char TransA, ref char TransB, ref int M,ref int N, ref int K, ref float alpha, IntPtr A,ref int lda, IntPtr B, ref int ldb, ref float beta,float[] C, ref int ldc);
+        [DllImport("mkl_custom32", EntryPoint = "CGEMM",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_cgemm(ref char TransA, ref char TransB, ref int M,ref int N, ref int K, ref fcomplex alpha, IntPtr A, ref int lda, IntPtr B, ref int ldb, ref fcomplex beta,[In,Out] fcomplex [] C, ref int ldc);
+        [DllImport("mkl_custom32", EntryPoint = "ZGEMM",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_zgemm(ref char TransA, ref char TransB, ref int M, ref int N, ref int K, ref complex alpha, IntPtr A, ref int lda, IntPtr B, ref int ldb, ref complex beta,[In,Out] complex [] C, ref int ldc);
+
+        [DllImport("mkl_custom32", EntryPoint = "DGESDD",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_dgesdd(ref char jobz, ref int m, ref int n,double[] a, ref int lda, double[] s,double[] u, ref int ldu, double[] vt,ref int ldvt, double[] work, ref int lwork,int[] iwork, ref int info);
+        [DllImport("mkl_custom32", EntryPoint = "SGESDD",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_sgesdd(ref char jobz, ref int m, ref int n,float[] a, ref int lda, float[] s,float[] u, ref int ldu, float[] vt, ref int ldvt, float[] work, ref int lwork,int[] iwork, ref int info);
+        [DllImport("mkl_custom32", EntryPoint = "CGESDD",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_cgesdd(ref char jobz, ref int m, ref int n,[In, Out] fcomplex[] a, ref int lda, float[] s,[In, Out] fcomplex[] u, ref int ldu, [In, Out]  fcomplex[] vt, ref int ldvt, [In, Out] fcomplex[] work, ref int lwork,[In,Out] float[] rwork, int[] iwork, ref int info);
+        [DllImport("mkl_custom32", EntryPoint = "ZGESDD",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_zgesdd(ref char jobz, ref int m, ref int n,[In, Out] complex[] a, ref int lda, double[] s,[In, Out] complex[] u, ref int ldu, [In, Out] complex[] vt,ref int ldvt, [In, Out] complex[] work, ref int lwork,[In,Out] double[] rwork, int[] iwork, ref int info);
+
+        [DllImport("mkl_custom32", EntryPoint = "DGESVD",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_dgesvd(ref char jobu, ref  char jobvt, ref int m, ref int n,double[] a, ref int lda, double[] s,double[] u, ref int ldu, double[] vt,ref int ldvt, double[] work, ref int lwork,int[] iwork,ref int info);
+        [DllImport("mkl_custom32", EntryPoint = "SGESVD",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_sgesvd(ref char jobu, ref  char jobvt, ref int m, ref int n, float[] a, ref int lda, float[] s,float[] u, ref int ldu, float[] vt,ref int ldvt, float[] work, ref int lwork,int[] iwork, ref int info);
+        [DllImport("mkl_custom32", EntryPoint = "CGESVD",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_cgesvd(ref char jobu, ref  char jobvt, ref int m, ref int n,[In, Out] fcomplex[] a, ref int lda, float[] s,[In, Out] fcomplex[] u, ref int ldu,[In,Out] fcomplex[] vt,ref int ldvt, [In, Out]  fcomplex[] work, ref int lwork,int[] iwork,ref int info);
+        [DllImport("mkl_custom32", EntryPoint = "ZGESVD",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_zgesvd(ref char jobu, ref  char jobvt, ref int m, ref int n,[In, Out] complex[] a, ref int lda, double[] s,[In, Out] complex[] u, ref int ldu, [In, Out] complex[] vt,ref int ldvt, [In, Out]  complex[] work, ref int lwork,int[] iwork,ref int info);
+
+        [DllImport("mkl_custom32", EntryPoint = "DPOTRF",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_dpotrf (ref char uplo, ref int n, double [] A, ref int lda, ref int info);
+        [DllImport("mkl_custom32", EntryPoint = "SPOTRF",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_spotrf (ref char uplo, ref int n, float [] A, ref int lda, ref int info);
+        [DllImport("mkl_custom32", EntryPoint = "CPOTRF",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_cpotrf (ref char uplo, ref int n,[In,Out] fcomplex [] A, ref int lda, ref int info);
+        [DllImport("mkl_custom32", EntryPoint = "ZPOTRF",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_zpotrf (ref char uplo, ref int n, [In,Out] complex [] A, ref int lda, ref int info);
+        
+        [DllImport("mkl_custom32", EntryPoint = "DPOTRI",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_dpotri (ref char uplo,ref  int n, double [] A, ref int lda, ref int info);
+        [DllImport("mkl_custom32", EntryPoint = "SPOTRI",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_spotri (ref char uplo, ref int n, float [] A, ref int lda, ref int info);
+        [DllImport("mkl_custom32", EntryPoint = "CPOTRI",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_cpotri (ref char uplo, ref int n,[In,Out] fcomplex [] A, ref int lda,ref int info);
+        [DllImport("mkl_custom32", EntryPoint = "ZPOTRI",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_zpotri (ref char uplo, ref int n, [In,Out] complex [] A, ref int lda,ref int info);
+
+        [DllImport("mkl_custom32", EntryPoint = "DPOTRS",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_dpotrs (ref char uplo,ref  int n, ref int NRHS, double [] A, ref int lda, double[] B, ref int ldb, ref int info);
+        [DllImport("mkl_custom32", EntryPoint = "SPOTRS",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_spotrs (ref char uplo,ref  int n, ref int NRHS, float [] A, ref int lda, float[] B, ref int ldb, ref int info);
+        [DllImport("mkl_custom32", EntryPoint = "CPOTRS",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_cpotrs (ref char uplo,ref  int n, ref int NRHS, [In,Out] fcomplex [] A, ref int lda, [In,Out] fcomplex[] B, ref int ldb, ref int info);
+        [DllImport("mkl_custom32", EntryPoint = "ZPOTRS",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_zpotrs (ref char uplo,ref  int n, ref int NRHS, [In,Out] complex [] A, ref int lda, [In,Out] complex[] B, ref int ldb, ref int info);
+
+        [DllImport("mkl_custom32", EntryPoint = "DGETRF",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_dgetrf (ref int M, ref int N, double [] A, ref int LDA, int[] IPIV, ref int info);
+        [DllImport("mkl_custom32", EntryPoint = "SGETRF",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_sgetrf (ref int M, ref int N, float[] A, ref int LDA, int [] IPIV, ref int info);
+        [DllImport("mkl_custom32", EntryPoint = "CGETRF",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_cgetrf (ref int M, ref int N, [In,Out] fcomplex [] A, ref int LDA, int [] IPIV, ref int info);
+        [DllImport("mkl_custom32", EntryPoint = "ZGETRF",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_zgetrf (ref int M, ref int N, [In,Out] complex [] A, ref int LDA, int [] IPIV, ref int info);
+
+        [DllImport("mkl_custom32", EntryPoint = "DGETRI",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_dgetri (ref int N, double[] A,ref  int LDA, int[] IPIV, double[] work, ref int lwork, ref int info);
+        [DllImport("mkl_custom32", EntryPoint = "SGETRI",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_sgetri (ref int N, float [] A, ref int LDA, int [] IPIV, float[] work, ref int lwork, ref int info);
+        [DllImport("mkl_custom32", EntryPoint = "CGETRI",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_cgetri (ref int N, [In,Out] fcomplex [] A, ref int LDA,[In,Out] int [] IPIV, [In,Out] fcomplex[] work, ref int lwork, ref int info);
+        [DllImport("mkl_custom32", EntryPoint = "ZGETRI",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_zgetri (ref int N, [In,Out] complex [] A, ref int LDA, int [] IPIV, [In,Out] complex[] work, ref int lwork, ref int info);
+
+        [DllImport("mkl_custom32", EntryPoint = "DGEQRF",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_dgeqrf (ref int M, ref int N, double [] A, ref int lda, double [] tau, double[] work, ref int lwork, ref int info);
+        [DllImport("mkl_custom32", EntryPoint = "SGEQRF",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_sgeqrf (ref int M, ref int N, float [] A, ref int lda, float [] tau, float[] work, ref int lwork,  ref int info);
+        [DllImport("mkl_custom32", EntryPoint = "CGEQRF",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_cgeqrf (ref int M, ref int N, [In,Out] fcomplex [] A, ref int lda, [In,Out] fcomplex [] tau, [In,Out] fcomplex[] work, ref int lwork, ref int info);
+        [DllImport("mkl_custom32", EntryPoint = "ZGEQRF",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_zgeqrf (ref int M, ref int N, [In,Out] complex [] A, ref int lda, [In,Out] complex [] tau, [In,Out] complex[] work, ref int lwork,  ref int info);
+
+        [DllImport("mkl_custom32", EntryPoint = "DGEQP3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_dgeqp3 (ref int M, ref int N, double [] A, ref int LDA, int [] JPVT, double [] tau, double [] work, ref int lwork, ref int info );
+        [DllImport("mkl_custom32", EntryPoint = "SGEQP3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_sgeqp3 (ref int M, ref int N, float [] A, ref int LDA, int [] JPVT, float [] tau, float [] work, ref int lwork, ref int info );
+        [DllImport("mkl_custom32", EntryPoint = "CGEQP3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_cgeqp3 (ref int M, ref int N,[In,Out] fcomplex [] A, ref int LDA,[In,Out] int [] JPVT, [In,Out] fcomplex [] tau, [In,Out] fcomplex [] work, ref int lwork,[In,Out] float [] rwork, ref int info );
+        [DllImport("mkl_custom32", EntryPoint = "ZGEQP3",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_zgeqp3 (ref int M, ref int N, [In,Out] complex [] A, ref int LDA, [In,Out] int [] JPVT, [In,Out] complex [] tau, [In,Out] complex [] work, ref int lwork, [In,Out] double [] rwork, ref int info );
+
+        [DllImport("mkl_custom32", EntryPoint = "DORMQR",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_dormqr (ref char side, ref char trans, ref int m, ref int n, ref int k, double[] A, int lda, double[] tau, double[] C, ref int ldc, ref int info);
+        [DllImport("mkl_custom32", EntryPoint = "SORMQR",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_sormqr (ref char side, ref char trans, ref int m, ref int n, ref int k, float [] A, ref int lda, float [] tau , float [] C, ref int ldc, ref int info);
+        
+        [DllImport("mkl_custom32", EntryPoint = "DORGQR",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_dorgqr (ref int m, ref int n, ref int k, double[] A,ref int lda, double[] tau, double[] work, ref int lwork, ref int info);
+        [DllImport("mkl_custom32", EntryPoint = "SORGQR",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_sorgqr (ref int m, ref int n, ref int k, float [] A, ref int lda, float [] tau , float[] work, ref int lwork,  ref int info);
+        [DllImport("mkl_custom32", EntryPoint = "CUNGQR",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_cungqr (ref int m, ref int n, ref int k, [In,Out] fcomplex[] A,ref int lda, [In,Out] fcomplex[] tau, [In,Out] fcomplex[] work, ref int lwork, ref int info);
+        [DllImport("mkl_custom32", EntryPoint = "ZUNGQR",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_zungqr (ref int m, ref int n, ref int k, [In,Out] complex[] A,ref int lda, [In,Out] complex[] tau, [In,Out] complex[] work, ref int lwork, ref int info);
+        
+        [DllImport("mkl_custom32", EntryPoint = "DTRTRS", ExactSpelling = false, CallingConvention = CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_dtrtrs (ref char uplo, ref char transA, ref char diag, ref int N, ref int nrhs, IntPtr A, ref int LDA, IntPtr B, ref int LDB, ref int info);
+        [DllImport("mkl_custom32", EntryPoint = "STRTRS",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_strtrs (ref char uplo, ref char transA, ref char diag, ref int N, ref int nrhs, IntPtr A, ref int LDA, IntPtr B, ref int LDB, ref int info);
+        [DllImport("mkl_custom32", EntryPoint = "CTRTRS",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_ctrtrs (ref char uplo, ref char transA, ref char diag, ref int N, ref int nrhs, IntPtr A, ref int LDA, IntPtr B, ref int LDB, ref int info);
+        [DllImport("mkl_custom32", EntryPoint = "ZTRTRS",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_ztrtrs (ref char uplo, ref char transA, ref char diag, ref int N, ref int nrhs, IntPtr A, ref int LDA, IntPtr B, ref int LDB, ref int info);
+        
+        [DllImport("mkl_custom32", EntryPoint = "DGETRS",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_dgetrs(ref char trans, ref int N, ref int NRHS, double[] A, ref int LDA, int[] IPIV, double[] B, ref int LDB, ref int info);
+        [DllImport("mkl_custom32", EntryPoint = "SGETRS",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_sgetrs(ref char trans, ref int N, ref int NRHS, float[] A, ref int LDA, int[] IPIV, float[] B, ref int LDB, ref int info);
+        [DllImport("mkl_custom32", EntryPoint = "CGETRS",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_cgetrs(ref char trans, ref int N, ref int NRHS, [In,Out] fcomplex[] A, ref int LDA, int[] IPIV, [In,Out] fcomplex[] B, ref int LDB, ref int info);
+        [DllImport("mkl_custom32", EntryPoint = "ZGETRS",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_zgetrs(ref char trans, ref int N, ref int NRHS, [In,Out] complex[] A, ref int LDA, int[] IPIV, [In,Out] complex[] B, ref int LDB, ref int info);
+
+        [DllImport("mkl_custom32", EntryPoint = "DGELSD",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_dgelsd (ref int m,ref int n,ref int nrhs, double[] A,ref int lda, double[] B,ref int ldb, double[] S, ref double RCond, ref int rank, double[] work,ref int lwork, int[] iwork, ref int info); 
+        [DllImport("mkl_custom32", EntryPoint = "SGELSD",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_sgelsd (ref int m,ref int n,ref int nrhs, float[] A,ref int lda, float[] B,ref int ldb, float[] S, ref float RCond, ref int rank, float[] work,ref int lwork, int[] iwork, ref int info); 
+        [DllImport("mkl_custom32", EntryPoint = "CGELSD",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_cgelsd (ref int m,ref int n,ref int nrhs, [In,Out] fcomplex[] A,ref int lda, [In,Out] fcomplex[] B,ref int ldb, float[] S , ref float RCond, ref int rank, [In,Out] fcomplex[] work, ref int lwork, float[] rwork, int[] iwork, ref int info); 
+        [DllImport("mkl_custom32", EntryPoint = "ZGELSD",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_zgelsd (ref int m,ref int n,ref int nrhs, [In,Out] complex[] A,ref int lda, [In,Out] complex[] B,ref int ldb, double[] S, ref double RCond, ref int rank, [In,Out]  complex[] work,ref int lwork, double[] rwork, int[] iwork, ref int info); 
+        
+        [DllImport("mkl_custom32", EntryPoint = "DGELSY",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_dgelsy (ref int m,ref int n,ref int nrhs, double[] A,ref int lda, double[] B,ref int ldb, int[] JPVT0, ref double RCond, ref int rank, double[] work, ref int lwork, ref int info); 
+        [DllImport("mkl_custom32", EntryPoint = "SGELSY",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_sgelsy (ref int m,ref int n,ref int nrhs, float[] A,ref int lda, float[] B,ref int ldb, int[] JPVT0, ref float RCond, ref int rank, float[] work,ref int lwork, ref int info); 
+        [DllImport("mkl_custom32", EntryPoint = "CGELSY",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_cgelsy (ref int m,ref int n,ref int nrhs, [In,Out] fcomplex[] A,ref int lda, [In,Out] fcomplex[] B,ref int ldb, int[] JPVT0, ref float RCond, ref int rank, [In,Out] fcomplex[] work, ref int lwork, float[] rwork, ref int info); 
+        [DllImport("mkl_custom32", EntryPoint = "ZGELSY",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_zgelsy (ref int m,ref int n,ref int nrhs, [In,Out] complex[] A,ref int lda, [In,Out] complex[] B,ref int ldb, int[] JPVT0, ref double RCond, ref int rank, [In,Out]  complex[] work, ref int lwork, double[] rwork, ref int info); 
+        
+        [DllImport("mkl_custom32", EntryPoint = "DGEEVX",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_dgeevx (ref char balance, ref char jobvl, ref char jobvr, ref char sense, ref int n,            double[] A, ref int lda,          double[] wr, double[] wi, double[] vl, ref int ldvl,            double[] vr, ref int ldvr, ref int ilo, ref int ihi, double[] scale, ref double abnrm, double[] rconde, double[] rcondv, double[] work, ref int lwork, int [] iwork, ref int info); 
+        [DllImport("mkl_custom32", EntryPoint = "SGEEVX",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]       
+        private static extern void mkl_sgeevx (ref char balance, ref char jobvl, ref char jobvr, ref char sense, ref int n,             float[] A, ref int lda,             float[] wr, float[] wi, float[] vl, ref int ldvl,             float[] vr, ref int ldvr, ref int ilo, ref int ihi, float[]  scale, ref float  abnrm, float[]  rconde, float[]  rcondv, float [] work, ref int lwork, int [] iwork, ref int info); 
+        [DllImport("mkl_custom32", EntryPoint = "CGEEVX",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]       
+        private static extern void mkl_cgeevx (ref char balance, ref char jobvl, ref char jobvr, ref char sense, ref int n, [In,Out] fcomplex[] A, ref int lda, [In,Out] fcomplex[] w,  [In,Out] fcomplex[] vl, ref int ldvl, [In,Out] fcomplex[] vr, ref int ldvr, ref int ilo, ref int ihi, float[]  scale, ref float  abnrm, float[]  rconde, float[]  rcondv, [In,Out] fcomplex[] work, ref int lwork, float[] rwork, ref int info);
+        [DllImport("mkl_custom32", EntryPoint = "ZGEEVX",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]       
+        private static extern void mkl_zgeevx (ref char balance, ref char jobvl, ref char jobvr, ref char sense, ref int n, [In,Out]  complex[] A, ref int lda, [In,Out] complex[]  w,   [In,Out] complex[] vl, ref int ldvl, [In,Out]  complex[] vr, ref int ldvr, ref int ilo, ref int ihi, double[] scale, ref double abnrm, double[] rconde, double[] rcondv, [In,Out] complex[] work, ref int lwork, double[] rwork, ref int info);
+
+        [DllImport("mkl_custom32", EntryPoint = "DSYEVR",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_dsyevr (ref char jobz, ref char range, ref char uplo, ref int n,          double  [] A, ref int lda, ref double vl, ref double vu, ref int il, ref int iu, ref double abstol, ref int m, double[] w,          double  [] z, ref int ldz, int[] isuppz, double[] work, ref int lwork, int[] iwork, ref int liwork, ref int info); 
+        //[DllImport("mkl_custom32", EntryPoint = "DSYEVR",CallingConvention =CallingConvention.Cdecl)]
+        //private static extern void mkl_dsyevr (ref char jobz, ref char range, ref char uplo, ref int n,          double  [] A, ref int lda, ref double vl, ref double vu, ref int il, ref int iu, ref double abstol, ref int m, double[] w,          double  [] z, ref int ldz, int[] isuppz, double[] work, ref int lwork, int[] iwork, ref int liwork, ref int info); 
+        [DllImport("mkl_custom32", EntryPoint = "SSYEVR",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_ssyevr (ref char jobz, ref char range, ref char uplo, ref int n,          float   [] A, ref int lda, ref float  vl, ref float  vu, ref int il, ref int iu, ref float  abstol, ref int m, float [] w,          float   [] z, ref int ldz, int[] isuppz, float [] work, ref int lwork, int[] iwork, ref int liwork, ref int info); 
+        [DllImport("mkl_custom32", EntryPoint = "CHEEVR",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_cheevr (ref char jobz, ref char range, ref char uplo, ref int n, [In,Out] fcomplex[] A, ref int lda, ref float  vl, ref float  vu, ref int il, ref int iu, ref float  abstol, ref int m, float [] w, [In,Out] fcomplex[] z, ref int ldz, int[] isuppz, [In,Out] fcomplex[] work, ref int lwork, float[] rwork, ref int lrwork, int[] iwork, ref int liwork, ref int info); 
+        [DllImport("mkl_custom32", EntryPoint = "ZHEEVR",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_zheevr (ref char jobz, ref char range, ref char uplo, ref int n, [In,Out] complex [] A, ref int lda, ref double vl, ref double vu, ref int il, ref int iu, ref double abstol, ref int m, double[] w, [In,Out] complex [] z, ref int ldz, int[] isuppz, [In,Out] complex[] work, ref int lwork, double[] rwork, ref int lrwork, int[] iwork, ref int liwork, ref int info); 
+
+        [DllImport("mkl_custom32", EntryPoint = "DSYGV",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_dsygv (ref int itype, ref char jobz, ref char uplo, ref int n, double  [] A, ref int lda, double  [] B, ref int ldb, double [] w, double [] work, ref int lwork, ref int info); 
+        [DllImport("mkl_custom32", EntryPoint = "SSYGV",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_ssygv (ref int itype, ref char jobz, ref char uplo, ref int n, float   [] A, ref int lda, float   [] B, ref int ldb, float [] w,  float  [] work, ref int lwork, ref int info); 
+        [DllImport("mkl_custom32", EntryPoint = "CHEGV",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_chegv (ref int itype, ref char jobz, ref char uplo, ref int n, [In,Out] fcomplex[] A, ref int lda, [In,Out] fcomplex [] B, ref int ldb, float  [] w, [In,Out] fcomplex[] work , ref int lwork, float[] rwork, ref int info); 
+        [DllImport("mkl_custom32", EntryPoint = "ZHEGV",CallingConvention =CallingConvention.Cdecl),SuppressUnmanagedCodeSecurity]
+        private static extern void mkl_zhegv (ref int itype, ref char jobz, ref char uplo, ref int n, [In,Out] complex [] A, ref int lda, [In,Out] complex  [] B, ref int ldb, double [] w, [In,Out]  complex[] work , ref int lwork, double[] rwork, ref int info); 
+        #endregion
+#endif
+        #endregion DLL INCLUDES
+
+        public ILLapackMKL10_0() {
+            Init();
+        }
+
+        public static void Init() {
+            try {
+                // unless the user explicitely configured the number of threads, let omp configure it! 
+                if (Settings.MaxNumberThreadsConfigured) {
+                    SetDomainNumThreads(Settings.MaxNumberThreads);
+                }
+            } catch (System.IO.FileNotFoundException) { }
+        }
+
+        #region ILLAPACK INTERFACE 
+
+        private int ILAENV (int ispec, string name, string opts, int n1, int n2, int n3, int n4) {
+            return mkl_ilaenv(ref ispec, ref name, ref opts, ref n1, ref n2, ref n3, ref n4); 
+        }
+        private static void SetNumThreads(int numThreads) {
+            mkl_set_num_threads(numThreads);
+            //omp_set_num_threads(numThreads); 
+        }
+        private static void SetDomainNumThreads(int numThreads) {
+            int mklblas = MKLValues.MKL_BLAS;
+            mkl_domain_set_num_threads(ref numThreads,ref mklblas);
+            //omp_set_num_threads(numThreads); 
+        }
+        private static void SetDynamicThreads(bool dynamic) {
+            int val = dynamic ? 1 : 0; 
+            mkl_set_dynamic(ref val);
+        }
+        public static int GetMaxThreads() {
+            int dummy = MKLValues.MKL_BLAS; 
+            int ret = mkl_domain_get_max_threads(ref dummy);
+            return ret; 
+        }
+
+        /// <summary>
+        /// Implement wrapper for ATLAS GeneralMatrixMultiply
+        /// </summary>
+        /// <param name="TransA">Transposition state for matrix A: one of the constants in enum CBlas_Transpose</param>
+        /// <param name="TransB">Transposition state for matrix B: one of the constants in enum CBlas_Transpose</param>
+        /// <param name="M">Number of rows in A</param>
+        /// <param name="N">Number of columns in B</param>
+        /// <param name="K">Number of columns in A and number of rows in B</param>
+        /// <param name="alpha">multiplicationi factor for A</param>
+        /// <param name="A">pointer to double array A</param>
+        /// <param name="lda">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix B</param>
+        /// <param name="B">pointer to double array B</param>
+        /// <param name="ldb">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix A</param>
+        /// <param name="beta">multiplication faktor for matrix B</param>
+        /// <param name="C">pointer to predefined double array C of neccessary length</param>
+        /// <param name="ldc">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix C</param>
+        /// <remarks>All parameters except C are readonly. Only elements of matrix C will be altered. C must be a predefined 
+        /// continous double array of size MxN</remarks>
+        public void dgemm(char TransA, char TransB, int M, int N, int K, double alpha, IntPtr A, int lda, IntPtr B, int ldb, double beta, double[] C, int ldc) {
+            mkl_dgemm(ref TransA, ref TransB, ref M, ref  N, ref  K, ref  alpha, A, ref lda, B, ref ldb, ref  beta, C, ref  ldc);
+        }
+        /// <summary>
+        /// Implement wrapper for ATLAS GeneralMatrixMultiply
+        /// </summary>
+        /// <param name="TransA">Transposition state for matrix A: one of the constants in enum CBlas_Transpose</param>
+        /// <param name="TransB">Transposition state for matrix B: one of the constants in enum CBlas_Transpose</param>
+        /// <param name="M">Number of rows in A</param>
+        /// <param name="N">Number of columns in B</param>
+        /// <param name="K">Number of columns in A and number of rows in B</param>
+        /// <param name="alpha">multiplicationi factor for A</param>
+        /// <param name="A">pointer to double array A</param>
+        /// <param name="lda">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix B</param>
+        /// <param name="B">pointer to double array B</param>
+        /// <param name="ldb">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix A</param>
+        /// <param name="beta">multiplication faktor for matrix B</param>
+        /// <param name="C">pointer to predefined double array C of neccessary length</param>
+        /// <param name="ldc">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix C</param>
+        /// <remarks>All parameters except C are readonly. Only elements of matrix C will be altered. C must be a predefined 
+        /// continous double array of size MxN</remarks>
+        public void sgemm(char TransA, char TransB, int M, int N, int K, float alpha, IntPtr A, int lda, IntPtr B, int ldb, float beta, float[] C, int ldc) {
+            mkl_sgemm(ref TransA, ref TransB, ref M, ref  N, ref  K, ref  alpha, A, ref lda, B, ref ldb, ref  beta, C, ref  ldc);
+        }
+        /// <summary>
+        /// Implement wrapper for ATLAS GeneralMatrixMultiply
+        /// </summary>
+        /// <param name="TransA">Transposition state for matrix A: one of the constants in enum CBlas_Transpose</param>
+        /// <param name="TransB">Transposition state for matrix B: one of the constants in enum CBlas_Transpose</param>
+        /// <param name="M">Number of rows in A</param>
+        /// <param name="N">Number of columns in B</param>
+        /// <param name="K">Number of columns in A and number of rows in B</param>
+        /// <param name="alpha">multiplicationi factor for A</param>
+        /// <param name="A">pointer to double array A</param>
+        /// <param name="lda">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix B</param>
+        /// <param name="B">pointer to double array B</param>
+        /// <param name="ldb">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix A</param>
+        /// <param name="beta">multiplication faktor for matrix B</param>
+        /// <param name="C">pointer to predefined double array C of neccessary length</param>
+        /// <param name="ldc">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix C</param>
+        /// <remarks>All parameters except C are readonly. Only elements of matrix C will be altered. C must be a predefined 
+        /// continous double array of size MxN</remarks>
+        public void cgemm(char TransA, char TransB, int M, int N, int K, fcomplex alpha, IntPtr A, int lda, IntPtr B, int ldb, fcomplex beta, fcomplex[] C, int ldc) {
+            mkl_cgemm(ref TransA, ref TransB, ref M, ref  N, ref  K, ref  alpha, A, ref lda, B, ref ldb, ref  beta, C, ref  ldc);
+        }
+        /// <summary>
+        /// Implement wrapper for ATLAS GeneralMatrixMultiply
+        /// </summary>
+        /// <param name="TransA">Transposition state for matrix A: one of the constants in enum CBlas_Transpose</param>
+        /// <param name="TransB">Transposition state for matrix B: one of the constants in enum CBlas_Transpose</param>
+        /// <param name="M">Number of rows in A</param>
+        /// <param name="N">Number of columns in B</param>
+        /// <param name="K">Number of columns in A and number of rows in B</param>
+        /// <param name="alpha">multiplicationi factor for A</param>
+        /// <param name="A">pointer to double array A</param>
+        /// <param name="lda">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix B</param>
+        /// <param name="B">pointer to double array B</param>
+        /// <param name="ldb">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix A</param>
+        /// <param name="beta">multiplication faktor for matrix B</param>
+        /// <param name="C">pointer to predefined double array C of neccessary length</param>
+        /// <param name="ldc">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix C</param>
+        /// <remarks>All parameters except C are readonly. Only elements of matrix C will be altered. C must be a predefined 
+        /// continous double array of size MxN</remarks>
+        public void zgemm(char TransA, char TransB, int M, int N, int K, complex alpha, IntPtr A, int lda, IntPtr B, int ldb, complex beta, complex[] C, int ldc) {
+            mkl_zgemm(ref TransA, ref TransB, ref M, ref  N, ref  K, ref  alpha, A, ref lda, B, ref ldb, ref  beta, C, ref  ldc);
+        }
+
+
+        
+        public void  dgesdd (char jobz, int m, int n,  double [] a, int lda,  double [] s,  double [] u, int ldu,  double [] vt, int ldvt, ref int info) {
+            try {
+                 double [] work = new  double [1] { ( double )0.0 };
+                int lwork = -1;
+                int[] iwork = new int[((m < n) ? m : n) * 8];
+                 mkl_dgesdd (ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, iwork, ref info);
+                if (work[0] != 0) {
+                    work = new  double [(int)work[0]];
+                    lwork = work.Length;
+                     mkl_dgesdd (ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, iwork, ref info);
+                }
+            } catch (Exception e) {
+                if (e is OutOfMemoryException) {
+                     dgesvd (jobz, m, n, a, lda, s, u, ldu, vt, ldvt, ref info); 
+                }
+                throw new ILException("Unable to do " +  "dgesdd"  + ".", e); 
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+       
+        public void  sgesdd (char jobz, int m, int n,  float [] a, int lda,  float [] s,  float [] u, int ldu,  float [] vt, int ldvt, ref int info) {
+            try {
+                float [] work = new  float [1] { ( float )0.0 };
+                int lwork = -1;
+                int[] iwork = new int[((m < n) ? m : n) * 8];
+                mkl_sgesdd (ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, iwork, ref info);
+                if (work[0] != 0) {
+                    work = new  float [(int)work[0]];
+                    lwork = work.Length;
+                    mkl_sgesdd (ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, iwork, ref info);
+                }
+            } catch (Exception e) {
+                if (e is OutOfMemoryException) {
+                    sgesvd (jobz, m, n, a, lda, s, u, ldu, vt, ldvt, ref info); 
+                }
+                throw new ILException("Unable to do " +  "sgesdd"  + ".", e); 
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+
+
+        public void  zgesdd (char jobz, int m, int n,  complex [] a, int lda,  double [] s,  complex [] u, int ldu, complex [] vt, int ldvt, ref int info)
+        {
+            try {
+                 complex [] work = new  complex [1] { (  complex )0.0 };
+                 double [] rwork; 
+                int minMN = (m < n) ? m : n;
+                if (jobz == 'N') {
+                    rwork = new  double [minMN * 7];  
+                } else {
+                    rwork = new  double [5 * minMN * minMN + 5 * minMN];  
+                }
+                int lwork = -1;
+                int[] iwork = new int[minMN * 8];
+                 mkl_zgesdd (ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, rwork, iwork, ref info);
+                if (work[0] != 0) {
+                    work = new  complex [(int)work[0].real];
+                    lwork = work.Length;
+                     mkl_zgesdd (ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork,rwork, iwork, ref info);
+                }
+            } catch (Exception e) {
+                if (e is OutOfMemoryException) {
+                     zgesvd (jobz, m, n, a, lda, s, u, ldu, vt, ldvt, ref info); 
+                }
+                throw new ILException("Unable to do " +  "zgesdd"  + ".", e); 
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+
+        public void  cgesdd (char jobz, int m, int n,  fcomplex [] a, int lda,  float [] s,  fcomplex [] u, int ldu, fcomplex [] vt, int ldvt, ref int info)
+        {
+            try {
+                fcomplex [] work = new  fcomplex [1] { (  fcomplex )0.0 };
+                float [] rwork; 
+                int minMN = (m < n) ? m : n;
+                if (jobz == 'N') {
+                    rwork = new  float [minMN * 7];  
+                } else {
+                    rwork = new  float [5 * minMN * minMN + 5 * minMN];  
+                }
+                int lwork = -1;
+                int[] iwork = new int[minMN * 8];
+                mkl_cgesdd (ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, rwork, iwork, ref info);
+                if (work[0] != 0) {
+                    work = new  fcomplex [(int)work[0].real];
+                    lwork = work.Length;
+                    mkl_cgesdd (ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork,rwork, iwork, ref info);
+                }
+            } catch (Exception e) {
+                if (e is OutOfMemoryException) {
+                    cgesvd (jobz, m, n, a, lda, s, u, ldu, vt, ldvt, ref info); 
+                }
+                throw new ILException("Unable to do " +  "zgesdd"  + ".", e); 
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+
+        
+
+        /// <summary>
+        /// singular value decomposition
+        /// </summary>
+        /// <param name="jobz"></param>
+        /// <param name="m"></param>
+        /// <param name="n"></param>
+        /// <param name="a"></param>
+        /// <param name="lda"></param>
+        /// <param name="s"></param>
+        /// <param name="u"></param>
+        /// <param name="ldu"></param>
+        /// <param name="vt"></param>
+        /// <param name="ldvt"></param>
+        /// <param name="info"></param>
+        public void  dgesvd (char jobz, int m, int n,  double [] a, int lda,
+                            double [] s,  double [] u, int ldu,  double [] vt, int ldvt, ref int info) {
+            if (jobz != 'A' && jobz != 'S' && jobz != 'N')
+                throw new ILArgumentException("Argument jobz must be one of 'A','S' or 'N'"); 
+            try {
+                 double [] work = new  double [1] { ( double )0.0 };
+                int lwork = -1;
+                int[] iwork = new int[((m < n) ? m : n) * 8];
+                 mkl_dgesvd (ref jobz, ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, iwork, ref info);
+                if (work[0] != 0) {
+                    work = new  double [(int)work[0]];
+                    lwork = work.Length; 
+                     mkl_dgesvd (ref jobz, ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, iwork, ref info);
+                }
+            } catch (Exception e) {
+                if (e is OutOfMemoryException) {
+                    throw new ILMemoryException("Not enough memory for given arguments."); 
+                }
+                throw new ILException("Unable to do gesvd.", e);
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+       
+
+        /// <summary>
+        /// singular value decomposition
+        /// </summary>
+        /// <param name="jobz"></param>
+        /// <param name="m"></param>
+        /// <param name="n"></param>
+        /// <param name="a"></param>
+        /// <param name="lda"></param>
+        /// <param name="s"></param>
+        /// <param name="u"></param>
+        /// <param name="ldu"></param>
+        /// <param name="vt"></param>
+        /// <param name="ldvt"></param>
+        /// <param name="info"></param>
+        public void  sgesvd (char jobz, int m, int n,  float [] a, int lda,
+                           float [] s,  float [] u, int ldu,  float [] vt, int ldvt, ref int info) {
+            if (jobz != 'A' && jobz != 'S' && jobz != 'N')
+                throw new ILArgumentException("Argument jobz must be one of 'A','S' or 'N'"); 
+            try {
+                float [] work = new  float [1] { ( float )0.0 };
+                int lwork = -1;
+                int[] iwork = new int[((m < n) ? m : n) * 8];
+                mkl_sgesvd (ref jobz, ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, iwork, ref info);
+                if (work[0] != 0) {
+                    work = new  float [(int)work[0]];
+                    lwork = work.Length; 
+                    mkl_sgesvd (ref jobz, ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, iwork, ref info);
+                }
+            } catch (Exception e) {
+                if (e is OutOfMemoryException) {
+                    throw new ILMemoryException("Not enough memory for given arguments."); 
+                }
+                throw new ILException("Unable to do gesvd.", e);
+            }
+        }
+       
+
+        /// <summary>
+        /// singular value decomposition
+        /// </summary>
+        /// <param name="jobz"></param>
+        /// <param name="m"></param>
+        /// <param name="n"></param>
+        /// <param name="a"></param>
+        /// <param name="lda"></param>
+        /// <param name="s"></param>
+        /// <param name="u"></param>
+        /// <param name="ldu"></param>
+        /// <param name="vt"></param>
+        /// <param name="ldvt"></param>
+        /// <param name="info"></param>
+        public void  zgesvd (char jobz, int m, int n,  complex [] a, int lda,
+                           double [] s,  complex [] u, int ldu,  complex [] vt, int ldvt, ref int info) {
+            if (jobz != 'A' && jobz != 'S' && jobz != 'N')
+                throw new ILArgumentException("Argument jobz must be one of 'A','S' or 'N'"); 
+            try {
+                complex [] work = new  complex [1] { ( complex )0.0 };
+                int lwork = -1;
+                int[] iwork = new int[((m < n) ? m : n) * 8];
+                mkl_zgesvd (ref jobz, ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, iwork, ref info);
+                if (work[0] != 0) {
+                    work = new  complex [(int)work[0]];
+                    lwork = work.Length; 
+                    mkl_zgesvd (ref jobz, ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, iwork, ref info);
+                }
+            } catch (Exception e) {
+                if (e is OutOfMemoryException) {
+                    throw new ILMemoryException("Not enough memory for given arguments."); 
+                }
+                throw new ILException("Unable to do gesvd.", e);
+            }
+        }
+       
+
+        /// <summary>
+        /// singular value decomposition
+        /// </summary>
+        /// <param name="jobz"></param>
+        /// <param name="m"></param>
+        /// <param name="n"></param>
+        /// <param name="a"></param>
+        /// <param name="lda"></param>
+        /// <param name="s"></param>
+        /// <param name="u"></param>
+        /// <param name="ldu"></param>
+        /// <param name="vt"></param>
+        /// <param name="ldvt"></param>
+        /// <param name="info"></param>
+        public void  cgesvd (char jobz, int m, int n,  fcomplex [] a, int lda,
+                           float [] s,  fcomplex [] u, int ldu,  fcomplex [] vt, int ldvt, ref int info) {
+            if (jobz != 'A' && jobz != 'S' && jobz != 'N')
+                throw new ILArgumentException("Argument jobz must be one of 'A','S' or 'N'"); 
+            try {
+                fcomplex [] work = new  fcomplex [1] { ( fcomplex )0.0 };
+                int lwork = -1;
+                int[] iwork = new int[((m < n) ? m : n) * 8];
+                mkl_cgesvd (ref jobz, ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, iwork, ref info);
+                if (work[0] != 0) {
+                    work = new  fcomplex [(int)work[0]];
+                    lwork = work.Length; 
+                    mkl_cgesvd (ref jobz, ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, iwork, ref info);
+                }
+            } catch (Exception e) {
+                if (e is OutOfMemoryException) {
+                    throw new ILMemoryException("Not enough memory for given arguments."); 
+                }
+                throw new ILException("Unable to do gesvd.", e);
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+        public void dpotrf(char uplo, int n, double[] A, int lda, ref int info) {
+            mkl_dpotrf(ref uplo, ref n, A, ref lda, ref info);
+        }
+        public void spotrf(char uplo, int n, float[] A, int lda, ref int info) {
+            mkl_spotrf(ref uplo, ref n, A, ref lda, ref info);
+        }
+        public void cpotrf(char uplo, int n, fcomplex[] A, int lda, ref int info) {
+            mkl_cpotrf(ref uplo, ref n, A, ref lda, ref info);
+        }
+        public void zpotrf(char uplo, int n, complex[] A, int lda, ref int info) {
+            mkl_zpotrf(ref uplo, ref n, A, ref lda, ref info);
+        }
+
+
+        public void dpotri(char uplo, int n, double[] A, int lda, ref int info) {
+            mkl_dpotri(ref uplo, ref n, A, ref lda, ref info);
+        }
+        public void spotri(char uplo, int n, float[] A, int lda, ref int info) {
+            mkl_spotri(ref uplo, ref n, A, ref lda, ref info);
+        }
+        public void cpotri(char uplo, int n, fcomplex[] A, int lda, ref int info) {
+            mkl_cpotri(ref uplo, ref n, A, ref lda, ref info);
+        }
+        public void zpotri(char uplo, int n, complex[] A, int lda, ref int info) {
+            mkl_zpotri(ref uplo, ref n, A, ref lda, ref info);
+        }
+
+
+        public void dgetrf(int M, int N, double[] A, int LDA, int[] IPIV, ref int info) {
+            mkl_dgetrf(ref M, ref N, A, ref LDA, IPIV, ref info);
+        }
+        public void sgetrf(int M, int N, float[] A, int LDA, int[] IPIV, ref int info) {
+            mkl_sgetrf(ref M, ref N, A, ref LDA, IPIV, ref info);
+        }
+        public void cgetrf(int M, int N, fcomplex[] A, int LDA, int[] IPIV, ref int info) {
+            mkl_cgetrf(ref M, ref N, A, ref LDA, IPIV, ref info);
+        }
+        public void zgetrf(int M, int N, complex[] A, int LDA, int[] IPIV, ref int info) {
+            mkl_zgetrf(ref M, ref N, A, ref LDA, IPIV, ref info);
+        }
+
+
+        
+        public void  dgetri (int N,  double [] A, int LDA, int[] IPIV, ref int info) {
+             double [] work = new  double [1];  
+            int lwork = -1; 
+            try {
+                 mkl_dgetri (ref N, A, ref LDA, IPIV, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  double [lwork]; 
+                     mkl_dgetri (ref N, A, ref LDA, IPIV, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in mkl_dgetri"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on dgetri. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+       
+        public void  sgetri (int N,  float [] A, int LDA, int[] IPIV, ref int info) {
+            float [] work = new  float [1];  
+            int lwork = -1; 
+            try {
+                mkl_sgetri (ref N, A, ref LDA, IPIV, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  float [lwork]; 
+                    mkl_sgetri (ref N, A, ref LDA, IPIV, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in mkl_dgetri"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on dgetri. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+       
+        public void  zgetri (int N,  complex [] A, int LDA, int[] IPIV, ref int info) {
+            complex [] work = new  complex [1];  
+            int lwork = -1; 
+            try {
+                mkl_zgetri (ref N, A, ref LDA, IPIV, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  complex [lwork]; 
+                    mkl_zgetri (ref N, A, ref LDA, IPIV, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in mkl_dgetri"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on dgetri. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+       
+        public void  cgetri (int N,  fcomplex [] A, int LDA, int[] IPIV, ref int info) {
+            fcomplex [] work = new  fcomplex [1];  
+            int lwork = -1; 
+            try {
+                mkl_cgetri (ref N, A, ref LDA, IPIV, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  fcomplex [lwork]; 
+                    mkl_cgetri (ref N, A, ref LDA, IPIV, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in mkl_dgetri"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on dgetri. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+
+        
+        public void  dgeqrf (int M, int N,  double [] A, int lda,  double [] tau, ref int info) {
+             double [] work = new  double [1];  
+            int lwork = -1; 
+            try {
+                 mkl_dgeqrf (ref M, ref N, A, ref lda, tau, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  double [lwork]; 
+                     mkl_dgeqrf (ref M, ref N, A, ref lda, tau, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in mkl_?geqrf"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on ?geqrf. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+       
+        public void  sgeqrf (int M, int N,  float [] A, int lda,  float [] tau, ref int info) {
+            float [] work = new  float [1];  
+            int lwork = -1; 
+            try {
+                mkl_sgeqrf (ref M, ref N, A, ref lda, tau, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  float [lwork]; 
+                    mkl_sgeqrf (ref M, ref N, A, ref lda, tau, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in mkl_?geqrf"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on ?geqrf. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+       
+        public void  zgeqrf (int M, int N,  complex [] A, int lda,  complex [] tau, ref int info) {
+            complex [] work = new  complex [1];  
+            int lwork = -1; 
+            try {
+                mkl_zgeqrf (ref M, ref N, A, ref lda, tau, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  complex [lwork]; 
+                    mkl_zgeqrf (ref M, ref N, A, ref lda, tau, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in mkl_?geqrf"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on ?geqrf. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+       
+        public void  cgeqrf (int M, int N,  fcomplex [] A, int lda,  fcomplex [] tau, ref int info) {
+            fcomplex [] work = new  fcomplex [1];  
+            int lwork = -1; 
+            try {
+                mkl_cgeqrf (ref M, ref N, A, ref lda, tau, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  fcomplex [lwork]; 
+                    mkl_cgeqrf (ref M, ref N, A, ref lda, tau, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in mkl_?geqrf"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on ?geqrf. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+        public void dormqr(char side, char trans, int m, int n, int k, double[] A, int lda, double[] tau, double[] C, int LDC, ref int info) {
+            throw new Exception("The method or operation is not implemented.");
+        }
+        public void sormqr(char side, char trans, int m, int n, int k, float[] A, int lda, float[] tau, float[] C, int LDC, ref int info) {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+
+        
+        public void  dorgqr (int M, int N, int K,  double [] A, int lda,  double [] tau, ref int info) {
+             double [] work = new  double [1];  
+            int lwork = -1; 
+            try {
+                /*!HC:mkl_***gqr*/ mkl_dorgqr (ref M, ref N, ref K, A, ref lda, tau, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  double [lwork]; 
+                    /*!HC:mkl_***gqr*/ mkl_dorgqr (ref M, ref N, ref K, A, ref lda, tau, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in mkl_?[un/or]gqr"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on ?[un/or]gqr. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+       
+        public void  sorgqr (int M, int N, int K,  float [] A, int lda,  float [] tau, ref int info) {
+            float [] work = new  float [1];  
+            int lwork = -1; 
+            try {
+                mkl_sorgqr (ref M, ref N, ref K, A, ref lda, tau, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  float [lwork]; 
+                    mkl_sorgqr (ref M, ref N, ref K, A, ref lda, tau, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in mkl_?[un/or]gqr"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on ?[un/or]gqr. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+       
+        public void  zungqr (int M, int N, int K,  complex [] A, int lda,  complex [] tau, ref int info) {
+            complex [] work = new  complex [1];  
+            int lwork = -1; 
+            try {
+                mkl_zungqr (ref M, ref N, ref K, A, ref lda, tau, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  complex [lwork]; 
+                    mkl_zungqr (ref M, ref N, ref K, A, ref lda, tau, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in mkl_?[un/or]gqr"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on ?[un/or]gqr. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+       
+        public void  cungqr (int M, int N, int K,  fcomplex [] A, int lda,  fcomplex [] tau, ref int info) {
+            fcomplex [] work = new  fcomplex [1];  
+            int lwork = -1; 
+            try {
+                mkl_cungqr (ref M, ref N, ref K, A, ref lda, tau, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  fcomplex [lwork]; 
+                    mkl_cungqr (ref M, ref N, ref K, A, ref lda, tau, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in mkl_?[un/or]gqr"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on ?[un/or]gqr. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+
+        
+        public void  dgeqp3 ( int M,int N, double [] A,int LDA,int [] JPVT, double [] tau, ref int info ) {
+             double [] work = new  double [1];
+            int lwork = -1; 
+            try {
+                 
+                /*dummy*/
+                 
+                mkl_dgeqp3 (ref M, ref N, A, ref LDA, JPVT, tau, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = ILMemoryPool.Pool.New<  double >(lwork); 
+                     
+                    mkl_dgeqp3 (ref M, ref N, A, ref LDA, JPVT, tau, work, ref lwork, ref info);
+                    ILMemoryPool.Pool.Free(work); 
+                } else {
+                    throw new ILException("error in mkl_?geqp3"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on ?geqp3. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+       
+        public void  sgeqp3 ( int M,int N, float [] A,int LDA,int [] JPVT, float [] tau, ref int info ) {
+            float [] work = new  float [1];
+            int lwork = -1; 
+            try {
+                
+                mkl_sgeqp3 (ref M, ref N, A, ref LDA, JPVT, tau, work, ref lwork, ref info);
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = ILMemoryPool.Pool.New<  float >(lwork); 
+                    mkl_sgeqp3 (ref M, ref N, A, ref LDA, JPVT, tau, work, ref lwork, ref info);
+                    ILMemoryPool.Pool.Free(work); 
+                } else {
+                    throw new ILException("error in mkl_?geqp3"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on ?geqp3. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+       
+        public void  zgeqp3 ( int M,int N, complex [] A,int LDA,int [] JPVT, complex [] tau, ref int info ) {
+            complex [] work = new  complex [1];
+            int lwork = -1; 
+            try {
+                double[] rwork = new double[2 * N];
+                mkl_zgeqp3 (ref M, ref N, A, ref LDA, JPVT, tau, work, ref lwork, rwork, ref info);
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = ILMemoryPool.Pool.New<  complex >(lwork); 
+                    mkl_zgeqp3 (ref M, ref N, A, ref LDA, JPVT, tau, work, ref lwork, rwork, ref info);
+                    ILMemoryPool.Pool.Free(work); 
+                } else {
+                    throw new ILException("error in mkl_?geqp3"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on ?geqp3. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+       
+        public void  cgeqp3 ( int M,int N, fcomplex [] A,int LDA,int [] JPVT, fcomplex [] tau, ref int info ) {
+            fcomplex [] work = new  fcomplex [1];
+            int lwork = -1; 
+            try {
+                float[] rwork = new float[2 * N];
+                mkl_cgeqp3 (ref M, ref N, A, ref LDA, JPVT, tau, work, ref lwork, rwork, ref info);
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = ILMemoryPool.Pool.New<  fcomplex >(lwork); 
+                    mkl_cgeqp3 (ref M, ref N, A, ref LDA, JPVT, tau, work, ref lwork, rwork, ref info);
+                    ILMemoryPool.Pool.Free(work); 
+                } else {
+                    throw new ILException("error in mkl_?geqp3"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on ?geqp3. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+        public void dtrtrs(char uplo, char transA, char diag, int N, int nrhs, IntPtr A, int LDA, IntPtr B, int LDB, ref int info) {
+            mkl_dtrtrs(ref uplo, ref transA, ref diag, ref N, ref nrhs, A, ref LDA, B, ref LDB, ref info); 
+        }
+        public void strtrs(char uplo, char transA, char diag, int N, int nrhs, IntPtr A, int LDA, IntPtr B, int LDB, ref int info) {
+            mkl_strtrs(ref uplo, ref transA, ref diag, ref N, ref nrhs, A, ref LDA, B, ref LDB, ref info); 
+        }
+        public void ctrtrs(char uplo, char transA, char diag, int N, int nrhs, IntPtr A, int LDA, IntPtr B, int LDB, ref int info) {
+            mkl_ctrtrs(ref uplo, ref transA, ref diag, ref N, ref nrhs, A, ref LDA, B, ref LDB, ref info); 
+        }
+        public void ztrtrs(char uplo, char transA, char diag, int N, int nrhs, IntPtr A, int LDA, IntPtr B, int LDB, ref int info) {
+            mkl_ztrtrs(ref uplo, ref transA, ref diag, ref N, ref nrhs, A, ref LDA, B, ref LDB, ref info); 
+        }
+
+        public void dgetrs(char trans, int N, int NRHS, double[] A, int LDA, int[] IPIV, double[] B, int LDB, ref int info) {
+            mkl_dgetrs(ref trans,ref N,ref NRHS, A, ref LDA, IPIV, B, ref LDB, ref info);     
+        }
+
+        public void sgetrs(char trans, int N, int NRHS, float[] A, int LDA, int[] IPIV, float[] B, int LDB, ref int info) {
+            mkl_sgetrs(ref trans,ref N,ref NRHS, A, ref LDA, IPIV, B, ref LDB, ref info);     
+        }
+
+        public void cgetrs(char trans, int N, int NRHS, fcomplex[] A, int LDA, int[] IPIV, fcomplex[] B, int LDB, ref int info) {
+            mkl_cgetrs(ref trans,ref N,ref NRHS, A, ref LDA, IPIV, B, ref LDB, ref info);     
+        }
+
+        public void zgetrs(char trans, int N, int NRHS, complex[] A, int LDA, int[] IPIV, complex[] B, int LDB, ref int info) {
+            mkl_zgetrs(ref trans,ref N,ref NRHS, A, ref LDA, IPIV, B, ref LDB, ref info);
+        }
+        
+        public void dpotrs(char uplo, int n, int nrhs, double[] A, int lda, double[] B, int ldb, ref int info) {
+            mkl_dpotrs(ref uplo, ref n, ref nrhs, A, ref lda, B, ref ldb, ref info); 
+        }
+
+        public void spotrs(char uplo, int n, int nrhs, float[] A, int lda, float[] B, int ldb, ref int info) {
+            mkl_spotrs(ref uplo, ref n, ref nrhs, A, ref lda, B, ref ldb, ref info); 
+        }
+
+        public void cpotrs(char uplo, int n, int nrhs, fcomplex[] A, int lda, fcomplex[] B, int ldb, ref int info) {
+            mkl_cpotrs(ref uplo, ref n, ref nrhs, A, ref lda, B, ref ldb, ref info); 
+        }
+
+        public void zpotrs(char uplo, int n, int nrhs, complex[] A, int lda, complex[] B, int ldb, ref int info) {
+            mkl_zpotrs(ref uplo, ref n, ref nrhs, A, ref lda, B, ref ldb, ref info); 
+        }
+
+
+        
+        public void  dgelsd (int m, int n, int nrhs,  double [] A, int lda,  double [] B, int ldb,  double [] S,  double RCond, ref int rank, ref int info) {
+             double [] work = new  double [1]; 
+            int [] iwork = new int[1]; 
+            int lwork = -1; 
+            /*HC:HycalpTag1*/
+            mkl_dgelsd (ref m, ref n, ref nrhs, A, ref lda, B, ref ldb, S,ref RCond, ref rank, work, ref lwork, iwork, ref info);
+            if (info != 0) 
+                throw new ILArgumentException("dgelsd: invalid parameter: #" + (-info).ToString());
+            lwork = (int)work[0]; //ILAENV(9, "dgelsd", " ",0,0,0,0); 
+            if (lwork <= 0)
+                throw new ILArgumentException("dgelsd: unknown error determining working size lwork");
+            iwork = new int[lwork * 1000];
+            
+            work = ILMemoryPool.Pool.New<  double >(lwork); 
+            /*HC:HycalpTag2*/
+            mkl_dgelsd (ref m, ref n, ref nrhs, A, ref lda, B, ref ldb, S,ref RCond, ref rank, work, ref lwork, iwork, ref info);
+            ILMemoryPool.Pool.Free(work);
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+       
+        public void  sgelsd  (int m, int n, int nrhs,  float [] A, int lda,  float [] B, int ldb,  float [] S,  float RCond, ref int rank, ref int info) {
+            float [] work = new  float [1]; 
+            int [] iwork = new int[1]; 
+            int lwork = -1; 
+            mkl_sgelsd (ref m, ref n, ref nrhs, A, ref lda, B, ref ldb, S,ref RCond, ref rank, work, ref lwork, iwork, ref info);
+            if (info != 0) 
+                throw new ILArgumentException("dgelsd: invalid parameter: #" + (-info).ToString());
+            lwork = (int)work[0]; //ILAENV(9, "dgelsd", " ",0,0,0,0); 
+            if (lwork <= 0)
+                throw new ILArgumentException("dgelsd: unknown error determining working size lwork");
+            iwork = new int[lwork * 1000];
+            
+            work = ILMemoryPool.Pool.New<  float >(lwork); 
+            mkl_sgelsd (ref m, ref n, ref nrhs, A, ref lda, B, ref ldb, S,ref RCond, ref rank, work, ref lwork, iwork, ref info);
+            ILMemoryPool.Pool.Free(work);
+        }
+       
+        public void  zgelsd  (int m, int n, int nrhs,  complex [] A, int lda,  complex [] B, int ldb,  double [] S,  double RCond, ref int rank, ref int info) {
+            complex [] work = new  complex [1]; 
+            int [] iwork = new int[1]; 
+            int lwork = -1; 
+            double [] rwork = new double [1];  mkl_zgelsd (ref m, ref n, ref nrhs, A, ref lda, B, ref ldb, S,ref RCond, ref rank, work, ref lwork, rwork, iwork, ref info);
+            if (info != 0) 
+                throw new ILArgumentException("dgelsd: invalid parameter: #" + (-info).ToString());
+            lwork = (int)work[0]; //ILAENV(9, "dgelsd", " ",0,0,0,0); 
+            if (lwork <= 0)
+                throw new ILArgumentException("dgelsd: unknown error determining working size lwork");
+            iwork = new int[lwork * 1000];
+            
+            work = ILMemoryPool.Pool.New<  complex >(lwork); 
+            rwork = new double [(int)rwork[0]];  mkl_zgelsd (ref m, ref n, ref nrhs, A, ref lda, B, ref ldb, S,ref RCond, ref rank, work, ref lwork, rwork, iwork, ref info);
+            ILMemoryPool.Pool.Free(work);
+        }
+       
+        public void  cgelsd  (int m, int n, int nrhs,  fcomplex [] A, int lda,  fcomplex [] B, int ldb,  float [] S,  float RCond, ref int rank, ref int info) {
+            fcomplex [] work = new  fcomplex [1]; 
+            int [] iwork = new int[1]; 
+            int lwork = -1; 
+            float [] rwork = new float [1];  mkl_cgelsd (ref m, ref n, ref nrhs, A, ref lda, B, ref ldb, S,ref RCond, ref rank, work, ref lwork, rwork, iwork, ref info);
+            if (info != 0) 
+                throw new ILArgumentException("dgelsd: invalid parameter: #" + (-info).ToString());
+            lwork = (int)work[0]; //ILAENV(9, "dgelsd", " ",0,0,0,0); 
+            if (lwork <= 0)
+                throw new ILArgumentException("dgelsd: unknown error determining working size lwork");
+            iwork = new int[lwork * 1000];
+            
+            work = ILMemoryPool.Pool.New<  fcomplex >(lwork); 
+            rwork = new float [(int)rwork[0]];  mkl_cgelsd (ref m, ref n, ref nrhs, A, ref lda, B, ref ldb, S,ref RCond, ref rank, work, ref lwork, rwork, iwork, ref info);
+            ILMemoryPool.Pool.Free(work);
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+        #region ?gelsy  
+        public void dgelsy (int m, int n, int nrhs, double [] A, int lda, double [] B, int ldb, int[] JPVT0, double RCond, ref int rank, ref int info) {
+            int lwork = -1;
+            double [] work = new double [1]; 
+            mkl_dgelsy (ref m,ref n,ref nrhs,A,ref lda,B,ref ldb,JPVT0,ref RCond,ref rank,work,ref lwork,ref info);
+            if (info != 0)
+                throw new ILArgumentException("?gelsy: unable to determine optimal block size. cancelling...");
+            lwork = (int) work[0];
+            work = ILMemoryPool.Pool.New<double>(lwork);
+            mkl_dgelsy (ref m,ref n,ref nrhs,A,ref lda,B,ref ldb,JPVT0,ref RCond,ref rank,work,ref lwork,ref info);
+            ILMemoryPool.Pool.Free(work); 
+        }
+        public void  sgelsy  (int m, int n, int nrhs,  float [] A, int lda,  float [] B, int ldb, int[] JPVT0,  float RCond, ref int rank, ref int info) {
+            int lwork = -1;
+            float [] work = new  float [1]; 
+            mkl_sgelsy (ref m,ref n,ref nrhs,A,ref lda,B,ref ldb,JPVT0,ref RCond,ref rank,work,ref lwork,ref info);
+            if (info != 0)
+                throw new ILArgumentException("?gelsy: unable to determine optimal block size. cancelling...");
+            lwork = (int) work[0];
+            work = ILMemoryPool.Pool.New<float>(lwork);
+            mkl_sgelsy (ref m,ref n,ref nrhs,A,ref lda,B,ref ldb,JPVT0,ref RCond,ref rank,work,ref lwork,ref info);
+            ILMemoryPool.Pool.Free(work); 
+        }
+       
+        public void  zgelsy  (int m, int n, int nrhs,  complex [] A, int lda,  complex [] B, int ldb, int[] JPVT0,  double RCond, ref int rank, ref int info) {
+            int lwork = -1;
+            complex [] work = new  complex [1]; 
+            double[] rwork = new double[1];
+            mkl_zgelsy (ref m,ref n,ref nrhs,A,ref lda,B,ref ldb,JPVT0,ref RCond,ref rank,work,ref lwork, rwork, ref info);
+            if (info != 0)
+                throw new ILArgumentException("?gelsy: unable to determine optimal block size. cancelling...");
+            lwork = (int) work[0];
+            work = ILMemoryPool.Pool.New<complex>(lwork);
+            rwork = ILMemoryPool.Pool.New<double>(lwork);
+            mkl_zgelsy (ref m,ref n,ref nrhs,A,ref lda,B,ref ldb,JPVT0,ref RCond,ref rank,work,ref lwork, rwork, ref info);
+            ILMemoryPool.Pool.Free(work); 
+            ILMemoryPool.Pool.Free(rwork); 
+        }
+       
+        public void  cgelsy  (int m, int n, int nrhs,  fcomplex [] A, int lda,  fcomplex [] B, int ldb, int[] JPVT0,  float RCond, ref int rank, ref int info) {
+            int lwork = -1;
+            fcomplex [] work = new  fcomplex [1]; 
+            float[] rwork = new float[1];
+            mkl_cgelsy (ref m,ref n,ref nrhs,A,ref lda,B,ref ldb,JPVT0,ref RCond,ref rank,work,ref lwork, rwork, ref info);
+            if (info != 0)
+                throw new ILArgumentException("?gelsy: unable to determine optimal block size. cancelling...");
+            lwork = (int) work[0];
+            work = ILMemoryPool.Pool.New<fcomplex>(lwork);
+            rwork = ILMemoryPool.Pool.New<float>(lwork);
+            mkl_cgelsy (ref m,ref n,ref nrhs,A,ref lda,B,ref ldb,JPVT0,ref RCond,ref rank,work,ref lwork, rwork, ref info);
+            ILMemoryPool.Pool.Free(work); 
+            ILMemoryPool.Pool.Free(rwork); 
+        }
+#endregion
+
+        #region ?GEEVX
+        public void dgeevx(char balance, char jobvl, char jobvr, char sense, int n, double[] A, int lda, double[] wr, double[] wi, double[] vl, int ldvl, double[] vr, int ldvr, ref int ilo, ref int ihi, double[] scale, ref double abnrm, double[] rconde, double[] rcondv, ref int info) {
+            double [] work = new double[1]; 
+            int lwork = -1;
+            int [] iwork = ILMemoryPool.Pool.New<int>(2 * n - 2);
+            mkl_dgeevx(ref balance, ref jobvl, ref jobvr, ref sense, ref n, A, ref lda, wr, wi, vl, ref ldvl, vr, ref ldvr, ref ilo, ref ihi, scale, ref abnrm, rconde, rcondv, work, ref lwork, iwork, ref info);
+            if (info != 0) 
+                throw new ILArgumentException("error in lapack call: ?geevx. (" + info + ")");
+            lwork = (int)work[0]; 
+            work = ILMemoryPool.Pool.New<double>(lwork); 
+            mkl_dgeevx(ref balance, ref jobvl, ref jobvr, ref sense, ref n, A, ref lda, wr, wi, vl, ref ldvl, vr, ref ldvr, ref ilo, ref ihi, scale, ref abnrm, rconde, rcondv, work, ref lwork, iwork, ref info);
+            ILMemoryPool.Pool.Free(work);
+            ILMemoryPool.Pool.Free(iwork);
+        }
+        public void sgeevx(char balance, char jobvl, char jobvr, char sense, int n, float[] A, int lda, float[] wr, float[] wi, float[] vl, int ldvl, float[] vr, int ldvr, ref int ilo, ref int ihi, float[] scale, ref float abnrm, float[] rconde, float[] rcondv, ref int info) {
+            float [] work = new float[1]; 
+            int lwork = -1;
+            int [] iwork = ILMemoryPool.Pool.New<int>(2 * n - 2);
+            mkl_sgeevx(ref balance, ref jobvl, ref jobvr, ref sense, ref n, A, ref lda, wr, wi, vl, ref ldvl, vr, ref ldvr, ref ilo, ref ihi, scale, ref abnrm, rconde, rcondv, work, ref lwork, iwork, ref info);
+            if (info != 0) 
+                throw new ILArgumentException("error in lapack call: ?geevx. (" + info + ")");
+            lwork = (int)work[0]; 
+            work = ILMemoryPool.Pool.New<float>(lwork); 
+            mkl_sgeevx(ref balance, ref jobvl, ref jobvr, ref sense, ref n, A, ref lda, wr, wi, vl, ref ldvl, vr, ref ldvr, ref ilo, ref ihi, scale, ref abnrm, rconde, rcondv, work, ref lwork, iwork, ref info);
+            ILMemoryPool.Pool.Free(work);
+            ILMemoryPool.Pool.Free(iwork);
+        }
+        public void cgeevx(char balance, char jobvl, char jobvr, char sense, int n, fcomplex[] A, int lda, fcomplex[] w, fcomplex[] vl, int ldvl, fcomplex[] vr, int ldvr, ref int ilo, ref int ihi, float[] scale, ref float abnrm, float[] rconde, float[] rcondv, ref int info) {
+            fcomplex [] work = new fcomplex[1]; 
+            int lwork = -1;
+            float[] rwork = ILMemoryPool.Pool.New<float>(2 * n); 
+            mkl_cgeevx(ref balance, ref jobvl, ref jobvr, ref sense, ref n, A, ref lda, w, vl, ref ldvl, vr, ref ldvr, ref ilo, ref ihi, scale, ref abnrm, rconde, rcondv, work, ref lwork, rwork, ref info);
+            if (info != 0) 
+                throw new ILArgumentException("error in lapack call: ?geevx. (" + info + ")");
+            lwork = (int)work[0]; 
+            work = ILMemoryPool.Pool.New<fcomplex>(lwork); 
+            mkl_cgeevx(ref balance, ref jobvl, ref jobvr, ref sense, ref n, A, ref lda, w, vl, ref ldvl, vr, ref ldvr, ref ilo, ref ihi, scale, ref abnrm, rconde, rcondv, work, ref lwork, rwork, ref info);
+            ILMemoryPool.Pool.Free(work);
+            ILMemoryPool.Pool.Free(rwork);
+        }
+        public void zgeevx(char balance, char jobvl, char jobvr, char sense, int n, complex[] A, int lda, complex[] w, complex[] vl, int ldvl, complex[] vr, int ldvr, ref int ilo, ref int ihi, double[] scale, ref double abnrm, double[] rconde, double[] rcondv, ref int info) {
+            complex [] work = new complex[1]; 
+            int lwork = -1;
+            double[] rwork = ILMemoryPool.Pool.New<double>(2 * n); 
+            mkl_zgeevx(ref balance, ref jobvl, ref jobvr, ref sense, ref n, A, ref lda, w, vl, ref ldvl, vr, ref ldvr, ref ilo, ref ihi, scale, ref abnrm, rconde, rcondv, work, ref lwork, rwork, ref info);
+            if (info != 0) 
+                throw new ILArgumentException("error in lapack call: ?geevx. (" + info + ")");
+            lwork = (int)work[0]; 
+            work = ILMemoryPool.Pool.New<complex>(lwork); 
+            mkl_zgeevx(ref balance, ref jobvl, ref jobvr, ref sense, ref n, A, ref lda, w, vl, ref ldvl, vr, ref ldvr, ref ilo, ref ihi, scale, ref abnrm, rconde, rcondv, work, ref lwork, rwork, ref info);
+            ILMemoryPool.Pool.Free(work);
+            ILMemoryPool.Pool.Free(rwork);
+        }
+        #endregion
+
+        #region ?syevr
+        public void dsyevr(char jobz, char range, char uplo, int n, double[] A, int lda, double vl, double vu, int il, int iu, double abstol, ref int m, double[] w, double[] z, int ldz, int[] isuppz, ref int info) {
+            double [] work = new double[1]; 
+            int lwork = -1, liwork = -1; 
+            int [] iwork = new int[1]; 
+            //byte jz = (byte)jobz,rn = (byte) range,ul = (byte)uplo; 
+            mkl_dsyevr(ref jobz,ref range,ref uplo,ref n, A,ref lda, ref vl, ref vu, ref il, ref iu, ref abstol,ref m, w,z,ref ldz,isuppz, work,ref lwork,iwork,ref liwork,ref info);
+            if (info != 0) {
+                throw new ILArgumentException("?syevr: error returned from lapack: " + info);
+            }
+            lwork = (int)work[0]; 
+            bool dummy; 
+            work = ILMemoryPool.Pool.New<double>(lwork,true, out dummy);
+            liwork = (int) iwork[0]; 
+            iwork = ILMemoryPool.Pool.New<int>(liwork,true, out dummy);
+            mkl_dsyevr(ref jobz,ref range,ref uplo,ref n, A,ref lda, ref vl, ref vu, ref il, ref iu, ref abstol,ref m, w,z,ref ldz,isuppz, work,ref lwork,iwork,ref liwork,ref info);
+            ILMemoryPool.Pool.Free(iwork); 
+            ILMemoryPool.Pool.Free(work); 
+        }
+        public void ssyevr(char jobz, char range, char uplo, int n, float[] A, int lda, float vl, float vu, int il, int iu, float abstol, ref int m, float[] w, float[] z, int ldz, int[] isuppz, ref int info) {
+            float [] work = new float[1]; 
+            int lwork = -1, liwork = -1; 
+            int [] iwork = new int[1]; 
+            mkl_ssyevr(ref jobz,ref range,ref uplo,ref n, A,ref lda, ref vl, ref vu, ref il, ref iu, ref abstol,ref m, w,z,ref ldz,isuppz, work,ref lwork,iwork,ref liwork,ref info);
+            if (info != 0) {
+                throw new ILArgumentException("?syevr: error returned from lapack: " + info);
+            }
+            lwork = (int)work[0]; 
+            work = ILMemoryPool.Pool.New<float>(lwork);
+            liwork = (int) iwork[0]; 
+            iwork = ILMemoryPool.Pool.New<int>(liwork); 
+            mkl_ssyevr(ref jobz,ref range,ref uplo,ref n, A,ref lda, ref vl, ref vu, ref il, ref iu, ref abstol,ref m, w,z,ref ldz,isuppz, work,ref lwork,iwork,ref liwork,ref info);
+            ILMemoryPool.Pool.Free(iwork); 
+            ILMemoryPool.Pool.Free(work); 
+        }
+        public void cheevr(char jobz, char range, char uplo, int n, fcomplex[] A, int lda, float vl, float vu, int il, int iu, float abstol, ref int m, float[] w, fcomplex[] z, int ldz, int[] isuppz, ref int info) {
+            fcomplex[] work = new fcomplex[1]; 
+            float [] rwork = new float[1]; 
+            int [] iwork = new int[1]; 
+            int lrwork = -1, liwork = -1, lwork = -1; 
+            mkl_cheevr(ref jobz,ref range,ref uplo,ref n, A,ref lda, ref vl, ref vu, ref il, ref iu, ref abstol,ref m, w,z,ref ldz,isuppz, work,ref lwork,rwork,ref lrwork, iwork,ref liwork,ref info);
+            if (info != 0) {
+                throw new ILArgumentException("?syevr: error returned from lapack: " + info);
+            }
+            lrwork = (int)rwork[0]; 
+            rwork = ILMemoryPool.Pool.New<float>(lrwork);
+            lwork = (int) work[0]; 
+            work = ILMemoryPool.Pool.New<fcomplex>(lwork); 
+            liwork = (int) iwork[0]; 
+            iwork = ILMemoryPool.Pool.New<int>(liwork); 
+            mkl_cheevr(ref jobz,ref range,ref uplo,ref n, A,ref lda, ref vl, ref vu, ref il, ref iu, ref abstol,ref m, w,z,ref ldz,isuppz, work,ref lwork,rwork,ref lrwork,iwork,ref liwork,ref info);
+            ILMemoryPool.Pool.Free(iwork); 
+            ILMemoryPool.Pool.Free(work); 
+            ILMemoryPool.Pool.Free(rwork); 
+        }
+        public void zheevr(char jobz, char range, char uplo, int n, complex[] A, int lda, double vl, double vu, int il, int iu, double abstol, ref int m, double[] w, complex[] z, int ldz, int[] isuppz, ref int info) {
+            complex[] work = new complex[1]; 
+            double [] rwork = new double[1]; 
+            int [] iwork = new int[1]; 
+            int lrwork = -1, liwork = -1, lwork = -1; 
+            mkl_zheevr(ref jobz,ref range,ref uplo,ref n, A,ref lda, ref vl, ref vu, ref il, ref iu, ref abstol,ref m, w,z,ref ldz,isuppz, work,ref lwork,rwork,ref lrwork, iwork,ref liwork,ref info);
+            if (info != 0) {
+                throw new ILArgumentException("?syevr: error returned from lapack: " + info);
+            }
+            lrwork = (int)rwork[0]; 
+            rwork = ILMemoryPool.Pool.New<double>(lrwork);
+            lwork = (int) work[0]; 
+            work = ILMemoryPool.Pool.New<complex>(lwork); 
+            liwork = (int) iwork[0]; 
+            iwork = ILMemoryPool.Pool.New<int>(liwork); 
+            mkl_zheevr(ref jobz,ref range,ref uplo,ref n, A,ref lda, ref vl, ref vu, ref il, ref iu, ref abstol,ref m, w,z,ref ldz,isuppz, work,ref lwork,rwork,ref lrwork,iwork,ref liwork,ref info);
+            ILMemoryPool.Pool.Free(iwork); 
+            ILMemoryPool.Pool.Free(work); 
+            ILMemoryPool.Pool.Free(rwork); 
+        }
+        #endregion 
+
+        #region ?[he/sy]gv - generalized eigenproblem
+        public void dsygv (int itype, char jobz, char uplo, int n, double  [] A, int lda, double  [] B, int ldb, double [] w, ref int info) {
+            // query workspace 
+            int lwork = -1; 
+            double [] work = new double[1] {0.0}; 
+            mkl_dsygv (ref itype,ref jobz,ref uplo,ref n, A,ref lda, B,ref ldb, w, work, ref lwork, ref info); 
+            if (info != 0 || work[0] <= 0.0) return; 
+            // create temporary array(s)
+            lwork = (int) work[0]; 
+            work = ILMemoryPool.Pool.New<double>(lwork); 
+            mkl_dsygv (ref itype,ref jobz,ref uplo,ref n, A,ref lda, B,ref ldb, w, work, ref lwork, ref info); 
+            ILMemoryPool.Pool.Free(work); 
+        }        
+        public void ssygv (int itype, char jobz, char uplo, int n, float   [] A, int lda, float   [] B, int ldb, float  [] w, ref int info) {
+            // query workspace 
+            int lwork = -1; 
+            float [] work = new float[1] {0.0f}; 
+            mkl_ssygv (ref itype,ref jobz,ref uplo,ref n, A,ref lda, B,ref ldb, w, work, ref lwork, ref info); 
+            if (info != 0 || work[0] <= 0.0) return; 
+            // create temporary array(s)
+            lwork = (int) work[0]; 
+            work = ILMemoryPool.Pool.New<float>(lwork); 
+            mkl_ssygv (ref itype,ref jobz,ref uplo,ref n, A,ref lda, B,ref ldb, w, work, ref lwork, ref info); 
+            ILMemoryPool.Pool.Free(work); 
+        }
+        public void chegv (int itype, char jobz, char uplo, int n, fcomplex[] A, int lda, fcomplex[] B, int ldb, float  [] w, ref int info) {
+            // query workspace 
+            int lwork = -1; 
+            fcomplex [] work = new fcomplex[1] {0.0f}; 
+            float [] rwork = ILMemoryPool.Pool.New<float>(Math.Max(1,3*n-2)); 
+            mkl_chegv(ref itype,ref  jobz,ref  uplo,ref  n, A,ref  lda, B,ref  ldb, w, work, ref lwork, rwork, ref info); 
+            if (info != 0 || work[0] <= 0.0) return; 
+            // create temporary array(s)
+            lwork = (int) work[0]; 
+            work = ILMemoryPool.Pool.New<fcomplex>(lwork); 
+            mkl_chegv (ref itype,ref  jobz,ref  uplo,ref  n, A,ref  lda, B,ref  ldb, w, work, ref lwork, rwork, ref info); 
+            ILMemoryPool.Pool.Free(rwork); 
+            ILMemoryPool.Pool.Free(work); 
+        }
+        public void zhegv (int itype, char jobz, char uplo, int n, complex [] A, int lda, complex [] B, int ldb, double [] w, ref int info) { 
+            // query workspace 
+            int lwork = -1; 
+            complex [] work = new complex[1] {0.0f}; 
+            double [] rwork = ILMemoryPool.Pool.New<double>(Math.Max(1,3*n-2)); 
+            mkl_zhegv(ref itype,ref  jobz,ref  uplo,ref  n, A,ref  lda, B,ref  ldb, w, work, ref lwork, rwork, ref info); 
+            if (info != 0 || work[0] <= 0.0) return; 
+            // create temporary array(s)
+            lwork = (int) work[0]; 
+            work = ILMemoryPool.Pool.New<complex>(lwork); 
+            mkl_zhegv (ref itype,ref  jobz,ref  uplo,ref  n, A,ref  lda, B,ref  ldb, w, work, ref lwork, rwork, ref info); 
+            ILMemoryPool.Pool.Free(rwork); 
+            ILMemoryPool.Pool.Free(work); 
+        }
+        #endregion 
+
+        #endregion
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Native/lapack/ILLapackManaged.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Native/lapack/ILLapackManaged.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Native/lapack/ILLapackManaged.cs	(revision 9102)
@@ -0,0 +1,1317 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+#pragma warning disable 1591
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ILNumerics.Native;
+using System.Runtime.InteropServices;
+using ILNumerics.Exceptions;
+using System.Security; 
+using ILNumerics.Misc; 
+
+namespace ILNumerics.Native  {
+    /// <summary>
+    /// Generic LAPACK implementation, unsupported processor types
+    /// </summary>
+	public unsafe class ILLapackManaged : IILLapack {
+
+        #region DLL INCLUDES 
+        [DllImport("lapack_gen", EntryPoint = "ilaenv"),SuppressUnmanagedCodeSecurity]
+        private static extern int lapack_ilaenv(ref int ispec, ref string name, ref string opts, ref int n1, ref int n2, ref int n3, ref int n4);
+
+        ///////////////////////////   DOUBLE LAPACK /////////////////////////////////
+        [DllImport("lapack_gen", EntryPoint = "dgemm"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dgemm(ref char TransA, ref char TransB, ref int M,ref int N, ref int K, ref  double alpha, IntPtr A, ref int lda, IntPtr B, ref int ldb, ref double beta, double[] C, ref int ldc);
+        [DllImport("lapack_gen", EntryPoint = "sgemm"),SuppressUnmanagedCodeSecurity]
+		private static extern void lapack_sgemm(ref char TransA, ref char TransB, ref int M,ref int N, ref int K, ref float alpha, IntPtr A,ref int lda, IntPtr B, ref int ldb, ref float beta,float[] C, ref int ldc);
+        [DllImport("lapack_gen", EntryPoint = "cgemm"),SuppressUnmanagedCodeSecurity]
+		private static extern void lapack_cgemm(ref char TransA, ref char TransB, ref int M,ref int N, ref int K, ref fcomplex alpha, IntPtr A, ref int lda, IntPtr B, ref int ldb, ref fcomplex beta,[In,Out] fcomplex [] C, ref int ldc);
+        [DllImport("lapack_gen", EntryPoint = "zgemm"),SuppressUnmanagedCodeSecurity]
+		private static extern void lapack_zgemm(ref char TransA, ref char TransB, ref int M, ref int N, ref int K, ref complex alpha, IntPtr A, ref int lda, IntPtr B, ref int ldb, ref complex beta,[In,Out] complex [] C, ref int ldc);
+
+        [DllImport("lapack_gen", EntryPoint = "dgesdd"),SuppressUnmanagedCodeSecurity]
+		private static extern void lapack_dgesdd(ref char jobz, ref int m, ref int n,double[] a, ref int lda, double[] s,double[] u, ref int ldu, double[] vt,ref int ldvt, double[] work, ref int lwork,int[] iwork, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "sgesdd"),SuppressUnmanagedCodeSecurity]
+		private static extern void lapack_sgesdd(ref char jobz, ref int m, ref int n,float[] a, ref int lda, float[] s,float[] u, ref int ldu, float[] vt, ref int ldvt, float[] work, ref int lwork,int[] iwork, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "cgesdd"),SuppressUnmanagedCodeSecurity]
+		private static extern void lapack_cgesdd(ref char jobz, ref int m, ref int n,[In, Out] fcomplex[] a, ref int lda, float[] s,[In, Out] fcomplex[] u, ref int ldu, [In, Out]  fcomplex[] vt, ref int ldvt, [In, Out] fcomplex[] work, ref int lwork,[In,Out] float[] rwork, int[] iwork, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "zgesdd"),SuppressUnmanagedCodeSecurity]
+		private static extern void lapack_zgesdd(ref char jobz, ref int m, ref int n,[In, Out] complex[] a, ref int lda, double[] s,[In, Out] complex[] u, ref int ldu, [In, Out] complex[] vt,ref int ldvt, [In, Out] complex[] work, ref int lwork,[In,Out] double[] rwork, int[] iwork, ref int info);
+
+        [DllImport("lapack_gen", EntryPoint = "dgesvd"),SuppressUnmanagedCodeSecurity]
+		private static extern void lapack_dgesvd(ref char jobu, ref  char jobvt, ref int m, ref int n,double[] a, ref int lda, double[] s,double[] u, ref int ldu, double[] vt,ref int ldvt, double[] work, ref int lwork,int[] iwork,ref int info);
+        [DllImport("lapack_gen", EntryPoint = "sgesvd"),SuppressUnmanagedCodeSecurity]
+		private static extern void lapack_sgesvd(ref char jobu, ref  char jobvt, ref int m, ref int n, float[] a, ref int lda, float[] s,float[] u, ref int ldu, float[] vt,ref int ldvt, float[] work, ref int lwork,int[] iwork, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "cgesvd"),SuppressUnmanagedCodeSecurity]
+		private static extern void lapack_cgesvd(ref char jobu, ref  char jobvt, ref int m, ref int n,[In, Out] fcomplex[] a, ref int lda, float[] s,[In, Out] fcomplex[] u, ref int ldu,[In,Out] fcomplex[] vt,ref int ldvt, [In, Out]  fcomplex[] work, ref int lwork,int[] iwork,ref int info);
+        [DllImport("lapack_gen", EntryPoint = "zgesvd"),SuppressUnmanagedCodeSecurity]
+		private static extern void lapack_zgesvd(ref char jobu, ref  char jobvt, ref int m, ref int n,[In, Out] complex[] a, ref int lda, double[] s,[In, Out] complex[] u, ref int ldu, [In, Out] complex[] vt,ref int ldvt, [In, Out]  complex[] work, ref int lwork,int[] iwork,ref int info);
+
+        [DllImport("lapack_gen", EntryPoint = "dpotrf"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dpotrf (ref char uplo, ref int n, double [] A, ref int lda, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "spotrf"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_spotrf (ref char uplo, ref int n, float [] A, ref int lda, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "cpotrf"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_cpotrf (ref char uplo, ref int n,[In,Out] fcomplex [] A, ref int lda, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "zpotrf"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_zpotrf (ref char uplo, ref int n, [In,Out] complex [] A, ref int lda, ref int info);
+        
+        [DllImport("lapack_gen", EntryPoint = "dpotri"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dpotri (ref char uplo,ref  int n, double [] A, ref int lda, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "spotri"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_spotri (ref char uplo, ref int n, float [] A, ref int lda, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "cpotri"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_cpotri (ref char uplo, ref int n,[In,Out] fcomplex [] A, ref int lda,ref int info);
+        [DllImport("lapack_gen", EntryPoint = "zpotri"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_zpotri (ref char uplo, ref int n, [In,Out] complex [] A, ref int lda,ref int info);
+
+        [DllImport("lapack_gen", EntryPoint = "dpotrs"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dpotrs (ref char uplo,ref  int n, ref int NRHS, double [] A, ref int lda, double[] B, ref int ldb, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "spotrs"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_spotrs (ref char uplo,ref  int n, ref int NRHS, float [] A, ref int lda, float[] B, ref int ldb, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "cpotrs"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_cpotrs (ref char uplo,ref  int n, ref int NRHS, [In,Out] fcomplex [] A, ref int lda, [In,Out] fcomplex[] B, ref int ldb, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "zpotrs"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_zpotrs (ref char uplo,ref  int n, ref int NRHS, [In,Out] complex [] A, ref int lda, [In,Out] complex[] B, ref int ldb, ref int info);
+
+        [DllImport("lapack_gen", EntryPoint = "dgetrf"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dgetrf (ref int M, ref int N, double [] A, ref int LDA, int[] IPIV, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "sgetrf"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_sgetrf (ref int M, ref int N, float[] A, ref int LDA, int [] IPIV, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "cgetrf"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_cgetrf (ref int M, ref int N, [In,Out] fcomplex [] A, ref int LDA, int [] IPIV, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "zgetrf"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_zgetrf (ref int M, ref int N, [In,Out] complex [] A, ref int LDA, int [] IPIV, ref int info);
+
+        [DllImport("lapack_gen", EntryPoint = "dgetri"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dgetri (ref int N, double[] A,ref  int LDA, int[] IPIV, double[] work, ref int lwork, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "sgetri"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_sgetri (ref int N, float [] A, ref int LDA, int [] IPIV, float[] work, ref int lwork, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "cgetri"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_cgetri (ref int N, [In,Out] fcomplex [] A, ref int LDA,[In,Out] int [] IPIV, [In,Out] fcomplex[] work, ref int lwork, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "zgetri"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_zgetri (ref int N, [In,Out] complex [] A, ref int LDA, int [] IPIV, [In,Out] complex[] work, ref int lwork, ref int info);
+
+        [DllImport("lapack_gen", EntryPoint = "dgeqrf"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dgeqrf (ref int M, ref int N, double [] A, ref int lda, double [] tau, double[] work, ref int lwork, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "sgeqrf"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_sgeqrf (ref int M, ref int N, float [] A, ref int lda, float [] tau, float[] work, ref int lwork,  ref int info);
+        [DllImport("lapack_gen", EntryPoint = "cgeqrf"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_cgeqrf (ref int M, ref int N, [In,Out] fcomplex [] A, ref int lda, [In,Out] fcomplex [] tau, [In,Out] fcomplex[] work, ref int lwork, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "zgeqrf"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_zgeqrf (ref int M, ref int N, [In,Out] complex [] A, ref int lda, [In,Out] complex [] tau, [In,Out] complex[] work, ref int lwork,  ref int info);
+
+        [DllImport("lapack_gen", EntryPoint = "dgeqp3"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dgeqp3 (ref int M, ref int N, double [] A, ref int LDA, int [] JPVT, double [] tau, double [] work, ref int lwork, ref int info );
+        [DllImport("lapack_gen", EntryPoint = "sgeqp3"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_sgeqp3 (ref int M, ref int N, float [] A, ref int LDA, int [] JPVT, float [] tau, float [] work, ref int lwork, ref int info );
+        [DllImport("lapack_gen", EntryPoint = "cgeqp3"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_cgeqp3 (ref int M, ref int N,[In,Out] fcomplex [] A, ref int LDA,[In,Out] int [] JPVT, [In,Out] fcomplex [] tau, [In,Out] fcomplex [] work, ref int lwork,[In,Out] float [] rwork, ref int info );
+        [DllImport("lapack_gen", EntryPoint = "zgeqp3"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_zgeqp3 (ref int M, ref int N, [In,Out] complex [] A, ref int LDA, [In,Out] int [] JPVT, [In,Out] complex [] tau, [In,Out] complex [] work, ref int lwork, [In,Out] double [] rwork, ref int info );
+
+        [DllImport("lapack_gen", EntryPoint = "dormqr"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dormqr (ref char side, ref char trans, ref int m, ref int n, ref int k, double[] A, int lda, double[] tau, double[] C, ref int ldc, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "sormqr"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_sormqr (ref char side, ref char trans, ref int m, ref int n, ref int k, float [] A, ref int lda, float [] tau , float [] C, ref int ldc, ref int info);
+        
+        [DllImport("lapack_gen", EntryPoint = "dorgqr"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dorgqr (ref int m, ref int n, ref int k, double[] A,ref int lda, double[] tau, double[] work, ref int lwork, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "sorgqr"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_sorgqr (ref int m, ref int n, ref int k, float [] A, ref int lda, float [] tau , float[] work, ref int lwork,  ref int info);
+        [DllImport("lapack_gen", EntryPoint = "cungqr"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_cungqr (ref int m, ref int n, ref int k, [In,Out] fcomplex[] A,ref int lda, [In,Out] fcomplex[] tau, [In,Out] fcomplex[] work, ref int lwork, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "zungqr"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_zungqr (ref int m, ref int n, ref int k, [In,Out] complex[] A,ref int lda, [In,Out] complex[] tau, [In,Out] complex[] work, ref int lwork, ref int info);
+        
+        [DllImport("lapack_gen", EntryPoint = "dtrtrs"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dtrtrs (ref char uplo, ref char transA, ref char diag, ref int N, ref int nrhs, IntPtr A, ref int LDA, IntPtr B, ref int LDB, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "strtrs"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_strtrs (ref char uplo, ref char transA, ref char diag, ref int N, ref int nrhs, IntPtr A, ref int LDA, IntPtr B, ref int LDB, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "ctrtrs"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_ctrtrs (ref char uplo, ref char transA, ref char diag, ref int N, ref int nrhs, IntPtr A, ref int LDA, IntPtr B, ref int LDB, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "ztrtrs"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_ztrtrs (ref char uplo, ref char transA, ref char diag, ref int N, ref int nrhs, IntPtr A, ref int LDA, IntPtr B, ref int LDB, ref int info);
+        
+        [DllImport("lapack_gen", EntryPoint = "dgetrs"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dgetrs(ref char trans, ref int N, ref int NRHS, double[] A, ref int LDA, int[] IPIV, double[] B, ref int LDB, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "sgetrs"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_sgetrs(ref char trans, ref int N, ref int NRHS, float[] A, ref int LDA, int[] IPIV, float[] B, ref int LDB, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "cgetrs"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_cgetrs(ref char trans, ref int N, ref int NRHS, [In,Out] fcomplex[] A, ref int LDA, int[] IPIV, [In,Out] fcomplex[] B, ref int LDB, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "zgetrs"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_zgetrs(ref char trans, ref int N, ref int NRHS, [In,Out] complex[] A, ref int LDA, int[] IPIV, [In,Out] complex[] B, ref int LDB, ref int info);
+
+        [DllImport("lapack_gen", EntryPoint = "dgelsd"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dgelsd (ref int m,ref int n,ref int nrhs, double[] A,ref int lda, double[] B,ref int ldb, double[] S, ref double RCond, ref int rank, double[] work,ref int lwork, int[] iwork, ref int info); 
+        [DllImport("lapack_gen", EntryPoint = "sgelsd"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_sgelsd (ref int m,ref int n,ref int nrhs, float[] A,ref int lda, float[] B,ref int ldb, float[] S, ref float RCond, ref int rank, float[] work,ref int lwork, int[] iwork, ref int info); 
+        [DllImport("lapack_gen", EntryPoint = "cgelsd"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_cgelsd (ref int m,ref int n,ref int nrhs, [In,Out] fcomplex[] A,ref int lda, [In,Out] fcomplex[] B,ref int ldb, float[] S , ref float RCond, ref int rank, [In,Out] fcomplex[] work, ref int lwork, float[] rwork, int[] iwork, ref int info); 
+        [DllImport("lapack_gen", EntryPoint = "zgelsd"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_zgelsd (ref int m,ref int n,ref int nrhs, [In,Out] complex[] A,ref int lda, [In,Out] complex[] B,ref int ldb, double[] S, ref double RCond, ref int rank, [In,Out]  complex[] work,ref int lwork, double[] rwork, int[] iwork, ref int info); 
+        
+        [DllImport("lapack_gen", EntryPoint = "dgelsy"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dgelsy (ref int m,ref int n,ref int nrhs, double[] A,ref int lda, double[] B,ref int ldb, int[] JPVT0, ref double RCond, ref int rank, double[] work, ref int lwork, ref int info); 
+        [DllImport("lapack_gen", EntryPoint = "sgelsy"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_sgelsy (ref int m,ref int n,ref int nrhs, float[] A,ref int lda, float[] B,ref int ldb, int[] JPVT0, ref float RCond, ref int rank, float[] work,ref int lwork, ref int info); 
+        [DllImport("lapack_gen", EntryPoint = "cgelsy"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_cgelsy (ref int m,ref int n,ref int nrhs, [In,Out] fcomplex[] A,ref int lda, [In,Out] fcomplex[] B,ref int ldb, int[] JPVT0, ref float RCond, ref int rank, [In,Out] fcomplex[] work, ref int lwork, float[] rwork, ref int info); 
+        [DllImport("lapack_gen", EntryPoint = "zgelsy"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_zgelsy (ref int m,ref int n,ref int nrhs, [In,Out] complex[] A,ref int lda, [In,Out] complex[] B,ref int ldb, int[] JPVT0, ref double RCond, ref int rank, [In,Out]  complex[] work, ref int lwork, double[] rwork, ref int info); 
+        
+        [DllImport("lapack_gen", EntryPoint = "dgeevx"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dgeevx (ref char balance, ref char jobvl, ref char jobvr, ref char sense, ref int n,            double[] A, ref int lda,          double[] wr, double[] wi, double[] vl, ref int ldvl,            double[] vr, ref int ldvr, ref int ilo, ref int ihi, double[] scale, ref double abnrm, double[] rconde, double[] rcondv, double[] work, ref int lwork, int [] iwork, ref int info); 
+        [DllImport("lapack_gen", EntryPoint = "sgeevx"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_sgeevx (ref char balance, ref char jobvl, ref char jobvr, ref char sense, ref int n,             float[] A, ref int lda,             float[] wr, float[] wi, float[] vl, ref int ldvl,             float[] vr, ref int ldvr, ref int ilo, ref int ihi, float[]  scale, ref float  abnrm, float[]  rconde, float[]  rcondv, float [] work, ref int lwork, int [] iwork, ref int info); 
+        [DllImport("lapack_gen", EntryPoint = "cgeevx"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_cgeevx (ref char balance, ref char jobvl, ref char jobvr, ref char sense, ref int n, [In,Out] fcomplex[] A, ref int lda, [In,Out] fcomplex[] w,  [In,Out] fcomplex[] vl, ref int ldvl, [In,Out] fcomplex[] vr, ref int ldvr, ref int ilo, ref int ihi, float[]  scale, ref float  abnrm, float[]  rconde, float[]  rcondv, [In,Out] fcomplex[] work, ref int lwork, float[] rwork, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "zgeevx"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_zgeevx (ref char balance, ref char jobvl, ref char jobvr, ref char sense, ref int n, [In,Out]  complex[] A, ref int lda, [In,Out] complex[]  w,   [In,Out] complex[] vl, ref int ldvl, [In,Out]  complex[] vr, ref int ldvr, ref int ilo, ref int ihi, double[] scale, ref double abnrm, double[] rconde, double[] rcondv, [In,Out] complex[] work, ref int lwork, double[] rwork, ref int info);
+
+        [DllImport("lapack_gen", EntryPoint = "dsyevr"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dsyevr (ref char jobz, ref char range, ref char uplo, ref int n,          double  [] A, ref int lda, ref double vl, ref double vu, ref int il, ref int iu, ref double abstol, ref int m, double[] w,          double  [] z, ref int ldz, int[] isuppz, double[] work, ref int lwork, int[] iwork, ref int liwork, ref int info); 
+        [DllImport("lapack_gen", EntryPoint = "ssyevr"),SuppressUnmanagedCodeSecurity]                                                                                                                                                                                                                                         
+        private static extern void lapack_ssyevr (ref char jobz, ref char range, ref char uplo, ref int n,          float   [] A, ref int lda, ref float  vl, ref float  vu, ref int il, ref int iu, ref float  abstol, ref int m, float [] w,          float   [] z, ref int ldz, int[] isuppz, float [] work, ref int lwork, int[] iwork, ref int liwork, ref int info); 
+        [DllImport("lapack_gen", EntryPoint = "cheevr"),SuppressUnmanagedCodeSecurity]                                                                                                                                                                                                                                         
+        private static extern void lapack_cheevr (ref char jobz, ref char range, ref char uplo, ref int n, [In,Out] fcomplex[] A, ref int lda, ref float  vl, ref float  vu, ref int il, ref int iu, ref float  abstol, ref int m, float [] w, [In,Out] fcomplex[] z, ref int ldz, int[] isuppz, [In,Out] fcomplex[] work, ref int lwork, float[] rwork, ref int lrwork, int[] iwork, ref int liwork, ref int info);
+        [DllImport("lapack_gen", EntryPoint = "zheevr"),SuppressUnmanagedCodeSecurity]                                                                                                                                                                                                                                         
+        private static extern void lapack_zheevr (ref char jobz, ref char range, ref char uplo, ref int n, [In,Out] complex [] A, ref int lda, ref double vl, ref double vu, ref int il, ref int iu, ref double abstol, ref int m, double[] w, [In,Out] complex [] z, ref int ldz, int[] isuppz, [In,Out] complex[] work, ref int lwork, double[] rwork, ref int lrwork, int[] iwork, ref int liwork, ref int info);
+
+        [DllImport("lapack_gen", EntryPoint = "dsygv"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_dsygv (ref int itype, ref char jobz, ref char uplo, ref int n, double  [] A, ref int lda, double  [] B, ref int ldb, double [] w, double [] work, ref int lwork, ref int info); 
+        [DllImport("lapack_gen", EntryPoint = "ssygv"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_ssygv (ref int itype, ref char jobz, ref char uplo, ref int n, float   [] A, ref int lda, float   [] B, ref int ldb, float [] w,  float  [] work, ref int lwork, ref int info); 
+        [DllImport("lapack_gen", EntryPoint = "chegv"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_chegv (ref int itype, ref char jobz, ref char uplo, ref int n, [In,Out] fcomplex[] A, ref int lda, [In,Out] fcomplex [] B, ref int ldb, float  [] w, [In,Out] fcomplex[] work , ref int lwork, float[] rwork, ref int info); 
+        [DllImport("lapack_gen", EntryPoint = "zhegv"),SuppressUnmanagedCodeSecurity]
+        private static extern void lapack_zhegv (ref int itype, ref char jobz, ref char uplo, ref int n, [In,Out] complex [] A, ref int lda, [In,Out] complex  [] B, ref int ldb, double [] w, [In,Out]  complex[] work , ref int lwork, double[] rwork, ref int info); 
+
+#endregion DLL INCLUDES 
+
+        #region ILLAPACK INTERFACE 
+
+        private int ILAENV (int ispec, string name, string opts, int n1, int n2, int n3, int n4) {
+            //Salford.Fortran.Character a = new Salford.Fortran.Character(); 
+            //a = Salford.Fortran.Character.data
+            //return ManagedLapackF95.ILAENV(&ispec, &(Salford.Fortran.Character)(name[0]), &opts, &n1, &n2, &n3, &n4, name.Length, opts.Length); 
+            return 0; 
+        }
+
+        /// <summary>
+        /// Implement wrapper for ATLAS GeneralMatrixMultiply
+        /// </summary>
+        /// <param name="TransA">Transposition state for matrix A: one of the constants in enum CBlas_Transpose</param>
+        /// <param name="TransB">Transposition state for matrix B: one of the constants in enum CBlas_Transpose</param>
+        /// <param name="M">Number of rows in A</param>
+        /// <param name="N">Number of columns in B</param>
+        /// <param name="K">Number of columns in A and number of rows in B</param>
+        /// <param name="alpha">multiplicationi factor for A</param>
+        /// <param name="A">pointer to double array A</param>
+        /// <param name="lda">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix B</param>
+        /// <param name="B">pointer to double array B</param>
+        /// <param name="ldb">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix A</param>
+        /// <param name="beta">multiplication faktor for matrix B</param>
+        /// <param name="C">pointer to predefined double array C of neccessary length</param>
+        /// <param name="ldc">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix C</param>
+        /// <remarks>All parameters except C are readonly. Only elements of matrix C will be altered. C must be a predefined 
+        /// continous double array of size MxN</remarks>
+        public void dgemm(char TransA, char TransB, int M, int N, int K, double alpha, IntPtr A, int lda, IntPtr B, int ldb, double beta, double[] C, int ldc) {
+            lapack_dgemm(ref TransA, ref TransB, ref M, ref  N, ref  K, ref  alpha, A, ref lda, B, ref ldb, ref  beta, C, ref  ldc);
+        }
+        /// <summary>
+        /// Implement wrapper for ATLAS GeneralMatrixMultiply
+        /// </summary>
+        /// <param name="TransA">Transposition state for matrix A: one of the constants in enum CBlas_Transpose</param>
+        /// <param name="TransB">Transposition state for matrix B: one of the constants in enum CBlas_Transpose</param>
+        /// <param name="M">Number of rows in A</param>
+        /// <param name="N">Number of columns in B</param>
+        /// <param name="K">Number of columns in A and number of rows in B</param>
+        /// <param name="alpha">multiplicationi factor for A</param>
+        /// <param name="A">pointer to double array A</param>
+        /// <param name="lda">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix B</param>
+        /// <param name="B">pointer to double array B</param>
+        /// <param name="ldb">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix A</param>
+        /// <param name="beta">multiplication faktor for matrix B</param>
+        /// <param name="C">pointer to predefined double array C of neccessary length</param>
+        /// <param name="ldc">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix C</param>
+        /// <remarks>All parameters except C are readonly. Only elements of matrix C will be altered. C must be a predefined 
+        /// continous double array of size MxN</remarks>
+        public void sgemm(char TransA, char TransB, int M, int N, int K, float alpha, IntPtr A, int lda, IntPtr B, int ldb, float beta, float[] C, int ldc) {
+            //ManagedLapackF95.SGEMM((IntPtr)TransA, (IntPtr)TransB, (IntPtr)M, (IntPtr)N, (IntPtr)K, (IntPtr)alpha, (IntPtr)A, (IntPtr)lda, (IntPtr)B, (IntPtr)ldb, (IntPtr)beta, (IntPtr)C, (IntPtr)ldc);
+        }
+        /// <summary>
+        /// Implement wrapper for ATLAS GeneralMatrixMultiply
+        /// </summary>
+        /// <param name="TransA">Transposition state for matrix A: one of the constants in enum CBlas_Transpose</param>
+        /// <param name="TransB">Transposition state for matrix B: one of the constants in enum CBlas_Transpose</param>
+        /// <param name="M">Number of rows in A</param>
+        /// <param name="N">Number of columns in B</param>
+        /// <param name="K">Number of columns in A and number of rows in B</param>
+        /// <param name="alpha">multiplicationi factor for A</param>
+        /// <param name="A">pointer to double array A</param>
+        /// <param name="lda">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix B</param>
+        /// <param name="B">pointer to double array B</param>
+        /// <param name="ldb">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix A</param>
+        /// <param name="beta">multiplication faktor for matrix B</param>
+        /// <param name="C">pointer to predefined double array C of neccessary length</param>
+        /// <param name="ldc">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix C</param>
+        /// <remarks>All parameters except C are readonly. Only elements of matrix C will be altered. C must be a predefined 
+        /// continous double array of size MxN</remarks>
+        public void cgemm(char TransA, char TransB, int M, int N, int K, fcomplex alpha, IntPtr A, int lda, IntPtr B, int ldb, fcomplex beta, fcomplex[] C, int ldc) {
+            lapack_cgemm(ref TransA, ref TransB, ref M, ref  N, ref  K, ref  alpha, A, ref lda, B, ref ldb, ref  beta, C, ref  ldc);
+        }
+        /// <summary>
+        /// Implement wrapper for ATLAS GeneralMatrixMultiply
+        /// </summary>
+        /// <param name="TransA">Transposition state for matrix A: one of the constants in enum CBlas_Transpose</param>
+        /// <param name="TransB">Transposition state for matrix B: one of the constants in enum CBlas_Transpose</param>
+        /// <param name="M">Number of rows in A</param>
+        /// <param name="N">Number of columns in B</param>
+        /// <param name="K">Number of columns in A and number of rows in B</param>
+        /// <param name="alpha">multiplicationi factor for A</param>
+        /// <param name="A">pointer to double array A</param>
+        /// <param name="lda">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix B</param>
+        /// <param name="B">pointer to double array B</param>
+        /// <param name="ldb">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix A</param>
+        /// <param name="beta">multiplication faktor for matrix B</param>
+        /// <param name="C">pointer to predefined double array C of neccessary length</param>
+        /// <param name="ldc">distance between first elements of each column for column based orientation or 
+        /// distance between first elements of each row for row based orientation for matrix C</param>
+        /// <remarks>All parameters except C are readonly. Only elements of matrix C will be altered. C must be a predefined 
+        /// continous double array of size MxN</remarks>
+        public void zgemm(char TransA, char TransB, int M, int N, int K, complex alpha, IntPtr A, int lda, IntPtr B, int ldb, complex beta, complex[] C, int ldc) {
+            lapack_zgemm(ref TransA, ref TransB, ref M, ref  N, ref  K, ref  alpha, A, ref lda, B, ref ldb, ref  beta, C, ref  ldc);
+        }
+
+
+        
+        public void  dgesdd (char jobz, int m, int n,  double [] a, int lda,  double [] s,  double [] u, int ldu,  double [] vt, int ldvt, ref int info) {
+            try {
+                 double [] work = new  double [1] { ( double )0.0 };
+                int lwork = -1;
+                int[] iwork = new int[((m < n) ? m : n) * 8];
+                 lapack_dgesdd (ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, iwork, ref info);
+                if (work[0] != 0) {
+                    work = new  double [(int)work[0]];
+                    lwork = work.Length;
+                     lapack_dgesdd (ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, iwork, ref info);
+                }
+            } catch (Exception e) {
+                if (e is OutOfMemoryException) {
+                     dgesvd (jobz, m, n, a, lda, s, u, ldu, vt, ldvt, ref info); 
+                }
+                throw new ILException("Unable to do " +  "dgesdd"  + ".", e); 
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+       
+        public void  sgesdd (char jobz, int m, int n,  float [] a, int lda,  float [] s,  float [] u, int ldu,  float [] vt, int ldvt, ref int info) {
+            try {
+                float [] work = new  float [1] { ( float )0.0 };
+                int lwork = -1;
+                int[] iwork = new int[((m < n) ? m : n) * 8];
+                lapack_sgesdd (ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, iwork, ref info);
+                if (work[0] != 0) {
+                    work = new  float [(int)work[0]];
+                    lwork = work.Length;
+                    lapack_sgesdd (ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, iwork, ref info);
+                }
+            } catch (Exception e) {
+                if (e is OutOfMemoryException) {
+                    sgesvd (jobz, m, n, a, lda, s, u, ldu, vt, ldvt, ref info); 
+                }
+                throw new ILException("Unable to do " +  "sgesdd"  + ".", e); 
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+
+
+        public void  zgesdd (char jobz, int m, int n,  complex [] a, int lda,  double [] s,  complex [] u, int ldu, complex [] vt, int ldvt, ref int info)
+        {
+            try {
+                 complex [] work = new  complex [1] { (  complex )0.0 };
+                 double [] rwork; 
+                int minMN = (m < n) ? m : n;
+                if (jobz == 'N') {
+                    rwork = new  double [minMN * 7];  
+                } else {
+                    rwork = new  double [5 * minMN * minMN + 5 * minMN];  
+                }
+                int lwork = -1;
+                int[] iwork = new int[minMN * 8];
+                 lapack_zgesdd (ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, rwork, iwork, ref info);
+                if (work[0] != 0) {
+                    work = new  complex [(int)work[0].real];
+                    lwork = work.Length;
+                     lapack_zgesdd (ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork,rwork, iwork, ref info);
+                }
+            } catch (Exception e) {
+                if (e is OutOfMemoryException) {
+                     zgesvd (jobz, m, n, a, lda, s, u, ldu, vt, ldvt, ref info); 
+                }
+                throw new ILException("Unable to do " +  "zgesdd"  + ".", e); 
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+
+        public void  cgesdd (char jobz, int m, int n,  fcomplex [] a, int lda,  float [] s,  fcomplex [] u, int ldu, fcomplex [] vt, int ldvt, ref int info)
+        {
+            try {
+                fcomplex [] work = new  fcomplex [1] { (  fcomplex )0.0 };
+                float [] rwork; 
+                int minMN = (m < n) ? m : n;
+                if (jobz == 'N') {
+                    rwork = new  float [minMN * 7];  
+                } else {
+                    rwork = new  float [5 * minMN * minMN + 5 * minMN];  
+                }
+                int lwork = -1;
+                int[] iwork = new int[minMN * 8];
+                lapack_cgesdd (ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, rwork, iwork, ref info);
+                if (work[0] != 0) {
+                    work = new  fcomplex [(int)work[0].real];
+                    lwork = work.Length;
+                    lapack_cgesdd (ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork,rwork, iwork, ref info);
+                }
+            } catch (Exception e) {
+                if (e is OutOfMemoryException) {
+                    cgesvd (jobz, m, n, a, lda, s, u, ldu, vt, ldvt, ref info); 
+                }
+                throw new ILException("Unable to do " +  "zgesdd"  + ".", e); 
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+
+        
+
+        /// <summary>
+        /// singular value decomposition
+        /// </summary>
+        /// <param name="jobz"></param>
+        /// <param name="m"></param>
+        /// <param name="n"></param>
+        /// <param name="a"></param>
+        /// <param name="lda"></param>
+        /// <param name="s"></param>
+        /// <param name="u"></param>
+        /// <param name="ldu"></param>
+        /// <param name="vt"></param>
+        /// <param name="ldvt"></param>
+        /// <param name="info"></param>
+        public void  dgesvd (char jobz, int m, int n,  double [] a, int lda,
+                            double [] s,  double [] u, int ldu,  double [] vt, int ldvt, ref int info) {
+            if (jobz != 'A' && jobz != 'S' && jobz != 'N')
+                throw new ILArgumentException("Argument jobz must be one of 'A','S' or 'N'"); 
+            try {
+                 double [] work = new  double [1] { ( double )0.0 };
+                int lwork = -1;
+                int[] iwork = new int[((m < n) ? m : n) * 8];
+                 lapack_dgesvd (ref jobz, ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, iwork, ref info);
+                if (work[0] != 0) {
+                    work = new  double [(int)work[0]];
+                    lwork = work.Length; 
+                     lapack_dgesvd (ref jobz, ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, iwork, ref info);
+                }
+            } catch (Exception e) {
+                if (e is OutOfMemoryException) {
+                    throw new ILMemoryException("Not enough memory for given arguments."); 
+                }
+                throw new ILException("Unable to do gesvd.", e);
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+       
+
+        /// <summary>
+        /// singular value decomposition
+        /// </summary>
+        /// <param name="jobz"></param>
+        /// <param name="m"></param>
+        /// <param name="n"></param>
+        /// <param name="a"></param>
+        /// <param name="lda"></param>
+        /// <param name="s"></param>
+        /// <param name="u"></param>
+        /// <param name="ldu"></param>
+        /// <param name="vt"></param>
+        /// <param name="ldvt"></param>
+        /// <param name="info"></param>
+        public void  sgesvd (char jobz, int m, int n,  float [] a, int lda,
+                           float [] s,  float [] u, int ldu,  float [] vt, int ldvt, ref int info) {
+            if (jobz != 'A' && jobz != 'S' && jobz != 'N')
+                throw new ILArgumentException("Argument jobz must be one of 'A','S' or 'N'"); 
+            try {
+                float [] work = new  float [1] { ( float )0.0 };
+                int lwork = -1;
+                int[] iwork = new int[((m < n) ? m : n) * 8];
+                lapack_sgesvd (ref jobz, ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, iwork, ref info);
+                if (work[0] != 0) {
+                    work = new  float [(int)work[0]];
+                    lwork = work.Length; 
+                    lapack_sgesvd (ref jobz, ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, iwork, ref info);
+                }
+            } catch (Exception e) {
+                if (e is OutOfMemoryException) {
+                    throw new ILMemoryException("Not enough memory for given arguments."); 
+                }
+                throw new ILException("Unable to do gesvd.", e);
+            }
+        }
+       
+
+        /// <summary>
+        /// singular value decomposition
+        /// </summary>
+        /// <param name="jobz"></param>
+        /// <param name="m"></param>
+        /// <param name="n"></param>
+        /// <param name="a"></param>
+        /// <param name="lda"></param>
+        /// <param name="s"></param>
+        /// <param name="u"></param>
+        /// <param name="ldu"></param>
+        /// <param name="vt"></param>
+        /// <param name="ldvt"></param>
+        /// <param name="info"></param>
+        public void  zgesvd (char jobz, int m, int n,  complex [] a, int lda,
+                           double [] s,  complex [] u, int ldu,  complex [] vt, int ldvt, ref int info) {
+            if (jobz != 'A' && jobz != 'S' && jobz != 'N')
+                throw new ILArgumentException("Argument jobz must be one of 'A','S' or 'N'"); 
+            try {
+                complex [] work = new  complex [1] { ( complex )0.0 };
+                int lwork = -1;
+                int[] iwork = new int[((m < n) ? m : n) * 8];
+                lapack_zgesvd (ref jobz, ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, iwork, ref info);
+                if (work[0] != 0) {
+                    work = new  complex [(int)work[0]];
+                    lwork = work.Length; 
+                    lapack_zgesvd (ref jobz, ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, iwork, ref info);
+                }
+            } catch (Exception e) {
+                if (e is OutOfMemoryException) {
+                    throw new ILMemoryException("Not enough memory for given arguments."); 
+                }
+                throw new ILException("Unable to do gesvd.", e);
+            }
+        }
+       
+
+        /// <summary>
+        /// singular value decomposition
+        /// </summary>
+        /// <param name="jobz"></param>
+        /// <param name="m"></param>
+        /// <param name="n"></param>
+        /// <param name="a"></param>
+        /// <param name="lda"></param>
+        /// <param name="s"></param>
+        /// <param name="u"></param>
+        /// <param name="ldu"></param>
+        /// <param name="vt"></param>
+        /// <param name="ldvt"></param>
+        /// <param name="info"></param>
+        public void  cgesvd (char jobz, int m, int n,  fcomplex [] a, int lda,
+                           float [] s,  fcomplex [] u, int ldu,  fcomplex [] vt, int ldvt, ref int info) {
+            if (jobz != 'A' && jobz != 'S' && jobz != 'N')
+                throw new ILArgumentException("Argument jobz must be one of 'A','S' or 'N'"); 
+            try {
+                fcomplex [] work = new  fcomplex [1] { ( fcomplex )0.0 };
+                int lwork = -1;
+                int[] iwork = new int[((m < n) ? m : n) * 8];
+                lapack_cgesvd (ref jobz, ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, iwork, ref info);
+                if (work[0] != 0) {
+                    work = new  fcomplex [(int)work[0]];
+                    lwork = work.Length; 
+                    lapack_cgesvd (ref jobz, ref jobz, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref lwork, iwork, ref info);
+                }
+            } catch (Exception e) {
+                if (e is OutOfMemoryException) {
+                    throw new ILMemoryException("Not enough memory for given arguments."); 
+                }
+                throw new ILException("Unable to do gesvd.", e);
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+        public void dpotrf(char uplo, int n, double[] A, int lda, ref int info) {
+            lapack_dpotrf(ref uplo, ref n, A, ref lda, ref info);
+        }
+        public void spotrf(char uplo, int n, float[] A, int lda, ref int info) {
+            lapack_spotrf(ref uplo, ref n, A, ref lda, ref info);
+        }
+        public void cpotrf(char uplo, int n, fcomplex[] A, int lda, ref int info) {
+            lapack_cpotrf(ref uplo, ref n, A, ref lda, ref info);
+        }
+        public void zpotrf(char uplo, int n, complex[] A, int lda, ref int info) {
+            lapack_zpotrf(ref uplo, ref n, A, ref lda, ref info);
+        }
+
+
+        public void dpotri(char uplo, int n, double[] A, int lda, ref int info) {
+            lapack_dpotri(ref uplo, ref n, A, ref lda, ref info);
+        }
+        public void spotri(char uplo, int n, float[] A, int lda, ref int info) {
+            lapack_spotri(ref uplo, ref n, A, ref lda, ref info);
+        }
+        public void cpotri(char uplo, int n, fcomplex[] A, int lda, ref int info) {
+            lapack_cpotri(ref uplo, ref n, A, ref lda, ref info);
+        }
+        public void zpotri(char uplo, int n, complex[] A, int lda, ref int info) {
+            lapack_zpotri(ref uplo, ref n, A, ref lda, ref info);
+        }
+
+
+        public void dgetrf(int M, int N, double[] A, int LDA, int[] IPIV, ref int info) {
+            lapack_dgetrf(ref M, ref N, A, ref LDA, IPIV, ref info);
+        }
+        public void sgetrf(int M, int N, float[] A, int LDA, int[] IPIV, ref int info) {
+            lapack_sgetrf(ref M, ref N, A, ref LDA, IPIV, ref info);
+        }
+        public void cgetrf(int M, int N, fcomplex[] A, int LDA, int[] IPIV, ref int info) {
+            lapack_cgetrf(ref M, ref N, A, ref LDA, IPIV, ref info);
+        }
+        public void zgetrf(int M, int N, complex[] A, int LDA, int[] IPIV, ref int info) {
+            lapack_zgetrf(ref M, ref N, A, ref LDA, IPIV, ref info);
+        }
+
+
+        
+        public void  dgetri (int N,  double [] A, int LDA, int[] IPIV, ref int info) {
+             double [] work = new  double [1];  
+            int lwork = -1; 
+            try {
+                 lapack_dgetri (ref N, A, ref LDA, IPIV, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  double [lwork]; 
+                     lapack_dgetri (ref N, A, ref LDA, IPIV, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in lapack_dgetri"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on dgetri. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+       
+        public void  sgetri (int N,  float [] A, int LDA, int[] IPIV, ref int info) {
+            float [] work = new  float [1];  
+            int lwork = -1; 
+            try {
+                lapack_sgetri (ref N, A, ref LDA, IPIV, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  float [lwork]; 
+                    lapack_sgetri (ref N, A, ref LDA, IPIV, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in lapack_dgetri"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on dgetri. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+       
+        public void  zgetri (int N,  complex [] A, int LDA, int[] IPIV, ref int info) {
+            complex [] work = new  complex [1];  
+            int lwork = -1; 
+            try {
+                lapack_zgetri (ref N, A, ref LDA, IPIV, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  complex [lwork]; 
+                    lapack_zgetri (ref N, A, ref LDA, IPIV, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in lapack_dgetri"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on dgetri. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+       
+        public void  cgetri (int N,  fcomplex [] A, int LDA, int[] IPIV, ref int info) {
+            fcomplex [] work = new  fcomplex [1];  
+            int lwork = -1; 
+            try {
+                lapack_cgetri (ref N, A, ref LDA, IPIV, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  fcomplex [lwork]; 
+                    lapack_cgetri (ref N, A, ref LDA, IPIV, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in lapack_dgetri"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on dgetri. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+
+        
+        public void  dgeqrf (int M, int N,  double [] A, int lda,  double [] tau, ref int info) {
+             double [] work = new  double [1];  
+            int lwork = -1; 
+            try {
+                 lapack_dgeqrf (ref M, ref N, A, ref lda, tau, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  double [lwork]; 
+                     lapack_dgeqrf (ref M, ref N, A, ref lda, tau, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in lapack_?geqrf"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on ?geqrf. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+       
+        public void  sgeqrf (int M, int N,  float [] A, int lda,  float [] tau, ref int info) {
+            float [] work = new  float [1];  
+            int lwork = -1; 
+            try {
+                lapack_sgeqrf (ref M, ref N, A, ref lda, tau, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  float [lwork]; 
+                    lapack_sgeqrf (ref M, ref N, A, ref lda, tau, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in lapack_?geqrf"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on ?geqrf. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+       
+        public void  zgeqrf (int M, int N,  complex [] A, int lda,  complex [] tau, ref int info) {
+            complex [] work = new  complex [1];  
+            int lwork = -1; 
+            try {
+                lapack_zgeqrf (ref M, ref N, A, ref lda, tau, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  complex [lwork]; 
+                    lapack_zgeqrf (ref M, ref N, A, ref lda, tau, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in lapack_?geqrf"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on ?geqrf. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+       
+        public void  cgeqrf (int M, int N,  fcomplex [] A, int lda,  fcomplex [] tau, ref int info) {
+            fcomplex [] work = new  fcomplex [1];  
+            int lwork = -1; 
+            try {
+                lapack_cgeqrf (ref M, ref N, A, ref lda, tau, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  fcomplex [lwork]; 
+                    lapack_cgeqrf (ref M, ref N, A, ref lda, tau, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in lapack_?geqrf"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on ?geqrf. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+        public void dormqr(char side, char trans, int m, int n, int k, double[] A, int lda, double[] tau, double[] C, int LDC, ref int info) {
+            throw new Exception("The method or operation is not implemented.");
+        }
+        public void sormqr(char side, char trans, int m, int n, int k, float[] A, int lda, float[] tau, float[] C, int LDC, ref int info) {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+
+        
+        public void  dorgqr (int M, int N, int K,  double [] A, int lda,  double [] tau, ref int info) {
+             double [] work = new  double [1];  
+            int lwork = -1; 
+            try {
+                /*!HC:lapack_***gqr*/ lapack_dorgqr (ref M, ref N, ref K, A, ref lda, tau, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  double [lwork]; 
+                    /*!HC:lapack_***gqr*/ lapack_dorgqr (ref M, ref N, ref K, A, ref lda, tau, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in lapack_?[un/or]gqr"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on ?[un/or]gqr. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+       
+        public void  sorgqr (int M, int N, int K,  float [] A, int lda,  float [] tau, ref int info) {
+            float [] work = new  float [1];  
+            int lwork = -1; 
+            try {
+                lapack_sorgqr (ref M, ref N, ref K, A, ref lda, tau, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  float [lwork]; 
+                    lapack_sorgqr (ref M, ref N, ref K, A, ref lda, tau, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in lapack_?[un/or]gqr"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on ?[un/or]gqr. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+       
+        public void  zungqr (int M, int N, int K,  complex [] A, int lda,  complex [] tau, ref int info) {
+            complex [] work = new  complex [1];  
+            int lwork = -1; 
+            try {
+                lapack_zungqr (ref M, ref N, ref K, A, ref lda, tau, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  complex [lwork]; 
+                    lapack_zungqr (ref M, ref N, ref K, A, ref lda, tau, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in lapack_?[un/or]gqr"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on ?[un/or]gqr. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+       
+        public void  cungqr (int M, int N, int K,  fcomplex [] A, int lda,  fcomplex [] tau, ref int info) {
+            fcomplex [] work = new  fcomplex [1];  
+            int lwork = -1; 
+            try {
+                lapack_cungqr (ref M, ref N, ref K, A, ref lda, tau, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  fcomplex [lwork]; 
+                    lapack_cungqr (ref M, ref N, ref K, A, ref lda, tau, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in lapack_?[un/or]gqr"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on ?[un/or]gqr. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+
+        
+        public void  dgeqp3 ( int M,int N, double [] A,int LDA,int [] JPVT, double [] tau, ref int info ) {
+             double [] work = new  double [1];
+            int lwork = -1; 
+            try {
+                 
+                /*dummy*/
+                 
+                lapack_dgeqp3 (ref M, ref N, A, ref LDA, JPVT, tau, work, ref lwork, ref info); 
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  double [lwork]; 
+                     
+                    lapack_dgeqp3 (ref M, ref N, A, ref LDA, JPVT, tau, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in lapack_?geqp3"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on ?geqp3. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+       
+        public void  sgeqp3 ( int M,int N, float [] A,int LDA,int [] JPVT, float [] tau, ref int info ) {
+            float [] work = new  float [1];
+            int lwork = -1; 
+            try {
+                
+                lapack_sgeqp3 (ref M, ref N, A, ref LDA, JPVT, tau, work, ref lwork, ref info);
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  float [lwork]; 
+                    lapack_sgeqp3 (ref M, ref N, A, ref LDA, JPVT, tau, work, ref lwork, ref info);
+                } else {
+                    throw new ILException("error in lapack_?geqp3"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on ?geqp3. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+       
+        public void  zgeqp3 ( int M,int N, complex [] A,int LDA,int [] JPVT, complex [] tau, ref int info ) {
+            complex [] work = new  complex [1];
+            int lwork = -1; 
+            try {
+                double[] rwork = new double[2 * N];
+                lapack_zgeqp3 (ref M, ref N, A, ref LDA, JPVT, tau, work, ref lwork, rwork, ref info);
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  complex [lwork]; 
+                    lapack_zgeqp3 (ref M, ref N, A, ref LDA, JPVT, tau, work, ref lwork, rwork, ref info);
+                } else {
+                    throw new ILException("error in lapack_?geqp3"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on ?geqp3. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+       
+        public void  cgeqp3 ( int M,int N, fcomplex [] A,int LDA,int [] JPVT, fcomplex [] tau, ref int info ) {
+            fcomplex [] work = new  fcomplex [1];
+            int lwork = -1; 
+            try {
+                float[] rwork = new float[2 * N];
+                lapack_cgeqp3 (ref M, ref N, A, ref LDA, JPVT, tau, work, ref lwork, rwork, ref info);
+                lwork = (int)work[0]; 
+                if (lwork > 0 && info == 0) {
+                    work = new  fcomplex [lwork]; 
+                    lapack_cgeqp3 (ref M, ref N, A, ref LDA, JPVT, tau, work, ref lwork, rwork, ref info);
+                } else {
+                    throw new ILException("error in lapack_?geqp3"); 
+                }
+            } catch (OutOfMemoryException e) {
+                throw new ILException("error on ?geqp3. Not enough memory! " + (lwork * Marshal.SizeOf( work[0] )).ToString() + " bytes has been requested.",e); 
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+        public void dtrtrs(char uplo, char transA, char diag, int N, int nrhs, IntPtr A, int LDA, IntPtr B, int LDB, ref int info) {
+            lapack_dtrtrs(ref uplo, ref transA, ref diag, ref N, ref nrhs, A, ref LDA, B, ref LDB, ref info); 
+        }
+        public void strtrs(char uplo, char transA, char diag, int N, int nrhs, IntPtr A, int LDA, IntPtr B, int LDB, ref int info) {
+            lapack_strtrs(ref uplo, ref transA, ref diag, ref N, ref nrhs, A, ref LDA, B, ref LDB, ref info); 
+        }
+        public void ctrtrs(char uplo, char transA, char diag, int N, int nrhs, IntPtr A, int LDA, IntPtr B, int LDB, ref int info) {
+            lapack_ctrtrs(ref uplo, ref transA, ref diag, ref N, ref nrhs, A, ref LDA, B, ref LDB, ref info); 
+        }
+        public void ztrtrs(char uplo, char transA, char diag, int N, int nrhs, IntPtr A, int LDA, IntPtr B, int LDB, ref int info) {
+            lapack_ztrtrs(ref uplo, ref transA, ref diag, ref N, ref nrhs, A, ref LDA, B, ref LDB, ref info); 
+        }
+
+        public void dgetrs(char trans, int N, int NRHS, double[] A, int LDA, int[] IPIV, double[] B, int LDB, ref int info) {
+            lapack_dgetrs(ref trans,ref N,ref NRHS, A, ref LDA, IPIV, B, ref LDB, ref info);     
+        }
+
+        public void sgetrs(char trans, int N, int NRHS, float[] A, int LDA, int[] IPIV, float[] B, int LDB, ref int info) {
+            lapack_sgetrs(ref trans,ref N,ref NRHS, A, ref LDA, IPIV, B, ref LDB, ref info);     
+        }
+
+        public void cgetrs(char trans, int N, int NRHS, fcomplex[] A, int LDA, int[] IPIV, fcomplex[] B, int LDB, ref int info) {
+            lapack_cgetrs(ref trans,ref N,ref NRHS, A, ref LDA, IPIV, B, ref LDB, ref info);     
+        }
+
+        public void zgetrs(char trans, int N, int NRHS, complex[] A, int LDA, int[] IPIV, complex[] B, int LDB, ref int info) {
+            lapack_zgetrs(ref trans,ref N,ref NRHS, A, ref LDA, IPIV, B, ref LDB, ref info);
+        }
+        
+        public void dpotrs(char uplo, int n, int nrhs, double[] A, int lda, double[] B, int ldb, ref int info) {
+            lapack_dpotrs(ref uplo, ref n, ref nrhs, A, ref lda, B, ref ldb, ref info); 
+        }
+
+        public void spotrs(char uplo, int n, int nrhs, float[] A, int lda, float[] B, int ldb, ref int info) {
+            lapack_spotrs(ref uplo, ref n, ref nrhs, A, ref lda, B, ref ldb, ref info); 
+        }
+
+        public void cpotrs(char uplo, int n, int nrhs, fcomplex[] A, int lda, fcomplex[] B, int ldb, ref int info) {
+            lapack_cpotrs(ref uplo, ref n, ref nrhs, A, ref lda, B, ref ldb, ref info); 
+        }
+
+        public void zpotrs(char uplo, int n, int nrhs, complex[] A, int lda, complex[] B, int ldb, ref int info) {
+            lapack_zpotrs(ref uplo, ref n, ref nrhs, A, ref lda, B, ref ldb, ref info); 
+        }
+
+
+        
+        public void  dgelsd (int m, int n, int nrhs,  double [] A, int lda,  double [] B, int ldb,  double [] S,  double RCond, ref int rank, ref int info) {
+             double [] work = new  double [1]; 
+            int [] iwork = new int[1]; 
+            int lwork = -1; 
+            /*HC:HycalpTag1*/
+            lapack_dgelsd (ref m, ref n, ref nrhs, A, ref lda, B, ref ldb, S,ref RCond, ref rank, work, ref lwork, iwork, ref info);
+            if (info != 0) 
+                throw new ILArgumentException("dgelsd: invalid parameter: #" + (-info).ToString());
+            lwork = ILAENV(9, "dgelsd", " ",0,0,0,0); 
+            if (lwork <= 0)
+                throw new ILArgumentException("dgelsd: unknown error determining working size liwork");
+            iwork = new int[lwork];
+            lwork = (int)work[0];
+            work = new  double [lwork]; 
+            /*HC:HycalpTag2*/
+            lapack_dgelsd (ref m, ref n, ref nrhs, A, ref lda, B, ref ldb, S,ref RCond, ref rank, work, ref lwork, iwork, ref info);
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+       
+        public void  sgelsd  (int m, int n, int nrhs,  float [] A, int lda,  float [] B, int ldb,  float [] S,  float RCond, ref int rank, ref int info) {
+            float [] work = new  float [1]; 
+            int [] iwork = new int[1]; 
+            int lwork = -1; 
+            lapack_sgelsd (ref m, ref n, ref nrhs, A, ref lda, B, ref ldb, S,ref RCond, ref rank, work, ref lwork, iwork, ref info);
+            if (info != 0) 
+                throw new ILArgumentException("dgelsd: invalid parameter: #" + (-info).ToString());
+            lwork = ILAENV(9, "dgelsd", " ",0,0,0,0); 
+            if (lwork <= 0)
+                throw new ILArgumentException("dgelsd: unknown error determining working size liwork");
+            iwork = new int[lwork];
+            lwork = (int)work[0];
+            work = new  float [lwork]; 
+            lapack_sgelsd (ref m, ref n, ref nrhs, A, ref lda, B, ref ldb, S,ref RCond, ref rank, work, ref lwork, iwork, ref info);
+        }
+       
+        public void  zgelsd  (int m, int n, int nrhs,  complex [] A, int lda,  complex [] B, int ldb,  double [] S,  double RCond, ref int rank, ref int info) {
+            complex [] work = new  complex [1]; 
+            int [] iwork = new int[1]; 
+            int lwork = -1; 
+            double [] rwork = new double [1];  lapack_zgelsd (ref m, ref n, ref nrhs, A, ref lda, B, ref ldb, S,ref RCond, ref rank, work, ref lwork, rwork, iwork, ref info);
+            if (info != 0) 
+                throw new ILArgumentException("dgelsd: invalid parameter: #" + (-info).ToString());
+            lwork = ILAENV(9, "dgelsd", " ",0,0,0,0); 
+            if (lwork <= 0)
+                throw new ILArgumentException("dgelsd: unknown error determining working size liwork");
+            iwork = new int[lwork];
+            lwork = (int)work[0];
+            work = new  complex [lwork]; 
+            rwork = new double [(int)rwork[0]];  lapack_zgelsd (ref m, ref n, ref nrhs, A, ref lda, B, ref ldb, S,ref RCond, ref rank, work, ref lwork, rwork, iwork, ref info);
+        }
+       
+        public void  cgelsd  (int m, int n, int nrhs,  fcomplex [] A, int lda,  fcomplex [] B, int ldb,  float [] S,  float RCond, ref int rank, ref int info) {
+            fcomplex [] work = new  fcomplex [1]; 
+            int [] iwork = new int[1]; 
+            int lwork = -1; 
+            float [] rwork = new float [1];  lapack_cgelsd (ref m, ref n, ref nrhs, A, ref lda, B, ref ldb, S,ref RCond, ref rank, work, ref lwork, rwork, iwork, ref info);
+            if (info != 0) 
+                throw new ILArgumentException("dgelsd: invalid parameter: #" + (-info).ToString());
+            lwork = ILAENV(9, "dgelsd", " ",0,0,0,0); 
+            if (lwork <= 0)
+                throw new ILArgumentException("dgelsd: unknown error determining working size liwork");
+            iwork = new int[lwork];
+            lwork = (int)work[0];
+            work = new  fcomplex [lwork]; 
+            rwork = new float [(int)rwork[0]];  lapack_cgelsd (ref m, ref n, ref nrhs, A, ref lda, B, ref ldb, S,ref RCond, ref rank, work, ref lwork, rwork, iwork, ref info);
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+
+        
+        public void  dgelsy (int m, int n, int nrhs,  double [] A, int lda,  double [] B, int ldb, int[] JPVT0,  double RCond, ref int rank, ref int info) {
+            int lwork = -1;
+             double [] work = new  double [1]; 
+             //
+            /*!HC:lapack_?gelsy*/ 
+            lapack_dgelsy (ref m,ref n,ref nrhs,A,ref lda,B,ref ldb,JPVT0,ref RCond,ref rank,work,ref lwork,ref info);
+            if (info != 0)
+                throw new ILArgumentException("?gelsy: unable to determine optimal block size. cancelling...");
+            lwork = (int) work[0];
+            work = new  double [lwork];
+             //
+            /*!HC:lapack_?gelsy*/ 
+            lapack_dgelsy (ref m,ref n,ref nrhs,A,ref lda,B,ref ldb,JPVT0,ref RCond,ref rank,work,ref lwork,ref info);
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+       
+        public void  sgelsy  (int m, int n, int nrhs,  float [] A, int lda,  float [] B, int ldb, int[] JPVT0,  float RCond, ref int rank, ref int info) {
+            int lwork = -1;
+            float [] work = new  float [1]; 
+            
+            lapack_sgelsy (ref m,ref n,ref nrhs,A,ref lda,B,ref ldb,JPVT0,ref RCond,ref rank,work,ref lwork,ref info);
+            if (info != 0)
+                throw new ILArgumentException("?gelsy: unable to determine optimal block size. cancelling...");
+            lwork = (int) work[0];
+            work = new  float [lwork];
+            
+            lapack_sgelsy (ref m,ref n,ref nrhs,A,ref lda,B,ref ldb,JPVT0,ref RCond,ref rank,work,ref lwork,ref info);
+        }
+       
+        public void  zgelsy  (int m, int n, int nrhs,  complex [] A, int lda,  complex [] B, int ldb, int[] JPVT0,  double RCond, ref int rank, ref int info) {
+            int lwork = -1;
+            complex [] work = new  complex [1]; 
+            double[] rwork = new double[1];
+            lapack_zgelsy (ref m,ref n,ref nrhs,A,ref lda,B,ref ldb,JPVT0,ref RCond,ref rank,work,ref lwork, rwork, ref info);
+            if (info != 0)
+                throw new ILArgumentException("?gelsy: unable to determine optimal block size. cancelling...");
+            lwork = (int) work[0];
+            work = new  complex [lwork];
+            rwork = new double[lwork];
+            lapack_zgelsy (ref m,ref n,ref nrhs,A,ref lda,B,ref ldb,JPVT0,ref RCond,ref rank,work,ref lwork, rwork, ref info);
+        }
+       
+        public void  cgelsy  (int m, int n, int nrhs,  fcomplex [] A, int lda,  fcomplex [] B, int ldb, int[] JPVT0,  float RCond, ref int rank, ref int info) {
+            int lwork = -1;
+            fcomplex [] work = new  fcomplex [1]; 
+            float[] rwork = new float[1];
+            lapack_cgelsy (ref m,ref n,ref nrhs,A,ref lda,B,ref ldb,JPVT0,ref RCond,ref rank,work,ref lwork, rwork, ref info);
+            if (info != 0)
+                throw new ILArgumentException("?gelsy: unable to determine optimal block size. cancelling...");
+            lwork = (int) work[0];
+            work = new  fcomplex [lwork];
+            rwork = new float[lwork];
+            lapack_cgelsy (ref m,ref n,ref nrhs,A,ref lda,B,ref ldb,JPVT0,ref RCond,ref rank,work,ref lwork, rwork, ref info);
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+        #region ?GEEVX
+        public void dgeevx(char balance, char jobvl, char jobvr, char sense, int n, double[] A, int lda, double[] wr, double[] wi, double[] vl, int ldvl, double[] vr, int ldvr, ref int ilo, ref int ihi, double[] scale, ref double abnrm, double[] rconde, double[] rcondv, ref int info) {
+            double [] work = new double[1]; 
+            int lwork = -1;
+            int [] iwork = new int[2 * n - 2];
+            lapack_dgeevx(ref balance, ref jobvl, ref jobvr, ref sense, ref n, A, ref lda, wr, wi, vl, ref ldvl, vr, ref ldvr, ref ilo, ref ihi, scale, ref abnrm, rconde, rcondv, work, ref lwork, iwork, ref info);
+            if (info != 0) 
+                throw new ILArgumentException("error in lapack call: ?geevx. (" + info + ")");
+            lwork = (int)work[0]; 
+            work = new double[lwork]; 
+            lapack_dgeevx(ref balance, ref jobvl, ref jobvr, ref sense, ref n, A, ref lda, wr, wi, vl, ref ldvl, vr, ref ldvr, ref ilo, ref ihi, scale, ref abnrm, rconde, rcondv, work, ref lwork, iwork, ref info);
+        }
+        public void sgeevx(char balance, char jobvl, char jobvr, char sense, int n, float[] A, int lda, float[] wr, float[] wi, float[] vl, int ldvl, float[] vr, int ldvr, ref int ilo, ref int ihi, float[] scale, ref float abnrm, float[] rconde, float[] rcondv, ref int info) {
+            float [] work = new float[1]; 
+            int lwork = -1;
+            int [] iwork = new int[2 * n - 2];
+            lapack_sgeevx(ref balance, ref jobvl, ref jobvr, ref sense, ref n, A, ref lda, wr, wi, vl, ref ldvl, vr, ref ldvr, ref ilo, ref ihi, scale, ref abnrm, rconde, rcondv, work, ref lwork, iwork, ref info);
+            if (info != 0) 
+                throw new ILArgumentException("error in lapack call: ?geevx. (" + info + ")");
+            lwork = (int)work[0]; 
+            work = new float[lwork]; 
+            lapack_sgeevx(ref balance, ref jobvl, ref jobvr, ref sense, ref n, A, ref lda, wr, wi, vl, ref ldvl, vr, ref ldvr, ref ilo, ref ihi, scale, ref abnrm, rconde, rcondv, work, ref lwork, iwork, ref info);
+        }
+        public void cgeevx(char balance, char jobvl, char jobvr, char sense, int n, fcomplex[] A, int lda, fcomplex[] w, fcomplex[] vl, int ldvl, fcomplex[] vr, int ldvr, ref int ilo, ref int ihi, float[] scale, ref float abnrm, float[] rconde, float[] rcondv, ref int info) {
+            fcomplex [] work = new fcomplex[1]; 
+            int lwork = -1;
+            float[] rwork = new float[2 * n]; 
+            lapack_cgeevx(ref balance, ref jobvl, ref jobvr, ref sense, ref n, A, ref lda, w, vl, ref ldvl, vr, ref ldvr, ref ilo, ref ihi, scale, ref abnrm, rconde, rcondv, work, ref lwork, rwork, ref info);
+            if (info != 0) 
+                throw new ILArgumentException("error in lapack call: ?geevx. (" + info + ")");
+            lwork = (int)work[0]; 
+            work = new fcomplex[lwork]; 
+            lapack_cgeevx(ref balance, ref jobvl, ref jobvr, ref sense, ref n, A, ref lda, w, vl, ref ldvl, vr, ref ldvr, ref ilo, ref ihi, scale, ref abnrm, rconde, rcondv, work, ref lwork, rwork, ref info);
+        }
+        public void zgeevx(char balance, char jobvl, char jobvr, char sense, int n, complex[] A, int lda, complex[] w, complex[] vl, int ldvl, complex[] vr, int ldvr, ref int ilo, ref int ihi, double[] scale, ref double abnrm, double[] rconde, double[] rcondv, ref int info) {
+            complex [] work = new complex[1]; 
+            int lwork = -1;
+            double[] rwork = new double[2 * n]; 
+            lapack_zgeevx(ref balance, ref jobvl, ref jobvr, ref sense, ref n, A, ref lda, w, vl, ref ldvl, vr, ref ldvr, ref ilo, ref ihi, scale, ref abnrm, rconde, rcondv, work, ref lwork, rwork, ref info);
+            if (info != 0) 
+                throw new ILArgumentException("error in lapack call: ?geevx. (" + info + ")");
+            lwork = (int)work[0]; 
+            work = new complex[lwork]; 
+            lapack_zgeevx(ref balance, ref jobvl, ref jobvr, ref sense, ref n, A, ref lda, w, vl, ref ldvl, vr, ref ldvr, ref ilo, ref ihi, scale, ref abnrm, rconde, rcondv, work, ref lwork, rwork, ref info);
+        }
+        #endregion
+
+        #region ?SYEVR
+        public void dsyevr(char jobz, char range, char uplo, int n, double[] A, int lda, double vl, double vu, int il, int iu, double abstol, ref int m, double[] w, double[] z, int ldz, int[] isuppz, ref int info) {
+            double [] work = new double[1]; 
+            int lwork = -1, liwork = -1; 
+            int [] iwork = new int[1]; 
+            lapack_dsyevr(ref jobz,ref range,ref uplo,ref n, A,ref lda, ref vl, ref vu, ref il, ref iu, ref abstol,ref m, w,z,ref ldz,isuppz, work,ref lwork,iwork,ref liwork,ref info);
+            if (info != 0) {
+                throw new ILArgumentException("?syevr: error returned from lapack: " + info);
+            }
+            lwork = (int)work[0]; 
+            liwork = (int) iwork[0]; 
+            //work = ILMemoryPool.Pool.New<double>(lwork);
+            //iwork = ILMemoryPool.Pool.New<int>(liwork); 
+            work = new double[lwork];
+            iwork = new int[liwork]; 
+            lapack_dsyevr(ref jobz,ref range,ref uplo,ref n, A,ref lda, ref vl, ref vu, ref il, ref iu, ref abstol,ref m, w,z,ref ldz,isuppz, work,ref lwork,iwork,ref liwork,ref info);
+            //ILMemoryPool.Pool.RegisterObject(work);
+            //ILMemoryPool.Pool.RegisterObject(iwork);
+            if (info != 0) {
+                throw new ILArgumentException("?syevr: error returned from lapack: " + info);
+            }
+        }
+        public void ssyevr(char jobz, char range, char uplo, int n, float[] A, int lda, float vl, float vu, int il, int iu, float abstol, ref int m, float[] w, float[] z, int ldz, int[] isuppz, ref int info) {
+            float [] work = new float[1]; 
+            int lwork = -1, liwork = -1; 
+            int [] iwork = new int[1]; 
+            lapack_ssyevr(ref jobz,ref range,ref uplo,ref n, A,ref lda, ref vl, ref vu, ref il, ref iu, ref abstol,ref m, w,z,ref ldz,isuppz, work,ref lwork,iwork,ref liwork,ref info);
+            if (info != 0) {
+                throw new ILArgumentException("?syevr: error returned from lapack: " + info);
+            }
+            lwork = (int)work[0]; 
+            work = ILMemoryPool.Pool.New<float>(lwork);
+            liwork = (int) iwork[0]; 
+            iwork = ILMemoryPool.Pool.New<int>(liwork); 
+            lapack_ssyevr(ref jobz,ref range,ref uplo,ref n, A,ref lda, ref vl, ref vu, ref il, ref iu, ref abstol,ref m, w,z,ref ldz,isuppz, work,ref lwork,iwork,ref liwork,ref info);
+            ILMemoryPool.Pool.Free(work);
+            ILMemoryPool.Pool.Free(iwork);
+            if (info != 0) {
+                throw new ILArgumentException("?syevr: error returned from lapack: " + info);
+            }
+        }
+        public void cheevr(char jobz, char range, char uplo, int n, fcomplex[] A, int lda, float vl, float vu, int il, int iu, float abstol, ref int m, float[] w, fcomplex[] z, int ldz, int[] isuppz, ref int info) {
+            fcomplex[] work = new fcomplex[1]; 
+            float [] rwork = new float[1]; 
+            int [] iwork = new int[1]; 
+            int lrwork = -1, liwork = -1, lwork = -1; 
+            lapack_cheevr(ref jobz,ref range,ref uplo,ref n, A,ref lda, ref vl, ref vu, ref il, ref iu, ref abstol,ref m, w,z,ref ldz,isuppz, work,ref lwork,rwork,ref lrwork, iwork,ref liwork,ref info);
+            if (info != 0) {
+                throw new ILArgumentException("?chevr: error returned from lapack: " + info);
+            }
+            lrwork = (int)rwork[0]; 
+            rwork = ILMemoryPool.Pool.New<float>(lrwork);
+            lwork = (int) work[0]; 
+            work = ILMemoryPool.Pool.New<fcomplex>(lwork); 
+            liwork = (int) iwork[0]; 
+            iwork = ILMemoryPool.Pool.New<int>(liwork); 
+            lapack_cheevr(ref jobz,ref range,ref uplo,ref n, A,ref lda, ref vl, ref vu, ref il, ref iu, ref abstol,ref m, w,z,ref ldz,isuppz, work,ref lwork,rwork,ref lrwork,iwork,ref liwork,ref info);
+            ILMemoryPool.Pool.Free(rwork);
+            ILMemoryPool.Pool.Free(work);
+            ILMemoryPool.Pool.Free(iwork);
+            if (info != 0) {
+                throw new ILArgumentException("?syevr: error returned from lapack: " + info);
+            }
+        }
+        public void zheevr(char jobz, char range, char uplo, int n, complex[] A, int lda, double vl, double vu, int il, int iu, double abstol, ref int m, double[] w, complex[] z, int ldz, int[] isuppz, ref int info) {
+            complex[] work = new complex[1]; 
+            double [] rwork = new double[1]; 
+            int [] iwork = new int[1]; 
+            int lrwork = -1, liwork = -1, lwork = -1; 
+            lapack_zheevr(ref jobz,ref range,ref uplo,ref n, A,ref lda, ref vl, ref vu, ref il, ref iu, ref abstol,ref m, w,z,ref ldz,isuppz, work,ref lwork,rwork,ref lrwork, iwork,ref liwork,ref info);
+            if (info != 0) {
+                throw new ILArgumentException("?heevr: error returned from lapack: " + info);
+            }
+            lrwork = (int)rwork[0]; 
+            rwork = ILMemoryPool.Pool.New<double>(lrwork);
+            lwork = (int) work[0]; 
+            work = ILMemoryPool.Pool.New<complex>(lwork); 
+            liwork = (int) iwork[0]; 
+            iwork = ILMemoryPool.Pool.New<int>(liwork); 
+            lapack_zheevr(ref jobz,ref range,ref uplo,ref n, A,ref lda, ref vl, ref vu, ref il, ref iu, ref abstol,ref m, w,z,ref ldz,isuppz, work,ref lwork,rwork,ref lrwork,iwork,ref liwork,ref info);
+            ILMemoryPool.Pool.Free(rwork);
+            ILMemoryPool.Pool.Free(work);
+            ILMemoryPool.Pool.Free(iwork);
+            if (info != 0) {
+                throw new ILArgumentException("?syevr: error returned from lapack: " + info);
+            }
+        }
+        #endregion
+
+        #region ?[he/sy]gv - generalized eigenproblem
+        public void dsygv (int itype, char jobz, char uplo, int n, double  [] A, int lda, double  [] B, int ldb, double [] w, ref int info) {
+            // query workspace 
+            int lwork = -1; 
+            double [] work = new double[1] {0.0}; 
+            lapack_dsygv (ref itype,ref jobz,ref uplo,ref n, A,ref lda, B,ref ldb, w, work, ref lwork, ref info); 
+            if (info != 0 || work[0] <= 0.0) return; 
+            // create temporary array(s)
+            lwork = (int) work[0]; 
+            work = ILMemoryPool.Pool.New<double>(lwork); 
+            lapack_dsygv (ref itype,ref jobz,ref uplo,ref n, A,ref lda, B,ref ldb, w, work, ref lwork, ref info); 
+            ILMemoryPool.Pool.Free(work); 
+        }        
+        public void ssygv (int itype, char jobz, char uplo, int n, float   [] A, int lda, float   [] B, int ldb, float  [] w, ref int info) {
+            // query workspace 
+            int lwork = -1; 
+            float [] work = new float[1] {0.0f}; 
+            lapack_ssygv (ref itype,ref jobz,ref uplo,ref n, A,ref lda, B,ref ldb, w, work, ref lwork, ref info); 
+            if (info != 0 || work[0] <= 0.0) return; 
+            // create temporary array(s)
+            lwork = (int) work[0]; 
+            work = ILMemoryPool.Pool.New<float>(lwork); 
+            lapack_ssygv (ref itype,ref jobz,ref uplo,ref n, A,ref lda, B,ref ldb, w, work, ref lwork, ref info); 
+            ILMemoryPool.Pool.Free(work); 
+        }
+        public void chegv (int itype, char jobz, char uplo, int n, fcomplex[] A, int lda, fcomplex[] B, int ldb, float  [] w, ref int info) {
+            int lwork = (int)Math.Max(1,2*n-1); bool dummy; 
+            float [] rwork = ILMemoryPool.Pool.New<float>(Math.Max(1,3*n-2),false, out dummy); 
+            fcomplex [] work = ILMemoryPool.Pool.New<fcomplex>(lwork,false, out dummy); 
+            // NOTE: this implementation of LAPACK (netlib.org, not optimized) seems to overwrite B even if only a workspace query is assumed. 
+            // therefore this hack uses the (may not optimal efficiently) working size 2*n-1 for computation.
+            lapack_chegv(ref itype,ref  jobz,ref  uplo,ref  n, A,ref  lda, B,ref  ldb, w, work, ref lwork, rwork, ref info); 
+            ILMemoryPool.Pool.Free(rwork); 
+            ILMemoryPool.Pool.Free(work); 
+        }
+        public void zhegv (int itype, char jobz, char uplo, int n, complex [] A, int lda, complex [] B, int ldb, double [] w, ref int info) { 
+            // NOTE: this implementation of LAPACK (netlib.org, not optimized) seems to overwrite B even if only a workspace query is assumed. 
+            // therefore this hack uses the (may not optimal efficiently) working size 2*n-1 for computation.
+            int lwork = (int)Math.Max(1,2*n-1); bool dummy; 
+            double [] rwork = ILMemoryPool.Pool.New<double>(Math.Max(1,3*n-2)); 
+            complex [] work = ILMemoryPool.Pool.New<complex>(lwork,false, out dummy); 
+            lapack_zhegv(ref itype,ref  jobz,ref  uplo,ref  n, A,ref  lda, B,ref  ldb, w, work, ref lwork, rwork, ref info); 
+            ILMemoryPool.Pool.Free(rwork); 
+            ILMemoryPool.Pool.Free(work); 
+        }
+        #endregion
+
+        #endregion
+   }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Properties/AssemblyInfo.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Properties/AssemblyInfo.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Properties/AssemblyInfo.cs	(revision 9102)
@@ -0,0 +1,77 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Resources;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("ILNumerics")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("ILNumerics")]
+[assembly: AssemblyProduct("ILNumerics")]
+[assembly: AssemblyCopyright("Copyright Â© ILNumerics 2012")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(true)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("47bbf642-d4b1-4c6a-b25d-436fc6b30282")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("2.14.*")]
+[assembly: AssemblyFileVersion("2.14.0.0")]
+[assembly: NeutralResourcesLanguageAttribute("en-US")]
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Storage/ILCellStorage.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Storage/ILCellStorage.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Storage/ILCellStorage.cs	(revision 9102)
@@ -0,0 +1,1131 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.IO; 
+using System.Runtime.Serialization; 
+using System.Runtime.CompilerServices;
+using ILNumerics.Misc;
+using ILNumerics.Data;
+using ILNumerics.Exceptions;
+using System.Linq.Expressions; 
+
+namespace ILNumerics.Storage {
+
+    /// <summary>
+    /// The class realizes an internal storage wrapper for cell arrays. It takes care of value semantics for reference types. 
+    /// </summary>
+    [Serializable]
+    internal class ILCellStorage : ILDenseStorage<ILStorage> {
+
+        #region attributes
+        bool m_fromImplicitCast = false;
+        #endregion
+
+        #region properties
+        internal bool FromImplicitCast {
+            get { return m_fromImplicitCast; }
+            set { m_fromImplicitCast = value; }
+        }
+        #endregion
+
+        #region Constructors
+        /// <summary>
+        /// create new cell storage
+        /// </summary>
+        /// <param name="system_array">countable array</param>
+        /// <param name="dimensions">dimensions</param>
+        internal ILCellStorage(ILStorage[] system_array, ILSize dimensions) 
+            : base(system_array, dimensions) {
+                DeepReferenceElements(); 
+        }
+        internal ILCellStorage(ILBaseArray[] system_array, ILSize dimensions)
+            : base(baseArray2Storages(system_array, dimensions.NumberOfElements), dimensions) {     
+                DeepReferenceElements();
+        }
+        internal ILCellStorage(ILCountableArray<ILStorage> countableArray, ILSize dimensions)
+            : base(countableArray, dimensions) {
+                DeepReferenceElements(); 
+        }
+        internal ILCellStorage(ILSize dimensions) 
+            : base(dimensions) { }
+        #endregion
+
+        #region public interface
+        /// <summary>
+        /// replace array at specified location
+        /// </summary>
+        /// <param name="value">new scalar value for element</param>
+        /// <param name="indices">indices of element to be altered, supports 'deep indexing'</param>
+        internal override void SetValueTyped(ILStorage value, params int[] indices) {
+            //if (Object.ReferenceEquals(value, null) || value.Size.NumberOfElements == 0)
+            //    throw new ILArgumentException("cell removal is not supported for single integer indexing. value specified must not be null");
+            int mydimlen = Size.NumberOfDimensions;
+            if (indices.Length <= mydimlen) {
+                try {
+                    // address this ILCell
+                    ILStorage curVal = base.GetValueTyped(indices);
+                    if (curVal != null)
+                        curVal.Dispose();
+                    
+                } catch (IndexOutOfRangeException) {
+                } catch (ILArgumentException) {
+                    // address outside range -> no need to dispose 
+                } finally {
+                    base.SetValueTyped(value == null ? null: value.Clone(), indices);
+                }
+            } else {
+                if (value != null && value.Size.NumberOfElements > 1)
+                    throw new ILArgumentException("value given must be scalar or null");
+                // address element of an element of this ILCell
+                int[] innerIndices = new int[indices.Length - mydimlen];
+                int i = 1, elIndex = indices[0];
+                for (; i < mydimlen; i++)
+                    elIndex += (Size.SequentialIndexDistance(i) * indices[i]);
+                if (elIndex > Size.NumberOfElements)
+                    throw new ILArgumentException("index out of range");
+                for (int n = 0; i < indices.Length; i++)
+                    innerIndices[n++] = indices[i];
+                ILStorage innerElement = GetArrayForRead()[elIndex];
+                if (object.Equals(innerElement, null))
+                    throw new ILArgumentException("No array found in cell at indices specified. Invalid deep indices given.");
+                if (innerElement is ILCellStorage) {
+                    innerElement.SetValue(value, innerIndices);
+                } else {
+                    if (value != null && value.Size.NumberOfElements != 1)
+                        throw new ILArgumentException("deep cell indexing requires the new value to be a scalar. Given: " 
+                            + value.Size.ToString()); 
+                    innerElement.SetValue(value != null ? value.GetValue(0) : null, innerIndices);
+                }
+                //if (innerElement is ILDenseStorage<ILStorage>) {  // send the _reference_ of value to inner storage (clone will be done at the end)
+                //    (innerElement as ILDenseStorage<ILStorage>).SetValueTyped(value, innerIndices);
+                //} else if (value is ILStorage<double> && innerElement is ILStorage<double>) {
+                //    (innerElement as ILStorage<double>).SetValueTyped((value as ILStorage<double>).GetValueTyped(0), innerIndices);
+                //} else if (value is ILStorage<float> && innerElement is ILStorage<float>) {
+                //    (innerElement as ILStorage<float>).SetValueTyped((value as ILStorage<float>).GetValueTyped(0), innerIndices);
+                //} else if (value is ILStorage<complex> && innerElement is ILStorage<complex>) {
+                //    (innerElement as ILStorage<complex>).SetValueTyped((value as ILStorage<complex>).GetValueTyped(0), innerIndices);
+                //} else if (value is ILStorage<fcomplex> && innerElement is ILStorage<fcomplex>) {
+                //    (innerElement as ILStorage<fcomplex>).SetValueTyped((value as ILStorage<fcomplex>).GetValueTyped(0), innerIndices);
+                //} else if (value is ILStorage<Int32> && innerElement is ILStorage<Int32>) {
+                //    (innerElement as ILStorage<Int32>).SetValueTyped((value as ILStorage<Int32>).GetValueTyped(0), innerIndices);
+                //} else if (value is ILStorage<Int64> && innerElement is ILStorage<Int64>) {
+                //    (innerElement as ILStorage<Int64>).SetValueTyped((value as ILStorage<Int64>).GetValueTyped(0), innerIndices);
+                //} else if (value is ILStorage<byte> && innerElement is ILStorage<byte>) {
+                //    (innerElement as ILStorage<byte>).SetValueTyped((value as ILStorage<byte>).GetValueTyped(0), innerIndices);
+                //} else if (value is ILStorage<string> && innerElement is ILStorage<string>) {
+                //    (innerElement as ILStorage<string>).SetValueTyped((value as ILStorage<string>).GetValueTyped(0), innerIndices);
+                //} else {
+                //    throw new ILArgumentTypeException("right side argument type is not valid in this context. the value must have the same type as the inner array addressed");
+                //}
+            }
+        }
+        /// <summary>
+        /// get element from this cell storage
+        /// </summary>
+        /// <param name="indices">indices of element</param>
+        /// <returns>element </returns>
+        internal override ILStorage GetValueTyped(params int[] indices) {
+            int mydimlen = Size.NumberOfDimensions;
+            if (indices.Length <= mydimlen) {
+                // address this ILCell 
+                ILStorage element = base.GetValueTyped(indices);
+                return (element != null) ? element.Clone() : null; 
+            } else {
+                // address element of an element of this ILCell (deep addressing)
+                int[] innerIndices = new int[indices.Length - mydimlen];
+                int i = 1, elIndex = indices[0];
+                for (; i < mydimlen; i++)
+                    elIndex += (Size.SequentialIndexDistance(i) * indices[i]);
+                for (int n = 0; i < indices.Length; i++)
+                    innerIndices[n++] = indices[i];
+                ILStorage innerElement = base.GetValueTyped(elIndex);
+                if (innerElement == null)
+                    throw new ILArgumentException("Deep indices out of range. The specified element does not exist."); 
+                return innerElement.GetValueAsStorage(innerIndices); 
+            }
+        }
+        internal override ILStorage GetValueAsStorage(params int[] innerIndices) {
+            return GetValueTyped(innerIndices); 
+        }
+        /// <summary>
+        /// test if an element of the cell is an array of the given element type
+        /// </summary>
+        /// <typeparam name="T">the array element type to check the cell element against</typeparam>
+        /// <param name="position">position of the cell element to be tested</param>
+        /// <returns>true if the element found at the given position is an array of the element type <typeparamref name="T"/>, false otherwise</returns>
+        /// <remarks>The method is helpful in order to investigate the contents of a cell array. If you are not sure about the 
+        /// types of elements in the cell, this function can be used to make sure, elements are of the expected type before retrieving them as such.
+        /// <para>In most situations, elements of a cell are stored arrays of a distinct element type. That element type is given to IsTypeOf as 
+        /// typeparameter <typeparamref name="T"/>. That means, in order to find out, if the first cell element stores an array of int (<c>ILArray&lt;int></c>), 
+        /// one may use <c>cell.IsTypeOf&lt;int>(0)</c></para>
+        /// <para>In order to test, if a cell element is of cell type, one can provide the type <c>ILCell</c> as type parameter: 
+        /// <c>cell.IsTypeOf&lt;ILCell>(0)</c>. Note the different semantic when checking for cell elements of type cell. Here we do not test for the 
+        /// element type but for the array type itself, ie. <c>ILCell</c>. The reason of this is: the type of elements of <c>ILCell</c> is 
+        /// an implementation detail and therefore hidden to the user.</para>
+        /// </remarks>
+        /// <example>
+        /// <para>In the following example a ILCell of size 3x2 is created. It stores several array types, among which other cells are stored as elements of the outer cell.</para>
+        /// <code>ILCell cell = ILMath.cell(new ILSize(3, 2) 
+        ///                      , "first element"
+        ///                      , 2.0
+        ///                      , ILMath.cell(Math.PI, 100f)
+        ///                      , ILMath.create&lt;short>(1, 2, 3, 4, 5, 6)
+        ///                      , new double[] {-1.4, -1.5, -1.6});
+        /// </code>
+        /// The cell is now: 
+        /// <code>ILCell [3,2]
+        ///          &lt;String>      first element  &lt;Int16> [2,3,4,5,6] 
+        ///          &lt;Double>          2          ILCell [1,3]           
+        ///          ILCell [2,1]                                    (null)	
+        /// </code>
+        /// We test the element type of every element in the cell: 
+        /// <code>
+        /// Console.Out.WriteLine("cell[0,0] is of type 'string': {0}", cell.IsTypeOf&lt;string>(0));
+        /// Console.Out.WriteLine("cell[0,0] is of type 'double': {0}", cell.IsTypeOf&lt;double>(0));
+        ///                                      
+        /// Console.Out.WriteLine("cell[1,0] is of type 'double': {0}", cell.IsTypeOf&lt;double>(1));
+        /// Console.Out.WriteLine("cell[2,0] is of type 'ILCell': {0}", cell.IsTypeOf&lt;ILCell>(2));
+        ///                                                                         
+        /// Console.Out.WriteLine("cell[0,1] is of type 'short': {0}", cell.IsTypeOf&lt;short>(0, 1));
+        /// Console.Out.WriteLine("cell[1,1] is of type 'ILCell': {0}", cell.IsTypeOf&lt;ILCell>(1, 1));
+        /// Console.Out.WriteLine("cell[2,1] is of type 'double': {0}", cell.IsTypeOf&lt;double>(2, 1));
+        /// </code>
+        /// This gives the following output: 
+        /// <code>
+        /// cell[0,0] is element type 'string': True
+        /// cell[0,0] is element type 'double': False
+        /// cell[1,0] is element type 'double': True
+        /// cell[2,0] is element type 'ILCell': True
+        /// cell[0,1] is element type 'short': True
+        /// cell[1,1] is element type 'ILCell': True
+        /// cell[2,1] is element type 'double': False  // element is null, IsTypeOf&lt;> never gives true
+        /// </code></example>
+        public bool IsTypeOf<T>(params ILBaseArray[] position) {
+            ILCellStorage cellStorage = (ILCellStorage)Subarray(position);
+            try {
+                if (cellStorage.Size.NumberOfElements == 1) {
+                    ILStorage innerStorage = cellStorage.GetValueTyped(0);
+                    try {
+                        if (typeof(T) == typeof(ILCell)) {
+                            return innerStorage is ILCellStorage;
+                        }
+                        return (innerStorage is ILStorage<T>);
+                    } finally {
+                        if (innerStorage != null) {
+                            innerStorage.Dispose();
+                        }
+                    }
+                } else {
+                    throw new ILArgumentException("indices must define a scalar subarray range");
+                }
+            } finally {
+                cellStorage.Dispose();
+            }
+        }
+        /// <summary>
+        /// gives clone of value addressed, supports deep index addressing
+        /// </summary>
+        /// <param name="indices"></param>
+        /// <returns></returns>
+        internal override object GetValue(params int[] indices) {
+            int mydimlen = Size.NumberOfDimensions;
+            if (indices.Length <= mydimlen) {
+                // address this ILCell 
+                ILStorage element = base.GetValueTyped(indices);
+                return (element != null) ? element.Clone() : null;
+            } else {
+                // address element of an element of this ILCell (deep addressing)
+                int[] innerIndices = new int[indices.Length - mydimlen];
+                int i = 1, elIndex = indices[0];
+                for (; i < mydimlen; i++)
+                    elIndex += (Size.SequentialIndexDistance(i) * indices[i]);
+                for (int n = 0; i < indices.Length; i++)
+                    innerIndices[n++] = indices[i];
+                ILStorage innerElement = base.GetValueTyped(elIndex);
+                if (innerElement == null)
+                    throw new ILArgumentException("Deep indices out of range. The specified element does not exist.");
+                return innerElement.GetValue(innerIndices);
+            }
+        }
+        /// <summary>
+        /// get single element from cell storage, predefined element type 
+        /// </summary>
+        /// <typeparam name="T">predefined type</typeparam>
+        /// <param name="indices">location of element to return</param>
+        /// <returns>element</returns>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if the element found is not of the specified type</exception>
+        public T GetValue<T>(params int[] indices) {
+            object obj = GetValue(indices);
+            if (obj is T)
+                return (T)obj;
+            else
+                throw new ILArgumentException("the element at specified position is not of requested type or does not exist"); 
+        }
+
+        
+        /// <summary>
+        /// Alter elements of this storage adressed by sequential indices 
+        /// </summary>
+        /// <param name="indices">array specifying the elements to be altered, sequential indexing</param>
+        /// <param name="values">ILBaseArray of the same type than this array, holding the new values. 
+        /// The number of elements of storage must match the 
+        /// number of elements of indices. The only exception to this rule is if 'values' is a scalar array. The 
+        /// single value of 'values' is than used to set all elements addressed by 'indices'.</param>
+        /// <remarks><para>For empty arrays, scalar or vectors, indices outside the current bounds for 
+        /// this array will expand this array to the size neccessary. 
+        /// For other arrays the sequential indices given must fit inside this arrays dimensions. </para></remarks>
+        public override void SetRange(ILBaseArray<double> indices, ILDenseStorage<ILStorage> values) {
+            //if (object.Equals(indices,null))
+            //    throw new ILArgumentException("indices given must not be null");
+            if (object.Equals(values, null))
+                throw new ILArgumentException("values given must not be null. Use A[ind] = null; if removal was intended.");
+            #region set full shortcut
+            // if (indices is ILFullRange || object.Equals(indices, null)) {
+            if (object.Equals(indices, null))
+            {
+                int pos;
+                ILStorage[] myArray = GetArrayForWrite();
+                if (values.Size.NumberOfElements == 1) {
+                    pos = Size.NumberOfElements;
+                    ILStorage val = values.GetValueTyped(0);
+                    while (pos-- > 0) {
+                        if (myArray[pos] != null)
+                            myArray[pos].Dispose();
+                        myArray[pos] = val;
+                    }
+                } else {
+                    if (values.Size.NumberOfElements != Size.NumberOfElements)
+                        throw new ILArgumentException("number of elements in source must match number of elements in destination array");
+                    pos = 0;
+                    foreach (ILStorage val in values) {
+                        if (myArray[pos] != null)
+                            myArray[pos].Dispose();
+                        myArray[pos++] = val;
+                    }
+                }
+            } else if (indices.Size.NumberOfElements != values.Size.NumberOfElements
+                && values.Size.NumberOfElements != 1)
+                throw new ILArgumentException("number of elements in source must match number of elements in destination array");
+            #endregion
+            if (indices.IsEmpty)
+                return;
+            if (indices.Storage is ILDenseStorage< double>) {
+                
+                double maxIndex, minIndex;
+                ILDenseStorage< double> indStorage = indices.Storage as ILDenseStorage< double>;
+                indStorage.GetLimits(out minIndex, out maxIndex);
+                if (minIndex < 0)
+                    throw new ILArgumentException("sequential indices can not be negative");
+                if ((int)maxIndex >= m_size.NumberOfElements) {
+                    // handle resize
+                    if (m_size.NumberOfDimensions == 2) {
+                        if (m_size.NumberOfElements <= 1) {
+                            // scalar or empty -> expand along 1 
+                            ExpandArray(new int[] { (int)maxIndex + 1, 1 });
+                        } else if (m_size[0] > 1 && m_size[1] == 1) {
+                            ExpandArray(new int[] { (int)maxIndex + 1, 1 });
+                        } else if (m_size[0] == 1 && m_size[1] > 1) {
+                            ExpandArray(new int[] { 1, (int)maxIndex + 1 });
+                        } else
+                            throw new ILArgumentException("resizing array via sequential index access is supported for empty, scalar or vector only");
+                    } else
+                        throw new ILArgumentException("resizing array via sequential index access is supported for empty, scalar or vector only");
+                }
+                ILStorage[] myArray = GetArrayForWrite();
+                
+                double[] indArray = indStorage.GetArrayForRead();
+
+                int len = indices.Size.NumberOfElements;
+                int ind; 
+                if (values.Size.NumberOfElements == 1) {
+                    ILStorage scalarElement = values.GetValueTyped(0);
+                    for (int i = 0; i < len; i++) {
+                        ind = (int)indArray[i];
+                        if (myArray[ind] != null)
+                            myArray[ind].Dispose(); 
+                        myArray[ind] = scalarElement;
+                    }
+                } else {
+                    ILStorage[] valArray = values.GetArrayForRead();
+                    for (int i = 0; i < len; ) {
+                        ind = (int)indArray[i];
+                        if (myArray[ind] != null)
+                            myArray[ind].Dispose();
+                        myArray[(int)indArray[i]] = valArray[i++];
+                    }
+                }
+            } else {
+                throw new ILArgumentException("storage type of given indices is not supported");
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+       
+        /// <summary>
+        /// Alter elements of this storage adressed by sequential indices 
+        /// </summary>
+        /// <param name="indices">array specifying the elements to be altered, sequential indexing</param>
+        /// <param name="values">ILBaseArray of the same type than this array, holding the new values. 
+        /// The number of elements of storage must match the 
+        /// number of elements of indices. The only exception to this rule is if 'values' is a scalar array. The 
+        /// single value of 'values' is than used to set all elements addressed by 'indices'.</param>
+        /// <remarks><para>For empty arrays, scalar or vectors, indices outside the current bounds for 
+        /// this array will expand this array to the size neccessary. 
+        /// For other arrays the sequential indices given must fit inside this arrays dimensions. </para></remarks>
+        public override void SetRange(ILBaseArray<Int64> indices, ILDenseStorage<ILStorage> values) {
+            //if (object.Equals(indices,null))
+            //    throw new ILArgumentException("indices given must not be null");
+            if (object.Equals(values, null))
+                throw new ILArgumentException("values given must not be null. Use A[ind] = null; if removal was intended.");
+            #region set full shortcut
+            // if (indices is ILFullRange || object.Equals(indices, null)) {
+            if (object.Equals(indices, null))
+            {
+                int pos;
+                ILStorage[] myArray = GetArrayForWrite();
+                if (values.Size.NumberOfElements == 1) {
+                    pos = Size.NumberOfElements;
+                    ILStorage val = values.GetValueTyped(0);
+                    while (pos-- > 0) {
+                        if (myArray[pos] != null)
+                            myArray[pos].Dispose();
+                        myArray[pos] = val;
+                    }
+                } else {
+                    if (values.Size.NumberOfElements != Size.NumberOfElements)
+                        throw new ILArgumentException("number of elements in source must match number of elements in destination array");
+                    pos = 0;
+                    foreach (ILStorage val in values) {
+                        if (myArray[pos] != null)
+                            myArray[pos].Dispose();
+                        myArray[pos++] = val;
+                    }
+                }
+            } else if (indices.Size.NumberOfElements != values.Size.NumberOfElements
+                && values.Size.NumberOfElements != 1)
+                throw new ILArgumentException("number of elements in source must match number of elements in destination array");
+            #endregion
+            if (indices.IsEmpty)
+                return;
+            if (indices.Storage is ILDenseStorage< Int64>) {
+               
+                Int64 maxIndex, minIndex;
+                ILDenseStorage< Int64> indStorage = indices.Storage as ILDenseStorage< Int64>;
+                indStorage.GetLimits(out minIndex, out maxIndex);
+                if (minIndex < 0)
+                    throw new ILArgumentException("sequential indices can not be negative");
+                if ((int)maxIndex >= m_size.NumberOfElements) {
+                    // handle resize
+                    if (m_size.NumberOfDimensions == 2) {
+                        if (m_size.NumberOfElements <= 1) {
+                            // scalar or empty -> expand along 1 
+                            ExpandArray(new int[] { (int)maxIndex + 1, 1 });
+                        } else if (m_size[0] > 1 && m_size[1] == 1) {
+                            ExpandArray(new int[] { (int)maxIndex + 1, 1 });
+                        } else if (m_size[0] == 1 && m_size[1] > 1) {
+                            ExpandArray(new int[] { 1, (int)maxIndex + 1 });
+                        } else
+                            throw new ILArgumentException("resizing array via sequential index access is supported for empty, scalar or vector only");
+                    } else
+                        throw new ILArgumentException("resizing array via sequential index access is supported for empty, scalar or vector only");
+                }
+                ILStorage[] myArray = GetArrayForWrite();
+               
+                Int64[] indArray = indStorage.GetArrayForRead();
+
+                int len = indices.Size.NumberOfElements;
+                int ind; 
+                if (values.Size.NumberOfElements == 1) {
+                    ILStorage scalarElement = values.GetValueTyped(0);
+                    for (int i = 0; i < len; i++) {
+                        ind = (int)indArray[i];
+                        if (myArray[ind] != null)
+                            myArray[ind].Dispose(); 
+                        myArray[ind] = scalarElement;
+                    }
+                } else {
+                    ILStorage[] valArray = values.GetArrayForRead();
+                    for (int i = 0; i < len; ) {
+                        ind = (int)indArray[i];
+                        if (myArray[ind] != null)
+                            myArray[ind].Dispose();
+                        myArray[(int)indArray[i]] = valArray[i++];
+                    }
+                }
+            } else {
+                throw new ILArgumentException("storage type of given indices is not supported");
+            }
+        }
+       
+        /// <summary>
+        /// Alter elements of this storage adressed by sequential indices 
+        /// </summary>
+        /// <param name="indices">array specifying the elements to be altered, sequential indexing</param>
+        /// <param name="values">ILBaseArray of the same type than this array, holding the new values. 
+        /// The number of elements of storage must match the 
+        /// number of elements of indices. The only exception to this rule is if 'values' is a scalar array. The 
+        /// single value of 'values' is than used to set all elements addressed by 'indices'.</param>
+        /// <remarks><para>For empty arrays, scalar or vectors, indices outside the current bounds for 
+        /// this array will expand this array to the size neccessary. 
+        /// For other arrays the sequential indices given must fit inside this arrays dimensions. </para></remarks>
+        public override void SetRange(ILBaseArray<Int32> indices, ILDenseStorage<ILStorage> values) {
+            //if (object.Equals(indices,null))
+            //    throw new ILArgumentException("indices given must not be null");
+            if (object.Equals(values, null))
+                throw new ILArgumentException("values given must not be null. Use A[ind] = null; if removal was intended.");
+            #region set full shortcut
+            // if (indices is ILFullRange || object.Equals(indices, null)) {
+            if (object.Equals(indices, null))
+            {
+                int pos;
+                ILStorage[] myArray = GetArrayForWrite();
+                if (values.Size.NumberOfElements == 1) {
+                    pos = Size.NumberOfElements;
+                    ILStorage val = values.GetValueTyped(0);
+                    while (pos-- > 0) {
+                        if (myArray[pos] != null)
+                            myArray[pos].Dispose();
+                        myArray[pos] = val;
+                    }
+                } else {
+                    if (values.Size.NumberOfElements != Size.NumberOfElements)
+                        throw new ILArgumentException("number of elements in source must match number of elements in destination array");
+                    pos = 0;
+                    foreach (ILStorage val in values) {
+                        if (myArray[pos] != null)
+                            myArray[pos].Dispose();
+                        myArray[pos++] = val;
+                    }
+                }
+            } else if (indices.Size.NumberOfElements != values.Size.NumberOfElements
+                && values.Size.NumberOfElements != 1)
+                throw new ILArgumentException("number of elements in source must match number of elements in destination array");
+            #endregion
+            if (indices.IsEmpty)
+                return;
+            if (indices.Storage is ILDenseStorage< Int32>) {
+               
+                Int32 maxIndex, minIndex;
+                ILDenseStorage< Int32> indStorage = indices.Storage as ILDenseStorage< Int32>;
+                indStorage.GetLimits(out minIndex, out maxIndex);
+                if (minIndex < 0)
+                    throw new ILArgumentException("sequential indices can not be negative");
+                if ((int)maxIndex >= m_size.NumberOfElements) {
+                    // handle resize
+                    if (m_size.NumberOfDimensions == 2) {
+                        if (m_size.NumberOfElements <= 1) {
+                            // scalar or empty -> expand along 1 
+                            ExpandArray(new int[] { (int)maxIndex + 1, 1 });
+                        } else if (m_size[0] > 1 && m_size[1] == 1) {
+                            ExpandArray(new int[] { (int)maxIndex + 1, 1 });
+                        } else if (m_size[0] == 1 && m_size[1] > 1) {
+                            ExpandArray(new int[] { 1, (int)maxIndex + 1 });
+                        } else
+                            throw new ILArgumentException("resizing array via sequential index access is supported for empty, scalar or vector only");
+                    } else
+                        throw new ILArgumentException("resizing array via sequential index access is supported for empty, scalar or vector only");
+                }
+                ILStorage[] myArray = GetArrayForWrite();
+               
+                Int32[] indArray = indStorage.GetArrayForRead();
+
+                int len = indices.Size.NumberOfElements;
+                int ind; 
+                if (values.Size.NumberOfElements == 1) {
+                    ILStorage scalarElement = values.GetValueTyped(0);
+                    for (int i = 0; i < len; i++) {
+                        ind = (int)indArray[i];
+                        if (myArray[ind] != null)
+                            myArray[ind].Dispose(); 
+                        myArray[ind] = scalarElement;
+                    }
+                } else {
+                    ILStorage[] valArray = values.GetArrayForRead();
+                    for (int i = 0; i < len; ) {
+                        ind = (int)indArray[i];
+                        if (myArray[ind] != null)
+                            myArray[ind].Dispose();
+                        myArray[(int)indArray[i]] = valArray[i++];
+                    }
+                }
+            } else {
+                throw new ILArgumentException("storage type of given indices is not supported");
+            }
+        }
+       
+        /// <summary>
+        /// Alter elements of this storage adressed by sequential indices 
+        /// </summary>
+        /// <param name="indices">array specifying the elements to be altered, sequential indexing</param>
+        /// <param name="values">ILBaseArray of the same type than this array, holding the new values. 
+        /// The number of elements of storage must match the 
+        /// number of elements of indices. The only exception to this rule is if 'values' is a scalar array. The 
+        /// single value of 'values' is than used to set all elements addressed by 'indices'.</param>
+        /// <remarks><para>For empty arrays, scalar or vectors, indices outside the current bounds for 
+        /// this array will expand this array to the size neccessary. 
+        /// For other arrays the sequential indices given must fit inside this arrays dimensions. </para></remarks>
+        public override void SetRange(ILBaseArray<Int16> indices, ILDenseStorage<ILStorage> values) {
+            //if (object.Equals(indices,null))
+            //    throw new ILArgumentException("indices given must not be null");
+            if (object.Equals(values, null))
+                throw new ILArgumentException("values given must not be null. Use A[ind] = null; if removal was intended.");
+            #region set full shortcut
+            // if (indices is ILFullRange || object.Equals(indices, null)) {
+            if (object.Equals(indices, null))
+            {
+                int pos;
+                ILStorage[] myArray = GetArrayForWrite();
+                if (values.Size.NumberOfElements == 1) {
+                    pos = Size.NumberOfElements;
+                    ILStorage val = values.GetValueTyped(0);
+                    while (pos-- > 0) {
+                        if (myArray[pos] != null)
+                            myArray[pos].Dispose();
+                        myArray[pos] = val;
+                    }
+                } else {
+                    if (values.Size.NumberOfElements != Size.NumberOfElements)
+                        throw new ILArgumentException("number of elements in source must match number of elements in destination array");
+                    pos = 0;
+                    foreach (ILStorage val in values) {
+                        if (myArray[pos] != null)
+                            myArray[pos].Dispose();
+                        myArray[pos++] = val;
+                    }
+                }
+            } else if (indices.Size.NumberOfElements != values.Size.NumberOfElements
+                && values.Size.NumberOfElements != 1)
+                throw new ILArgumentException("number of elements in source must match number of elements in destination array");
+            #endregion
+            if (indices.IsEmpty)
+                return;
+            if (indices.Storage is ILDenseStorage< Int16>) {
+               
+                Int16 maxIndex, minIndex;
+                ILDenseStorage< Int16> indStorage = indices.Storage as ILDenseStorage< Int16>;
+                indStorage.GetLimits(out minIndex, out maxIndex);
+                if (minIndex < 0)
+                    throw new ILArgumentException("sequential indices can not be negative");
+                if ((int)maxIndex >= m_size.NumberOfElements) {
+                    // handle resize
+                    if (m_size.NumberOfDimensions == 2) {
+                        if (m_size.NumberOfElements <= 1) {
+                            // scalar or empty -> expand along 1 
+                            ExpandArray(new int[] { (int)maxIndex + 1, 1 });
+                        } else if (m_size[0] > 1 && m_size[1] == 1) {
+                            ExpandArray(new int[] { (int)maxIndex + 1, 1 });
+                        } else if (m_size[0] == 1 && m_size[1] > 1) {
+                            ExpandArray(new int[] { 1, (int)maxIndex + 1 });
+                        } else
+                            throw new ILArgumentException("resizing array via sequential index access is supported for empty, scalar or vector only");
+                    } else
+                        throw new ILArgumentException("resizing array via sequential index access is supported for empty, scalar or vector only");
+                }
+                ILStorage[] myArray = GetArrayForWrite();
+               
+                Int16[] indArray = indStorage.GetArrayForRead();
+
+                int len = indices.Size.NumberOfElements;
+                int ind; 
+                if (values.Size.NumberOfElements == 1) {
+                    ILStorage scalarElement = values.GetValueTyped(0);
+                    for (int i = 0; i < len; i++) {
+                        ind = (int)indArray[i];
+                        if (myArray[ind] != null)
+                            myArray[ind].Dispose(); 
+                        myArray[ind] = scalarElement;
+                    }
+                } else {
+                    ILStorage[] valArray = values.GetArrayForRead();
+                    for (int i = 0; i < len; ) {
+                        ind = (int)indArray[i];
+                        if (myArray[ind] != null)
+                            myArray[ind].Dispose();
+                        myArray[(int)indArray[i]] = valArray[i++];
+                    }
+                }
+            } else {
+                throw new ILArgumentException("storage type of given indices is not supported");
+            }
+        }
+       
+        /// <summary>
+        /// Alter elements of this storage adressed by sequential indices 
+        /// </summary>
+        /// <param name="indices">array specifying the elements to be altered, sequential indexing</param>
+        /// <param name="values">ILBaseArray of the same type than this array, holding the new values. 
+        /// The number of elements of storage must match the 
+        /// number of elements of indices. The only exception to this rule is if 'values' is a scalar array. The 
+        /// single value of 'values' is than used to set all elements addressed by 'indices'.</param>
+        /// <remarks><para>For empty arrays, scalar or vectors, indices outside the current bounds for 
+        /// this array will expand this array to the size neccessary. 
+        /// For other arrays the sequential indices given must fit inside this arrays dimensions. </para></remarks>
+        public override void SetRange(ILBaseArray<float> indices, ILDenseStorage<ILStorage> values) {
+            //if (object.Equals(indices,null))
+            //    throw new ILArgumentException("indices given must not be null");
+            if (object.Equals(values, null))
+                throw new ILArgumentException("values given must not be null. Use A[ind] = null; if removal was intended.");
+            #region set full shortcut
+            // if (indices is ILFullRange || object.Equals(indices, null)) {
+            if (object.Equals(indices, null))
+            {
+                int pos;
+                ILStorage[] myArray = GetArrayForWrite();
+                if (values.Size.NumberOfElements == 1) {
+                    pos = Size.NumberOfElements;
+                    ILStorage val = values.GetValueTyped(0);
+                    while (pos-- > 0) {
+                        if (myArray[pos] != null)
+                            myArray[pos].Dispose();
+                        myArray[pos] = val;
+                    }
+                } else {
+                    if (values.Size.NumberOfElements != Size.NumberOfElements)
+                        throw new ILArgumentException("number of elements in source must match number of elements in destination array");
+                    pos = 0;
+                    foreach (ILStorage val in values) {
+                        if (myArray[pos] != null)
+                            myArray[pos].Dispose();
+                        myArray[pos++] = val;
+                    }
+                }
+            } else if (indices.Size.NumberOfElements != values.Size.NumberOfElements
+                && values.Size.NumberOfElements != 1)
+                throw new ILArgumentException("number of elements in source must match number of elements in destination array");
+            #endregion
+            if (indices.IsEmpty)
+                return;
+            if (indices.Storage is ILDenseStorage< float>) {
+               
+                float maxIndex, minIndex;
+                ILDenseStorage< float> indStorage = indices.Storage as ILDenseStorage< float>;
+                indStorage.GetLimits(out minIndex, out maxIndex);
+                if (minIndex < 0)
+                    throw new ILArgumentException("sequential indices can not be negative");
+                if ((int)maxIndex >= m_size.NumberOfElements) {
+                    // handle resize
+                    if (m_size.NumberOfDimensions == 2) {
+                        if (m_size.NumberOfElements <= 1) {
+                            // scalar or empty -> expand along 1 
+                            ExpandArray(new int[] { (int)maxIndex + 1, 1 });
+                        } else if (m_size[0] > 1 && m_size[1] == 1) {
+                            ExpandArray(new int[] { (int)maxIndex + 1, 1 });
+                        } else if (m_size[0] == 1 && m_size[1] > 1) {
+                            ExpandArray(new int[] { 1, (int)maxIndex + 1 });
+                        } else
+                            throw new ILArgumentException("resizing array via sequential index access is supported for empty, scalar or vector only");
+                    } else
+                        throw new ILArgumentException("resizing array via sequential index access is supported for empty, scalar or vector only");
+                }
+                ILStorage[] myArray = GetArrayForWrite();
+               
+                float[] indArray = indStorage.GetArrayForRead();
+
+                int len = indices.Size.NumberOfElements;
+                int ind; 
+                if (values.Size.NumberOfElements == 1) {
+                    ILStorage scalarElement = values.GetValueTyped(0);
+                    for (int i = 0; i < len; i++) {
+                        ind = (int)indArray[i];
+                        if (myArray[ind] != null)
+                            myArray[ind].Dispose(); 
+                        myArray[ind] = scalarElement;
+                    }
+                } else {
+                    ILStorage[] valArray = values.GetArrayForRead();
+                    for (int i = 0; i < len; ) {
+                        ind = (int)indArray[i];
+                        if (myArray[ind] != null)
+                            myArray[ind].Dispose();
+                        myArray[(int)indArray[i]] = valArray[i++];
+                    }
+                }
+            } else {
+                throw new ILArgumentException("storage type of given indices is not supported");
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+        internal override void SetRangeFull(ILDenseStorage<ILStorage> values) {
+            if (values.Size.NumberOfElements != 1 && values.Size.NumberOfElements != Size.NumberOfElements)
+                throw new ILArgumentException("source and destination array must have the same number of arguments");
+            ILStorage[] myArr = GetArrayForWrite();
+            if (values.Size.NumberOfElements == 1) {
+                ILStorage scal = values.GetValueTyped(0);
+                for (int i = Size.NumberOfElements; i-- > 0; ) {
+                    if (myArr[i] != null)
+                        myArr[i].Dispose();
+                    myArr[i] = scal;
+                }
+            } else {
+                ILStorage[] valArr = values.GetArrayForRead();
+                for (int i = Size.NumberOfElements; i-- > 0; ) {
+                    if (myArr[i] != null)
+                        myArr[i].Dispose();
+                    myArr[i] = valArr[i];
+                }
+            }
+        }
+        public override void SetRange(ILRange range, ILDenseStorage<ILStorage> values) {
+            if (range.Size.NumberOfElements == 0) return;
+            int rangeDimLen = range.RangeArray.Length, higherDimSum = 0;
+            int leadDimLenRange = range[0].Count, leadDimLen = m_size[0];
+            int d, outElemCount = range.Size.NumberOfElements;
+            ILStorage[] myArr = GetArrayForWrite();
+            int[] idxArr = new int[rangeDimLen];    // used to store current position inside higher dims 
+            ILIntList[] rng = range.RangeArray;
+            int[] seqDistances = m_size.GetSequentialIndexDistances(range.Size.NumberOfDimensions);
+            int[] inFullDim = new int[rangeDimLen];
+            // initialize higher dimension summand and inFullDim[] flag array
+            for (int i = 1; i < idxArr.Length; i++) {
+                if (rng[i][0] < 0) {
+                    inFullDim[i] = rng[i][0];
+                } else {
+                    inFullDim[i] = 0;
+                    higherDimSum += seqDistances[i] * rng[i][0];
+                }
+            }
+            //for (int lIdx = 0; lIdx < leadDimLenRange; lIdx ++) { 
+            //    retArr[curPosOut++] = myArr[higherDimSum + rleadDim[lIdx]]; 
+            //}
+            if (values.Size.NumberOfElements == 1) {
+                #region scalar case
+                ILStorage scalar = values.GetValueTyped(0);
+                while (true) {
+                    #region copy along leading dimension
+                    for (int i = 0; i < rng[0].Count; i++) {
+                        if (rng[0][i] < 0) {
+                            for (int c = -rng[0][i]; c-- >= 0; ) {
+                                ILStorage cur = myArr[higherDimSum];
+                                if (cur != null)
+                                    cur.Dispose(); 
+                                myArr[higherDimSum] = scalar.Clone();
+                                higherDimSum++;
+                            }
+                            higherDimSum += (rng[0][i] - 1); // negative value in rng!  
+                        } else {
+                            int ind = higherDimSum + rng[0][i]; 
+                            ILStorage cur = myArr[ind];
+                            if (cur != null)
+                                cur.Dispose();
+                            myArr[ind] = scalar.Clone();      
+                        }
+                    }
+                    #endregion
+                    #region increase higher dims
+                    d = 1; 
+                    while (d < idxArr.Length) {
+                        if (inFullDim[d] < 0) {
+                            higherDimSum += seqDistances[d];
+                            inFullDim[d]++;
+                            break;
+                        }
+
+                        if (rng[d][idxArr[d]] >= 0) {
+                            higherDimSum -= (rng[d][idxArr[d]] * seqDistances[d]);
+                        } else {
+                            higherDimSum += (rng[d][idxArr[d]] * seqDistances[d]);
+                        }
+                        idxArr[d]++;
+                        if (idxArr[d] == rng[d].Count) {
+                            idxArr[d] = 0;
+                            if (rng[d][idxArr[d]] < 0) {
+                                inFullDim[d] = rng[d][idxArr[d]];
+                            }
+                            d++;
+                        } else if (rng[d][idxArr[d]] < 0) {
+                            inFullDim[d] = rng[d][idxArr[d]];
+                            break;
+                        } else {
+                            higherDimSum += seqDistances[d] * rng[d][idxArr[d]];
+                            break;
+                        }
+
+                    }
+                    #endregion
+                    if (d >= idxArr.Length)
+                        break;
+                }
+                scalar.Dispose();  // we have only made copies of scalar input
+                #endregion
+            } else {
+                #region non scalar case
+                ILStorage[] valuesArr = values.GetArrayForRead();
+                int valuesPos = 0;
+                while (true) {
+                    // copy along leading dimension
+                    for (int i = 0; i < rng[0].Count; i++) {
+                        if (rng[0][i] < 0) {
+                            for (int c = -rng[0][i]; c-- >= 0; ) {
+                                ILStorage cur = myArr[higherDimSum];
+                                if (cur != null)
+                                    cur.Dispose();
+                                myArr[higherDimSum] = valuesArr[valuesPos];
+                                valuesPos++;
+                                higherDimSum++;
+                            }
+                            higherDimSum += (rng[0][i] - 1); // negative value in rng!  
+                        } else {
+                            int ind = higherDimSum + rng[0][i];
+                            ILStorage cur = myArr[ind];
+                            if (cur != null)
+                                cur.Dispose();
+                            myArr[ind] = valuesArr[valuesPos];
+                            valuesPos++;
+                        }
+                    }
+
+                    // increase higher dims 
+                    d = 1;
+                    while (d < idxArr.Length) {
+                        if (inFullDim[d] < 0) {
+                            higherDimSum += seqDistances[d];
+                            inFullDim[d]++;
+                            break;
+                        }
+
+                        if (rng[d][idxArr[d]] >= 0) {
+                            higherDimSum -= (rng[d][idxArr[d]] * seqDistances[d]);
+                        } else {
+                            higherDimSum += (rng[d][idxArr[d]] * seqDistances[d]);
+                        }
+                        idxArr[d]++;
+                        if (idxArr[d] == rng[d].Count) {
+                            idxArr[d] = 0;
+                            if (rng[d][idxArr[d]] < 0) {
+                                inFullDim[d] = rng[d][idxArr[d]];
+                            }
+                            d++;
+                        } else if (rng[d][idxArr[d]] < 0) {
+                            inFullDim[d] = rng[d][idxArr[d]];
+                            break;
+                        } else {
+                            higherDimSum += seqDistances[d] * rng[d][idxArr[d]];
+                            break;
+                        }
+
+                    }
+                    if (d >= idxArr.Length)
+                        break;
+                }
+                #endregion
+            }
+        }
+        /// <summary>
+        /// detach this storage: copy its countable array if needed
+        /// </summary>
+        protected override void Detach() {
+            if (m_data.ReferenceCount <= 1)
+                return;
+            Data = m_data.CreateCopy();
+        }
+        /// <summary>
+        /// walk all elements of this cell and recursively replace them with clones of themself 
+        /// </summary>
+        /// <remarks>Due to the cloning mechanism of ILNumerics, the full clone 
+        /// will be cheap by using lazy copies of the data. Cloned elements will automatically be detached on write access.</remarks>
+        internal void DeepReferenceElements() {
+            int len = Size.NumberOfElements;
+            ILStorage[] myArr = GetArrayForWrite();
+            for (int i = 0; i < len; i++) {
+                ILStorage a = myArr[i];
+                if (!Object.ReferenceEquals(a, null) && !a.IsDisposed) {
+                    ILStorage clone = a.Clone(); 
+                    myArr[i] =clone;
+                } else
+                    myArr[i] = null;
+            }
+        }
+        internal ILDenseStorage<T> GetDenseStorage<T>(params ILBaseArray[] indices) {
+            ILCellStorage retStorage = (ILCellStorage)Subarray(indices);
+            if (retStorage.Size.NumberOfElements == 1) {
+                ILStorage innerStorage = (retStorage as ILCellStorage).GetValueTyped(0);
+                if (innerStorage is ILDenseStorage<T>) {
+                    return innerStorage as ILDenseStorage<T>; 
+                } else {
+                    if (innerStorage == null) {
+                        throw new ILArgumentException("the type of the element at the specified position could not be determined"); 
+                    }
+                    Type innerStorageType = innerStorage.GetType();
+                    if (innerStorageType == typeof(ILCellStorage)) 
+                        throw new ILArgumentException("The cell element specified contains a cell storage. Use GetCell() in order to retrieve cells from cells!");
+                    if (!innerStorageType.Name.Contains("ILDenseStorage")) // unlikely to happen in ILNumerics R2
+                        throw new ILArgumentException("the type of the element at the specified position is not valid in this context"); 
+                    Type[] arguments =  innerStorageType.GetGenericArguments(); 
+                    if (arguments.Length > 0) 
+                        throw new ILArgumentException(String.Format("the array found at the specified location is of type <{0}> and not of the requested type <{1}>",arguments[0].Name, typeof(T).Name));  
+                    throw new ILArgumentException("an unknown error occoured while trying to retrieve the cell element"); 
+                }
+            } else {
+                throw new ILArgumentException("indices must define a scalar subarray range to an existing cell element");
+            }
+        }
+        internal ILBaseArray GetScalar(params ILBaseArray[] indices) {
+            ILCellStorage cellStorage = (ILCellStorage)Subarray(indices);
+            if (cellStorage.Size.NumberOfElements == 1) {
+                ILStorage innerStorage = cellStorage.GetValueTyped(0);
+                return (innerStorage == null) ? null : innerStorage.GetAsBaseArray(); 
+            } else {
+                throw new ILArgumentException("indices must define a scalar subarray range");
+            }
+
+        }
+        internal override ILBaseArray GetAsBaseArray() {
+            return new ILRetCell((ILCellStorage)Clone());
+        }
+        internal override void Dispose(bool manual) {
+            if (IsDisposed) return; 
+            
+            for (int i = m_size.NumberOfElements; i--> 0;) {
+                ILStorage storage = m_data.Data[i]; 
+                if(storage != null)
+                    storage.Dispose(manual); 
+            }
+            base.Dispose(manual);
+        }
+        internal override bool Equals(object obj) {
+            if (object.Equals(obj, null)) return false;
+            ILCellStorage obStor = obj as ILCellStorage;
+            if (obStor != null) {
+                if (!obStor.Size.IsSameSize(Size)) return false;
+                ILStorage[] myArr = GetArrayForRead();
+                ILStorage[] objArr = obStor.GetArrayForRead();
+
+                for (int i = Size.NumberOfElements; i --> 0; ) {
+                    ILStorage stor1 = myArr[i];
+                    ILStorage stor2 = objArr[i];
+                    if (stor1 == null ^ stor2 == null) return false;
+                    if (stor1 == null) continue;
+                    if (!myArr[i].Equals(objArr[i])) return false;
+                }
+                return true;
+            } else {
+                return false; 
+            }
+        }
+        #endregion
+
+        #region helper 
+        private static ILStorage[] baseArray2Storages(ILBaseArray[] system_array, int minLength) {
+            using (ILScope.Enter(system_array)) {
+                ILStorage[] ret = ILMemoryPool.Pool.New<ILStorage>(minLength);
+                int i = 0;
+                for (; i < system_array.Length; i++) {
+                    ILBaseArray curArr = system_array[i];
+                    if (curArr == null) {
+                        ret[i] = null;
+                    } else {
+                        ILStorage cur = system_array[i].Storage;
+                        ret[i] = cur; 
+                    }
+                }
+                // clear the rest of the array
+                for (; i < minLength; i++)
+                    ret[i] = null; 
+                return ret; 
+            }
+        }
+        protected override ILDenseStorage<ILStorage> CreateSelf(ILStorage[] data, ILSize size) {
+            ILCellStorage ret = new ILCellStorage(data, size);
+            //ret.DeepReferenceElements();
+            return ret; 
+        }
+        protected override ILDenseStorage<ILStorage> CreateSelf(ILSize size) {
+            ILCellStorage ret = new ILCellStorage(size);
+            //ret.DeepReferenceElements();
+            return ret; 
+        }
+        protected override ILDenseStorage<ILStorage> CreateSelf(ILCountableArray<ILStorage> Data, ILSize ILSize) {
+            ILCellStorage ret = new ILCellStorage(Data, ILSize);
+            //ret.DeepReferenceElements();
+            return ret; 
+        }
+        internal override string ShortInfo() {
+            if (IsDisposed)
+                return "Cell (disposed)";
+            return "Cell " + Size.ToString();
+        }
+        //internal override void Remove(int dimension, ILIntList indices) {
+        //    using (ILScope.Enter()) {
+        //        if (dimension >= Dimensions.NumberOfDimensions)
+        //            throw new ILArgumentException("index out of range");
+        //        if (dimension == -1) {
+        //            Data = new ILCountableArray<ILStorage>(0);
+        //            m_dimensions = ILSize.Empty00;
+        //            return;
+        //        }
+        //        // TODO: may should be replaced with a faster (&fancier? ) version... ??
+        //        ILBaseArray[] dims = new ILBaseArray[Dimensions.NumberOfDimensions];
+        //        ILIntList keepInd = ILIntList.Create();
+        //        ILIntList remvInd = indices;
+        //        int max = Dimensions[dimension];
+        //        foreach (int i in indices)
+        //            if (i >= max || i < 0) throw new ILArgumentException("removal index out of range");
+        //        for (int i = 0; i < max; i++) {
+        //            if (!remvInd.Contains(i)) {
+        //                keepInd.Add(i);
+        //            }
+        //        }
+        //        // we give the indices to _keep_ to the subarray function
+        //        ILArray<int> remIndices = ILMath.create<int>(keepInd.GetArray(), new ILSize(1, keepInd.Count));
+        //        if (remIndices.Dimensions.NumberOfElements == Dimensions[dimension]) {
+        //            // nothing to do
+        //            return;
+        //        }
+        //        for (int i = 0; i < dims.Length; i++) {
+        //            dims[i] = ILMath.full;
+        //        }
+        //        dims[dimension] = remIndices;
+        //        ILCellStorage ret = (ILCellStorage)Subarray(dims);
+        //        //ret.DeepReferenceElements(); 
+                
+        //        Dispose();
+        //        Data = ret.Data;
+        //        m_dimensions = ret.Dimensions;
+        //    }
+        //}
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Storage/ILCountableArray.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Storage/ILCountableArray.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Storage/ILCountableArray.cs	(revision 9102)
@@ -0,0 +1,157 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Threading; 
+using System.Linq;
+using System.Text;
+
+namespace ILNumerics.Storage {
+    [Serializable]
+    internal sealed class ILCountableArray<ElementType> {
+    
+        private ElementType[] m_data; 
+        private int m_length; 
+        private int m_referenceCount;
+
+        #region properties
+        /// <summary>
+        /// Access to the internal system array
+        /// </summary>
+        internal ElementType[] Data  { get { return m_data; } } 
+        /// <summary>
+        /// minimal length of the system array to be used for computations
+        /// </summary>
+        internal int Length  { get { return m_length; } } 
+	    #endregion
+
+        /// <summary>
+        /// create new countable array by size
+        /// </summary>
+        /// <param name="length"></param>
+        /// <remarks>The memory for the newly created array is requested from memory pool. All elements of the array 
+        /// are initialized with default(ElementType).</remarks>
+        internal ILCountableArray(int length) {
+            bool dummy; 
+            m_data = ILMemoryPool.Pool.New<ElementType>(length, false, out dummy);
+            m_length = length; 
+            // reference counting is matter of the hosting object!
+            m_referenceCount = 0;
+        }
+        /// <summary>
+        /// create new countable array by size
+        /// </summary>
+        /// <param name="length"></param>
+        /// <remarks>The memory for the newly created array is requested from memory pool. Depending on the value of 
+        /// 'clear', the elements of the array are NOT initialized and therefore may contain garbage data!.</remarks>
+        internal ILCountableArray(int length, bool clear) {
+            bool dummy;
+            m_data = ILMemoryPool.Pool.New<ElementType>(length, clear, out dummy);
+            m_length = length; 
+            // reference counting is matter of the hosting object!
+            m_referenceCount = 0;
+        }
+
+        /// <summary>
+        /// create new countable array, provide system array
+        /// </summary>
+        /// <param name="data">system array to be used as storage array directly</param>
+        /// <param name="length">minimum lenght of array needed</param>
+        internal ILCountableArray(ElementType[] data, int length) {
+#if VERBOSE
+            //DebuggerTraceHelper.Output.Append(
+            //    String.Format("CountableArray (T[]{0}) " + GetHashCode(),data.GetHashCode())
+            //); 
+#endif
+            m_data = data; 
+            m_length = length; 
+            // reference counting is matter of the hosting object!
+            m_referenceCount = 0; 
+        }
+        /// <summary>
+        /// increase reference counter 
+        /// </summary>
+        internal void IncreaseReference() {
+            Interlocked.Increment(ref m_referenceCount); 
+        }
+        /// <summary>
+        /// decrease reference counter
+        /// </summary>
+        internal void DecreaseReference() {
+            Interlocked.Decrement(ref m_referenceCount); 
+            if (m_referenceCount == 0) {
+                Dispose();
+            }
+        }
+        /// <summary>
+        /// Dispose off this array: register it in pool
+        /// </summary>
+        internal void Dispose() {
+#if VERBOSE
+            //System.Diagnostics.Debug.Assert(m_referenceCount == 0); 
+            //DebuggerTraceHelper.Output.Append(String.Format("\r\nCountableArray HashCode: " + GetHashCode())); 
+#endif
+            if (m_data != null) {
+                ILMemoryPool.Pool.Free(m_data);
+                m_data = null;
+                m_length = 0;
+            }
+        }
+        /// <summary>
+        /// number of storages referencing to this array
+        /// </summary>
+        /// <remarks>In order to in-/decrease the reference counter, use 
+        /// the <see cref="ILNumerics.Storage.ILCountableArray&lt;ElementType>.IncreaseReference()"/>
+        /// and <see cref="ILNumerics.Storage.ILCountableArray&lt;ElementType>.DecreaseReference()"/> functions.</remarks>
+        internal int ReferenceCount { 
+            get { return m_referenceCount; }
+        
+        }
+        /// <summary>
+        /// return (solid) copy of this countable array
+        /// </summary>
+        /// <returns>newly created array</returns>
+        internal ILCountableArray<ElementType> CreateCopy() {
+            ILCountableArray<ElementType> ret = new ILCountableArray<ElementType>(Length, false);
+            System.Array.Copy(m_data,ret.Data,Length); 
+            return ret; 
+        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Storage/ILDenseStorage.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Storage/ILDenseStorage.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Storage/ILDenseStorage.cs	(revision 9102)
@@ -0,0 +1,2868 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.IO; 
+using System.Runtime.Serialization; 
+using System.Runtime.CompilerServices;
+using System.Numerics; 
+using ILNumerics.Misc;
+using ILNumerics.Data;
+using ILNumerics.Exceptions;
+using System.Linq.Expressions; 
+
+namespace ILNumerics.Storage {
+
+    /// <summary>
+    /// The class realizes an internal storage wrapper. It stores the internal data array
+    /// and the dimension specifications for both: ILRetArray and ILDenseStorage (reference and solid). 
+    /// </summary>
+    [System.Diagnostics.DebuggerTypeProxy(typeof(ILNumerics.Misc.ILArrayDebuggerProxy<>))]
+    [System.Diagnostics.DebuggerDisplay("{ShortInfo(),nq}")]
+    [Serializable]
+    internal partial class ILDenseStorage<ElementType> : ILStorage<ElementType> {
+
+        #region attributes
+        /// <summary> 
+        /// Internal storage object. Contains the final System.Array storage and a reference counter.
+        /// </summary>
+        [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)] 
+        protected ILCountableArray<ElementType> m_data;
+        #endregion
+
+        #region properties 
+
+        /// <summary>
+        /// number of storages referencing the current data array
+        /// </summary>
+        internal int ReferenceCount {
+            get {
+                return m_data.ReferenceCount; 
+            }
+        }
+
+        /// <summary>
+        /// Determine, if this storage has already been disposed.
+        /// </summary>
+        internal override bool IsDisposed {
+            get {
+                return m_data == null; 
+            } 
+        }
+        protected ILCountableArray<ElementType> Data {
+            get { 
+                return m_data; 
+            }
+            set {
+                ILCountableArray<ElementType> old = m_data;
+                m_data = value; 
+                m_data.IncreaseReference(); 
+                if (old != null) 
+                    old.DecreaseReference(); 
+            }
+        }
+        /// <summary>
+        /// Get minimum and maximum value of all elements - if these exist.
+        /// </summary>
+        /// <param name="minValue">Output: minimum value.</param>
+        /// <param name="maxValue">Output: maximum value.</param>
+        /// <returns>True if the limits exists and could be computed, false otherwise.</returns>
+        /// <remarks>Empty arrays will return false. The output parameter will be default(type).</remarks>
+        internal override bool GetLimits(out ElementType minValue, out ElementType maxValue) { 
+            return GetLimits(out minValue, out maxValue, true); 
+        }
+        /// <summary>
+        /// Get minimum and maximum value of all elements - if existing
+        /// </summary>
+        /// <param name="minValue">Output: minimum value.</param>
+        /// <param name="maxValue">Output: maximum value.</param>
+        /// <param name="includeInfNaNs">true: recognize Inf, NaN values; false: ignore those values</param>
+        /// <returns>True if the limits exists and could be computed, false otherwise.</returns>
+        /// <remarks>Empty arrays will return false. The output parameter will be default(ElementType) then.</remarks>
+        internal override bool GetLimits(out ElementType minValue, out ElementType maxValue, bool includeInfNaNs) {
+            minValue = default(ElementType);   
+            maxValue = default(ElementType);
+            if (m_size.NumberOfElements == 0)
+                return false; 
+            if (false) {
+
+    
+                } else if (this is ILDenseStorage<double> ) {    
+                     double [] data = ( double [])(object) GetArrayForRead(); 
+                     double curVal; 
+                     double curMin =  Double.PositiveInfinity ;
+                     double curMax =  Double.NegativeInfinity ;
+                    int curMinInd = 0; 
+                    int curMaxInd = 0; 
+                    int len = m_size.NumberOfElements; 
+
+                    for (int i = 0; i < len; i++) { 
+                        curVal = data[i]; 
+                        
+                        if (double.IsInfinity(curVal)) continue; 
+                        if (curVal < curMin) { 
+                            curMin = curVal; 
+                            curMinInd = i; 
+                        }
+                        if (curVal > curMax) { 
+                            curMax = curVal; 
+                            curMaxInd = i; 
+                        }
+                    }
+                    maxValue = m_data.Data[curMaxInd];
+                    minValue = m_data.Data[curMinInd]; 
+                    return (curMax >  Double.NegativeInfinity || curMin <  Double.PositiveInfinity ); 
+
+#region HYCALPER AUTO GENERATED CODE
+
+    
+                } else if (this is ILDenseStorage<fcomplex> ) {    
+                    fcomplex [] data = ( fcomplex [])(object) GetArrayForRead(); 
+                    fcomplex curVal; 
+                    fcomplex curMin =  new fcomplex(float.PositiveInfinity,float.PositiveInfinity) ;
+                    fcomplex curMax =  new fcomplex(float.NegativeInfinity,float.NegativeInfinity) ;
+                    int curMinInd = 0; 
+                    int curMaxInd = 0; 
+                    int len = m_size.NumberOfElements; 
+
+                    for (int i = 0; i < len; i++) { 
+                        curVal = data[i]; 
+                        if (fcomplex.IsInfinity(curVal)) continue;
+                        if (curVal < curMin) { 
+                            curMin = curVal; 
+                            curMinInd = i; 
+                        }
+                        if (curVal > curMax) { 
+                            curMax = curVal; 
+                            curMaxInd = i; 
+                        }
+                    }
+                    maxValue = m_data.Data[curMaxInd];
+                    minValue = m_data.Data[curMinInd]; 
+                    return (curMax >  new fcomplex(float.NegativeInfinity,float.NegativeInfinity) || curMin <  new fcomplex(float.NegativeInfinity,float.NegativeInfinity) ); 
+    
+                } else if (this is ILDenseStorage<complex> ) {    
+                    complex [] data = ( complex [])(object) GetArrayForRead(); 
+                    complex curVal; 
+                    complex curMin =  new complex(Double.PositiveInfinity,Double.PositiveInfinity) ;
+                    complex curMax =  new complex(Double.NegativeInfinity,Double.NegativeInfinity) ;
+                    int curMinInd = 0; 
+                    int curMaxInd = 0; 
+                    int len = m_size.NumberOfElements; 
+
+                    for (int i = 0; i < len; i++) { 
+                        curVal = data[i]; 
+                        if (complex.IsInfinity(curVal)) continue;
+                        if (curVal < curMin) { 
+                            curMin = curVal; 
+                            curMinInd = i; 
+                        }
+                        if (curVal > curMax) { 
+                            curMax = curVal; 
+                            curMaxInd = i; 
+                        }
+                    }
+                    maxValue = m_data.Data[curMaxInd];
+                    minValue = m_data.Data[curMinInd]; 
+                    return (curMax >  new complex(Double.NegativeInfinity,Double.NegativeInfinity) || curMin <  new complex(Double.NegativeInfinity,Double.NegativeInfinity) ); 
+    
+                } else if (this is ILDenseStorage<byte> ) {    
+                    byte [] data = ( byte [])(object) GetArrayForRead(); 
+                    byte curVal; 
+                    byte curMin =  Byte.MaxValue ;
+                    byte curMax =  Byte.MinValue ;
+                    int curMinInd = 0; 
+                    int curMaxInd = 0; 
+                    int len = m_size.NumberOfElements; 
+
+                    for (int i = 0; i < len; i++) { 
+                        curVal = data[i]; 
+                        
+                        if (curVal < curMin) { 
+                            curMin = curVal; 
+                            curMinInd = i; 
+                        }
+                        if (curVal > curMax) { 
+                            curMax = curVal; 
+                            curMaxInd = i; 
+                        }
+                    }
+                    maxValue = m_data.Data[curMaxInd];
+                    minValue = m_data.Data[curMinInd]; 
+                    return (curMax >  Byte.MinValue || curMin <  Byte.MinValue ); 
+    
+                } else if (this is ILDenseStorage<Int64> ) {    
+                    Int64 [] data = ( Int64 [])(object) GetArrayForRead(); 
+                    Int64 curVal; 
+                    Int64 curMin =  Int64.MaxValue ;
+                    Int64 curMax =  Int64.MinValue ;
+                    int curMinInd = 0; 
+                    int curMaxInd = 0; 
+                    int len = m_size.NumberOfElements; 
+
+                    for (int i = 0; i < len; i++) { 
+                        curVal = data[i]; 
+                        
+                        if (curVal < curMin) { 
+                            curMin = curVal; 
+                            curMinInd = i; 
+                        }
+                        if (curVal > curMax) { 
+                            curMax = curVal; 
+                            curMaxInd = i; 
+                        }
+                    }
+                    maxValue = m_data.Data[curMaxInd];
+                    minValue = m_data.Data[curMinInd]; 
+                    return (curMax >  Int64.MinValue || curMin <  Int64.MinValue ); 
+    
+                } else if (this is ILDenseStorage<Int32> ) {    
+                    Int32 [] data = ( Int32 [])(object) GetArrayForRead(); 
+                    Int32 curVal; 
+                    Int32 curMin =  Int32.MaxValue ;
+                    Int32 curMax =  Int32.MinValue ;
+                    int curMinInd = 0; 
+                    int curMaxInd = 0; 
+                    int len = m_size.NumberOfElements; 
+
+                    for (int i = 0; i < len; i++) { 
+                        curVal = data[i]; 
+                        
+                        if (curVal < curMin) { 
+                            curMin = curVal; 
+                            curMinInd = i; 
+                        }
+                        if (curVal > curMax) { 
+                            curMax = curVal; 
+                            curMaxInd = i; 
+                        }
+                    }
+                    maxValue = m_data.Data[curMaxInd];
+                    minValue = m_data.Data[curMinInd]; 
+                    return (curMax >  Int32.MinValue || curMin <  Int32.MinValue ); 
+    
+                } else if (this is ILDenseStorage<float> ) {    
+                    float [] data = ( float [])(object) GetArrayForRead(); 
+                    float curVal; 
+                    float curMin =  float.PositiveInfinity ;
+                    float curMax =  float.NegativeInfinity ;
+                    int curMinInd = 0; 
+                    int curMaxInd = 0; 
+                    int len = m_size.NumberOfElements; 
+
+                    for (int i = 0; i < len; i++) { 
+                        curVal = data[i]; 
+                        if(float.IsInfinity(curVal)) continue;
+                        if (curVal < curMin) { 
+                            curMin = curVal; 
+                            curMinInd = i; 
+                        }
+                        if (curVal > curMax) { 
+                            curMax = curVal; 
+                            curMaxInd = i; 
+                        }
+                    }
+                    maxValue = m_data.Data[curMaxInd];
+                    minValue = m_data.Data[curMinInd]; 
+                    return (curMax >  float.NegativeInfinity || curMin <  float.NegativeInfinity ); 
+
+#endregion HYCALPER AUTO GENERATED CODE
+           } else if ((typeof(ElementType) is IComparable<ElementType>)) {
+                ElementType[] tmpArr = GetArrayForRead();
+                for (int i = 0; i < m_size.NumberOfElements; i++) {
+                    ElementType val = tmpArr[i];
+                    if (((IComparable<ElementType>)val).CompareTo(minValue) < 0)
+                        minValue = val;
+                    if (((IComparable<ElementType>)val).CompareTo(minValue) > 0)
+                        maxValue = val;
+                }
+                return true;
+            }
+            return false; 
+        }
+#endregion
+
+        #region overriding object.ToString(), Equals()
+        /// <summary>
+        /// Write information about the ILDenseStorage to string.
+        /// </summary>
+        /// <returns>String containing general information about the current instance of 
+        /// ILDenseStorage and the formatted elements' values.</returns>
+        /// <remarks>If the number of elements exceeds a certain amount, the display will be abreviated.</remarks>
+        public override string ToString() {
+            return ValuesToString(0).ToString();
+        }
+        /// <summary>
+        /// print formated values to string
+        /// </summary>
+        /// <param name="maxLength">Maximum number of characters per line. 0: no limit</param>
+        /// <returns>StringBuilder object filled with formated values.</returns>
+        internal override StringBuilder ValuesToString(int maxLength) {
+            StringBuilder s = new StringBuilder();
+            if (maxLength <= 0) maxLength = int.MaxValue;
+            //if (m_dimensions.NumberOfElements > 100000) {
+            //    s.Append(String.Format("({0})", m_dimensions.ToString()));
+            //    return s;
+            //}
+            if (m_size.NumberOfElements < 1)
+                return new StringBuilder("(Empty)"); 
+            int[] acc = new int[m_size.NumberOfDimensions];
+            int d;
+            String sElement;
+            int elemLength = 10; 
+            //string format = "{0,20: E13;-E13; 0.0         } "; 
+            int curLineLength = 0, curRowsCount = 0;
+            int maxRows = (maxLength == int.MaxValue) ? int.MaxValue : 500; // limit data rows in debugger view 
+            if (false) {
+
+                
+            } else if (this.Data.Data.GetType() == typeof(  double [] )) {
+                #region 
+                 double element;
+                 double [] elements = (this.Data.Data as  double []);
+                elemLength =  10 ; 
+                 
+                double scaling = getScalingForPrint(); 
+                elemLength++; 
+                while (acc[m_size.NumberOfDimensions - 1] <
+                        m_size[m_size.NumberOfDimensions - 1]) {
+                    // show only two first dimensions at the same time ... 
+                    // print header
+                    if (m_size.NumberOfDimensions > 2 || scaling != 1) {
+                        if (s.Length > 0) s.Append(Environment.NewLine);
+                        s.Append("(:,:");
+                        for (d = 2; d < m_size.NumberOfDimensions; d++)
+                            s.Append(String.Format(",{0}", acc[d]));
+                        s.Append(") " + ((scaling!=1.0)? (scaling.ToString("e0") + " * "):""));
+                    }
+                    // show this for 2 leading dimensions
+                    for (int d0 = 0; d0 < m_size[0]; d0++) {
+                        if (++curRowsCount > maxRows) {
+                            s.Append(Environment.NewLine + "( ... more rows exist)");    
+                            return s; 
+                        }
+                        if (s.Length > 0) s.Append(Environment.NewLine);
+                        acc[0] = d0; curLineLength = 0; 
+                        for (int d1 = 0; d1 < m_size[1]; d1++) {
+                            acc[1] = d1;
+                            element = elements [m_size.IndexFromArray(acc)];
+                            if (!Object.ReferenceEquals(element,null)) {
+                                
+                                sElement = String.Format ((scaling == 1 && (int)element == element) ? "{0} " : "{0:f5} ", element / scaling).PadLeft(elemLength);
+                            } else {
+                                sElement = "(null)".PadLeft(elemLength);
+                            }
+                            curLineLength += sElement.Length;
+                            if (curLineLength > maxLength - " ...".Length) {
+                                s.Append(" ...");
+                                break;  
+                            } else {
+                                s.Append(sElement);
+                            }
+                        }
+                    }
+                    // increase higher dimension
+                    d = 2;
+                    while (d <= m_size.NumberOfDimensions - 1) {
+                        acc[d]++;
+                        if (acc[d] < m_size[d]) break;
+                        acc[d] = 0;
+                        d++;
+                    }
+                    if (d >= m_size.NumberOfDimensions) break;
+                }
+                #endregion
+
+#region HYCALPER AUTO GENERATED CODE
+
+               
+            } else if (this.Data.Data.GetType() == typeof(  float [] )) {
+                #region 
+                float element;
+                float [] elements = (this.Data.Data as  float []);
+                elemLength =  5 ; 
+                float scaling = (float)getScalingForPrint();
+                elemLength++; 
+                while (acc[m_size.NumberOfDimensions - 1] <
+                        m_size[m_size.NumberOfDimensions - 1]) {
+                    // show only two first dimensions at the same time ... 
+                    // print header
+                    if (m_size.NumberOfDimensions > 2 || scaling != 1) {
+                        if (s.Length > 0) s.Append(Environment.NewLine);
+                        s.Append("(:,:");
+                        for (d = 2; d < m_size.NumberOfDimensions; d++)
+                            s.Append(String.Format(",{0}", acc[d]));
+                        s.Append(") " + ((scaling!=1.0)? (scaling.ToString("e0") + " * "):""));
+                    }
+                    // show this for 2 leading dimensions
+                    for (int d0 = 0; d0 < m_size[0]; d0++) {
+                        if (++curRowsCount > maxRows) {
+                            s.Append(Environment.NewLine + "( ... more rows exist)");    
+                            return s; 
+                        }
+                        if (s.Length > 0) s.Append(Environment.NewLine);
+                        acc[0] = d0; curLineLength = 0; 
+                        for (int d1 = 0; d1 < m_size[1]; d1++) {
+                            acc[1] = d1;
+                            element = elements [m_size.IndexFromArray(acc)];
+                            if (!Object.ReferenceEquals(element,null)) {
+                                sElement = String.Format ("{0:f5} ", element / scaling).PadLeft(elemLength);
+                            } else {
+                                sElement = "(null)".PadLeft(elemLength);
+                            }
+                            curLineLength += sElement.Length;
+                            if (curLineLength > maxLength - " ...".Length) {
+                                s.Append(" ...");
+                                break;  
+                            } else {
+                                s.Append(sElement);
+                            }
+                        }
+                    }
+                    // increase higher dimension
+                    d = 2;
+                    while (d <= m_size.NumberOfDimensions - 1) {
+                        acc[d]++;
+                        if (acc[d] < m_size[d]) break;
+                        acc[d] = 0;
+                        d++;
+                    }
+                    if (d >= m_size.NumberOfDimensions) break;
+                }
+                #endregion
+               
+            } else if (this.Data.Data.GetType() == typeof(  fcomplex [] )) {
+                #region 
+                fcomplex element;
+                fcomplex [] elements = (this.Data.Data as  fcomplex []);
+                elemLength =  24 ; 
+                float scaling = (float)getScalingForPrint();
+                elemLength++; 
+                while (acc[m_size.NumberOfDimensions - 1] <
+                        m_size[m_size.NumberOfDimensions - 1]) {
+                    // show only two first dimensions at the same time ... 
+                    // print header
+                    if (m_size.NumberOfDimensions > 2 || scaling != 1) {
+                        if (s.Length > 0) s.Append(Environment.NewLine);
+                        s.Append("(:,:");
+                        for (d = 2; d < m_size.NumberOfDimensions; d++)
+                            s.Append(String.Format(",{0}", acc[d]));
+                        s.Append(") " + ((scaling!=1.0)? (scaling.ToString("e0") + " * "):""));
+                    }
+                    // show this for 2 leading dimensions
+                    for (int d0 = 0; d0 < m_size[0]; d0++) {
+                        if (++curRowsCount > maxRows) {
+                            s.Append(Environment.NewLine + "( ... more rows exist)");    
+                            return s; 
+                        }
+                        if (s.Length > 0) s.Append(Environment.NewLine);
+                        acc[0] = d0; curLineLength = 0; 
+                        for (int d1 = 0; d1 < m_size[1]; d1++) {
+                            acc[1] = d1;
+                            element = elements [m_size.IndexFromArray(acc)];
+                            if (!Object.ReferenceEquals(element,null)) {
+                                sElement = String.Format ("{0} ", (element / scaling).ToString(5)).PadLeft(elemLength);
+                            } else {
+                                sElement = "(null)".PadLeft(elemLength);
+                            }
+                            curLineLength += sElement.Length;
+                            if (curLineLength > maxLength - " ...".Length) {
+                                s.Append(" ...");
+                                break;  
+                            } else {
+                                s.Append(sElement);
+                            }
+                        }
+                    }
+                    // increase higher dimension
+                    d = 2;
+                    while (d <= m_size.NumberOfDimensions - 1) {
+                        acc[d]++;
+                        if (acc[d] < m_size[d]) break;
+                        acc[d] = 0;
+                        d++;
+                    }
+                    if (d >= m_size.NumberOfDimensions) break;
+                }
+                #endregion
+               
+            } else if (this.Data.Data.GetType() == typeof(  complex [] )) {
+                #region 
+                complex element;
+                complex [] elements = (this.Data.Data as  complex []);
+                elemLength =  36 ; 
+                double scaling = getScalingForPrint();
+                elemLength++; 
+                while (acc[m_size.NumberOfDimensions - 1] <
+                        m_size[m_size.NumberOfDimensions - 1]) {
+                    // show only two first dimensions at the same time ... 
+                    // print header
+                    if (m_size.NumberOfDimensions > 2 || scaling != 1) {
+                        if (s.Length > 0) s.Append(Environment.NewLine);
+                        s.Append("(:,:");
+                        for (d = 2; d < m_size.NumberOfDimensions; d++)
+                            s.Append(String.Format(",{0}", acc[d]));
+                        s.Append(") " + ((scaling!=1.0)? (scaling.ToString("e0") + " * "):""));
+                    }
+                    // show this for 2 leading dimensions
+                    for (int d0 = 0; d0 < m_size[0]; d0++) {
+                        if (++curRowsCount > maxRows) {
+                            s.Append(Environment.NewLine + "( ... more rows exist)");    
+                            return s; 
+                        }
+                        if (s.Length > 0) s.Append(Environment.NewLine);
+                        acc[0] = d0; curLineLength = 0; 
+                        for (int d1 = 0; d1 < m_size[1]; d1++) {
+                            acc[1] = d1;
+                            element = elements [m_size.IndexFromArray(acc)];
+                            if (!Object.ReferenceEquals(element,null)) {
+                                sElement = String.Format ("{0} ", (element / scaling).ToString(5)).PadLeft(elemLength);
+                            } else {
+                                sElement = "(null)".PadLeft(elemLength);
+                            }
+                            curLineLength += sElement.Length;
+                            if (curLineLength > maxLength - " ...".Length) {
+                                s.Append(" ...");
+                                break;  
+                            } else {
+                                s.Append(sElement);
+                            }
+                        }
+                    }
+                    // increase higher dimension
+                    d = 2;
+                    while (d <= m_size.NumberOfDimensions - 1) {
+                        acc[d]++;
+                        if (acc[d] < m_size[d]) break;
+                        acc[d] = 0;
+                        d++;
+                    }
+                    if (d >= m_size.NumberOfDimensions) break;
+                }
+                #endregion
+               
+            } else if (this.Data.Data.GetType() == typeof(  Complex [] )) {
+                #region 
+                Complex element;
+                Complex [] elements = (this.Data.Data as  Complex []);
+                elemLength =  36 ; 
+                double scaling = getScalingForPrint();
+                elemLength++; 
+                while (acc[m_size.NumberOfDimensions - 1] <
+                        m_size[m_size.NumberOfDimensions - 1]) {
+                    // show only two first dimensions at the same time ... 
+                    // print header
+                    if (m_size.NumberOfDimensions > 2 || scaling != 1) {
+                        if (s.Length > 0) s.Append(Environment.NewLine);
+                        s.Append("(:,:");
+                        for (d = 2; d < m_size.NumberOfDimensions; d++)
+                            s.Append(String.Format(",{0}", acc[d]));
+                        s.Append(") " + ((scaling!=1.0)? (scaling.ToString("e0") + " * "):""));
+                    }
+                    // show this for 2 leading dimensions
+                    for (int d0 = 0; d0 < m_size[0]; d0++) {
+                        if (++curRowsCount > maxRows) {
+                            s.Append(Environment.NewLine + "( ... more rows exist)");    
+                            return s; 
+                        }
+                        if (s.Length > 0) s.Append(Environment.NewLine);
+                        acc[0] = d0; curLineLength = 0; 
+                        for (int d1 = 0; d1 < m_size[1]; d1++) {
+                            acc[1] = d1;
+                            element = elements [m_size.IndexFromArray(acc)];
+                            if (!Object.ReferenceEquals(element,null)) {
+                                sElement = String.Format ("{0} ", ComplexHelper(element / scaling,5)).PadLeft(elemLength);
+                            } else {
+                                sElement = "(null)".PadLeft(elemLength);
+                            }
+                            curLineLength += sElement.Length;
+                            if (curLineLength > maxLength - " ...".Length) {
+                                s.Append(" ...");
+                                break;  
+                            } else {
+                                s.Append(sElement);
+                            }
+                        }
+                    }
+                    // increase higher dimension
+                    d = 2;
+                    while (d <= m_size.NumberOfDimensions - 1) {
+                        acc[d]++;
+                        if (acc[d] < m_size[d]) break;
+                        acc[d] = 0;
+                        d++;
+                    }
+                    if (d >= m_size.NumberOfDimensions) break;
+                }
+                #endregion
+               
+            } else if (this.Data.Data.GetType() == typeof(  byte [] )) {
+                #region 
+                byte element;
+                byte [] elements = (this.Data.Data as  byte []);
+                elemLength =  3 ; 
+                double scaling = 1.0; 
+                elemLength++; 
+                while (acc[m_size.NumberOfDimensions - 1] <
+                        m_size[m_size.NumberOfDimensions - 1]) {
+                    // show only two first dimensions at the same time ... 
+                    // print header
+                    if (m_size.NumberOfDimensions > 2 || scaling != 1) {
+                        if (s.Length > 0) s.Append(Environment.NewLine);
+                        s.Append("(:,:");
+                        for (d = 2; d < m_size.NumberOfDimensions; d++)
+                            s.Append(String.Format(",{0}", acc[d]));
+                        s.Append(") " + ((scaling!=1.0)? (scaling.ToString("e0") + " * "):""));
+                    }
+                    // show this for 2 leading dimensions
+                    for (int d0 = 0; d0 < m_size[0]; d0++) {
+                        if (++curRowsCount > maxRows) {
+                            s.Append(Environment.NewLine + "( ... more rows exist)");    
+                            return s; 
+                        }
+                        if (s.Length > 0) s.Append(Environment.NewLine);
+                        acc[0] = d0; curLineLength = 0; 
+                        for (int d1 = 0; d1 < m_size[1]; d1++) {
+                            acc[1] = d1;
+                            element = elements [m_size.IndexFromArray(acc)];
+                            if (!Object.ReferenceEquals(element,null)) {
+                                sElement = String.Format ("{0,3:G} ", element).PadLeft(elemLength);
+                            } else {
+                                sElement = "(null)".PadLeft(elemLength);
+                            }
+                            curLineLength += sElement.Length;
+                            if (curLineLength > maxLength - " ...".Length) {
+                                s.Append(" ...");
+                                break;  
+                            } else {
+                                s.Append(sElement);
+                            }
+                        }
+                    }
+                    // increase higher dimension
+                    d = 2;
+                    while (d <= m_size.NumberOfDimensions - 1) {
+                        acc[d]++;
+                        if (acc[d] < m_size[d]) break;
+                        acc[d] = 0;
+                        d++;
+                    }
+                    if (d >= m_size.NumberOfDimensions) break;
+                }
+                #endregion
+               
+            } else if (this.Data.Data.GetType() == typeof(  char [] )) {
+                #region 
+                char element;
+                char [] elements = (this.Data.Data as  char []);
+                elemLength =  3 ; 
+                double scaling = 1.0; 
+                elemLength++; 
+                while (acc[m_size.NumberOfDimensions - 1] <
+                        m_size[m_size.NumberOfDimensions - 1]) {
+                    // show only two first dimensions at the same time ... 
+                    // print header
+                    if (m_size.NumberOfDimensions > 2 || scaling != 1) {
+                        if (s.Length > 0) s.Append(Environment.NewLine);
+                        s.Append("(:,:");
+                        for (d = 2; d < m_size.NumberOfDimensions; d++)
+                            s.Append(String.Format(",{0}", acc[d]));
+                        s.Append(") " + ((scaling!=1.0)? (scaling.ToString("e0") + " * "):""));
+                    }
+                    // show this for 2 leading dimensions
+                    for (int d0 = 0; d0 < m_size[0]; d0++) {
+                        if (++curRowsCount > maxRows) {
+                            s.Append(Environment.NewLine + "( ... more rows exist)");    
+                            return s; 
+                        }
+                        if (s.Length > 0) s.Append(Environment.NewLine);
+                        acc[0] = d0; curLineLength = 0; 
+                        for (int d1 = 0; d1 < m_size[1]; d1++) {
+                            acc[1] = d1;
+                            element = elements [m_size.IndexFromArray(acc)];
+                            if (!Object.ReferenceEquals(element,null)) {
+                                sElement = String.Format ("{0,3:G} ", element).PadLeft(elemLength);
+                            } else {
+                                sElement = "(null)".PadLeft(elemLength);
+                            }
+                            curLineLength += sElement.Length;
+                            if (curLineLength > maxLength - " ...".Length) {
+                                s.Append(" ...");
+                                break;  
+                            } else {
+                                s.Append(sElement);
+                            }
+                        }
+                    }
+                    // increase higher dimension
+                    d = 2;
+                    while (d <= m_size.NumberOfDimensions - 1) {
+                        acc[d]++;
+                        if (acc[d] < m_size[d]) break;
+                        acc[d] = 0;
+                        d++;
+                    }
+                    if (d >= m_size.NumberOfDimensions) break;
+                }
+                #endregion
+               
+            } else if (this.Data.Data.GetType() == typeof(  UInt64 [] )) {
+                #region 
+                UInt64 element;
+                UInt64 [] elements = (this.Data.Data as  UInt64 []);
+                elemLength =  18 ; 
+                double scaling = 1.0; 
+                elemLength++; 
+                while (acc[m_size.NumberOfDimensions - 1] <
+                        m_size[m_size.NumberOfDimensions - 1]) {
+                    // show only two first dimensions at the same time ... 
+                    // print header
+                    if (m_size.NumberOfDimensions > 2 || scaling != 1) {
+                        if (s.Length > 0) s.Append(Environment.NewLine);
+                        s.Append("(:,:");
+                        for (d = 2; d < m_size.NumberOfDimensions; d++)
+                            s.Append(String.Format(",{0}", acc[d]));
+                        s.Append(") " + ((scaling!=1.0)? (scaling.ToString("e0") + " * "):""));
+                    }
+                    // show this for 2 leading dimensions
+                    for (int d0 = 0; d0 < m_size[0]; d0++) {
+                        if (++curRowsCount > maxRows) {
+                            s.Append(Environment.NewLine + "( ... more rows exist)");    
+                            return s; 
+                        }
+                        if (s.Length > 0) s.Append(Environment.NewLine);
+                        acc[0] = d0; curLineLength = 0; 
+                        for (int d1 = 0; d1 < m_size[1]; d1++) {
+                            acc[1] = d1;
+                            element = elements [m_size.IndexFromArray(acc)];
+                            if (!Object.ReferenceEquals(element,null)) {
+                                sElement = String.Format ("{0,18:G} ", element).PadLeft(elemLength);
+                            } else {
+                                sElement = "(null)".PadLeft(elemLength);
+                            }
+                            curLineLength += sElement.Length;
+                            if (curLineLength > maxLength - " ...".Length) {
+                                s.Append(" ...");
+                                break;  
+                            } else {
+                                s.Append(sElement);
+                            }
+                        }
+                    }
+                    // increase higher dimension
+                    d = 2;
+                    while (d <= m_size.NumberOfDimensions - 1) {
+                        acc[d]++;
+                        if (acc[d] < m_size[d]) break;
+                        acc[d] = 0;
+                        d++;
+                    }
+                    if (d >= m_size.NumberOfDimensions) break;
+                }
+                #endregion
+               
+            } else if (this.Data.Data.GetType() == typeof(  UInt32 [] )) {
+                #region 
+                UInt32 element;
+                UInt32 [] elements = (this.Data.Data as  UInt32 []);
+                elemLength =  10 ; 
+                double scaling = 1.0; 
+                elemLength++; 
+                while (acc[m_size.NumberOfDimensions - 1] <
+                        m_size[m_size.NumberOfDimensions - 1]) {
+                    // show only two first dimensions at the same time ... 
+                    // print header
+                    if (m_size.NumberOfDimensions > 2 || scaling != 1) {
+                        if (s.Length > 0) s.Append(Environment.NewLine);
+                        s.Append("(:,:");
+                        for (d = 2; d < m_size.NumberOfDimensions; d++)
+                            s.Append(String.Format(",{0}", acc[d]));
+                        s.Append(") " + ((scaling!=1.0)? (scaling.ToString("e0") + " * "):""));
+                    }
+                    // show this for 2 leading dimensions
+                    for (int d0 = 0; d0 < m_size[0]; d0++) {
+                        if (++curRowsCount > maxRows) {
+                            s.Append(Environment.NewLine + "( ... more rows exist)");    
+                            return s; 
+                        }
+                        if (s.Length > 0) s.Append(Environment.NewLine);
+                        acc[0] = d0; curLineLength = 0; 
+                        for (int d1 = 0; d1 < m_size[1]; d1++) {
+                            acc[1] = d1;
+                            element = elements [m_size.IndexFromArray(acc)];
+                            if (!Object.ReferenceEquals(element,null)) {
+                                sElement = String.Format ("{0,10:G} ", element).PadLeft(elemLength);
+                            } else {
+                                sElement = "(null)".PadLeft(elemLength);
+                            }
+                            curLineLength += sElement.Length;
+                            if (curLineLength > maxLength - " ...".Length) {
+                                s.Append(" ...");
+                                break;  
+                            } else {
+                                s.Append(sElement);
+                            }
+                        }
+                    }
+                    // increase higher dimension
+                    d = 2;
+                    while (d <= m_size.NumberOfDimensions - 1) {
+                        acc[d]++;
+                        if (acc[d] < m_size[d]) break;
+                        acc[d] = 0;
+                        d++;
+                    }
+                    if (d >= m_size.NumberOfDimensions) break;
+                }
+                #endregion
+               
+            } else if (this.Data.Data.GetType() == typeof(  UInt16 [] )) {
+                #region 
+                UInt16 element;
+                UInt16 [] elements = (this.Data.Data as  UInt16 []);
+                elemLength =  5 ; 
+                double scaling = 1.0; 
+                elemLength++; 
+                while (acc[m_size.NumberOfDimensions - 1] <
+                        m_size[m_size.NumberOfDimensions - 1]) {
+                    // show only two first dimensions at the same time ... 
+                    // print header
+                    if (m_size.NumberOfDimensions > 2 || scaling != 1) {
+                        if (s.Length > 0) s.Append(Environment.NewLine);
+                        s.Append("(:,:");
+                        for (d = 2; d < m_size.NumberOfDimensions; d++)
+                            s.Append(String.Format(",{0}", acc[d]));
+                        s.Append(") " + ((scaling!=1.0)? (scaling.ToString("e0") + " * "):""));
+                    }
+                    // show this for 2 leading dimensions
+                    for (int d0 = 0; d0 < m_size[0]; d0++) {
+                        if (++curRowsCount > maxRows) {
+                            s.Append(Environment.NewLine + "( ... more rows exist)");    
+                            return s; 
+                        }
+                        if (s.Length > 0) s.Append(Environment.NewLine);
+                        acc[0] = d0; curLineLength = 0; 
+                        for (int d1 = 0; d1 < m_size[1]; d1++) {
+                            acc[1] = d1;
+                            element = elements [m_size.IndexFromArray(acc)];
+                            if (!Object.ReferenceEquals(element,null)) {
+                                sElement = String.Format ("{0,5:G} ", element).PadLeft(elemLength);
+                            } else {
+                                sElement = "(null)".PadLeft(elemLength);
+                            }
+                            curLineLength += sElement.Length;
+                            if (curLineLength > maxLength - " ...".Length) {
+                                s.Append(" ...");
+                                break;  
+                            } else {
+                                s.Append(sElement);
+                            }
+                        }
+                    }
+                    // increase higher dimension
+                    d = 2;
+                    while (d <= m_size.NumberOfDimensions - 1) {
+                        acc[d]++;
+                        if (acc[d] < m_size[d]) break;
+                        acc[d] = 0;
+                        d++;
+                    }
+                    if (d >= m_size.NumberOfDimensions) break;
+                }
+                #endregion
+               
+            } else if (this.Data.Data.GetType() == typeof(  Int64 [] )) {
+                #region 
+                Int64 element;
+                Int64 [] elements = (this.Data.Data as  Int64 []);
+                elemLength =  18 ; 
+                double scaling = 1.0; 
+                elemLength++; 
+                while (acc[m_size.NumberOfDimensions - 1] <
+                        m_size[m_size.NumberOfDimensions - 1]) {
+                    // show only two first dimensions at the same time ... 
+                    // print header
+                    if (m_size.NumberOfDimensions > 2 || scaling != 1) {
+                        if (s.Length > 0) s.Append(Environment.NewLine);
+                        s.Append("(:,:");
+                        for (d = 2; d < m_size.NumberOfDimensions; d++)
+                            s.Append(String.Format(",{0}", acc[d]));
+                        s.Append(") " + ((scaling!=1.0)? (scaling.ToString("e0") + " * "):""));
+                    }
+                    // show this for 2 leading dimensions
+                    for (int d0 = 0; d0 < m_size[0]; d0++) {
+                        if (++curRowsCount > maxRows) {
+                            s.Append(Environment.NewLine + "( ... more rows exist)");    
+                            return s; 
+                        }
+                        if (s.Length > 0) s.Append(Environment.NewLine);
+                        acc[0] = d0; curLineLength = 0; 
+                        for (int d1 = 0; d1 < m_size[1]; d1++) {
+                            acc[1] = d1;
+                            element = elements [m_size.IndexFromArray(acc)];
+                            if (!Object.ReferenceEquals(element,null)) {
+                                sElement = String.Format ("{0,18:G} ", element).PadLeft(elemLength);
+                            } else {
+                                sElement = "(null)".PadLeft(elemLength);
+                            }
+                            curLineLength += sElement.Length;
+                            if (curLineLength > maxLength - " ...".Length) {
+                                s.Append(" ...");
+                                break;  
+                            } else {
+                                s.Append(sElement);
+                            }
+                        }
+                    }
+                    // increase higher dimension
+                    d = 2;
+                    while (d <= m_size.NumberOfDimensions - 1) {
+                        acc[d]++;
+                        if (acc[d] < m_size[d]) break;
+                        acc[d] = 0;
+                        d++;
+                    }
+                    if (d >= m_size.NumberOfDimensions) break;
+                }
+                #endregion
+               
+            } else if (this.Data.Data.GetType() == typeof(  Int32 [] )) {
+                #region 
+                Int32 element;
+                Int32 [] elements = (this.Data.Data as  Int32 []);
+                elemLength =  10 ; 
+                double scaling = 1.0; 
+                elemLength++; 
+                while (acc[m_size.NumberOfDimensions - 1] <
+                        m_size[m_size.NumberOfDimensions - 1]) {
+                    // show only two first dimensions at the same time ... 
+                    // print header
+                    if (m_size.NumberOfDimensions > 2 || scaling != 1) {
+                        if (s.Length > 0) s.Append(Environment.NewLine);
+                        s.Append("(:,:");
+                        for (d = 2; d < m_size.NumberOfDimensions; d++)
+                            s.Append(String.Format(",{0}", acc[d]));
+                        s.Append(") " + ((scaling!=1.0)? (scaling.ToString("e0") + " * "):""));
+                    }
+                    // show this for 2 leading dimensions
+                    for (int d0 = 0; d0 < m_size[0]; d0++) {
+                        if (++curRowsCount > maxRows) {
+                            s.Append(Environment.NewLine + "( ... more rows exist)");    
+                            return s; 
+                        }
+                        if (s.Length > 0) s.Append(Environment.NewLine);
+                        acc[0] = d0; curLineLength = 0; 
+                        for (int d1 = 0; d1 < m_size[1]; d1++) {
+                            acc[1] = d1;
+                            element = elements [m_size.IndexFromArray(acc)];
+                            if (!Object.ReferenceEquals(element,null)) {
+                                sElement = String.Format ("{0,10:G} ", element).PadLeft(elemLength);
+                            } else {
+                                sElement = "(null)".PadLeft(elemLength);
+                            }
+                            curLineLength += sElement.Length;
+                            if (curLineLength > maxLength - " ...".Length) {
+                                s.Append(" ...");
+                                break;  
+                            } else {
+                                s.Append(sElement);
+                            }
+                        }
+                    }
+                    // increase higher dimension
+                    d = 2;
+                    while (d <= m_size.NumberOfDimensions - 1) {
+                        acc[d]++;
+                        if (acc[d] < m_size[d]) break;
+                        acc[d] = 0;
+                        d++;
+                    }
+                    if (d >= m_size.NumberOfDimensions) break;
+                }
+                #endregion
+               
+            } else if (this.Data.Data.GetType() == typeof(  Int16 [] )) {
+                #region 
+                Int16 element;
+                Int16 [] elements = (this.Data.Data as  Int16 []);
+                elemLength =  5 ; 
+                double scaling = 1.0; 
+                elemLength++; 
+                while (acc[m_size.NumberOfDimensions - 1] <
+                        m_size[m_size.NumberOfDimensions - 1]) {
+                    // show only two first dimensions at the same time ... 
+                    // print header
+                    if (m_size.NumberOfDimensions > 2 || scaling != 1) {
+                        if (s.Length > 0) s.Append(Environment.NewLine);
+                        s.Append("(:,:");
+                        for (d = 2; d < m_size.NumberOfDimensions; d++)
+                            s.Append(String.Format(",{0}", acc[d]));
+                        s.Append(") " + ((scaling!=1.0)? (scaling.ToString("e0") + " * "):""));
+                    }
+                    // show this for 2 leading dimensions
+                    for (int d0 = 0; d0 < m_size[0]; d0++) {
+                        if (++curRowsCount > maxRows) {
+                            s.Append(Environment.NewLine + "( ... more rows exist)");    
+                            return s; 
+                        }
+                        if (s.Length > 0) s.Append(Environment.NewLine);
+                        acc[0] = d0; curLineLength = 0; 
+                        for (int d1 = 0; d1 < m_size[1]; d1++) {
+                            acc[1] = d1;
+                            element = elements [m_size.IndexFromArray(acc)];
+                            if (!Object.ReferenceEquals(element,null)) {
+                                sElement = String.Format ("{0,5:G} ", element).PadLeft(elemLength);
+                            } else {
+                                sElement = "(null)".PadLeft(elemLength);
+                            }
+                            curLineLength += sElement.Length;
+                            if (curLineLength > maxLength - " ...".Length) {
+                                s.Append(" ...");
+                                break;  
+                            } else {
+                                s.Append(sElement);
+                            }
+                        }
+                    }
+                    // increase higher dimension
+                    d = 2;
+                    while (d <= m_size.NumberOfDimensions - 1) {
+                        acc[d]++;
+                        if (acc[d] < m_size[d]) break;
+                        acc[d] = 0;
+                        d++;
+                    }
+                    if (d >= m_size.NumberOfDimensions) break;
+                }
+                #endregion
+               
+            } else if (this.Data.Data.GetType() == typeof(  ILStorage [] )) {
+                #region 
+                ILStorage element;
+                ILStorage [] elements = (this.Data.Data as  ILStorage []);
+                elemLength =  0 ; 
+                double scaling = 1.0; 
+                for (int i = 0; i < m_size.NumberOfElements; i++) { 
+                    element = elements[i]; 
+                    int l = (element == null)? 6 : element.ShortInfo().Length; 
+                    if (l > elemLength) elemLength = l; 
+                }
+
+                elemLength++; 
+                while (acc[m_size.NumberOfDimensions - 1] <
+                        m_size[m_size.NumberOfDimensions - 1]) {
+                    // show only two first dimensions at the same time ... 
+                    // print header
+                    if (m_size.NumberOfDimensions > 2 || scaling != 1) {
+                        if (s.Length > 0) s.Append(Environment.NewLine);
+                        s.Append("(:,:");
+                        for (d = 2; d < m_size.NumberOfDimensions; d++)
+                            s.Append(String.Format(",{0}", acc[d]));
+                        s.Append(") " + ((scaling!=1.0)? (scaling.ToString("e0") + " * "):""));
+                    }
+                    // show this for 2 leading dimensions
+                    for (int d0 = 0; d0 < m_size[0]; d0++) {
+                        if (++curRowsCount > maxRows) {
+                            s.Append(Environment.NewLine + "( ... more rows exist)");    
+                            return s; 
+                        }
+                        if (s.Length > 0) s.Append(Environment.NewLine);
+                        acc[0] = d0; curLineLength = 0; 
+                        for (int d1 = 0; d1 < m_size[1]; d1++) {
+                            acc[1] = d1;
+                            element = elements [m_size.IndexFromArray(acc)];
+                            if (!Object.ReferenceEquals(element,null)) {
+                                sElement = element.ShortInfo().PadRight(elemLength);
+                            } else {
+                                sElement = "(null)".PadLeft(elemLength);
+                            }
+                            curLineLength += sElement.Length;
+                            if (curLineLength > maxLength - " ...".Length) {
+                                s.Append(" ...");
+                                break;  
+                            } else {
+                                s.Append(sElement);
+                            }
+                        }
+                    }
+                    // increase higher dimension
+                    d = 2;
+                    while (d <= m_size.NumberOfDimensions - 1) {
+                        acc[d]++;
+                        if (acc[d] < m_size[d]) break;
+                        acc[d] = 0;
+                        d++;
+                    }
+                    if (d >= m_size.NumberOfDimensions) break;
+                }
+                #endregion
+               
+            } else if (this.Data.Data.GetType() == typeof(  object [] )) {
+                #region 
+                object element;
+                object [] elements = (this.Data.Data as  object []);
+                elemLength =  18 ; 
+                double scaling = 1.0; 
+                elemLength++; 
+                while (acc[m_size.NumberOfDimensions - 1] <
+                        m_size[m_size.NumberOfDimensions - 1]) {
+                    // show only two first dimensions at the same time ... 
+                    // print header
+                    if (m_size.NumberOfDimensions > 2 || scaling != 1) {
+                        if (s.Length > 0) s.Append(Environment.NewLine);
+                        s.Append("(:,:");
+                        for (d = 2; d < m_size.NumberOfDimensions; d++)
+                            s.Append(String.Format(",{0}", acc[d]));
+                        s.Append(") " + ((scaling!=1.0)? (scaling.ToString("e0") + " * "):""));
+                    }
+                    // show this for 2 leading dimensions
+                    for (int d0 = 0; d0 < m_size[0]; d0++) {
+                        if (++curRowsCount > maxRows) {
+                            s.Append(Environment.NewLine + "( ... more rows exist)");    
+                            return s; 
+                        }
+                        if (s.Length > 0) s.Append(Environment.NewLine);
+                        acc[0] = d0; curLineLength = 0; 
+                        for (int d1 = 0; d1 < m_size[1]; d1++) {
+                            acc[1] = d1;
+                            element = elements [m_size.IndexFromArray(acc)];
+                            if (!Object.ReferenceEquals(element,null)) {
+                                sElement = String.Format ("{0} ", element).PadLeft(elemLength);
+                            } else {
+                                sElement = "(null)".PadLeft(elemLength);
+                            }
+                            curLineLength += sElement.Length;
+                            if (curLineLength > maxLength - " ...".Length) {
+                                s.Append(" ...");
+                                break;  
+                            } else {
+                                s.Append(sElement);
+                            }
+                        }
+                    }
+                    // increase higher dimension
+                    d = 2;
+                    while (d <= m_size.NumberOfDimensions - 1) {
+                        acc[d]++;
+                        if (acc[d] < m_size[d]) break;
+                        acc[d] = 0;
+                        d++;
+                    }
+                    if (d >= m_size.NumberOfDimensions) break;
+                }
+                #endregion
+
+#endregion HYCALPER AUTO GENERATED CODE
+           } else if (this is ILDenseStorage<string> ) {
+                #region
+                string element;
+                string[] elements = (this.Data.Data as string[]);
+                elemLength = 18;
+                int maxElemLength = 50;  // todo: may better be a setting? abreviate after as many chars
+                elemLength++;
+                while (acc[m_size.NumberOfDimensions - 1] <
+                        m_size[m_size.NumberOfDimensions - 1]) {
+                    // show only two first dimensions at the same time ... 
+                    // print header
+                    if (m_size.NumberOfDimensions > 2) {
+                        if (s.Length > 0) s.Append(Environment.NewLine);
+                        s.Append("(:,:");
+                        for (d = 2; d < m_size.NumberOfDimensions; d++)
+                            s.Append(String.Format(",{0}", acc[d]));
+                        s.Append(") ");
+                    }
+                    // show this for 2 leading dimensions
+                    for (int d0 = 0; d0 < m_size[0]; d0++) {
+                        if (++curRowsCount > maxRows) {
+                            s.Append(Environment.NewLine + "( ... more rows exist)");
+                            return s;
+                        }
+                        if (s.Length > 0) s.Append(Environment.NewLine);
+                        acc[0] = d0; curLineLength = 0;
+                        for (int d1 = 0; d1 < m_size[1]; d1++) {
+                            acc[1] = d1;
+                            element = elements[m_size.IndexFromArray(acc)];
+                            if (!Object.ReferenceEquals(element, null)) {
+                                if (element.Length > maxElemLength) {
+                                    sElement = element.Substring(0,maxElemLength - 3) + "..."; 
+                                } else {
+                                    sElement = String.Format("{0} ", element).PadLeft(elemLength);
+                                }
+                            } else {
+                                sElement = "(null)".PadLeft(elemLength);
+                            }
+                            curLineLength += sElement.Length;
+                            if (curLineLength > maxLength - " ...".Length) {
+                                s.Append(" ...");
+                                break;
+                            } else {
+                                s.Append(sElement);
+                            }
+                        }
+                    }
+                    // increase higher dimension
+                    d = 2;
+                    while (d <= m_size.NumberOfDimensions - 1) {
+                        acc[d]++;
+                        if (acc[d] < m_size[d]) break;
+                        acc[d] = 0;
+                        d++;
+                    }
+                    if (d >= m_size.NumberOfDimensions) break;
+                }
+                #endregion
+            } else { 
+                return new StringBuilder ("(Unknown data type.)"); 
+           } 
+            return s;
+        }
+        private double getScalingForPrint() {
+            ElementType min, max; 
+            if (GetLimits(out min, out max, false)) {
+                try {
+                    double scaling = Math.Max(
+                                        Math.Abs(double.Parse(min.ToString())),
+                                        Math.Abs( double.Parse(max.ToString())) 
+                                     ); 
+                    if (scaling == 0  || (scaling > 1e-1 && scaling < 1e1)) 
+                        scaling = 1; 
+                    scaling = Math.Pow(10,Math.Floor(Math.Log10(scaling)));
+                    if (scaling < 10000 && scaling >= 1) 
+                        scaling = 1; 
+                    return scaling; 
+                } catch (Exception) {
+                    return 1.0;
+                }
+            } else {
+                return 1.0; 
+            }
+        }
+        private int GetTypedElementStringProperties(double scaling, out string format) {
+            format = "E+00000000000000;0.0;-E+00000000000000";
+            if (this is ILDenseStorage<double>) {
+                return double.MaxValue.ToString().Length;
+            } else if (this is ILDenseStorage<float>) {
+                return float.MaxValue.ToString().Length;
+            } else if (this is ILDenseStorage<Complex>) {
+                return double.MaxValue.ToString().Length * 2 + 2;
+            } else if (this is ILDenseStorage<complex>) {
+                return double.MaxValue.ToString().Length * 2 + 2;
+            } else if (this is ILDenseStorage<fcomplex>) {
+                return float.MaxValue.ToString().Length * 2 + 2;
+            } else if (this is ILDenseStorage<char>) {
+                return char.MaxValue.ToString().Length;
+            } else if (this is ILDenseStorage<byte>) {
+                return byte.MaxValue.ToString().Length;
+            } else if (this is ILDenseStorage<Int16>) {
+                return Int16.MaxValue.ToString().Length;
+            } else if (this is ILDenseStorage<Int32>) {
+                return Int32.MaxValue.ToString().Length;
+            } else if (this is ILDenseStorage<Int64>) {
+                return Int64.MaxValue.ToString().Length;
+            } else if (this is ILDenseStorage<UInt16>) {
+                return UInt16.MaxValue.ToString().Length;
+            } else if (this is ILDenseStorage<UInt32>) {
+                return UInt32.MaxValue.ToString().Length;
+            } else if (this is ILDenseStorage<UInt64>) {
+                return UInt64.MaxValue.ToString().Length;
+            } else
+                return 10; 
+        }
+        private string ComplexHelper(Complex a, int digits) {
+            if (digits < 1) return ""; 
+            if (a.Imaginary >= 0) {
+                return String.Format("{0:f10}+{1:f10}", a.Real, a.Imaginary); 
+            } else {
+                return String.Format("{0:f10}-{1:f10}", a.Real, -a.Imaginary); 
+            }
+        }
+        /// <summary>
+        /// Check if the content of this array equals the content of obj.
+        /// </summary>
+        /// <param name="obj">storage containing the values with which to compare this array.</param>
+        /// <returns>True if all elements contained in obj are equal to the 
+        /// elements of this array, false otherwise.</returns>
+        /// <remarks>This method compares the object references of corresponding elements. 
+        /// The size and type of both arrays must match. Otherwise false will be returned.</remarks>
+        internal override bool Equals(object obj) {
+            if (object.Equals(obj,null)) return false; 
+            if (obj is ElementType)
+                if (Size.NumberOfElements == 1
+                    && obj.ToString() == GetValueTyped(0).ToString())
+                    return true;
+                else 
+                    return false; 
+            ILDenseStorage<ElementType> denseStorage = obj as ILDenseStorage<ElementType>;
+            if (object.Equals(denseStorage,null))
+                return false;
+            return Equals(denseStorage);
+        }
+        /// <summary>
+        /// Test if this dense storage equals another dense storage.
+        /// </summary>
+        /// <param name="A">storage to compare this storage with</param>
+        /// <returns>True if all elements and dimension sizes match, false otherwise.</returns>
+        internal bool Equals(ILDenseStorage<ElementType> A) {
+            if (A == null) return false;
+            if (!A.Size.IsSameSize(m_size))
+                return false;
+            int len = m_size.NumberOfElements; 
+            if (typeof(ElementType).IsValueType) {
+                for (int i = 0; i < len;i++) {
+                    if (!GetValueTyped(i).Equals(A.GetValueTyped(i)))
+                        return false; 
+                }
+            } else {
+                // references may contain null element values! 
+                for (int i = 0; i < len;i++) {
+                    ElementType t1 = GetValueTyped(i); 
+                    if (t1 == null) {
+                        if (!A.GetValueTyped(i).Equals(null))
+                            return false; 
+                    } else {
+                        if (!t1.Equals(A.GetValueTyped(i))) 
+                            return false; 
+                    }
+                }
+            }
+            return true;
+        }
+        /// <summary>
+        /// generate a hash code based on the current arrays values
+        /// </summary>
+        /// <returns>hash code</returns>
+        /// <remarks>The hashcode is generated by taking the values currently stored in the array into account.
+        /// Therefore, the function must iterate over all elements in the array - which makes it somehow a expensive 
+        /// operation. Take this into account, if you consider using large arrays in collections like dictionaries 
+        /// or hashtables, which make great use of hash codes.</remarks>
+        public override int GetHashCode() {
+            if (IsDisposed) return base.GetHashCode();
+            int ret = Size.GetHashCode();
+            ElementType[] data = GetArrayForRead();
+            ret = (ret * 17) + data.Length;
+            foreach (ElementType t in data) {
+                ret = unchecked( ret * 17 );
+                if (t != null) 
+                    ret = unchecked(ret + t.GetHashCode());
+            }
+            return (int)ret;
+        }
+        #endregion
+
+        #region subarray + range get / set 
+        /// <summary>
+        ///	Alter values specified by range.
+        /// </summary>
+        /// <param name="range">ILRange specifying the dimensions/indices to be altered.</param>
+        /// <param name="values">new values</param>
+        /// <remarks>
+        /// The values pointed to by range will be replaced with the values 
+        /// found in 'values'. Important: the range cannot specify indices outside of my dimensions! 
+        /// Therefore, the storage must have been expanded in advance, if needed!</remarks>
+        public virtual void SetRange(ILRange range, ILDenseStorage<ElementType> values) {
+            if (range.Size.NumberOfElements == 0) return; 
+            int rangeDimLen = range.RangeArray.Length,higherDimSum = 0;
+            int leadDimLenRange = range[0].Count, leadDimLen = m_size[0]; 
+            int d, outElemCount = range.Size.NumberOfElements; 
+            ElementType[] myArr = GetArrayForWrite(); 
+            int[] idxArr = new int[rangeDimLen];    // used to store current position inside higher dims 
+            ILIntList[] rng = range.RangeArray; 
+            int[] seqDistances = m_size.GetSequentialIndexDistances(range.Size.NumberOfDimensions); 
+            int[] inFullDim = new int[rangeDimLen]; 
+            // initialize higher dimension summand and inFullDim[] flag array
+            for (int i = 1; i < idxArr.Length; i++) {
+                if (rng[i][0] < 0) {
+                    inFullDim[i] = rng[i][0]; 
+                } else {
+                    inFullDim[i] = 0; 
+                    higherDimSum += seqDistances[i] * rng[i][0]; 
+                }
+            }
+            //for (int lIdx = 0; lIdx < leadDimLenRange; lIdx ++) { 
+            //    retArr[curPosOut++] = myArr[higherDimSum + rleadDim[lIdx]]; 
+            //}
+            if (values.Size.NumberOfElements == 1) {
+#region scalar case 
+                ElementType scalar = values.GetValueTyped(0); 
+                while (true) {
+                    // copy along leading dimension
+                    for (int i = 0; i < rng[0].Count; i++) {
+                        if (rng[0][i] < 0) {
+                            for (int c = -rng[0][i]; c-- >= 0; ) {
+                                // we need a upward counter variable anyway, initialized with 
+                                // higherDimSum. So we simply take that and reset it after the loop: 
+                                myArr[ higherDimSum++ ] = scalar;  
+                            }
+                            higherDimSum += (rng[0][i]-1); // negative value in rng!  
+                        } else {
+                             myArr[ higherDimSum + rng[0][i] ] = scalar;
+                        }
+
+                    }
+                
+                    // increase higher dims 
+                    d = 1; 
+                    while  (d < idxArr.Length) {
+                        if (inFullDim[d] < 0)  {
+                            higherDimSum += seqDistances[d];  
+                            inFullDim[d]++; 
+                            break; 
+                        } 
+
+                        if (rng[d][idxArr[d]] >= 0) {
+                            higherDimSum -= (rng[d][idxArr[d]] * seqDistances[d]); 
+                        } else {
+                            higherDimSum += (rng[d][idxArr[d]] * seqDistances[d]); 
+                        }
+                        idxArr[d]++; 
+                        if (idxArr[d] == rng[d].Count) {
+                            idxArr[d] = 0;
+                            if (rng[d][0] < 0) {
+                                inFullDim[d] = rng[d][idxArr[d]];
+                            } else {
+                                higherDimSum += (rng[d][0] * seqDistances[d]);
+                            }
+                            d++; 
+                        } else if (rng[d][idxArr[d]] < 0) {
+                            inFullDim[d] = rng[d][idxArr[d]]; 
+                            break; 
+                        } else {
+                            higherDimSum += seqDistances[d] * rng[d][idxArr[d]]; 
+                            break; 
+                        }
+
+                    }
+                    if (d >= idxArr.Length) 
+                        break; 
+                }
+#endregion 
+            } else {
+#region non scalar case 
+                ElementType [] valuesArr = values.GetArrayForRead(); 
+                int valuesPos = 0; 
+                while (true) {
+                    // copy along leading dimension
+                    for (int i = 0; i < rng[0].Count; i++) {
+                        if (rng[0][i] < 0) {
+                            for (int c = -rng[0][i]; c-- >= 0; ) {
+                                myArr[ higherDimSum++ ] = valuesArr[ valuesPos++ ];  
+                            }
+                            higherDimSum += (rng[0][i]-1); // negative value in rng!  
+                        } else {
+                            myArr[ higherDimSum + rng[0][i] ] = valuesArr[ valuesPos++ ];
+                        }
+                    }
+                
+                    // increase higher dims 
+                    d = 1; 
+                    while  (d < idxArr.Length) {
+                        if (inFullDim[d] < 0)  {
+                            higherDimSum += seqDistances[d];  
+                            inFullDim[d]++; 
+                            break; 
+                        } 
+
+                        if (rng[d][idxArr[d]] >= 0) {
+                            higherDimSum -= (rng[d][idxArr[d]] * seqDistances[d]); 
+                        } else {
+                            higherDimSum += (rng[d][idxArr[d]] * seqDistances[d]); 
+                        }
+                        idxArr[d]++; 
+                        if (idxArr[d] == rng[d].Count) {
+                            idxArr[d] = 0;
+                            if (rng[d][idxArr[d]] < 0) {
+                                inFullDim[d] = rng[d][idxArr[d]];
+                            } else {
+                                higherDimSum += (rng[d][0] * seqDistances[d]);
+                            }
+                            d++; 
+                        } else if (rng[d][idxArr[d]] < 0) {
+                            inFullDim[d] = rng[d][idxArr[d]]; 
+                            break; 
+                        } else {
+                            higherDimSum += seqDistances[d] * rng[d][idxArr[d]]; 
+                            break; 
+                        }
+
+                    }
+                    if (d >= idxArr.Length) 
+                        break; 
+                }
+#endregion 
+            }
+        }
+
+        internal virtual void SetRangeFull(ILDenseStorage<ElementType> values) {
+            if (values.Size.NumberOfElements != 1 && values.Size.NumberOfElements != Size.NumberOfElements) 
+                throw new ILArgumentException("source and destination array must have the same number of arguments"); 
+            ElementType[] myArr = GetArrayForWrite(); 
+            if (values.Size.NumberOfElements == 1) {
+                ElementType scal = values.GetValueTyped(0); 
+                for (int i = 0; i < myArr.Length; i++) {
+                    myArr[i] = scal; 
+                }
+            } else {
+                ElementType[] valArr = values.GetArrayForRead(); 
+                System.Array.Copy(valArr,myArr,Size.NumberOfElements); 
+            }
+        }
+        
+
+        
+        /// <summary>
+        /// Alter elements of this storage adressed by sequential indices 
+        /// </summary>
+        /// <param name="indices">array specifying the elements to be altered, sequential indexing</param>
+        /// <param name="values">ILBaseArray of the same type than this array, holding the new values. 
+        /// The number of elements of storage must match the 
+        /// number of elements of indices. The only exception to this rule is if 'values' is a scalar array. The 
+        /// single value of 'values' is than used to set all elements addressed by 'indices'.</param>
+        /// <remarks><para>For empty arrays, scalar or vectors, indices outside the current bounds for 
+        /// this array will expand this array to the size neccessary. 
+        /// For other arrays the sequential indices given must fit inside this arrays dimensions. </para></remarks>
+        public virtual void SetRange(ILBaseArray<double> indices, ILDenseStorage<ElementType> values) {
+            //if (object.Equals(indices,null))
+            //    throw new ILArgumentException("indices given must not be null");
+            if (object.Equals(values, null))
+                throw new ILArgumentException("values given must not be null. Use A[ind] = null; if removal was intended.");
+            using (ILScope.Enter(indices)) {
+                #region set full shortcut
+                if (indices is ILFullRange || object.Equals(indices, null)) {
+                    int pos;
+                    ElementType[] myArray = GetArrayForWrite();
+                    if (values.Size.NumberOfElements == 1) {
+                        pos = Size.NumberOfElements;
+                        ElementType val = values.GetValueTyped(0);
+                        while (pos-- > 0)
+                            myArray[pos] = val;
+                    } else {
+                        if (values.Size.NumberOfElements != Size.NumberOfElements)
+                            throw new ILArgumentException("number of elements in source must match number of elements in destination array");
+                        pos = 0;
+                        foreach (ElementType val in values) {
+                            myArray[pos++] = val;
+                        }
+                    }
+                } else if (indices.Size.NumberOfElements != values.Size.NumberOfElements
+                    && values.Size.NumberOfElements != 1)
+                    throw new ILArgumentException("number of elements in source must match number of elements in destination array");
+                #endregion
+                if (indices.IsEmpty)
+                    return;
+                if (indices.Storage is ILDenseStorage< double>) {
+                    
+                    double maxIndex, minIndex;
+                    ILDenseStorage< double> indStorage = indices.Storage as ILDenseStorage< double>;
+                    indStorage.GetLimits(out minIndex, out maxIndex);
+                    if (minIndex < 0)
+                        throw new ILArgumentException("sequential indices can not be negative");
+                    if ((int)maxIndex >= m_size.NumberOfElements) {
+                        // handle resize
+                        if (m_size.NumberOfDimensions == 2) {
+                            if (m_size.NumberOfElements <= 1) {
+                                // scalar or empty -> expand along 1 
+                                ExpandArray(new int[] { (int)maxIndex + 1, 1 });
+                            } else if (m_size[0] > 1 && m_size[1] == 1) {
+                                ExpandArray(new int[] { (int)maxIndex + 1, 1 });
+                            } else if (m_size[0] == 1 && m_size[1] > 1) {
+                                ExpandArray(new int[] { 1, (int)maxIndex + 1 });
+                            } else
+                                throw new ILArgumentException("resizing array via sequential index access is supported for empty, scalar or vector only");
+                        } else
+                            throw new ILArgumentException("resizing array via sequential index access is supported for empty, scalar or vector only");
+                    }
+                    ElementType[] myArray = GetArrayForWrite();
+                    
+                    double[] indArray = indStorage.GetArrayForRead();
+
+                    int len = indices.Size.NumberOfElements;
+                    if (values.Size.NumberOfElements == 1) {
+                        ElementType scalarElement = values.GetValueTyped(0);
+                        for (int i = 0; i < len; ) {
+                            myArray[(int)indArray[i++]] = scalarElement;
+                        }
+                    } else {
+                        ElementType[] valArray = values.GetArrayForRead();
+                        for (int i = 0; i < len; ) {
+                            myArray[(int)indArray[i]] = valArray[i++];
+                        }
+                    }
+                } else {
+                    throw new ILArgumentException("storage type of given indices is not supported");
+                }
+            }
+        }  
+
+#region HYCALPER AUTO GENERATED CODE
+
+       
+        /// <summary>
+        /// Alter elements of this storage adressed by sequential indices 
+        /// </summary>
+        /// <param name="indices">array specifying the elements to be altered, sequential indexing</param>
+        /// <param name="values">ILBaseArray of the same type than this array, holding the new values. 
+        /// The number of elements of storage must match the 
+        /// number of elements of indices. The only exception to this rule is if 'values' is a scalar array. The 
+        /// single value of 'values' is than used to set all elements addressed by 'indices'.</param>
+        /// <remarks><para>For empty arrays, scalar or vectors, indices outside the current bounds for 
+        /// this array will expand this array to the size neccessary. 
+        /// For other arrays the sequential indices given must fit inside this arrays dimensions. </para></remarks>
+        public virtual void SetRange(ILBaseArray<Int64> indices, ILDenseStorage<ElementType> values) {
+            //if (object.Equals(indices,null))
+            //    throw new ILArgumentException("indices given must not be null");
+            if (object.Equals(values, null))
+                throw new ILArgumentException("values given must not be null. Use A[ind] = null; if removal was intended.");
+            using (ILScope.Enter(indices)) {
+                #region set full shortcut
+                if (indices is ILFullRange || object.Equals(indices, null)) {
+                    int pos;
+                    ElementType[] myArray = GetArrayForWrite();
+                    if (values.Size.NumberOfElements == 1) {
+                        pos = Size.NumberOfElements;
+                        ElementType val = values.GetValueTyped(0);
+                        while (pos-- > 0)
+                            myArray[pos] = val;
+                    } else {
+                        if (values.Size.NumberOfElements != Size.NumberOfElements)
+                            throw new ILArgumentException("number of elements in source must match number of elements in destination array");
+                        pos = 0;
+                        foreach (ElementType val in values) {
+                            myArray[pos++] = val;
+                        }
+                    }
+                } else if (indices.Size.NumberOfElements != values.Size.NumberOfElements
+                    && values.Size.NumberOfElements != 1)
+                    throw new ILArgumentException("number of elements in source must match number of elements in destination array");
+                #endregion
+                if (indices.IsEmpty)
+                    return;
+                if (indices.Storage is ILDenseStorage< Int64>) {
+                   
+                    Int64 maxIndex, minIndex;
+                    ILDenseStorage< Int64> indStorage = indices.Storage as ILDenseStorage< Int64>;
+                    indStorage.GetLimits(out minIndex, out maxIndex);
+                    if (minIndex < 0)
+                        throw new ILArgumentException("sequential indices can not be negative");
+                    if ((int)maxIndex >= m_size.NumberOfElements) {
+                        // handle resize
+                        if (m_size.NumberOfDimensions == 2) {
+                            if (m_size.NumberOfElements <= 1) {
+                                // scalar or empty -> expand along 1 
+                                ExpandArray(new int[] { (int)maxIndex + 1, 1 });
+                            } else if (m_size[0] > 1 && m_size[1] == 1) {
+                                ExpandArray(new int[] { (int)maxIndex + 1, 1 });
+                            } else if (m_size[0] == 1 && m_size[1] > 1) {
+                                ExpandArray(new int[] { 1, (int)maxIndex + 1 });
+                            } else
+                                throw new ILArgumentException("resizing array via sequential index access is supported for empty, scalar or vector only");
+                        } else
+                            throw new ILArgumentException("resizing array via sequential index access is supported for empty, scalar or vector only");
+                    }
+                    ElementType[] myArray = GetArrayForWrite();
+                   
+                    Int64[] indArray = indStorage.GetArrayForRead();
+
+                    int len = indices.Size.NumberOfElements;
+                    if (values.Size.NumberOfElements == 1) {
+                        ElementType scalarElement = values.GetValueTyped(0);
+                        for (int i = 0; i < len; ) {
+                            myArray[(int)indArray[i++]] = scalarElement;
+                        }
+                    } else {
+                        ElementType[] valArray = values.GetArrayForRead();
+                        for (int i = 0; i < len; ) {
+                            myArray[(int)indArray[i]] = valArray[i++];
+                        }
+                    }
+                } else {
+                    throw new ILArgumentException("storage type of given indices is not supported");
+                }
+            }
+        }  
+       
+        /// <summary>
+        /// Alter elements of this storage adressed by sequential indices 
+        /// </summary>
+        /// <param name="indices">array specifying the elements to be altered, sequential indexing</param>
+        /// <param name="values">ILBaseArray of the same type than this array, holding the new values. 
+        /// The number of elements of storage must match the 
+        /// number of elements of indices. The only exception to this rule is if 'values' is a scalar array. The 
+        /// single value of 'values' is than used to set all elements addressed by 'indices'.</param>
+        /// <remarks><para>For empty arrays, scalar or vectors, indices outside the current bounds for 
+        /// this array will expand this array to the size neccessary. 
+        /// For other arrays the sequential indices given must fit inside this arrays dimensions. </para></remarks>
+        public virtual void SetRange(ILBaseArray<Int32> indices, ILDenseStorage<ElementType> values) {
+            //if (object.Equals(indices,null))
+            //    throw new ILArgumentException("indices given must not be null");
+            if (object.Equals(values, null))
+                throw new ILArgumentException("values given must not be null. Use A[ind] = null; if removal was intended.");
+            using (ILScope.Enter(indices)) {
+                #region set full shortcut
+                if (indices is ILFullRange || object.Equals(indices, null)) {
+                    int pos;
+                    ElementType[] myArray = GetArrayForWrite();
+                    if (values.Size.NumberOfElements == 1) {
+                        pos = Size.NumberOfElements;
+                        ElementType val = values.GetValueTyped(0);
+                        while (pos-- > 0)
+                            myArray[pos] = val;
+                    } else {
+                        if (values.Size.NumberOfElements != Size.NumberOfElements)
+                            throw new ILArgumentException("number of elements in source must match number of elements in destination array");
+                        pos = 0;
+                        foreach (ElementType val in values) {
+                            myArray[pos++] = val;
+                        }
+                    }
+                } else if (indices.Size.NumberOfElements != values.Size.NumberOfElements
+                    && values.Size.NumberOfElements != 1)
+                    throw new ILArgumentException("number of elements in source must match number of elements in destination array");
+                #endregion
+                if (indices.IsEmpty)
+                    return;
+                if (indices.Storage is ILDenseStorage< Int32>) {
+                   
+                    Int32 maxIndex, minIndex;
+                    ILDenseStorage< Int32> indStorage = indices.Storage as ILDenseStorage< Int32>;
+                    indStorage.GetLimits(out minIndex, out maxIndex);
+                    if (minIndex < 0)
+                        throw new ILArgumentException("sequential indices can not be negative");
+                    if ((int)maxIndex >= m_size.NumberOfElements) {
+                        // handle resize
+                        if (m_size.NumberOfDimensions == 2) {
+                            if (m_size.NumberOfElements <= 1) {
+                                // scalar or empty -> expand along 1 
+                                ExpandArray(new int[] { (int)maxIndex + 1, 1 });
+                            } else if (m_size[0] > 1 && m_size[1] == 1) {
+                                ExpandArray(new int[] { (int)maxIndex + 1, 1 });
+                            } else if (m_size[0] == 1 && m_size[1] > 1) {
+                                ExpandArray(new int[] { 1, (int)maxIndex + 1 });
+                            } else
+                                throw new ILArgumentException("resizing array via sequential index access is supported for empty, scalar or vector only");
+                        } else
+                            throw new ILArgumentException("resizing array via sequential index access is supported for empty, scalar or vector only");
+                    }
+                    ElementType[] myArray = GetArrayForWrite();
+                   
+                    Int32[] indArray = indStorage.GetArrayForRead();
+
+                    int len = indices.Size.NumberOfElements;
+                    if (values.Size.NumberOfElements == 1) {
+                        ElementType scalarElement = values.GetValueTyped(0);
+                        for (int i = 0; i < len; ) {
+                            myArray[(int)indArray[i++]] = scalarElement;
+                        }
+                    } else {
+                        ElementType[] valArray = values.GetArrayForRead();
+                        for (int i = 0; i < len; ) {
+                            myArray[(int)indArray[i]] = valArray[i++];
+                        }
+                    }
+                } else {
+                    throw new ILArgumentException("storage type of given indices is not supported");
+                }
+            }
+        }  
+       
+        /// <summary>
+        /// Alter elements of this storage adressed by sequential indices 
+        /// </summary>
+        /// <param name="indices">array specifying the elements to be altered, sequential indexing</param>
+        /// <param name="values">ILBaseArray of the same type than this array, holding the new values. 
+        /// The number of elements of storage must match the 
+        /// number of elements of indices. The only exception to this rule is if 'values' is a scalar array. The 
+        /// single value of 'values' is than used to set all elements addressed by 'indices'.</param>
+        /// <remarks><para>For empty arrays, scalar or vectors, indices outside the current bounds for 
+        /// this array will expand this array to the size neccessary. 
+        /// For other arrays the sequential indices given must fit inside this arrays dimensions. </para></remarks>
+        public virtual void SetRange(ILBaseArray<Int16> indices, ILDenseStorage<ElementType> values) {
+            //if (object.Equals(indices,null))
+            //    throw new ILArgumentException("indices given must not be null");
+            if (object.Equals(values, null))
+                throw new ILArgumentException("values given must not be null. Use A[ind] = null; if removal was intended.");
+            using (ILScope.Enter(indices)) {
+                #region set full shortcut
+                if (indices is ILFullRange || object.Equals(indices, null)) {
+                    int pos;
+                    ElementType[] myArray = GetArrayForWrite();
+                    if (values.Size.NumberOfElements == 1) {
+                        pos = Size.NumberOfElements;
+                        ElementType val = values.GetValueTyped(0);
+                        while (pos-- > 0)
+                            myArray[pos] = val;
+                    } else {
+                        if (values.Size.NumberOfElements != Size.NumberOfElements)
+                            throw new ILArgumentException("number of elements in source must match number of elements in destination array");
+                        pos = 0;
+                        foreach (ElementType val in values) {
+                            myArray[pos++] = val;
+                        }
+                    }
+                } else if (indices.Size.NumberOfElements != values.Size.NumberOfElements
+                    && values.Size.NumberOfElements != 1)
+                    throw new ILArgumentException("number of elements in source must match number of elements in destination array");
+                #endregion
+                if (indices.IsEmpty)
+                    return;
+                if (indices.Storage is ILDenseStorage< Int16>) {
+                   
+                    Int16 maxIndex, minIndex;
+                    ILDenseStorage< Int16> indStorage = indices.Storage as ILDenseStorage< Int16>;
+                    indStorage.GetLimits(out minIndex, out maxIndex);
+                    if (minIndex < 0)
+                        throw new ILArgumentException("sequential indices can not be negative");
+                    if ((int)maxIndex >= m_size.NumberOfElements) {
+                        // handle resize
+                        if (m_size.NumberOfDimensions == 2) {
+                            if (m_size.NumberOfElements <= 1) {
+                                // scalar or empty -> expand along 1 
+                                ExpandArray(new int[] { (int)maxIndex + 1, 1 });
+                            } else if (m_size[0] > 1 && m_size[1] == 1) {
+                                ExpandArray(new int[] { (int)maxIndex + 1, 1 });
+                            } else if (m_size[0] == 1 && m_size[1] > 1) {
+                                ExpandArray(new int[] { 1, (int)maxIndex + 1 });
+                            } else
+                                throw new ILArgumentException("resizing array via sequential index access is supported for empty, scalar or vector only");
+                        } else
+                            throw new ILArgumentException("resizing array via sequential index access is supported for empty, scalar or vector only");
+                    }
+                    ElementType[] myArray = GetArrayForWrite();
+                   
+                    Int16[] indArray = indStorage.GetArrayForRead();
+
+                    int len = indices.Size.NumberOfElements;
+                    if (values.Size.NumberOfElements == 1) {
+                        ElementType scalarElement = values.GetValueTyped(0);
+                        for (int i = 0; i < len; ) {
+                            myArray[(int)indArray[i++]] = scalarElement;
+                        }
+                    } else {
+                        ElementType[] valArray = values.GetArrayForRead();
+                        for (int i = 0; i < len; ) {
+                            myArray[(int)indArray[i]] = valArray[i++];
+                        }
+                    }
+                } else {
+                    throw new ILArgumentException("storage type of given indices is not supported");
+                }
+            }
+        }  
+       
+        /// <summary>
+        /// Alter elements of this storage adressed by sequential indices 
+        /// </summary>
+        /// <param name="indices">array specifying the elements to be altered, sequential indexing</param>
+        /// <param name="values">ILBaseArray of the same type than this array, holding the new values. 
+        /// The number of elements of storage must match the 
+        /// number of elements of indices. The only exception to this rule is if 'values' is a scalar array. The 
+        /// single value of 'values' is than used to set all elements addressed by 'indices'.</param>
+        /// <remarks><para>For empty arrays, scalar or vectors, indices outside the current bounds for 
+        /// this array will expand this array to the size neccessary. 
+        /// For other arrays the sequential indices given must fit inside this arrays dimensions. </para></remarks>
+        public virtual void SetRange(ILBaseArray<float> indices, ILDenseStorage<ElementType> values) {
+            //if (object.Equals(indices,null))
+            //    throw new ILArgumentException("indices given must not be null");
+            if (object.Equals(values, null))
+                throw new ILArgumentException("values given must not be null. Use A[ind] = null; if removal was intended.");
+            using (ILScope.Enter(indices)) {
+                #region set full shortcut
+                if (indices is ILFullRange || object.Equals(indices, null)) {
+                    int pos;
+                    ElementType[] myArray = GetArrayForWrite();
+                    if (values.Size.NumberOfElements == 1) {
+                        pos = Size.NumberOfElements;
+                        ElementType val = values.GetValueTyped(0);
+                        while (pos-- > 0)
+                            myArray[pos] = val;
+                    } else {
+                        if (values.Size.NumberOfElements != Size.NumberOfElements)
+                            throw new ILArgumentException("number of elements in source must match number of elements in destination array");
+                        pos = 0;
+                        foreach (ElementType val in values) {
+                            myArray[pos++] = val;
+                        }
+                    }
+                } else if (indices.Size.NumberOfElements != values.Size.NumberOfElements
+                    && values.Size.NumberOfElements != 1)
+                    throw new ILArgumentException("number of elements in source must match number of elements in destination array");
+                #endregion
+                if (indices.IsEmpty)
+                    return;
+                if (indices.Storage is ILDenseStorage< float>) {
+                   
+                    float maxIndex, minIndex;
+                    ILDenseStorage< float> indStorage = indices.Storage as ILDenseStorage< float>;
+                    indStorage.GetLimits(out minIndex, out maxIndex);
+                    if (minIndex < 0)
+                        throw new ILArgumentException("sequential indices can not be negative");
+                    if ((int)maxIndex >= m_size.NumberOfElements) {
+                        // handle resize
+                        if (m_size.NumberOfDimensions == 2) {
+                            if (m_size.NumberOfElements <= 1) {
+                                // scalar or empty -> expand along 1 
+                                ExpandArray(new int[] { (int)maxIndex + 1, 1 });
+                            } else if (m_size[0] > 1 && m_size[1] == 1) {
+                                ExpandArray(new int[] { (int)maxIndex + 1, 1 });
+                            } else if (m_size[0] == 1 && m_size[1] > 1) {
+                                ExpandArray(new int[] { 1, (int)maxIndex + 1 });
+                            } else
+                                throw new ILArgumentException("resizing array via sequential index access is supported for empty, scalar or vector only");
+                        } else
+                            throw new ILArgumentException("resizing array via sequential index access is supported for empty, scalar or vector only");
+                    }
+                    ElementType[] myArray = GetArrayForWrite();
+                   
+                    float[] indArray = indStorage.GetArrayForRead();
+
+                    int len = indices.Size.NumberOfElements;
+                    if (values.Size.NumberOfElements == 1) {
+                        ElementType scalarElement = values.GetValueTyped(0);
+                        for (int i = 0; i < len; ) {
+                            myArray[(int)indArray[i++]] = scalarElement;
+                        }
+                    } else {
+                        ElementType[] valArray = values.GetArrayForRead();
+                        for (int i = 0; i < len; ) {
+                            myArray[(int)indArray[i]] = valArray[i++];
+                        }
+                    }
+                } else {
+                    throw new ILArgumentException("storage type of given indices is not supported");
+                }
+            }
+        }  
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+        /// <summary>
+        /// Create referencing or solid array from this array, with shifted dimensions.
+        /// </summary>
+        /// <param name="shift">Number of dimensions to shift the array.</param>
+        /// <returns>Shifted ILDenseStorage of the same type.</returns>
+        /// <remarks><para>Shift is done 'to the left'.</para></remarks>
+		public virtual ILDenseStorage<ElementType> ShiftDimensions (int shift) {
+            return CreateShiftedStorage(shift);
+        }
+
+        #endregion
+
+        #region Reshape, Concat, Repmat  - overriding ILBaseArray<ElementType>
+
+        /// <summary>
+        /// reshape <b>this</b> storage
+        /// </summary>
+        /// <param name="newDimensions">new dimensions of the storage.</param>
+        /// <remarks><para>This storage will be changed! The operation is cheap, since the 
+        /// number of elements (and their values) do not change. The same countable array
+        /// is used in conjunction with a new dimension specifier. </para>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the number of elements in 'newDimension'
+        /// do not match the number of elements in this storage.</exception>
+        internal void Reshape(ILSize newDimensions) {
+            if (newDimensions.NumberOfElements != m_size.NumberOfElements)
+                throw new ILArgumentSizeException ("the number of elements must not change");
+            m_size = newDimensions; 
+        }
+        /// <summary>
+        /// reshape <b>this</b> storage
+        /// </summary>
+        /// <param name="dims">new dimension length of the storage.</param>
+        /// <remarks><para>This storage will be changed! The operation is cheap, since the 
+        /// number of elements (and their values) do not change. The same underlying storage 
+        /// is used in conjunction with the new dimension specifier.</para>
+        /// </remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If the number of elements in 'newDimension'
+        /// do not match the number of elements in this storage.</exception>
+        public void Reshape(params int[] dims) {
+            ILSize newDimension = new ILSize(dims); 
+            Reshape(newDimension); 
+        }
+        /// <summary>
+        /// concatenate this storage 
+        /// </summary>
+        /// <param name="A">n dimensional storage</param>
+        /// <param name="dim">Index of dimension along which to concatenate the arrays.
+        /// If dim is larger than the number of dimensions of one of the arrays
+        /// its value will be used in modulus.</param>
+        /// <returns>Array having the size of both input arrays laid beside one 
+        /// another along the <paramref name="dim"/>'s-dimension</returns>
+        /// <remarks>The array returned will be a copy of both arrays involved. None 
+        /// of the input arrays will be altered.</remarks>
+        public virtual ILDenseStorage<ElementType> Concat(ILDenseStorage<ElementType> A, int dim) {
+            ILSize inDim = A.m_size;
+            for (int i = 0; i < Math.Max(inDim.NumberOfDimensions, m_size.NumberOfDimensions); i++) {
+                if (i != dim)
+                    if (m_size[i] != inDim[i])
+                        throw new ILArgumentSizeException("the length of dimensions of both arrays (except the dimension "
+                                            + "to be concatenated) must match");
+            }
+            // concatenate 
+            if (inDim.NumberOfElements == 1 && m_size.NumberOfElements == 1) {
+                // both scalars
+                int[] dims = new int[2] { 1, 1 };
+                dims[dim] = 2;
+                ElementType[] retArr = ILMemoryPool.Pool.New<ElementType>(2);
+                retArr[0] = m_data.Data[0];
+                retArr[1] = A.m_data.Data[0];
+                return CreateSelf(retArr, new ILSize(dims)); 
+            }
+            int lenOutArr = m_size.NumberOfElements + inDim.NumberOfElements;
+            int[] retDims = m_size.ToIntArray(dim+1);
+            retDims[dim] += inDim[dim];
+            ILSize retDimension = new ILSize(retDims);
+            ElementType[] retData = ILMemoryPool.Pool.New<ElementType>(retDimension.NumberOfElements);
+            ElementType[] myData = GetArrayForRead();
+            ElementType[] inData = A.GetArrayForRead(); 
+
+            int len1 = m_size.SequentialIndexDistance(dim + 1);
+            int len2 = inDim.SequentialIndexDistance(dim + 1);
+            int posOutArr = 0, inPos = 0, myPos = 0;
+            while (posOutArr < lenOutArr) {
+                for (int i = 0; i < len1; i++)
+                    retData[posOutArr++] = myData[myPos++]; 
+                for (int i = 0; i < len2; i++)
+                    retData[posOutArr++] = inData[inPos++]; 
+            }
+            return CreateSelf(retData,retDimension);
+        }
+
+        /// <summary>
+        /// Replicate this storage to create a larger array.
+        /// </summary>
+        /// <param name="sizes">Sizes description. This may be a 
+        /// list or an array of integer values. If the number of elements in <paramref name="sizes"/> is 
+        /// less the number of dimensions in this array, the trailing dimensions will 
+        /// be set to 1 (singleton dimensions). On the other hand, if the number specified 
+        /// is larger then the number of dimensions of this array, the result 
+        /// will have its number of dimensions extended accordingly. </param>
+        /// <returns>array which is made out of multiple copies of this array along 
+        /// specified dimensions, according to <paramref name="sizes"/>.</returns>
+        internal virtual ILDenseStorage<ElementType> Repmat(params int[] sizes) {
+            if (m_size.NumberOfElements == 0)
+                return CreateSelf(new ILSize(sizes));
+            ILRightSideRange rsRange = new ILRightSideRange(m_size, sizes);
+            return CreateSubarrayStorage(rsRange); 
+
+            
+            // experimental: via subindexing full dimensions 
+            //ILBaseArray[] dimArrays = new ILBaseArray[dims.Length];
+            //for (int i = 0; i < dimArrays.Length; i++) {
+            //    dimArrays[i] = ILMath.cell(ILMath.full)[ILMath.zeros(1,dims[i])]; 
+            //}
+            //return Subarray(dimArrays); 
+            
+            //build return dimensions
+            //int[] newDim = new int[Math.Max(dims.Length, m_dimensions.NumberOfDimensions)];
+            //for (int d = 0; d < newDim.Length; d++) {
+            //    if (d < dims.Length) {
+            //        newDim[d] = m_dimensions[d] * dims[d];
+            //    } else {
+            //        newDim[d] = m_dimensions[d];
+            //    }
+            //}
+            //ILSize outDim = new ILSize(true, newDim);
+            //if (m_dimensions.NumberOfElements == 0 || outDim.NumberOfElements == 0)
+            //    return new ILDenseStorage<ElementType>(new ILCountableArray<ElementType>(0), outDim);
+            //ILDenseStorage<ElementType> ret = new ILDenseStorage<ElementType>(
+            //                    new ILCountableArray<ElementType>(outDim.NumberOfElements), outDim);
+            //ElementType[] retArray = ret.GetArrayForWrite();
+            //ElementType[] myArray = GetArrayForRead();
+            //int[] outStrides = outDim.GetSequentialIndexDistances(m_dimensions.NumberOfDimensions); 
+            //int[] myStrides = m_dimensions.GetSequentialIndexDistances(m_dimensions.NumberOfDimensions); 
+            //retArray[0] = myArray[0];
+            //if (outDim.NumberOfElements < ILNumerics.Settings.s_minParallelElement1Count) {
+            //    for (int outPos = 1; outPos < outDim.NumberOfElements; ) {
+            //        int inPos = 0;
+            //        for (int d = m_dimensions.NumberOfDimensions; d-- > 0; ) {
+            //            inPos += ((outPos / outStrides[d]) % m_dimensions[d])
+            //                     * myStrides[d];
+            //        }
+            //        retArray[outPos++] = myArray[inPos];
+            //    }
+            //} else {
+            //    System.Threading.Tasks.Parallel.For(1,outDim.NumberOfElements, i => {
+            //        int inPos = 0;
+            //        for (int d = m_dimensions.NumberOfDimensions; d-- > 0; ) {
+            //            inPos += ((i / outStrides[d]) % m_dimensions[d])
+            //                     * myStrides[d];
+            //        }
+            //        retArray[i] = myArray[inPos];
+            //    }); 
+            //}
+            //return ret;
+        }
+
+        /// <summary>
+        /// Remove individual parts of a dimension from <b>this</b> storage
+        /// </summary>
+        /// <param name="dimension">index of the dimension, where <c>indices</c> are to be removed</param>
+        /// <param name="indices">indices to be removed from <paramref name="dimension"/>, -1 for "wipe" (make this an empty storage)</param>
+        /// <remarks>The function directly operates on <b>this</b> storage! After the function returns, 
+        /// this storage may have its dimensions changed!</remarks>
+        internal virtual void Remove(int dimension, ILIntList indices) {
+            using (ILScope.Enter()) {
+                if (dimension >= Size.NumberOfDimensions)
+                    throw new ILArgumentException("index out of range");
+                if (dimension == -1) {
+                    Data = new ILCountableArray<ElementType>(0);
+                    m_size = ILSize.Empty00;
+                    return;
+                }
+                // TODO: may should be replaced with a faster (&fancier? ) version... ??
+                ILBaseArray[] dims = new ILBaseArray[Size.NumberOfDimensions];
+                ILIntList keepInd = ILIntList.Create();
+                ILIntList remvInd = indices;
+                int max = Size[dimension];
+                foreach (int i in indices)
+                    if (i >= max || i < 0) throw new ILArgumentException("removal index out of range");
+                for (int i = 0; i < max; i++) {
+                    if (!remvInd.Contains(i)) {
+                        keepInd.Add(i);
+                    }
+                }
+                // we give the indices to _keep_ to the subarray function
+                int keepIndCount = keepInd.Count;
+                ILArray<int> remIndices = ILMath.array<int>(keepInd.GetArray(), new ILSize(1, keepIndCount));
+                if (remIndices.Size.NumberOfElements == Size[dimension]) {
+                    // nothing to do
+                    return;
+                }
+                for (int i = 0; i < dims.Length; i++) {
+                    dims[i] = ILMath.full;
+                }
+                dims[dimension] = remIndices;
+                ILDenseStorage<ElementType> ret = Subarray(dims);
+                Dispose();  // this will for reference element types (e.g. ILCell) also dispose the removed elements 
+                
+                Data = ret.Data;
+                m_size = ret.Size;
+                
+            }
+        }
+
+        #endregion
+
+        #region serialize 
+        /// <summary>
+        /// Prepare for serialization.
+        /// </summary>
+        /// <param name="context">Streaming Context - provided by the formatter.</param>
+        /// <remarks>nothing to do here</remarks>
+        [OnSerializing]
+        private void OnSerialize(StreamingContext context) {
+        }
+
+        /// <summary>
+        /// Post operations aftre deserializing is finished.
+        /// </summary>
+        /// <param name="context">Streaming context provided by the formatter.</param>
+        /// <remarks>nothing to do here</remarks>
+        [OnDeserialized]
+        void OnDeserialized(StreamingContext context) {
+        }
+
+        #endregion 
+
+        #region single element access 
+
+        /// <summary>
+        /// Get single value from this storage.
+        /// </summary>
+        /// <param name="idx">Integer array holding the dimension specifier</param>
+        /// <returns>Element at the position pointed to by idx.</returns>
+        internal override object GetValue(params int[] idx) {
+            return GetValueTyped(idx); 
+        }
+        /// <summary>
+        /// Get single value from this storage.
+        /// </summary>
+        /// <param name="idx">Integer array holding the dimension specifier</param>
+        /// <returns>Element at the position pointed to by idx.</returns>
+        internal override ElementType GetValueTyped(params int[] idx) {
+            if (idx.Length == 1)
+                return m_data.Data[idx[0]]; 
+            int destIdx = idx[0], d, highDims; 
+            if (destIdx >= m_size[0] || destIdx < 0)
+                    throw new ILArgumentException("GetValue: index out of bound for dimensions: 0");
+            int [] seqDist = m_size.GetSequentialIndexDistances(0); 
+            if (idx.Length <= m_size.NumberOfDimensions) {
+                for (d = 1; d < idx.Length - 1; d++) {
+                    if (idx[d] >= m_size[d] || idx[d] < 0)
+                        throw new ILArgumentException("GetValue: index out of bound for dimensions: " + d.ToString());
+                    destIdx += idx[d] * seqDist[d]; 
+                }
+                for (highDims = idx[d]; d<m_size.NumberOfDimensions && highDims > 0; d++) {
+                    destIdx += (highDims % m_size[d]) * seqDist[d]; 
+                    highDims /= m_size[d]; 
+                }
+                if (highDims > 0) throw new ILArgumentException ("GetValue: index out of bound!"); 
+                return m_data.Data[destIdx];
+            } else {
+                highDims = m_size.NumberOfDimensions; 
+                for (d = 1; d < highDims; d++) {
+                    if (idx[d] >= m_size[d] || idx[d] < 0)
+                        throw new ILArgumentException("GetValue: index out of bound for dimensions: " + d.ToString());
+                    destIdx += idx[d] * seqDist[d]; 
+                }
+                for (; d<idx.Length; d++) {
+                    if (idx[d] != 0) 
+                        throw new ILArgumentException("GetValue: index out of bound for dimension: " + d.ToString() + ". Trailing indices must be 0!");
+                }
+                return m_data.Data[destIdx];
+            }
+        }
+        internal override ILStorage GetValueAsStorage(params int[] innerIndices) {
+            return new ILDenseStorage<ElementType>(new ElementType[1] { GetValueTyped(innerIndices) }, ILSize.Scalar1_1);  
+        }
+        internal override ILBaseArray GetAsBaseArray() {
+            return new ILRetArray<ElementType>((ILDenseStorage<ElementType>)Clone());
+        }
+
+        /// <summary>
+        /// Get single value from this storage by a single sequential access.
+        /// </summary>
+        /// <param name="idx">Integer array holding the dimension specifier 
+        /// pointing to the value.</param>
+        /// <param name="dims">Out value: return position mapped to dimensions.</param>
+        /// <returns>Object in the position pointed to by idx.</returns>
+        /// <remarks>dims is the final position into the array for the sequential index specification <c>idx</c>.</remarks>
+        internal override object GetValueSeq(int idx, ref int[] dims) {
+            int IdxCpy = idx; 
+            for (int d = 0; d<m_size.NumberOfDimensions; d++) {
+                dims[d] = (IdxCpy % m_size[d]); 
+                IdxCpy /= m_size[d];  // must go to end, to fully clear dims
+            }
+            return m_data.Data[idx];
+        }
+        /// <summary>
+        /// Set single value to element at the specified index.
+        /// </summary>
+        /// <param name="value">New value.</param>
+        /// <param name="idx">Index of the element to be altered.</param>
+        internal override void SetValue(object value, params int[] idx) {
+            try {
+                SetValueTyped((ElementType)value, idx);
+            } catch (InvalidCastException) {
+                SetValueTyped((ElementType)Convert.ChangeType(value, typeof(ElementType)), idx);
+            }
+        }
+        /// <summary>
+        /// Set value of element at the specified position.
+        /// </summary>
+        /// <param name="value">new value</param>
+        /// <param name="idx">position of the element to be altered</param>
+        /// <remarks><para>This function does support automatic expansion of the array
+        /// if indices lay outside the dimension limits of the array. However, because 
+        /// of ambiguity reasons this is not reliable supported for vector sized arrays.</para></remarks>
+        internal override void SetValueTyped(ElementType value, params int[] idx) {
+            try {
+                if (idx.Length < 2) {
+                    if (idx.Length == 1) {
+                        if (idx[0] >= m_size.NumberOfElements)
+                            throw new IndexOutOfRangeException(); 
+                        GetArrayForWrite()[idx[0]] = value; 
+                    }
+                    return; 
+                }
+                int i = m_size.IndexFromArray(idx);
+                if (i >= m_size.NumberOfElements)
+                    throw new IndexOutOfRangeException(); 
+                GetArrayForWrite()[i] = (ElementType)value; 
+            } catch (Exception exc) {
+                if (exc is ILArgumentException 
+                    || exc is IndexOutOfRangeException ) {
+                    // expanding ?
+                    int [] dimensions = m_size.ToIntArray(Math.Max(idx.Length,m_size.NumberOfDimensions));  
+                    bool mustExpand = false; 
+                    int i = m_size.IndexFromArray(ref mustExpand, ref dimensions, idx);  
+                    if (mustExpand) {
+                        ExpandArray(dimensions);
+                        m_data.Data[i] = value;
+                    } else {
+                        throw;
+                    }
+                }
+            }
+        }
+
+        /// <summary>
+        /// [depricated] Convert index array into sequential index for storage access.
+        /// </summary>
+        /// <param name="idx">int array with dimension specification.</param>
+        /// <returns>Index of requested value inside the solid storage. This 
+        /// value can directly be used to query the corresponding value via GetArrayForRead()[return_value].
+        /// </returns>
+        /// <remarks><b>This function is deprecated! Use <see cref="ILNumerics.ILSize.IndexFromArray(int[])"/> instead!</b><br/>
+        /// If the length of idx is smaler than the number of dimensions 
+        /// of this storage, the trailing dimensions will be replaced with "0". I.e 
+        /// the first index of each non specified dimension will be used. 
+        /// If length of idx is larger than the dimensions of this storage, the behavior
+        /// is undefined. Therefore this function should be enclosed in try, catch blocks 
+        /// to handle this case!</remarks>
+        internal int getBaseIndex(params int[] idx) {
+            // arghs! -> ugly! piuh!!
+            if (idx == null) throw new ILArgumentException("indices specified must not be null"); 
+            if (idx.Length < m_size.NumberOfDimensions) {
+                bool dummy; 
+                int [] tmp = ILMemoryPool.Pool.New<int>(m_size.NumberOfDimensions,true, out dummy); 
+                for (int i = 0; i < idx.Length; i++) {
+                    tmp[i] = idx[i]; 
+                }
+                return m_size.IndexFromArray(tmp);
+            }
+            return m_size.IndexFromArray(idx); 
+        }
+        /// <summary>
+        /// [depricated] Convert index array into sequential index for storage access. Ommit any bound checking. 
+        /// </summary>
+        /// <param name="idx">int array with dimensions specification.</param>
+        /// <param name="MustExpand">Output parameter. On return determine, if the index 
+        /// specification points outside of the dimensions of this ILDenseStorage and the array 
+        /// must be expanded before accessing elements on that position.</param>
+        /// <param name="dimensions">if the array was found to be expanded, this are the 
+        /// needed dimension sizes for the new array. The sizes are computed from the range 
+        /// specification given.</param>
+        /// <returns>Index of requested value inside the solid storage. This 
+        /// value may directly be used to query the value via m_data[return_value].
+        /// The value returned is valid for solid storages as well as for reference 
+        /// storages.
+        /// </returns>
+        /// <remarks>
+        /// <para>idx must be not null and must contain at least one element.</para>
+        /// <para>If the length of idx is smaler than the number of dimensions 
+        /// of this storage, the trailing dimensions will be replaced with "0". I.e 
+        /// the first index of each non specified dimensions will be used. 
+        /// If length of idx is larger than the dimensions of this storage, the index of 
+        /// the expanded array will be returned.</para></remarks>
+        internal int getBaseIndex(ref bool MustExpand, ref int[] dimensions, params int[] idx) {
+            int destIdx = 0;
+            if (idx.Length == 1) {
+                destIdx = idx[0]; 
+                if (destIdx < 0)
+                    throw new ILArgumentException("check index for dimension 0!");
+                if (destIdx >= m_size.NumberOfElements) {
+                    MustExpand = true; 
+                    dimensions[0] = destIdx + 1; 
+                }
+                return destIdx;
+            }
+            return m_size.IndexFromArray(ref MustExpand, ref dimensions, idx);
+        }
+        /// <summary>
+        /// Copy values of all elements into System.Array.
+        /// </summary>
+        /// <param name="result">System.Array, holding all element values of this ILDenseStorage.</param>
+        /// <remarks>The System.Array may be predefined. If its length is sufficient, it will be used and 
+        /// its leading elements will be overwritten when function returns. If 'result' is null or has too few elements, 
+        /// it will be recreated from the ILNumerics memory pool.</remarks>
+        public void ExportValues(ref ElementType[] result) {
+            if (result == null || result.Length < m_size.NumberOfElements)
+                result = ILMemoryPool.Pool.New<ElementType>(m_size.NumberOfElements);
+            int pos = 0; 
+            foreach (ElementType v in this) {
+                result[pos++] = v; 
+            }
+        }
+        /// <summary>
+        /// Get direct reference to inner System.Array storage for <b>write access</b>
+        /// </summary>
+        /// <returns>reference to inner System.Array</returns>
+        /// <remarks>Altering this array can be done directly. If necessary, the array is detached before 
+        /// returned. Watch the column order format of storages in ILNumerics! Keep in minds, the length 
+        /// of the array may exceeds the number of elements.
+        /// <para>Accessing the inner system array directly should be left to ILNumerics experts only! 
+        /// Unless you really know, what you are doing, you should rather use the higher order access 
+        /// methods provided by ILArray&lt;T>! (You have been warned!)</para></remarks>
+        internal ElementType[] GetArrayForWrite() {
+            if (m_data.ReferenceCount > 1) {
+                Detach(); 
+            }
+            return m_data.Data; 
+        }
+        /// <summary>
+        /// Get direct reference to inner System.Array storage for <b>read access</b>
+        /// </summary>
+        /// <returns>reference to inner System.Array for reading</returns>
+        /// <remarks>This method is provided for experts only! Altering elements of this 
+        /// array may cause the data to be invalidated or corrupted! Use this array only for reading! Note 
+        /// the ILNumerics array storage format (column major). Keep in mind, the length 
+        /// of the array may exceeds the number of elements! 
+        /// <para>Accessing the inner system array directly should be left to ILNumerics experts only! 
+        /// Unless you really know, what you are doing, you should rather use the higher order access 
+        /// methods provided by ILArray&lt;T>! (You have been warned!)</para></remarks>
+        internal ElementType[] GetArrayForRead() {
+            //if (PendingTasks > 0) 
+            //    System.Threading.SpinWait.SpinUntil(() => { return PendingTasks == 0; });
+            return m_data.Data; 
+        }
+
+        #endregion 
+
+        /// <summary>
+        /// Create lazy,shallow copy of this array 
+        /// </summary>
+        /// <returns>ILDenseStorage as copy of this storage.</returns>
+        /// <remarks>The ILDenseStorage object returned will be of the same size and type than this object.
+        /// <para>The copy is done lazy. This means, the new storage will at first share the memory 
+        /// with that storage. This will take almost no memory / processor time. As soon as attempts 
+        /// are made to <b>alter</b> the new storage, it will be detached from this storage and use own memeory.</para></remarks>
+        internal override ILStorage Clone() { 
+            return CreateSelf(m_data,m_size); 
+        }
+        internal ILCountableArray<ElementType> GetDataArray() {
+            return m_data;
+        }
+        internal virtual void IndexSubrange(ILDenseStorage<ElementType> value, ILBaseArray[] range) {
+            using (ILScope.Enter(range)) {
+                if (Object.ReferenceEquals(value, null) || value.Size.NumberOfElements == 0) {
+                    #region remove
+                    if (range == null) return;
+
+                    ILLeftSideRange rng = new ILLeftSideRange(Size, range);
+                    if (rng.Expanding) {
+                        throw new ILArgumentException("invalid range for removal specified");
+                    }
+                    if (rng.Size.NumberOfElements == 0) {
+                        return;
+                    }
+                    int nonFullDims = 0;
+                    int dimIdx = -1;
+                    // check validity
+                    for (int i = 0; i < rng.RangeArray.Length; i++) {
+                        if (rng[i].Count != 1 || rng[i][0] >= 0) {
+                            if (++nonFullDims > 1)
+                                throw new ILArgumentException("for removal only one dimension can be 'non-full'");
+                            dimIdx = i;
+                            foreach (int ind in rng[i]) {
+                                if (ind < 0) {
+                                    throw new ILArgumentException("invalid removal indices: all but at most one dimensions must be specified as 'full'. check dimension #" + i.ToString());
+                                }
+                            }
+                        }
+                    }
+                    // remove
+                    ILSize newDim = new ILSize(Size.ToIntArrayEx(rng.RangeArray.Length));
+                    ILSize oldDimensions = Size;
+                    try {
+                        Reshape(newDim); // <- cheap!
+                        if (dimIdx >= 0) {
+                            Remove(dimIdx, rng[dimIdx]); // <- expensive! 
+                        } else {
+                            // all dims full specified
+                            Remove(dimIdx, null); // <- expensive! 
+                        }
+                    } catch (Exception) {
+                        Reshape(oldDimensions);
+                        throw;
+                    }
+                    #endregion
+                } else {
+                    #region setrange
+                    if (range == null || range.Length == 0) {
+                        return;
+                    } else if (range.Length == 1) {
+                        if (range[0] is ILDenseArray<double>) {
+                            SetRange(range[0] as ILDenseArray<double>, value);
+                            return;
+                        } else if (range[0] is ILDenseArray<string>) {
+                            // special case? A[":;0:3;0:end;..."] -> multiple dimensions given as single string
+                            string indStr = (string)(range[0] as ILDenseArray<string>).GetValue(0);
+                            string[] dimParts = indStr.Split(';');
+                            if (dimParts.Length == 0) {
+                                // empty range given 
+                                return;
+                            } else if (dimParts.Length > 1) {
+                                range = new ILBaseArray[dimParts.Length];
+                                for (int i = 0; i < dimParts.Length; i++) {
+                                    range[i] = dimParts[i];
+                                } 
+                                // re-enter function to push the new arrays into scope
+                                IndexSubrange(value,range); 
+                                return; 
+                            } else {
+                                ILBaseArray indices = ILRange.ParseDimension(indStr, Size.NumberOfElements);
+                                if (indices is ILBaseArray<Misc.ILFullRange>) {
+                                    SetRangeFull(value);
+                                } else {
+                                    SetRange(indices as ILDenseArray<int>, value);
+                                }
+                                return;
+                            }
+                        } else if (range[0] is ILDenseArray<float>) {
+                            SetRange(range[0] as ILDenseArray<float>, value);
+                            return;
+                        } else if (range[0] is ILDenseArray<Int32>) {
+                            SetRange(range[0] as ILDenseArray<Int32>, value);
+                            return;
+                        } else if (range[0] is ILDenseArray<Int64>) {
+                            SetRange(range[0] as ILDenseArray<Int64>, value);
+                            return;
+                        } else if (range[0] is ILLogical) {
+                            SetRange(ILNumerics.ILMath.find(range[0] as ILLogical), value);
+                            return;
+                        } else if (range[0] is ILRetLogical) {
+                            SetRange(ILNumerics.ILMath.find(range[0] as ILRetLogical), value);
+                            return;
+                        }
+                    }
+                    ILLeftSideRange rng = new ILLeftSideRange(Size, range);
+                    if (rng.Expanding) {
+                        ExpandArray(rng);
+                    }
+                    SetRange(rng, value);
+                    #endregion
+                }
+            }
+        }
+
+        #region IEnumerable<ILBaseArray<ElementType>> Member
+
+        /// <summary>
+        /// enumerator returning elements as ElementType
+        /// </summary>
+        public override IEnumerator<ElementType> GetEnumerator ( ) {
+            int len = m_size.NumberOfElements; 
+            ElementType[] myData = GetArrayForRead(); 
+            for (int i = 0; i < len; i++) 
+                yield return myData[i];
+        }
+        #endregion
+
+        #region private helper 
+        /// <summary>
+        /// helper function to gather some parameters for partial dimension removal 
+        /// </summary>
+        /// <param name="rng">object with index specifications. May be of 
+        /// type ILBaseArray[] with numeric arrays or a string array according 
+        /// to the format of <see cref="ILNumerics.Storage.ILRange"/>. 
+        /// </param>
+        /// <param name="dimensionIdx">Out parameter: index of dimension the indices to be removed lie in.</param>
+        /// <param name="indices">Indices to be removed.</param>
+        /// <param name="dimensions">Dimension structure, can be used to reshape the storage <b>before</b> the removal</param>
+        /// <remarks>If range comprises a range dimension specification which is smaller than 
+        /// the actual number of dimension of this storage, the storage must be reshaped in advance of the removal. 
+        /// This reshaping proccess will <b>not</b> be done inside this function! However 
+        /// the <c>dimension</c> value returned reflects the size of the storage before removing and therefore
+        /// can be utilized for reshaping the storage.</remarks>
+        /// <exception cref="ILNumerics.Exceptions.ILArgumentException">If:<list type="bullet">
+        /// <item>The length of range exceeds the dimensions of this storage.</item>
+        /// <item>More than one or less than one dimension of <c>range</c> was not null.</item>
+        /// <item>The type of range was invalid, or</item>
+        /// <item>Range is of type <see cref="ILNumerics.ILBaseArray"/>, but the element type is not numeric</item>
+        /// </list></exception>
+        internal void ExtractRemovalParameter(ILBaseArray[] rng, out int dimensionIdx, ref ILIntList indices, out ILSize dimensions) {
+            dimensionIdx = 0;
+            dimensions = null;
+            if (rng.Length > m_size.NumberOfDimensions)
+                throw new ILArgumentException("Error removing: dimension specification exceeds matrix dimensions.");
+            int specCount = 0;
+            int tmp = 0;
+            if (rng.Length == 1 && rng[0] is ILBaseArray<string>) {
+                string allRangeString = (string)(rng[0] as ILBaseArray<string>).GetValue(0);
+                string[] ranges = allRangeString.Split(';'); 
+                if (ranges.Length > 1) {
+                    rng = new ILBaseArray[ranges.Length];
+                    for (int i = 0; i < ranges.Length; i++) {
+                        rng[i] = ranges[i]; 
+                    }
+                }
+            }
+            int[] outDim = Size.GetReshapedSize(rng.Length); 
+            for (int i = 0; i < rng.Length; i++) {
+                if (object.Equals(rng[i], null)) {
+                    // nothing to remove
+                    if (indices != null) {
+                        indices.Clear(); 
+                    }
+                    return; 
+                } else if (!rng[i].IsEmpty) {
+                    if (rng[i] is ILDenseArray<string>) {
+                        string stringVal = (rng[i] as ILDenseArray<string>).GetValue(0);  
+                        ILBaseArray indFromString = ILRange.ParseDimension(stringVal,outDim[i]);
+                        if (!(indFromString is ILBaseArray<ILFullRange>)) {
+                            if (specCount++ > 0) {
+                                throw new ILArgumentException("only one dimension can be non-fully specified for removal");
+                            }
+                            dimensionIdx = i;
+                            indices = new ILIntList(indFromString as ILDenseArray<int>);
+                        }
+                        continue; 
+                    } 
+                    dimensionIdx = i;
+                    if (specCount++ > 0) {
+                        throw new ILArgumentException("only one dimension can be non-fully specified for removal");
+                    }
+                    if (rng[i] is ILBaseArray<Expression>) {
+                        // A[end + ...] given
+                        Expression expr = (rng[i] as ILBaseArray<Expression>).GetValue(0); 
+                        int exprVal = ILExpression.Evaluate(expr, Size[i] - 1); 
+                        indices = ILIntList.Create();
+                        for (int p = 0; p < tmp; p++) {
+                            indices.Add(exprVal);
+                        }
+                    } else if (rng[i] is ILLogical) {
+                        ILArray<double> ind = ILNumerics.ILMath.find((ILLogical) rng[i]);
+                        tmp = ind.Size.NumberOfElements;
+                        indices = ILIntList.Create();
+                        for (int p = 0; p < tmp; p++) {
+                            indices.Add((int)ind.GetValue(p));
+                        }
+                    } else if (rng[i] is ILRetLogical) {
+                        ILArray<double> ind = ILNumerics.ILMath.find((ILRetLogical) rng[i]);
+                        tmp = ind.Size.NumberOfElements;
+                        indices = ILIntList.Create();
+                        for (int p = 0; p < tmp; p++) {
+                            indices.Add((int)ind.GetValue(p));
+                        }
+
+/* !HC:TYPELIST:
+<hycalper>
+<type>
+<source locate="after">
+    inArr1
+</source>
+<destination>float</destination>
+<destination>Int16</destination>
+<destination>Int32</destination>
+<destination>Int64</destination>
+<destination>byte</destination>
+</type>
+</hycalper>
+*/
+
+                    } else if (rng[i] is ILDenseArray<double> ) {
+                        ILDenseArray<double> ind = rng[i] as ILDenseArray<double> ;
+                        tmp = ind.Size.NumberOfElements;
+                        indices = ILIntList.Create();
+                        for (int p = 0; p < tmp; p++) {
+                            indices.Add((int)ind.GetValue(p));
+                        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+/* !HC:TYPELIST:
+
+*/
+
+                    } else if (rng[i] is ILDenseArray<byte> ) {
+                        ILDenseArray<byte> ind = rng[i] as ILDenseArray<byte> ;
+                        tmp = ind.Size.NumberOfElements;
+                        indices = ILIntList.Create();
+                        for (int p = 0; p < tmp; p++) {
+                            indices.Add((int)ind.GetValue(p));
+                        }
+/* !HC:TYPELIST:
+
+*/
+
+                    } else if (rng[i] is ILDenseArray<Int64> ) {
+                        ILDenseArray<Int64> ind = rng[i] as ILDenseArray<Int64> ;
+                        tmp = ind.Size.NumberOfElements;
+                        indices = ILIntList.Create();
+                        for (int p = 0; p < tmp; p++) {
+                            indices.Add((int)ind.GetValue(p));
+                        }
+/* !HC:TYPELIST:
+
+*/
+
+                    } else if (rng[i] is ILDenseArray<Int32> ) {
+                        ILDenseArray<Int32> ind = rng[i] as ILDenseArray<Int32> ;
+                        tmp = ind.Size.NumberOfElements;
+                        indices = ILIntList.Create();
+                        for (int p = 0; p < tmp; p++) {
+                            indices.Add((int)ind.GetValue(p));
+                        }
+/* !HC:TYPELIST:
+
+*/
+
+                    } else if (rng[i] is ILDenseArray<Int16> ) {
+                        ILDenseArray<Int16> ind = rng[i] as ILDenseArray<Int16> ;
+                        tmp = ind.Size.NumberOfElements;
+                        indices = ILIntList.Create();
+                        for (int p = 0; p < tmp; p++) {
+                            indices.Add((int)ind.GetValue(p));
+                        }
+/* !HC:TYPELIST:
+
+*/
+
+                    } else if (rng[i] is ILDenseArray<float> ) {
+                        ILDenseArray<float> ind = rng[i] as ILDenseArray<float> ;
+                        tmp = ind.Size.NumberOfElements;
+                        indices = ILIntList.Create();
+                        for (int p = 0; p < tmp; p++) {
+                            indices.Add((int)ind.GetValue(p));
+                        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+                   } else
+                        throw new ILArgumentTypeException("error removing: invalid dimensions specifier, dimension #" + i.ToString());
+                }
+            }
+            if (indices == null) {
+                dimensionIdx = 0;
+                dimensions = m_size;
+                //indices = new int[0] { };
+                return;
+            }
+            // if only one dimension specified -> make row vector
+            //if (rng.Length < 2) {
+            //    outDim[1] = outDim[0];
+            //    outDim[0] = 1;
+            //    dimensionIdx = 1;
+            //}
+            dimensions = new ILSize(outDim);
+        }
+
+        /// <summary>
+        /// Expanded <b>this</b> storage for index addressing outside of my dimensions
+        /// </summary>
+        /// <param name="range">range specification with size for destination array</param>
+        internal void ExpandArray (ILLeftSideRange range) {
+            int[] outDims; 
+            int i= 0;
+            ILSize outDimensions; 
+            if (range.Size.NumberOfDimensions > m_size.NumberOfDimensions) {
+                outDims = new int[range.Size.NumberOfDimensions]; 
+                for (; i < m_size.NumberOfDimensions; i ++) {
+                    outDims[i] = (range.ExpandDimensions[i] > m_size[i]) ?
+                        range.ExpandDimensions[i] : m_size[i]; 
+                }
+                for(; i < range.Size.NumberOfDimensions; i++) 
+                    outDims[i] = range.ExpandDimensions[i];
+            } else {
+                outDims = new int[m_size.NumberOfDimensions]; 
+                for (; i < range.Size.NumberOfDimensions; i ++) {
+                    outDims[i] = (range.ExpandDimensions[i] > m_size[i]) ?
+                        range.ExpandDimensions[i] : m_size[i]; 
+                }
+                for(; i < m_size.NumberOfDimensions; i++) 
+                    outDims[i] = m_size[i];
+            }
+            outDimensions = new ILSize(outDims); 
+            ElementType [] outData = ILMemoryPool.Pool.New<ElementType>(outDimensions.NumberOfElements); 
+            // transfer old data to new array
+            int [] tmpIdx = new int[outDims.Length]; 
+            for (i = 0; i < m_size.NumberOfElements; i++) {
+                ElementType tmp = (ElementType)GetValueSeq(i,ref tmpIdx); 
+                outData[outDimensions.IndexFromArray(tmpIdx)] = tmp; 
+            }
+            // exchange my data 
+            Data = new ILCountableArray<ElementType>(outData, outDimensions.NumberOfElements); 
+            m_size = outDimensions; 
+        }
+        /// <summary>
+        /// Expand <b>this</b> storage for index addressing outside of my dimensions
+        /// </summary>
+        /// <param name="indices">sizes of dimensions for the new storage</param>
+        protected void ExpandArray(int[] indices) {
+            if (indices.Length == 2 && (indices[0] * indices[1] == 0)) {
+               if (indices[0] > 0) 
+                   indices[1] = 1; 
+               else if (indices[1] > 0) 
+                   indices[0] = 1; 
+            }
+            ILSize outDimensions = new ILSize(indices); 
+            bool cleared; 
+            ElementType [] outData = ILMemoryPool.Pool.New<ElementType>(outDimensions.NumberOfElements,true,out cleared); 
+            // transfer old data to new array
+            int [] tmpIdx = new int[indices.Length]; 
+            for (int i = 0; i < m_size.NumberOfElements; i++) {
+                ElementType tmpData = (ElementType)GetValueSeq(i,ref tmpIdx); 
+                outData[outDimensions.IndexFromArray(tmpIdx)] = tmpData; 
+            }
+            // replace with my data
+            Data = new ILCountableArray<ElementType>(outData,outDimensions.NumberOfElements); 
+            m_size = outDimensions; 
+        }
+        /// <summary>
+        /// Copy upper triangular part of this array into new solid array.
+        /// </summary>
+        /// <param name="n">Length of first dimension of destination array.</param>
+        /// <returns>Solid array of size [n x {ThisColumnCount})].</returns>
+        internal ILDenseStorage<ElementType> copyUpperTriangle(int n) {
+            ILDenseStorage<ElementType> ret = new ILDenseStorage<ElementType>(new ILSize(n,n)); 
+            ElementType[] arr = ret.GetArrayForWrite();
+            ElementType[] myData = GetArrayForRead();
+            if (m_size[0] == n) {
+                for (int rcount = 0 , pos = 0; rcount < n; rcount++) {
+                    for (int i = 0; i <= rcount; i++) {
+                        arr[pos] = myData[pos++];
+                    }
+                    pos += (n - rcount - 1);
+                }
+            } else {
+                for (int rcount = 0 , posIn = 0, posOut = 0, lenA = m_size[0]; rcount < n; rcount++) {
+                    for (int i = 0; i <= rcount; i++) {
+                        arr[posOut++] = myData[posIn++];
+                    }
+                    posOut += (n - rcount - 1);
+                    posIn += (lenA - rcount - 1);
+                }
+            }
+            return ret;
+        }
+        /// <summary>
+        /// Copy lower triangular part of this array into new solid array.
+        /// </summary>
+        /// <returns>Solid array of same size than this array.</returns>
+        /// <remarks>If this is not a 2D array, only the first dimension is referenced.</remarks>
+        internal ILDenseStorage<ElementType> copyLowerTriangle() {
+            int n = m_size[0],pos = 0; 
+            ILDenseStorage<ElementType> ret = new ILDenseStorage<ElementType>(new ILSize(n,n)); 
+            ElementType[] arr = ret.GetArrayForRead();
+            ElementType[] myData = GetArrayForRead();
+            for (int c = 0; c < m_size[1]; c++) {
+                pos += c;
+                for (int r = c; r < n; r++,pos++) {
+                    arr[pos] = myData[pos];
+                    pos++; 
+                } 
+            }
+            return ret; 
+        }
+
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Storage/ILDenseStorage_Constructors.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Storage/ILDenseStorage_Constructors.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Storage/ILDenseStorage_Constructors.cs	(revision 9102)
@@ -0,0 +1,473 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.IO; 
+using System.Linq.Expressions;
+using System.Runtime.Serialization; 
+using ILNumerics;
+using ILNumerics.Misc;
+using ILNumerics.Data;
+using ILNumerics.Exceptions;
+
+namespace ILNumerics.Storage {
+
+    [System.Diagnostics.DebuggerTypeProxy(typeof(ILNumerics.Misc.ILArrayDebuggerProxy<>))]
+    [System.Diagnostics.DebuggerDisplay("{ShortInfo(),nq}")]
+    internal partial class ILDenseStorage<ElementType> : ILStorage<ElementType> {
+        
+        #region Constructors
+        /// <summary>
+        /// create new dense storage
+        /// </summary>
+        /// <param name="system_array">countable array</param>
+        /// <param name="dimensions">dimensions</param>
+        internal ILDenseStorage(ElementType[] system_array, ILSize dimensions) 
+            : base(dimensions) {
+                if (system_array == null || dimensions == null) 
+                throw new ILArgumentException("system array and dimensions parameter may not be null");
+#if DEBUG
+            //DebuggerTraceHelper.Output.Append("\r\nILDenseStorage(ElementType[],dim) : "); 
+            //var m = new System.Diagnostics.StackTrace().GetFrame(1).GetMethod();
+            //DebuggerTraceHelper.Output.Append(String.Format("Called from: {1} - {0}",m.ToString(),m.ReflectedType.Name)); 
+#endif
+            m_data = new ILCountableArray<ElementType>(system_array,dimensions.NumberOfElements); 
+            m_data.IncreaseReference(); 
+        }
+        internal ILDenseStorage(ILCountableArray<ElementType> countableArray, ILSize dimensions) 
+            : base(dimensions) {
+                if (countableArray == null || dimensions == null) 
+                throw new ILArgumentException("countableArray and dimensions parameter may not be null");
+            m_data = countableArray; 
+            m_data.IncreaseReference(); 
+        }
+        internal ILDenseStorage(ILSize dimensions) 
+            : base(dimensions) {
+            m_data = new ILCountableArray<ElementType>(dimensions.NumberOfElements,true); 
+            m_data.IncreaseReference(); 
+        }
+        #endregion
+
+        #region Destructor + Dispose
+
+        /// <summary>
+		/// dispose this storage
+		/// </summary>
+		/// <remarks><para>Calling Dispose should be the last method called for an ILDenseStorage.</para></remarks>
+        internal override void Dispose(bool manual) {
+
+#if VERBOSE
+            System.Diagnostics.Debug.WriteLine("Disposing " + this.GetHashCode() + " called from: " + getCallee() ); 
+#endif 
+            if (manual) {
+                if (Settings.s_measurePerformanceAtRuntime && m_size.NumberOfElements >= ILMemoryPool.Pool.MinArrayLength<ElementType>()) {
+                    ILMemoryPoolInternal<ElementType>.s_performanceCounters.PCDisposedHighIncrement(); 
+                }
+            }
+            if (!IsDisposed) {
+                if (m_data != null) {
+#if DEBUG
+                    //DebuggerTraceHelper.Output.Append(String.Format("\r\nDenseStorage Dispose HashCode: " + GetHashCode())); 
+#endif
+                    m_data.DecreaseReference(); 
+                    m_data = null; 
+                }
+            } 
+        }
+        /// <summary>
+        /// detach this storage: copy its countable array if necessary
+        /// </summary>
+        protected virtual void Detach() {
+            if (m_data.ReferenceCount <= 1) 
+                return; 
+            Data = m_data.CreateCopy(); 
+        }
+        #endregion
+
+        #region Subarray interface
+        /// <summary>
+        ///	Subarray from this array
+        /// </summary>
+        /// <param name="range"> arrays specifying the ranges to create subarray from</param>
+        /// <returns>subarray as specified</returns>
+        internal virtual ILDenseStorage<ElementType> Subarray (params ILBaseArray[] range) {
+            if (range.Length == 0) {
+                return CreateSelf(ILSize.Empty00);
+            } else if (range.Length == 1) {
+                #region sequential index access
+                if (object.Equals(range[0],null)) {
+                    return CreateSelf(ILSize.Empty00);
+                } else if (range[0] is ILBaseArray<ILFullRange>) {
+                    return CreateSubarrayStorageFull(); 
+                } else if (range[0] is ILBaseArray<ILRegularRange>) {
+                    return CreateRangedSubarray(range[0] as ILBaseArray<ILRegularRange>); 
+                } else if (range[0] is ILBaseArray<double>) {
+                    return CreateSubarrayStorageSequential((ILBaseArray<double>)range[0]); 
+                } else if (range[0] is ILDenseArray<string>) {
+                    // special case? A[":;0:3;0:end;..."] -> multiple dimensions given as single string
+                    string indStr = (string)(range[0] as ILDenseArray<string>).GetValue(0); 
+                    string[] dimParts = indStr.Split(';'); 
+                    if (dimParts.Length == 0) {
+                        // empty range given 
+                        return CreateSelf(ILSize.Empty00); 
+                    } else if (dimParts.Length > 1) {
+                        range = new ILBaseArray [dimParts.Length];
+                        for (int i = 0; i < dimParts.Length; i++) {
+                            range[i] = dimParts[i]; 
+                        } // continue below: multi-dim range specification
+                    } else { 
+                        return Subarray(ILRange.ParseDimension(indStr, Size.NumberOfElements));  
+                    }
+                } else if (range[0].Storage is ILCellStorage) {
+                    ILCellStorage indices = range[0].Storage as ILCellStorage;  
+                    if (indices.Size.NumberOfElements == 1) {
+                        return Subarray(indices.GetScalar(0));       
+                    } else if (indices.Size.NumberOfElements == 0) {
+                        return CreateSelf(ILSize.Empty00); 
+                    } else {
+                        ILRightSideRange rngCell = new ILRightSideRange(Size, range); 
+                        return CreateSubarrayStorage(rngCell); 
+                    }
+                } else if (range[0] is ILRetLogical) {
+                    return CreateSubarrayStorageSequential(ILNumerics.ILMath.find((ILRetLogical)range[0])); 
+                } else if (range[0] is ILLogical) {
+                    return CreateSubarrayStorageSequential(ILNumerics.ILMath.find((ILLogical)range[0])); 
+                } else if (range[0] is ILBaseArray<float>) { 
+                    return CreateSubarrayStorageSequential((ILBaseArray<float>)range[0]); 
+                } else if (range[0] is ILBaseArray<Int32>) {
+                    return CreateSubarrayStorageSequential((ILBaseArray<Int32>)range[0]); 
+                } else if (range[0] is ILBaseArray<Int64>) {
+                    return CreateSubarrayStorageSequential((ILBaseArray<Int64>)range[0]); 
+                } else if (range[0] is ILExpression) {
+                    return CreateSubarrayStorageSequential((ILExpression)range[0]); 
+                } else 
+                    throw new ILArgumentException ("specified type of indices array is not supported for sequential addressing!");
+                #endregion sequential index access
+            } 
+            ILRightSideRange rng = new ILRightSideRange(m_size, range); 
+            if (rng.Size.NumberOfElements == 0) 
+                return CreateSelf(ILSize.Empty00); 
+            return CreateSubarrayStorage(rng); 
+        }
+
+        /// <summary>
+        /// subarray from single dim, single range
+        /// </summary>
+        /// <returns>subarray (column vector)</returns>
+        private ILDenseStorage<ElementType> CreateRangedSubarray(ILBaseArray<ILRegularRange> range) {
+            System.Diagnostics.Debug.Assert(range.IsScalar); 
+            ILRegularRange regRange = range.GetValue(0); 
+            regRange.Evaluate(Size.NumberOfElements - 1); 
+            bool dummy; 
+            ElementType[] retArr = ILMemoryPool.Pool.New<ElementType>(regRange.Length,false, out dummy);
+            regRange.Extract(GetArrayForRead(),retArr, Size.NumberOfElements - 1);
+            return CreateSelf(retArr, new ILSize(regRange.Length, 1)); 
+        }
+
+        /// <summary>
+        /// create new subarray storage, sequentially addressed elements
+        /// </summary>
+        /// <param name="indices">sequential indices, arbitrary size</param>
+        /// <returns>new storage, type of this storage, size and shape of indices</returns>
+        private ILDenseStorage<ElementType> CreateSubarrayStorageSequential(ILBaseArray<Expression> indices) {
+            if (indices.Storage is  ILDenseStorage<Expression> ) {
+                Expression expr = (indices.Storage as ILDenseStorage<Expression>).GetArrayForRead()[0]; 
+                int idx = ILExpression.Evaluate(expr,Size.NumberOfElements-1); 
+                if (idx < 0 || idx >= Size.NumberOfElements)
+                    throw new ILArgumentException("sequential index out of range"); 
+                return CreateSelf(new ElementType[]{GetArrayForRead()[idx]}, indices.Size);
+            } else {
+                throw new ILArgumentException("Unsupported storage method for indices!"); 
+            }
+        }
+
+
+        
+
+        /// <summary>
+        /// create new subarray storage, sequentially addressed elements
+        /// </summary>
+        /// <param name="indices">sequential indices, arbitrary size</param>
+        /// <returns>new storage, type of this storage, size and shape of indices</returns>
+        private ILDenseStorage<ElementType> CreateSubarrayStorageSequential(ILBaseArray<double> indices) {
+            if (indices.Storage is  ILDenseStorage< double > ) {
+                  double [] indArr = (indices.Storage as ILDenseStorage< double >).GetArrayForRead(); 
+                int outLen = indices.Size.NumberOfElements; 
+                int myLen = Size.NumberOfElements; 
+                ElementType[] outdata = ILMemoryPool.Pool.New<ElementType> (outLen);
+                ElementType[] myData = GetArrayForRead(); 
+                for (int i = 0; i < outLen; i++) {
+                    int targetIndex = (int)indArr[i]; 
+                    if (targetIndex < 0 || targetIndex >= myLen)
+                        throw new ILArgumentException(String.Format("sequential index at position {0} out of range: {1}", i, targetIndex)); 
+                    outdata[i] = myData[targetIndex]; 
+                }
+                return CreateSelf(outdata, indices.Size);
+            } else {
+                throw new ILArgumentException("unsupported storage type for indices"); 
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+       
+
+        /// <summary>
+        /// create new subarray storage, sequentially addressed elements
+        /// </summary>
+        /// <param name="indices">sequential indices, arbitrary size</param>
+        /// <returns>new storage, type of this storage, size and shape of indices</returns>
+        private ILDenseStorage<ElementType> CreateSubarrayStorageSequential(ILBaseArray<long> indices) {
+            if (indices.Storage is  ILDenseStorage< long > ) {
+                 long [] indArr = (indices.Storage as ILDenseStorage< long >).GetArrayForRead(); 
+                int outLen = indices.Size.NumberOfElements; 
+                int myLen = Size.NumberOfElements; 
+                ElementType[] outdata = ILMemoryPool.Pool.New<ElementType> (outLen);
+                ElementType[] myData = GetArrayForRead(); 
+                for (int i = 0; i < outLen; i++) {
+                    int targetIndex = (int)indArr[i]; 
+                    if (targetIndex < 0 || targetIndex >= myLen)
+                        throw new ILArgumentException(String.Format("sequential index at position {0} out of range: {1}", i, targetIndex)); 
+                    outdata[i] = myData[targetIndex]; 
+                }
+                return CreateSelf(outdata, indices.Size);
+            } else {
+                throw new ILArgumentException("unsupported storage type for indices"); 
+            }
+        }
+       
+
+        /// <summary>
+        /// create new subarray storage, sequentially addressed elements
+        /// </summary>
+        /// <param name="indices">sequential indices, arbitrary size</param>
+        /// <returns>new storage, type of this storage, size and shape of indices</returns>
+        private ILDenseStorage<ElementType> CreateSubarrayStorageSequential(ILBaseArray<int> indices) {
+            if (indices.Storage is  ILDenseStorage< int > ) {
+                 int [] indArr = (indices.Storage as ILDenseStorage< int >).GetArrayForRead(); 
+                int outLen = indices.Size.NumberOfElements; 
+                int myLen = Size.NumberOfElements; 
+                ElementType[] outdata = ILMemoryPool.Pool.New<ElementType> (outLen);
+                ElementType[] myData = GetArrayForRead(); 
+                for (int i = 0; i < outLen; i++) {
+                    int targetIndex = (int)indArr[i]; 
+                    if (targetIndex < 0 || targetIndex >= myLen)
+                        throw new ILArgumentException(String.Format("sequential index at position {0} out of range: {1}", i, targetIndex)); 
+                    outdata[i] = myData[targetIndex]; 
+                }
+                return CreateSelf(outdata, indices.Size);
+            } else {
+                throw new ILArgumentException("unsupported storage type for indices"); 
+            }
+        }
+       
+
+        /// <summary>
+        /// create new subarray storage, sequentially addressed elements
+        /// </summary>
+        /// <param name="indices">sequential indices, arbitrary size</param>
+        /// <returns>new storage, type of this storage, size and shape of indices</returns>
+        private ILDenseStorage<ElementType> CreateSubarrayStorageSequential(ILBaseArray<float> indices) {
+            if (indices.Storage is  ILDenseStorage< float > ) {
+                 float [] indArr = (indices.Storage as ILDenseStorage< float >).GetArrayForRead(); 
+                int outLen = indices.Size.NumberOfElements; 
+                int myLen = Size.NumberOfElements; 
+                ElementType[] outdata = ILMemoryPool.Pool.New<ElementType> (outLen);
+                ElementType[] myData = GetArrayForRead(); 
+                for (int i = 0; i < outLen; i++) {
+                    int targetIndex = (int)indArr[i]; 
+                    if (targetIndex < 0 || targetIndex >= myLen)
+                        throw new ILArgumentException(String.Format("sequential index at position {0} out of range: {1}", i, targetIndex)); 
+                    outdata[i] = myData[targetIndex]; 
+                }
+                return CreateSelf(outdata, indices.Size);
+            } else {
+                throw new ILArgumentException("unsupported storage type for indices"); 
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+       
+        /// <summary>
+        /// create column vector of all this array elements
+        /// </summary>
+        /// <returns>new storage, type of this storage, size and shape of indices</returns>
+        private ILDenseStorage<ElementType> CreateSubarrayStorageFull( ) {
+            return CreateSelf(Data,new ILSize(Size.NumberOfElements,1)); 
+        }
+
+      
+        /// <summary>
+        /// create subarray from ILDenseStorage 
+        /// </summary>
+        /// <param name="range"></param>
+        /// <returns></returns>
+        private ILDenseStorage<ElementType> CreateSubarrayStorage( ILRange range ) {
+            using (range) {
+                if (range == null || range.Size.NumberOfElements == 0)
+                    return CreateSelf(ILSize.Empty00);
+                int rangeDimLen = range.RangeArray.Length, higherDimSum = 0;
+                int leadDimLenRange = range[0].Count, leadDimLen = m_size[0];
+                int curPosOut = 0, d, outElemCount = range.Size.NumberOfElements;
+                ElementType[] retArr = ILMemoryPool.Pool.New<ElementType>(outElemCount);
+                ElementType[] myArr = GetArrayForRead();
+                int[] idxArr = new int[rangeDimLen];    // used to store current position inside higher dims 
+                ILIntList[] rng = range.RangeArray;
+                int[] seqDistances = m_size.GetSequentialIndexDistances(range.Size.NumberOfDimensions);
+                int[] inFullDim = new int[rangeDimLen];
+                // initialize higher dimension summand and inFullDim[] flag array
+                for (int i = 1; i < idxArr.Length; i++) {
+                    if (rng[i][0] < 0) {
+                        inFullDim[i] = rng[i][0];
+                    } else {
+                        inFullDim[i] = 0;
+                        higherDimSum += seqDistances[i] * rng[i][0];
+                    }
+                }
+                //for (int lIdx = 0; lIdx < leadDimLenRange; lIdx ++) { 
+                //    retArr[curPosOut++] = myArr[higherDimSum + rleadDim[lIdx]]; 
+                //}
+                
+                while (true) {
+                    // copy along leading dimension
+                    int rng0Count = rng[0].Count; int[] rng0 = rng[0].GetArray();  
+                    for (int i = 0; i < rng0Count; i++) {
+                        int rng0i = rng0[i]; 
+                        if (rng0i < 0) {
+                            if (-rng0i > Settings.s_minElementLength4SystemArrayCopy) {
+                                //int endOut = curPosOut -(rng0i - 1), startIn = higherDimSum;
+                                //for (; curPosOut < retArr.Length; curPosOut++) {
+                                //    if (curPosOut >= endOut) break; 
+                                //    retArr[curPosOut] = myArr[startIn++];
+                                //}
+                                System.Array.Copy(myArr, higherDimSum, retArr, curPosOut, -(rng0i - 1));
+                                curPosOut -= (rng0i - 1);
+                            } else {
+                                //for (int c = -rng0[i]; c-- >= 0; ) {
+                                //    retArr[curPosOut++] = myArr[higherDimSum++];
+                                //}
+                                //higherDimSum += (rng0[i] - 1); // negative value in rng!  
+                                int endOut = curPosOut - (rng0i - 1), startIn = higherDimSum;
+                                for (; curPosOut < outElemCount; curPosOut++) {
+                                    if (curPosOut >= endOut) break;
+                                    retArr[curPosOut] = myArr[startIn++];
+                                }
+                            }
+                        } else {
+                            retArr[curPosOut++] = myArr[higherDimSum + rng0i];
+                        }
+                    }
+
+                    // increase higher dims 
+                    d = 1;
+                    while (d < rangeDimLen) {
+                        if (inFullDim[d] < 0) {
+                            higherDimSum += seqDistances[d];
+                            inFullDim[d]++;
+                            break;
+                        }
+
+                        if (rng[d][idxArr[d]] >= 0) {
+                            higherDimSum -= (rng[d][idxArr[d]] * seqDistances[d]);
+                        } else {
+                            higherDimSum += (rng[d][idxArr[d]] * seqDistances[d]);
+                        }
+                        idxArr[d]++;
+                        if (idxArr[d] == rng[d].Count) {
+                            idxArr[d] = 0;
+                            if (rng[d][0] < 0) {
+                                inFullDim[d] = rng[d][0];
+                            } else {
+                                higherDimSum += seqDistances[d] * rng[d][0];
+                            }
+                            d++;
+                        } else if (rng[d][idxArr[d]] < 0) {
+                            inFullDim[d] = rng[d][idxArr[d]];
+                            break;
+                        } else {
+                            higherDimSum += seqDistances[d] * rng[d][idxArr[d]];
+                            break;
+                        }
+
+                    }
+                    if (d >= idxArr.Length)
+                        break;
+                }
+                return CreateSelf(retArr, range.Size);
+            }
+        }
+        /// <summary>
+        /// create new storage, shift dimensions 
+        /// </summary>
+        /// <param name="shift">number of dimensions to shift</param>
+        /// <returns>shifted storage </returns>
+        private ILDenseStorage<ElementType> CreateShiftedStorage(int shift) {
+            ILSize retDimensions = m_size.GetShifted(shift); 
+            int numElem = m_size.NumberOfElements - 1;
+            ElementType[] retArr = ILMemoryPool.Pool.New<ElementType>(retDimensions.NumberOfElements);
+            ElementType[] myArr = GetArrayForRead();
+            int inc = m_size.SequentialIndexDistance(Math.Min(shift, m_size.NumberOfDimensions));
+            int pos = 0;
+            int i = 0;
+            while (i < numElem) {
+                retArr[i++] = myArr[pos];
+                pos = (pos + inc) % numElem;
+            }
+            if (numElem >= 0) // except empty 
+                retArr[i] = myArr[numElem];
+            return CreateSelf(retArr,retDimensions);
+        }
+
+        protected virtual ILDenseStorage<ElementType> CreateSelf(ElementType[] data, ILSize size) {
+            return new ILDenseStorage<ElementType>(data, size);
+        }
+        protected virtual ILDenseStorage<ElementType> CreateSelf(ILSize size) {
+            return new ILDenseStorage<ElementType>(size);
+        }
+        protected virtual ILDenseStorage<ElementType> CreateSelf(ILCountableArray<ElementType> Data, ILSize iLDimension) {
+            return new ILDenseStorage<ElementType>(Data, iLDimension); 
+        }
+
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Storage/ILLeftSideRange.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Storage/ILLeftSideRange.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Storage/ILLeftSideRange.cs	(revision 9102)
@@ -0,0 +1,160 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using ILNumerics.Data;
+
+namespace ILNumerics.Storage {
+    internal class ILLeftSideRange : ILRange {       
+        /// <summary>
+        /// true for left side ranges, if at least one dimension must be expanded
+        /// </summary>
+        internal bool Expanding {
+            get {
+                return m_expanding;
+            }
+            set {
+                m_expanding = value; 
+            }
+        }
+        /// <summary>
+        /// sizes of dimensions to be expanded
+        /// </summary>
+        private int[] m_expandDimensions; 
+       /// <summary>
+        /// internal field, stores expanding flag
+        /// </summary>
+        private bool m_expanding; 
+        /// <summary>
+        /// array with sizes of dimensions to be expanded
+        /// </summary>
+        internal int[] ExpandDimensions {
+            get {
+                return m_expandDimensions; 
+            }
+        }
+
+        #region constructor
+        // indices may not address a single dimension! This case is handled by sequential addressing from callee (ILDenseArray<T>)
+        public ILLeftSideRange(ILSize dimension, ILBaseArray[] indices) : base()  {
+            create(indices,dimension);
+        }
+	    #endregion
+
+        protected void create(ILBaseArray[] indices, ILSize dimensions) {
+            using (ILScope.Enter(indices)) {
+                if (indices.Length == 0) {
+                    m_range = new ILIntList[0];
+                    m_size = ILSize.Empty00;
+                    return;
+                }
+                if (indices.Length == 1) {
+                    if (indices[0] is ILDenseArray<string> && indices[0].IsScalar) {
+                        // special case? A[":;0:3;0:end;..."] -> multiple dimensions given as single string
+                        //System.Diagnostics.Debug.Fail("single dimension subarray specification should be handled seperately by ILDenseStorage.Subarray()"); 
+                        // (some rare cases (remove e.g.) use this path to parse given dimensions... ) 
+                        string indStr = (string)(indices[0] as ILDenseArray<string>).GetValue(0);
+                        if (String.IsNullOrWhiteSpace(indStr)) {
+                            m_range = new ILIntList[0];
+                            m_size = ILSize.Empty00;
+                            return;
+                        }
+                        string[] dimParts = indStr.Split(';');
+                        if (dimParts.Length > 1) {
+                            indices = new ILBaseArray[dimParts.Length];
+                            for (int i = 0; i < dimParts.Length; i++) {
+                                indices[i] = dimParts[i];
+                            }
+                            // caution: using ILBaseArray as input is EVIL!! 
+                            // now we have an array of temparrays! Those are too fragile
+                            // to work with - so start again and safe them in a scope
+                            create(indices,dimensions); 
+                            return; 
+                        }
+                    }
+                }
+                m_range = new ILIntList[indices.Length];
+                // outdims: immer so wie der range (indices), min 2
+                int[] outDims = new int[Math.Max(2, m_range.Length)];
+                outDims[1] = 1; // in case it is not set later 
+                // if indices addresses less dimensions than ex, in dimensions -> expand last dimension 
+                int[] inDims = dimensions.ToIntArrayEx(m_range.Length);
+
+                for (int d = 0; d < m_range.Length; d++) {
+                    int min = int.MaxValue, max = int.MinValue, outLen = 0;
+                    m_range[d] = ILIntList.Create();
+                    extractDimension(m_range[d], ref outLen, indices[d], d, ref min, ref max, inDims);
+                    outDims[d] = outLen;
+                    // check limits
+                    if (min < 0) {
+                        throw new Exceptions.ILArgumentException(String.Format("index < 0: {1}, dimension  #{0}", d, min));
+                    }
+                    if (max >= ((d < inDims.Length) ? inDims[d] : 1)) {
+                        #region special cases A(ind) = B
+                        if (dimensions.NonSingletonDimensions > 1 &&
+                            (d == m_range.Length - 1)
+                            && (m_range.Length < dimensions.NumberOfDimensions)) {
+                            throw new Exceptions.ILArgumentException(String.Format("Cannot expand array along ambiguous dimension #{0}", d));
+                        }
+                        m_expanding = true;
+                        if (m_expandDimensions == null) {
+                            m_expandDimensions = new int[Math.Max(indices.Length, 2)];
+                        }
+                        if (indices.Length == 1 /* -> d == 0! */
+                            && dimensions.NonSingletonDimensions == 1 && dimensions[1] > 1) {
+                            // special case: row vector, adressing by single dimension A(end+1) = ...
+                            m_expandDimensions[1] = max + 1;
+                            outDims[1] = outLen;
+                            outDims[0] = 1;
+                            break;
+                        } else {
+                            // common case 
+                            m_expandDimensions[d] = max + 1;
+                        }
+                        #endregion
+                    }
+                }
+                m_size = new ILSize(outDims);
+            }
+        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Storage/ILLogicalStorage.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Storage/ILLogicalStorage.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Storage/ILLogicalStorage.cs	(revision 9102)
@@ -0,0 +1,88 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace ILNumerics.Storage {
+    
+    [Serializable]
+    internal class ILLogicalStorage : ILDenseStorage<byte> {
+
+        #region attributes 
+        protected long m_numberNonZero; 
+        #endregion
+
+        #region properties
+        /// <summary>
+        /// cached number of non-zero elements in this logical storage
+        /// </summary>
+        internal long NumberNonZero {
+            get { return m_numberNonZero; }
+            set { m_numberNonZero = value; }
+        }
+        #endregion
+
+        #region constructors
+        internal ILLogicalStorage(byte[] system_array, ILSize dimensions) 
+            : base(system_array, dimensions) {
+        }
+        internal ILLogicalStorage(ILCountableArray<byte> countableArray, ILSize dimensions)
+            : base(countableArray, dimensions) {
+        }
+        internal ILLogicalStorage(ILSize dimensions) 
+            : base(dimensions) { }
+
+        #endregion
+
+        #region public
+        protected override ILDenseStorage<byte> CreateSelf(byte[] data, ILSize size) {
+            return new ILLogicalStorage(data, size);
+        }
+        protected override ILDenseStorage<byte> CreateSelf(ILCountableArray<byte> Data, ILSize iLDimension) {
+            return new ILLogicalStorage(Data, iLDimension);
+        }
+        protected override ILDenseStorage<byte> CreateSelf(ILSize size) {
+            return new ILLogicalStorage(size);
+        }
+        #endregion
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Storage/ILRange.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Storage/ILRange.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Storage/ILRange.cs	(revision 9102)
@@ -0,0 +1,450 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using ILNumerics; 
+using ILNumerics.Misc; 
+using ILNumerics.Exceptions;
+using ILNumerics.Data;
+using System.Collections.Generic;
+using System.Linq.Expressions;
+
+namespace ILNumerics.Storage {
+
+	/// <summary>
+	/// base class for ranges, used to define subarray ranges
+    /// </summary>
+	/// <description>ILRange is used to define those parts of indices of an array,
+    /// which are to be extracted into a new subarray. 
+    /// The class (and derived classes) parse indices given for each dimension and expand them into a 2-dimensional 
+    /// integer array, needed for fast element traversal.
+    /// <para>The class is internally used only and not intended to be used from outside ILNumerics.</para></description>
+	internal abstract class ILRange : IDisposable {
+
+		/// <summary>
+		/// hold ranges as 2 dimensional System.Array
+		/// </summary>
+		protected ILIntList[] m_range; 
+        /// <summary>
+        /// for performance reasons: give reference to internal array
+        /// </summary>
+        internal ILIntList[] RangeArray {
+            get{
+                return m_range;
+            }
+        }
+		/// <summary>
+		/// Index access for ILRange objects. Set/returns Index array for specified dimension.
+        /// </summary>
+        /// <remarks>A reference to the internal object will be returned directly! (performance)</remarks>
+		internal ILIntList this [int idx] {
+			get {
+				return m_range[idx];
+            }
+		}
+		/// <summary>
+		/// Index access for ILRange objects. returns the destIndex destination dimension for dimension specifyied by dimNr.
+		/// </summary>
+		/// <remarks>The access is readonly! No checks are made, if the requested indices exist.</remarks>
+		internal int this [int dimNr,int destIndx ] {
+			get {
+				return m_range[dimNr][destIndx];
+			}
+		}
+
+        internal void ILRanges() {}
+
+		/// <summary>
+		/// Evaluates (maps) index array on my range. 
+		/// </summary>
+		/// <param name="idx">int array indexing location inside this range</param>
+        /// <param name="retIdx">(output) also return the result into array given</param>
+		/// <returns>Mapped int[] array. It can be used for direct addressing the physical storage object.</returns>
+        /// <remarks>retIdx must be at least of length m_nrDims. No check is made for this assumption!</remarks>
+		internal int[] Map(int[] idx, ref int [] retIdx) {
+            int tmpVal; 
+			for (int d = 0; d < m_size.NumberOfDimensions; d++) {
+				tmpVal = m_range[d][0]; 
+                if (tmpVal < 0)
+                    retIdx[d] = idx[d];
+                else 
+                    retIdx[d] = m_range[d][idx[d]];
+			} 
+            return retIdx; 
+		}
+        /// <summary>
+        /// parse single dimension specifier from string
+        /// </summary>
+        /// <param name="indices">valid index specification</param>
+        /// <param name="dimlen">number of elements in dimension to be parsed</param>
+        /// <returns>array with indices defined in 'indices'</returns>
+        /// <remarks>the indices are parsed the way needed for sequential addressing. This means: 
+        /// full dimensions address the whole array. Full dimensions are transformed into negative 
+        /// placeholder indices nevertheless! SetRange must handle that accordingly.</remarks>
+        internal static ILBaseArray ParseDimension(string indices, int dimlen) {
+            if (indices.Trim() == ":") {
+                return ILMath.full; 
+            }
+            int pos = 0, min = 0, max = 0; 
+            ILIntList list = ILIntList.Create(); 
+            expand(list, ref pos, indices, ref min, ref max, dimlen, 0, false); 
+            
+            return list.ToTempArray(); 
+        }
+
+        protected ILSize m_size; 
+        /// <summary>
+        /// Create trimmed size descriptor from indices in ILRange object
+		/// </summary>
+        /// <returns>new size descriptor with the neccessary size to define 
+        /// an array as defined by all indices in this range</returns>
+		internal ILSize Size {
+            get {
+                return m_size; 
+            }
+		}
+
+        #region private helper  
+        protected static void extractDimension(ILIntList target, ref int outLen, ILBaseArray A, int dim, ref int min, ref int max, int[] dimensions) {
+            if (object.Equals(A, null)) {
+                return;
+            }
+            using (ILScope.Enter(A)) {
+                int dimLen = dimensions[dim];
+                if (A is ILDenseArray<ILFullRange>) {
+                    // taken as ':' (i.e.: full)
+                    if (dimLen <= 0) return;
+                    min = 0;
+                    target.Add(-(dimLen - 1));
+                    max = dimLen - 1;
+                    outLen += dimLen;
+                } else if (A is ILBaseArray<ILRegularRange>) {
+                    (A as ILBaseArray<ILRegularRange>).GetValue(0).Expand(target, ref outLen, ref min, ref max, dimLen - 1);
+                } else if (A is ILDenseArray<double>) {
+                    expand(target, ref outLen, A as ILDenseArray<double>, ref min, ref max, dim);
+                } else if (A is ILBaseArray<Expression>) {
+                    if (dimensions[dim] > 0) {
+                        Expression exp = (A as ILBaseArray<Expression>).GetValue(0);
+                        int end = ILExpression.Evaluate(exp, dimLen - 1);
+                        target.Add(end);
+                        outLen++;
+                        if (end < min) min = end;
+                        if (end > max) max = end;
+                    }
+                } else if (A is ILDenseArray<float>) {
+                    expand(target, ref outLen, A as ILDenseArray<float>, ref min, ref max, dim);
+                } else if (A is ILDenseArray<string>) {
+                    if (!A.IsScalar)
+                        throw new ILArgumentException("string index specification: only one string is allowed per dimension");
+                    expand(target, ref outLen, (A as ILDenseArray<string>).GetValue(0), ref min, ref max, (dim < dimensions.Length) ? dimLen : 0, dim, true);
+                } else if (A is ILDenseArray<int>) {
+                    expand(target, ref outLen, A as ILDenseArray<int>, ref min, ref max, dim);
+                } else if (A is ILDenseArray<byte>) {
+                    expand(target, ref outLen, ILMath.find((A as ILDenseArray<byte>).C), ref min, ref max, dim);
+                } else if (A is ILDenseArray<Int64>) {
+                    expand(target, ref outLen, A as ILDenseArray<Int64>, ref min, ref max, dim);
+                } else if (A.Storage is ILCellStorage) {
+                    ILCellStorage cellStorage = A.Storage as ILCellStorage;
+                    for (int ind = 0; ind < cellStorage.Size.NumberOfElements; ind++ ) {
+                        extractDimension(target, ref outLen, cellStorage.GetScalar(ind), dim, ref min, ref max, dimensions);
+                    }
+                } else
+                    throw new ILArgumentException(String.Format("invalid type of index specification: '{0}'", A.GetType().Name));
+            }
+        }
+
+
+
+        protected static void expand(ILIntList target, ref int outLen, ILDenseArray</*HC:inArr1*/ double> A, ref int min, ref int max, int dimIdx) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    return;
+                }
+                if (!A.IsVector)
+                    throw new ILArgumentException("index specification must be vector sized. found: " + A.Size.ToString());
+                foreach (/*HC:inArr1*/ double val in A) {
+                    /*HC:NaNCheck*/
+                    if (Double.IsInfinity(val) || Double.IsNaN(val)) throw new ILArgumentException("invalid index specification, dimension idx " + dimIdx);
+                    Int32 v = (int)val;
+                    target.Add(v);
+                    if (v < min) min = v;
+                    if (v > max) max = v;
+                }
+                outLen += A.Length;
+            }
+        }
+
+#region HYCALPER AUTO GENERATED CODE
+
+
+        protected static void expand(ILIntList target, ref int outLen, ILDenseArray</*HC:*/ Int64> A, ref int min, ref int max, int dimIdx) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    return;
+                }
+                if (!A.IsVector)
+                    throw new ILArgumentException("index specification must be vector sized. found: " + A.Size.ToString());
+                foreach (/*HC:*/ Int64 val in A) {
+                    /*HC:NaNCheck*/
+                    if (Double.IsInfinity(val) || Double.IsNaN(val)) throw new ILArgumentException("invalid index specification, dimension idx " + dimIdx);
+                    Int32 v = (int)val;
+                    target.Add(v);
+                    if (v < min) min = v;
+                    if (v > max) max = v;
+                }
+                outLen += A.Length;
+            }
+        }
+
+        protected static void expand(ILIntList target, ref int outLen, ILDenseArray</*HC:*/ Int32> A, ref int min, ref int max, int dimIdx) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    return;
+                }
+                if (!A.IsVector)
+                    throw new ILArgumentException("index specification must be vector sized. found: " + A.Size.ToString());
+                foreach (/*HC:*/ Int32 val in A) {
+                    /*HC:NaNCheck*/
+                    if (Double.IsInfinity(val) || Double.IsNaN(val)) throw new ILArgumentException("invalid index specification, dimension idx " + dimIdx);
+                    Int32 v = (int)val;
+                    target.Add(v);
+                    if (v < min) min = v;
+                    if (v > max) max = v;
+                }
+                outLen += A.Length;
+            }
+        }
+
+        protected static void expand(ILIntList target, ref int outLen, ILDenseArray</*HC:*/ float> A, ref int min, ref int max, int dimIdx) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    return;
+                }
+                if (!A.IsVector)
+                    throw new ILArgumentException("index specification must be vector sized. found: " + A.Size.ToString());
+                foreach (/*HC:*/ float val in A) {
+                    /*HC:NaNCheck*/
+                    if (Double.IsInfinity(val) || Double.IsNaN(val)) throw new ILArgumentException("invalid index specification, dimension idx " + dimIdx);
+                    Int32 v = (int)val;
+                    target.Add(v);
+                    if (v < min) min = v;
+                    if (v > max) max = v;
+                }
+                outLen += A.Length;
+            }
+        }
+
+        protected static void expand(ILIntList target, ref int outLen, ILDenseArray</*HC:*/ byte> A, ref int min, ref int max, int dimIdx) {
+            using (ILScope.Enter(A)) {
+                if (A.IsEmpty) {
+                    return;
+                }
+                if (!A.IsVector)
+                    throw new ILArgumentException("index specification must be vector sized. found: " + A.Size.ToString());
+                foreach (/*HC:*/ byte val in A) {
+                    /*HC:NaNCheck*/
+                    if (Double.IsInfinity(val) || Double.IsNaN(val)) throw new ILArgumentException("invalid index specification, dimension idx " + dimIdx);
+                    Int32 v = (int)val;
+                    target.Add(v);
+                    if (v < min) min = v;
+                    if (v > max) max = v;
+                }
+                outLen += A.Length;
+            }
+        }
+
+#endregion HYCALPER AUTO GENERATED CODE
+
+        // parse SINGLE (!) dimension given by string
+        protected static void expand(ILIntList target, ref int outLen, string p, ref int min, ref int max, int dimLen, int dimIdx, bool useFullDimTag) {
+            // possible input: ":", "0:19", "20:-2:5", "1,2,3,4:2:16,end:-2:0,:"
+            if (p.Contains(";")) 
+                throw new ILArgumentException("invalid string index specification: ambiguous dimension seperator ';'"); 
+            string[] parts = p.Split(','); 
+            if (parts.Length == 0) {
+                // empty dimension? 
+                return; 
+            } else if (parts.Length > 1) {
+                foreach (string part in parts) {
+                    expand(target, ref outLen, part, ref min, ref max, dimLen, dimIdx, useFullDimTag); 
+                }
+                return; 
+            }
+            // only one range specifier 
+            if (p.Trim() == ":") {
+                // full dimension
+                if (dimLen <= 0) return; 
+                if (useFullDimTag) {
+                    target.Add(-(dimLen-1)); 
+                } else {
+                    for (int i = 0; i < dimLen; i++) {
+                        target.Add(i); 
+                    }
+                }
+                outLen += dimLen; 
+            } else {
+                int tmpValue, start, end, step; 
+                string[] rngitems = p.Split(':');
+                switch (rngitems.Length) {
+                    case 1:
+                        // single number specified 
+                        if (rngitems[0].Contains("end")) {
+                            if (rngitems[0].Trim() != "end") throw new ILArgumentException("index expression evaluation is not supported for string definitions. Use non-string definitions instead!");
+                            if (dimLen <= 0) break; 
+                            tmpValue = (dimLen-1);
+                        } else if (String.IsNullOrWhiteSpace(rngitems[0])) {
+                            break;   
+                        } else if (! int.TryParse(rngitems[0].Trim(),out tmpValue)) {
+                            throw new ILArgumentException(String.Format("invalid index for dimension {0}: ({1})", dimIdx,rngitems[0])); 
+                        }
+                        if (tmpValue < min) min = tmpValue; 
+                        if (tmpValue > max) max = tmpValue; 
+                        target.Add (tmpValue);
+                        outLen++; 
+                        break;
+                    case 2: 
+                        // unstepped range specified 
+                        if (rngitems[0].Contains("end")) {
+                            if (rngitems[0].Trim() != "end") throw new ILArgumentException("index expression evaluation is not supported for string definitions. Use non-string definitions instead!");
+                            if (dimLen <= 0) break; 
+                            start = dimLen - 1;
+                        } else if (!int.TryParse(rngitems[0],out start)) {
+                            throw new ILArgumentException("invalid start index for range in dimension " + dimIdx.ToString());                                        
+                        } 
+                        if (rngitems[1].Contains("end")) {
+                            if (rngitems[1].Trim() != "end") throw new ILArgumentException("index expression evaluation is not supported for string definitions. Use non-string definitions instead!");
+                            if (dimLen <= 0) break; 
+                            end = dimLen - 1;
+                        } else if (!int.TryParse(rngitems[1],out end)) {
+                            throw new ILArgumentException("invalid end index for range in dimension " + dimIdx.ToString());                                        
+                        } 
+                        step = (start <= end) ? 1 : 1; // -1 - make consistent with non-string spec: unspecified step is always 1! 
+
+                        if (start<=end) {
+                            for (int t = start; t <= end;) {
+                                target.Add (t++);
+                            }
+                            if (start < min) min = start; 
+                            if (end > max) max = end; 
+                            outLen += (end-start)+1; 
+                        } else {
+                            //for (int t = start; t >= end;) {
+                            //    target.Add (t--);
+                            //}
+                            //if (end < min) min = end; 
+                            //if (start > max) max = start; 
+                            //outLen += (start-end)+1
+
+                            // ^ this is not allowed: unspecified step will always avaluate to 1! 
+                        }
+                        break;
+                    case 3:
+                        // stepped range specified
+                        if (rngitems[0].Contains("end")) {
+                            if (rngitems[0].Trim() != "end") throw new ILArgumentException("index expression evaluation is not supported for string definitions. Use non-string definitions instead!");
+                            if (dimLen <= 0) break; 
+                            start = dimLen - 1;
+                        } else if (!int.TryParse(rngitems[0],out start)) {
+                            throw new ILArgumentException("invalid start index for range in dimension " + dimIdx.ToString());                                        
+                        } 
+                        if (rngitems[1].Contains("end")) {
+                            if (rngitems[1].Trim() != "end") throw new ILArgumentException("index expression evaluation is not supported for string definitions. Use non-string definitions instead!");
+                            if (dimLen <= 0) break; 
+                            step = dimLen - 1;
+                        } else if (!int.TryParse(rngitems[1],out step)) {
+                            throw new ILArgumentException("invalid step index for range in dimension " + dimIdx.ToString());                                        
+                        } 
+                        if (rngitems[2].Contains("end")) {
+                            if (rngitems[2].Trim() != "end") throw new ILArgumentException("index expression evaluation is not supported for string definitions. Use non-string definitions instead!");
+                            if (dimLen <= 0) break; 
+                            end = dimLen - 1;
+                        } else if (!int.TryParse(rngitems[2],out end)) {
+                            throw new ILArgumentException("invalid end index for range in dimension " + dimIdx.ToString());                                        
+                        } 
+                        if (step == 0) {
+                            // empty
+                            return; 
+                        }
+                        int i = start; 
+                        if (start == end) {
+                            target.Add(start); 
+                            outLen++; 
+                            if (start < min) min = start; 
+                            if (start > max) max = start;   
+                        } else if (start < end) {
+                            if (step < 0) return; 
+                            for (; i <= end; i += step) {
+                                target.Add(i); 
+                                outLen++; 
+			                }
+                            if (start < min) min = start; 
+                            if (i - step > max) max = i - step;   // cannot compare to end, since it may was not reached!
+                        } else {
+                            if (step > 0) return; 
+                            for (; i >= end; i += step) {
+                                target.Add(i); 
+                                outLen++; 
+			                }
+                            if (start > max) max = start; 
+                            if (i - step < min) min = i - step; 
+                        }
+                        break;
+                    default: 
+                        throw new ILArgumentException("invalid index for dimension " + dimIdx.ToString());
+                }
+            }
+        }
+        #endregion
+
+        #region IDisposable Members
+
+        public void Dispose() {
+            if (m_range != null) {
+                foreach (ILIntList list in m_range) {
+                    if (list != null) {
+                        list.Dispose();
+                    }
+                }
+            }
+            m_range = null; 
+        }
+
+        #endregion
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Storage/ILRightSideRange.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Storage/ILRightSideRange.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Storage/ILRightSideRange.cs	(revision 9102)
@@ -0,0 +1,145 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using ILNumerics.Data;
+
+namespace ILNumerics.Storage {
+    internal class ILRightSideRange : ILRange {
+        /// <summary>
+        /// rempat consctructor - for performance reasons 
+        /// </summary>
+        /// <param name="dimension">source array dimensions</param>
+        /// <param name="range">destination array repmattings </param>
+        internal ILRightSideRange(ILSize dimension, params int[] range) {
+            if (range == null || range.Length == 0) {
+                m_range = new ILIntList[0]; 
+                m_size = ILSize.Empty00; 
+            } else {
+                m_range = new ILIntList[Math.Max(range.Length, dimension.NumberOfDimensions)];
+                int[] outSizes = dimension.ToIntArray(m_range.Length); 
+                int i = 0;
+                for (; i < range.Length; i++) {
+                    int limit = range[i];
+                    if (limit < 0) 
+                        throw new Exceptions.ILArgumentException("dimension specifier must not be negative"); 
+                    // 'full' dimension addressed
+                    int fullVal = -(dimension[i] - 1);
+                    ILIntList intList = ILIntList.Create(limit, fullVal);
+                    //for (int c = limit; c --> 0; ) {
+                    //    intList.Add(val);
+                    //}
+                    m_range[i] = intList; 
+                    outSizes[i] *= limit; 
+                }
+                for (; i < m_range.Length; i++) {
+                    if (i < dimension.NumberOfDimensions) {
+                        int fullVal = -(dimension[i] - 1);
+                        m_range[i] = ILIntList.Create(1, fullVal);
+                    } else {
+                        m_range[i] = ILIntList.Create(1, 0); 
+                    }
+                }
+                m_size = new ILSize(outSizes); 
+            }
+        }
+        internal ILRightSideRange(ILSize dimension, ILBaseArray[] indices) 
+            : base()  { 
+            create(indices,dimension); 
+        }
+        protected void create(ILBaseArray[] indices, ILSize dimensions) {
+            using (ILScope.Enter(indices)) {
+                //if (object.Equals(indices, null)) {
+                //    // A(null)
+                //    indices = new ILBaseArray[] { null }; 
+                //}
+                if (indices.Length == 0) {
+                    m_range = new ILIntList[0];
+                    m_size = ILSize.Empty00;
+                    return;
+                }
+                if (indices.Length == 1) {
+                    if (indices[0] is ILDenseArray<string> && indices[0].IsScalar) {
+                        // special case? A[":;0:3;0:end;..."] -> multiple dimensions given as single string
+                        System.Diagnostics.Debug.Fail("single dimension subarray specification should be handled seperately by ILDenseStorage.Subarray()");
+                        string indStr = (string)(indices[0] as ILDenseArray<string>).GetValue(0);
+                        if (String.IsNullOrWhiteSpace(indStr)) {
+                            m_range = new ILIntList[0];
+                            m_size = ILSize.Empty00;
+                            return;
+                        }
+                        string[] dimParts = indStr.Split(';');
+                        if (dimParts.Length > 1) {
+                            indices = new ILBaseArray[dimParts.Length];
+                            for (int i = 0; i < dimParts.Length; i++) {
+                                indices[i] = dimParts[i];
+                            }
+                            create(indices,dimensions); 
+                            return; 
+                        }
+                    }
+                }
+                m_range = new ILIntList[indices.Length];  // due to outer constraines: >= 2 dimensions
+                // outdims: immer so wie der range (indices), min 2
+                int[] outDims = new int[m_range.Length];
+                // if indices addresses less dimensions than ex, in dimensions -> expand last dimension 
+                int[] inDims = dimensions.ToIntArrayEx(m_range.Length);
+
+                for (int d = 0; d < m_range.Length; d++) {
+                    int min = int.MaxValue, max = int.MinValue, outLen = 0;
+                    m_range[d] = ILIntList.Create();
+                    extractDimension(m_range[d], ref outLen, indices[d], d, ref min, ref max, inDims);
+                    outDims[d] = outLen;
+                    // check limits
+                    if (min < 0) {
+                        throw new Exceptions.ILArgumentException(String.Format("index < 0: {1}, dimension  #{0}", d, min));
+                    }
+                    if (max >= ((d < inDims.Length) ? inDims[d] : 1)) {
+                        throw new Exceptions.ILArgumentException(String.Format("index out of range: {1}, dimension: {0}", d, max));
+                    }
+                }
+                m_size = new ILSize(outDims);
+            }
+        }
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Storage/ILStorage.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Storage/ILStorage.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Storage/ILStorage.cs	(revision 9102)
@@ -0,0 +1,104 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.ComponentModel;
+
+namespace ILNumerics.Storage {
+    /// <summary>
+    /// Background storage object used internally.
+    /// </summary>
+    [Serializable]
+    [Browsable(false)]
+    [EditorBrowsable(EditorBrowsableState.Never)]
+    public abstract class ILStorage { 
+        
+        /// <summary>
+        /// size of this storage
+        /// </summary>
+        protected ILSize m_size;
+        /// <summary>
+        /// Size of the storage
+        /// </summary>
+        public ILSize Size { 
+            get { return m_size; }
+        }
+        internal ILStorage(ILSize dimensions) {
+            m_size = dimensions;
+        }
+
+        internal abstract StringBuilder ValuesToString(int len);
+        internal abstract ILStorage Clone();
+        internal abstract bool IsDisposed { get; } 
+        internal abstract void SetValue(object value, int[] idx); 
+        internal abstract object GetValue(params int[] idx); 
+        internal abstract object GetValueSeq(int idx, ref int[] dims);
+        internal abstract ILStorage GetValueAsStorage(params int[] innerIndices);
+        internal abstract ILBaseArray GetAsBaseArray(); 
+        internal abstract bool Equals(object storage); 
+        internal abstract void Dispose(bool manual); 
+        internal virtual String ShortInfo() {
+            StringBuilder ret = new StringBuilder(20); 
+            Type type = GetType(); 
+            if (IsDisposed)
+                return "(disposed)";
+            if (type.GetGenericArguments() != null && type.GetGenericArguments().Length > 0) {
+                ret.Append("<"+type.GetGenericArguments()[0].Name+"> "); 
+            } else {
+                ret.Append(GetType().Name + " ");
+            }
+            if (m_size.NumberOfElements == 1) {
+                ILStorage val = GetValueAsStorage(0);
+                if (val is ILCellStorage) 
+                    ret.Append((val as ILCellStorage).ToString()); 
+                else 
+                    ret.Append(val.ToString());
+            } else 
+                ret.Append(Size.ToString()); 
+            return ret.ToString(); 
+        }
+
+        internal void Dispose() {
+            Dispose(true); 
+        }
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Storage/ILStorageGeneric.cs
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Storage/ILStorageGeneric.cs	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Storage/ILStorageGeneric.cs	(revision 9102)
@@ -0,0 +1,70 @@
+///
+///    This file is part of ILNumerics Community Edition.
+///
+///    ILNumerics Community Edition - high performance computing for applications.
+///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
+///
+///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
+///    it under the terms of the GNU General Public License version 3 as published by
+///    the Free Software Foundation.
+///
+///    ILNumerics Community Edition is distributed in the hope that it will be useful,
+///    but WITHOUT ANY WARRANTY; without even the implied warranty of
+///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+///    GNU General Public License for more details.
+///
+///    You should have received a copy of the GNU General Public License
+///    along with ILNumerics Community Edition. See the file License.txt in the root
+///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
+///
+///    In addition this software uses the following components and/or licenses: 
+///
+///    =================================================================================
+///    The Open Toolkit Library License
+///    
+///    Copyright (c) 2006 - 2009 the Open Toolkit library.
+///    
+///    Permission is hereby granted, free of charge, to any person obtaining a copy
+///    of this software and associated documentation files (the "Software"), to deal
+///    in the Software without restriction, including without limitation the rights to 
+///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+///    the Software, and to permit persons to whom the Software is furnished to do
+///    so, subject to the following conditions:
+///
+///    The above copyright notice and this permission notice shall be included in all
+///    copies or substantial portions of the Software.
+///
+///    =================================================================================
+///    
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace ILNumerics.Storage {
+    [Serializable]
+    internal abstract class ILStorage<ElementType> : ILStorage {
+
+        internal ILStorage(ILSize dimensions) : base(dimensions) { }
+
+        #region abstract interface
+        internal abstract bool GetLimits(out ElementType minValue, out ElementType maxValue); 
+        internal abstract bool GetLimits(out ElementType minValue, out ElementType maxValue, bool includeInfNaNs); 
+        public abstract IEnumerator<ElementType> GetEnumerator(); 
+        /// <summary>
+        /// Get single value from this storage.
+        /// </summary>
+        /// <param name="idx">Integer array holding the dimension specifier</param>
+        /// <returns>Element at the position pointed to by idx.</returns>
+        internal abstract ElementType GetValueTyped(params int[] idx); 
+        /// <summary>
+        /// Set value of element at the specified position.
+        /// </summary>
+        /// <param name="value">new value</param>
+        /// <param name="idx">position of the element to be altered</param>
+        internal abstract void SetValueTyped(ElementType value, params int[] idx);
+        #endregion
+
+    }
+}
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/app.config
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/app.config	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/app.config	(revision 9102)
@@ -0,0 +1,5 @@
+﻿<?xml version="1.0" encoding="utf-8" ?>
+<configuration>
+    <dllmap os="linux" dll="i:opengl32.dll" target="libGL.so.1"/>
+    <dllmap os="linux" dll="i:glu32.dll" target="libGLU.so.4"/>
+</configuration>
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/bin32/ILNumerics32.dll.config
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/bin32/ILNumerics32.dll.config	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/bin32/ILNumerics32.dll.config	(revision 9102)
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<configuration>
+    <dllmap os="linux" dll="i:opengl32.dll" target="libGL.so.1"/>
+</configuration>
Index: /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/changelog.txt
===================================================================
--- /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/changelog.txt	(revision 9102)
+++ /branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/changelog.txt	(revision 9102)
@@ -0,0 +1,504 @@
+Changes in version 3.0 (RC/CTP)
+=============================================
+* new scene graph implementation
+* bugfix: complete dimension array removal retains other dim sizes
+
+Changes in version 2.14a (patch) 
+=============================================
+* reverted to unsigned assemblies due to several reported issues 
+   (signed assemblies will be provided in the pro edition seperately 
+    in the future)
+* made the initialization of Renderer Types more robust + trace infos
+
+Changes in version 2.14
+=============================================
+* bugfix in mvnrnd: certain input data led to dimension mismatch error
+* bugfix in ILSize.IndexFromArray, corrected OOB checks 
+* Updated MKL: version 11.1 (Windows, large matrix eigSymm bugfix)
+* Community + Professional Edition: strongly named assemblies
+
+Changes in version 2.13
+=============================================
+* implemented cross(A,B,normalize) for array columns
+* included Powershell module into nuget package
+  see: http://ilnumerics.net/blog
+
+Changes in version 2.12
+=============================================
+* Added partial support for ILArray<System.Numerics.Complex>
+  + ToString(), ILMath.convert<Complex,complex> and vice versa.
+* Added Complex[].ToILArray and ILArray<complex>.ToMSComplex 
+  Extension Methods
+* bugfix: expansion on emtpy arrays with first dim specified > 0 failed
+* bugfix: sort, on arrays with all but the last element sorted and no 
+  nans failed in certain cases
+* improved/closed hole in memory management: GetArrayForRead/Write()
+  do only exist for non-temporary arrays (all except ILRet???)
+* removed license manager and toolbox license control
+* introduced Community (GPL) and Professional Edition
+* removed free and evaluation licenses (-> Community Edition)
+
+Changes in version 2.11
+=============================================
+* bug in var() fixed: in optimized scenarios may lead to inefficient memory handling
+* more robust license file handling for Free Trial Licenses
+
+Changes in version 2.10
+=============================================
+* loading of license from resources more robust: 
+  Now works even in secondary app domain scenarios. Recommended:
+  Licenses should be loaded from file if the application is not started within a 
+  managed application domain (what happens when started from a console f.e.). 
+  This bugfix makes the library ignore an empty AppDomain Resource Manager and 
+  try to load the license from a regular file instead. 
+* parallelized randn()
+
+Changes in version 2.9 (bugfix release)
+=============================================
+* fixes a bug in repmat: repmat did not handle insufficient dimension 
+  specifications for row vectors properly
+
+Changes in version 2.8.4408.34136
+=============================================
+* increased speed of all binary and unary functions
+* improved vector expansion: more efficient implace operations
+* some ML functions 2..3 times faster (especially kmeans) 
+* new optimized ML function: distL1 (user request) 
+* more robust license file handling: ignoring common encoding issues
+* option to (re)load license file at runtime 
+* option to embed license file into execution assembly
+* removed a common privilege issue with performance counter installation
+
+Changes in version 2.7.4368.41400 (bugfix patch)
+=============================================
+bugfix: qr in economy mode failed in certain situations 
+
+Changes in version 2.7.4363.39308 
+=============================================
+bugfix: memory management had limited efficiency in certain situations
+ILMath.check: provide "Default" parameter on input 'null'
+reworked threading control for MKL
+added support for 32 bit Linux, MKL, v.10.3
+new Drawing example: LitSurfaceExample
+enabled COM/Interop for ILNumerics
+
+Changes in version 2.6.4343.42870  (first commercial release)
+=============================================
+removed namespace ILNumerics.BuiltInFunctions -> ILNumerics
+MachineParameterFloat -> MachineParameterSingle
+reduced number of supported types
+removed reference array feature -> lazy full clones instead
+removed CreateReference(), ILArray<T>.R
+removed "shifted subarrays" 
+all binary operators receive arrays of same type only! (or System.Value type) 
+types array creation: ILMath.create<>, .empty<>, .zeros<>
+removed: ILArray.Diagonal -> use ILMath.diag
+ILArray.GetShifted -> ILArray.Shifted
+removed ILIterator
+GetArrayForRead()/-Write()
+improved array debugger display
+ILCell (always) returns ILArrays!, scalars are unboxed
+optional setting: implicitly cast logical array to bool with allall()
+ILArray.Reshape does return reshaped array but does NOT alter self
+binary functions (add, subtract... ) dimension SIZE sufficient to match (was:shape) 
+trailing singleton dimensions are not trimmed by default
+renamed: ILMath.vector -> ILMath.vec, explicit element type overloads (double, float, int) 
+A[int[]] is not supported anymore due to conflicts with A[cell(1,2,3,4,5)]
+A[string[]] is integrated into A[params BaseArray[]], reducing compiler overload resolution problems
+ .. -> simply replace "new int[]" (double,string,..) with "new ILBaseArray[]"
+A[null] -> empty !
+new subarray specifications: cell(A,B,2,full,r(1,2)),r(0:end(A,1)-1),full): 
+* ILMath.end allows simple calculations (via expressions) 
+* ILMath.full selects full dimension
+default vector orientation: column (specification by single dimension)
+Reshape on arrays: removed params int[] overload, use ILMath.size(dim1,dim2,..) instead 
+meshgrid -> return arrays as cell
+subarray index specifier can now be mixed between string and array format: A[":",i,end]
+ILNumerics.Drawing is integrated into ILNumerics
+removed ILNumerics.Drawing.Controls namespace -> ILNumerics.Drawing 
+changed function signatures for functions with multiple return parameters: removed ref keyword, incoming out parameters (if needed) are expected to be initialized already, f.e. ILMath.empty<>() 
+removed ILArray<T>.zeros - use ILMath.zeros<T>() instead
+cart2pol removed result type. regular new ILNumerics API instead
+ILMath.FFT renamed to: ILMath.FFTImplementation (VB compatibility)
+ILMemoryPool: created generic equivalents for some functionality 
+ILMath... API: removed all ref parameter (according to new general API parameter type schema)
+C# limited support: var and compound assignment operators are not supported anymore!!
+removed namespace ILNumerics.Settings -> ILSettings renamed to ILNumerics.Settings
+parallelized all internal functions
+complex structs are now serializable
+speed up repmat by factor 200 
+changed typed interface for ILCell: indexer return cells only, scalar cells are dereferenced, added GetArray<T>, GetCell, GetScalar<T>
+homogenized interface for ILMatfile 
+added xor()
+enabled virtual vector expansion on matching arrays for all binary operators (saving repmats)
+added isempty, mod + % operator, std, var, cov
+default orientation for vectors from elements: column vector
+conf setting: CreateRowVectorByDefault, defaults to: false / 'column'
+renamed ILDimension -> ILSize
+renamed A.Dimensions -> A.Size (original is deprecated)
+renamed A.D[] -> A.S[] (orig. is deprecated)
+added pif (single prec. pi constant) 
+added epsf (single prec. eps constant) 
+added nanmean(), nansum()
+added license management 
+reworked all examples
+provided 64 bit binaries (MKL) 
+primary support for MKL now, options for FFTW3 and ACML kept 
+implemented new memory management
+simplyfied ILNumerics.Drawing namespace 
+removed support for ILFigure, ILControl
+removed ILNumerics.BuiltinFunctions namespace; moved ILMath -> ILNumerics
+several new settings -> ILSettings class 
+implemented windows performance counters for memory pool 
+windows performance counter for thread pool measures 
+
+=======================================================
+Changelog for old (open source) core module: 
+
+Changes in version 1.4.11
+=========================
+* small docu bugfix: ILArray<T>[int] (contributed)
+* added AutoTestCaseGeneration project 
+  (permutes all parameter for all Core functions) 
+
+Changes in version 1.4.10
+=========================
+* implemented nonrecursive quicksort
+* some documentation fixes
+* new Settings in ILSettings (rel. sorting)
+* refinements in ILArray.ToString() for NaN/Inf
+
+Changes in version 1.4.09
+=========================
+* switched to .NET 3.5/ VS2008
+* refinements to complex.ToString() (contributed)
+* refinements to ILArray.ToString() (contributed)
+* made public internal QuickSort public
+* bugfix: sequential index access on reference arrays failed in certain situations
+
+Changes in version 1.4.08
+==========================
+(skipped)
+
+Changes in version 1.4.07
+==========================
+* added builtin function: atan2
+
+Changes in version 1.4.06
+==========================
+* bugfix: ILACML1_4.cs: incorrect mapping for ?potri
+
+Changes in version 1.4.05
+==========================
+* fixed a bug in ILMath.rank
+
+Changes in version 1.4.04
+===========================
+* fixed a bug in single element set acces: 
+  (setting element in referencing array led to wrong result for certain subarrays) 
+* sped up implicit cast operator T[,] and T[,,] 
+
+Changes in version 1.4.03
+===========================
+* sort: return indices rel. to dim length
+* repmat: simplified interface (no 'rows' parameter)
+* horzcat, vertcat: improved exception handling
+* added: isequal, isequalwithequalnans 
+* max,min handling NaN and Inf properly now
+* new testing framework: ILAutoTestCaseGenerator
+* ILMatFile: added Int64, UInt64 capabilities
+* binary function (add,.. etc) allowing one empty if the other parameter ist scalar
+* binary functions (add,...) saturate for integral types
+* fixed a bug in pinv for complex types (conj missed transpose)
+* complex division operator: properly handles NaN inputs
+* any() now truely ignores NaN values
+
+Changes in version 1.4.01
+===========================
+* bugfix and(scalar, array), or(scalar,array) 
+* ILArray.Reshape(params int[]) added
+* added: ILDimension.IsSameShape()
+* implemented FFT (generic interface)
+* implemented 3 FFT modules
+* moved all TESTs into seperate assembly 
+* ILDimension is _really_ immutable now
+* ILDimension.getShiftedVersion -> GetShifted()
+* ILMath.reshape(A,...) preserving A
+* empty arrays dimensions preserve true sizes
+* ILArray can have trailing singleton dimensions
+* AMD ACML updated to version 4.1 
+* ACML provided as seperate module 
+
+Changes in version 1.3.15
+===========================
+C: bugfix: diag(vect,-d)
+C: complex division with real values improved for NAN
+C: bugfix:ILArray<>.MaxValue, .MinValue on all NaN's
+C: bugfix:complex subtraction
+C: implemented unary minus on complex
+C: added ILMath.conj() - complex conjugate
+C: bugfix on n-dim reference unary operators for n>2 in certain situations
+
+Changes in version 1.3.14
+===========================
+* C: mkl update to 10.0.3.21
+* C: MatrixProperties: Unknown,None
+* C: complex: support for NaN
+* C: complex division 0/inf=>NaN
+* C: + robust against overflow
+* C: strong name for core dll
+* D: 0.10.0
+* D: ILAxisLabel -> ILLabel (in NS also)
+* D: AxisLabelAlign -> LabelAlign
+* D: legends implemented 
+
+Changes in version 1.3.13
+===========================
+* C: bugfix:binary operator (some ref.matrices op. on scalar)
+* C: bugfix:complex division handling inf's
+* C: bugfix:ILDimension (semi)immutable
+* C: added ILSpecialData.sphere(int), moebius()
+* D: 0.9.29: plot controls
+* D: Y-Line graphs starting at '0' now
+* D: all markers (and more), -> <a href="http://ilnumerics.net/main.php?site=5136312">docu</a>
+* D: implemented colormaps for ILPanel
+* D: surface graphs receive X,Y,C arguments
+* D: colorbar renders current colormap
+* D: SaveToBitmap for ILPanel, ILSubfigure
+
+Changes in version 1.3.12
+===========================
+* C: new function 'diff'
+* C: complex number bug fixes
+* D: 0.9.28: plot controls 
+* D: internal labeling redesign 
+* D: partial tex interpreter
+* D: X/Y plots
+
+Changes in version 1.3.11
+===========================
+* D: 0.9.27: more speaking trace log
+* D: removed assertion failure on TickMode.Manual
+* C: bugfix: expand emtpy ILArrays
+
+Changes in version 1.3.10
+===========================
+* new ILArray member: ExportValues(ref BaseT[] result)
+* bugfix on ILMath.ccomplex (had empty imag part)
+* new special data provider: ILSpecialData
+* redesigned ILFigure.dll -> ILNumerics.Drawing.dll
+* removed binary installer
+
+Changes in version 1.3.9
+===========================
+* ILMath.convert supports numeric ILBaseArray as argument
+* Intel MKL merged into single lib
+* Redesign for OpenGL plot panel (beta)
+
+Changes in version 1.3.8
+===========================
+* support for generalized eigenproblems for symmetrical/hermitian matrices A and B
+* improved string/debug display for complex number types
+* performance optimiziations for MKL working arrays (utilizing ILMemoryPool)
+
+Changes in version 1.3.7
+===========================
+* License changed to LGPL v3
+* implemented Intel's MKL v10.0 (sequential)
+
+Changes in version 1.3.6
+===========================
+* bugfix: expanding ILArray with left side ranges out of bounds, would not expand correctly in a special case
+* ILArray<T> A -> comparison with 'null' now also possible in boolean expressions like 'if (A==null) {...'
+* Improved array naming when writing to Matlab *.mat file. 
+
+Changes in version 1.3.5
+===========================
+* all ILMath.* functions now lowercase!
+-> PLEASE RENAME! find,vertact,horzcat!
+* bugfix: ILAsyncAlgorithm possibly caused
+  dead lock on start
+* bugfix: in certain situations sort(A,out B)
+  returned wrong indices
+
+Changes in version 1.3.4
+===========================
++ new determinant function: ILMath.det(A)
+* implicit cast System.Array ->ILArray
+* some changes/corrections for docu
+
+Changes in version 1.3.3
+===========================
+* Bugfix: calling linsolve with hermitian, pos.def. matrix A 
+  on non-AMD-processors was causing exception
+* added xml documentation files for IDE support: 
+  -> +ILNumerics.Net.xml, 
+  -> +ILFigure.xml
+
+=======================================================
+Changelog for old (open source) drawing module: 
+
+Changes in version 0.13.03
+===========================
+* reset defaults for ILSubfigure 
+* reset defaults for Plot2dGraph
+* lots of documentation fixes
+* aligned web/html docu and chm files
+* fixed IILPanelConfigurator for older graphs
+* added > 10 examples to SVN repos.
+
+Changes in version 0.13.02
+===========================
+* renamed: Drawing.Plots.ILLitBox3D 
+       ->  Drawing.Shapes.ILLitBox
+* moved:   Drawing.Graphs.ILBarGraph2D
+       ->  Drawing.Plots.ILBarGraph2D
+* implemented ILPlot (custom plots base)
+* ILPanel.Create() sets Dock=Filled also
+* added new plot: ILLitSink (demo)
+* added ILSceneGraphNode.EventingSuspend()
+* added ILSceneGraphNode.EventingResume()
+* new ILPanel.InteractiveMode: Translating (via CTRL key)
+* renamed ILLitBox3D.Wireframe -> ILLitBox3D.Edges
+* sped up ILLitBox3D
+* added ILPanel.Graph.AddPlot()
+* improved ILPanel event handling
+* ILPanel.AutoZoomContent -> AutoZoomOptions
+* IILPanelConfigurator interface
+* added ILSceneGraph.NodeAdded event
+* added ILSceneGraph.NodeRemoved event
+* removed! scene graph IEnumerable implementation
+  -> use ILSceneGraphNode instead
+* added ILSceneGraphInnerNode.Remove(ILShape)
+* removed! IILLegendRenderer.Label
+* added IILLegendRenderer.LabelSize
+* renamed: IILRenderer -> IILTextRenderer
+* improved stability of axis ticks (NaN, Inf)
+* added Plots.ILBarGraph3D: IILPanelConfigurator
+* some documentation
+* added Plots.ILLitSurface: IILPanelConfigurator
+* improved ILLitSurface performance
+* renamed: Drawing.Plots.ILVectorField
+        -> Drawing.Plots.ILVectorField2D
+* Implemented ILBorderedShape.Update()
+* improved sorting for transparent composite shapes
+* ILLitPolygon, ILPolygon, ILLines accept 
+  changed datalength on Update()
+* ILTriangles, ILQuads: added missing constructors
+
+Changes in version 0.13.01
+===========================
+* hides labeled ticks also when hiding axis main lines
+* ILLitSurface: option to update X and Y values as well
+* added line properties for ILLines also
+* hides edge tick lines in 2D mode
+* renamed ILPanel.Transform -> ILPanel.World2Screen
+* added new shape: ILLitSphere via triangularization
+* ILLabel.Anchor, repl. ILTickLabelAlign
+* bugfix: ILPanel.DrawToBitmap()
+* Zoom actions more robust
+* lots of documentation
+* added ILPanel.PlotBoxScreenRect
+* added ILPanel.PlotBoxScreenSizeMode
+* added ILPanel.AspectRatio
+* switched to .NET 3.5/ VS2008
+* improved sorting of graphs for rendering
+* general performance tunings
+* added ILTickCollection.TicksAllowOverlap
+* some tick label tuning
+* added DefaultView handling for ILPanel (AutoDefaultView)
+* rebuilt rendering section (ILPanel,ILRenderProperties)
+* added ILLabel.Visible property
+* added ILCamera.Top
+* added ILCamera.LookAt
+
+Changes in version 0.12.12
+===========================
+* addes some convenience constructors for ILLine shapes
+* improved properties interface for ILLine (lokal properties are aliased to local ILProperties class)
+* fixed a minor bug in ILTextRenderer (char caching may failed at edge of texture sheets) 
+* added update capabilities for all composite shapes
+* new higher level plots: ILLitSurface, ILBarGraph3D, ILVectorField
+* much improved text rendering for shape labels: ILShapeLabel.FringeColor
+* some slight layout improvements (f.e. backcolor for ILPanel > light gray)
+* bugfix in ILColormap, handling out-o-range values
+
+Changes in version 0.12.11
+===========================
+* reworked scene graph inner node structure
+* fixed automatic invalidation on changes to scene graph children collection
+* improved lightning for shapes
+* added new shapes: ILLitBorderedShape, ILLitQuad, ILLitTriangle
+* added new plots: ILLitBox3D, ILBarGraph3D (still under construction)
+* possibly breaking change: ILShape.Visible moved to ILSceneGraphNode.Visible
+  (as well as some other properties of ILShape)
+
+Changes in version 0.12.10
+===========================
+* corrected color (byte) -> OpenGL (float) translation in
+  vertex renderer
+
+Changes in version 0.12.09
+===========================
+* added Material to ILLitCompositShapes
+* removed unneeded/ outdated classes/files
+
+Changes in version 0.12.08
+===========================
+* bugfix: ILLines did not apply line properties correctly
+* bugfix: compute normal vectors for composite shapes
+
+Changes in version 0.12.07
+===========================
+* improved light capabilities
+* added ILLitSurfaceShape
+* improved performance on ILLitCompositeShapes
+
+Changes in version 0.12.06
+===========================
+* added ILShape.Visible property
+ 
+Changes in version 0.12.05
+===========================
+* fixes Zoom in 3D
+* implements morphing feature for Zoom
+
+Changes in version 0.12.04
+===========================
+* removed AutoFitContent from graphs - caused confusion
+* added AutoZoomContent to ILPanel as replacement
+
+Changes in version 0.12.03
+===========================
+bugfix on zero-height planes (surf)
++ added ILClippingData: AllowZeroVolume
++ moved m_* attributes of ILClippingData to private
++ zero planes get _middle_ color from colormap
++ fixed colorbar accordingly
+
+Changes in version 0.12.02
+===========================
+* bugfix: ILColorBar.RegisterRangeSource improved parameter checking
+
+Changes in version 0.12.01
+===========================
+* complete scene graph implementation
+* support for transparency (sorting of graphs)
+* more cleaner eventing / signaling model
+* scene graph partial invalidation/ reconfiguration
+* light for scene objects 
+* dynamic graphs 
+* ILCamera: new property: Position (X,Y,Z)
+* ... (just too much to count)
+
+Changes in version 0.10.02
+===========================
+* detaching events on disposals
+* ILRendererAtrribute: added CoordSystem 
+* ILRenderers are reused everywhere
+
+Changes in version: 0.10.01 
+===========================
+* ILAxisLabel -> ILLabel (in NS also)
+* AxisLabelAlign -> LabelAlign
+* legends implemented 
